mirror of
https://gitee.com/ant-design/ant-design.git
synced 2024-12-03 04:30:06 +08:00
Merge pull request #24537 from ant-design/master-to-merge-feature
chore: Master to merge feature
This commit is contained in:
commit
7c77a764e1
12
components/_util/__tests__/transButton.test.js
Normal file
12
components/_util/__tests__/transButton.test.js
Normal file
@ -0,0 +1,12 @@
|
||||
import React from 'react';
|
||||
import { mount } from 'enzyme';
|
||||
import TransButton from '../transButton';
|
||||
|
||||
describe('transButton component', () => {
|
||||
it('disabled should update style', () => {
|
||||
const wrapper = mount(<TransButton disabled />);
|
||||
expect(wrapper.find('div').first().props().style).toEqual(
|
||||
expect.objectContaining({ pointerEvents: 'none' }),
|
||||
);
|
||||
});
|
||||
});
|
@ -18,24 +18,42 @@ describe('Wave component', () => {
|
||||
it('isHidden works', () => {
|
||||
const TEST_NODE_ENV = process.env.NODE_ENV;
|
||||
process.env.NODE_ENV = 'development';
|
||||
const wrapper = mount(<Wave><button type="button">button</button></Wave>);
|
||||
const wrapper = mount(
|
||||
<Wave>
|
||||
<button type="button">button</button>
|
||||
</Wave>,
|
||||
);
|
||||
expect(wrapper.find('button').getDOMNode().className).toBe('');
|
||||
wrapper.find('button').getDOMNode().click();
|
||||
expect(wrapper.find('button').getDOMNode().hasAttribute('ant-click-animating-without-extra-node')).toBe(false);
|
||||
expect(
|
||||
wrapper.find('button').getDOMNode().hasAttribute('ant-click-animating-without-extra-node'),
|
||||
).toBe(false);
|
||||
wrapper.unmount();
|
||||
process.env.NODE_ENV = TEST_NODE_ENV;
|
||||
});
|
||||
|
||||
it('isHidden is mocked', () => {
|
||||
const wrapper = mount(<Wave><button type="button">button</button></Wave>);
|
||||
const wrapper = mount(
|
||||
<Wave>
|
||||
<button type="button">button</button>
|
||||
</Wave>,
|
||||
);
|
||||
expect(wrapper.find('button').getDOMNode().className).toBe('');
|
||||
wrapper.find('button').getDOMNode().click();
|
||||
expect(wrapper.find('button').getDOMNode().getAttribute('ant-click-animating-without-extra-node')).toBe('false');
|
||||
expect(
|
||||
wrapper.find('button').getDOMNode().getAttribute('ant-click-animating-without-extra-node'),
|
||||
).toBe('false');
|
||||
wrapper.unmount();
|
||||
});
|
||||
|
||||
it('wave color is grey', async () => {
|
||||
const wrapper = mount(<Wave><button type="button" style={{ borderColor: 'rgb(0, 0, 0)' }}>button</button></Wave>);
|
||||
const wrapper = mount(
|
||||
<Wave>
|
||||
<button type="button" style={{ borderColor: 'rgb(0, 0, 0)' }}>
|
||||
button
|
||||
</button>
|
||||
</Wave>,
|
||||
);
|
||||
wrapper.find('button').getDOMNode().click();
|
||||
await sleep(0);
|
||||
const styles = document.getElementsByTagName('style');
|
||||
@ -44,7 +62,13 @@ describe('Wave component', () => {
|
||||
});
|
||||
|
||||
it('wave color is not grey', async () => {
|
||||
const wrapper = mount(<Wave><button type="button" style={{ borderColor: 'red' }}>button</button></Wave>);
|
||||
const wrapper = mount(
|
||||
<Wave>
|
||||
<button type="button" style={{ borderColor: 'red' }}>
|
||||
button
|
||||
</button>
|
||||
</Wave>,
|
||||
);
|
||||
wrapper.find('button').getDOMNode().click();
|
||||
await sleep(200);
|
||||
const styles = document.getElementsByTagName('style');
|
||||
@ -54,7 +78,11 @@ describe('Wave component', () => {
|
||||
});
|
||||
|
||||
it('read wave color from border-top-color', async () => {
|
||||
const wrapper = mount(<Wave><div style={{ borderTopColor: 'blue' }}>button</div></Wave>);
|
||||
const wrapper = mount(
|
||||
<Wave>
|
||||
<div style={{ borderTopColor: 'blue' }}>button</div>
|
||||
</Wave>,
|
||||
);
|
||||
wrapper.find('div').getDOMNode().click();
|
||||
await sleep(0);
|
||||
const styles = document.getElementsByTagName('style');
|
||||
@ -64,7 +92,11 @@ describe('Wave component', () => {
|
||||
});
|
||||
|
||||
it('read wave color from background color', async () => {
|
||||
const wrapper = mount(<Wave><div style={{ backgroundColor: 'green' }}>button</div></Wave>);
|
||||
const wrapper = mount(
|
||||
<Wave>
|
||||
<div style={{ backgroundColor: 'green' }}>button</div>
|
||||
</Wave>,
|
||||
);
|
||||
wrapper.find('div').getDOMNode().click();
|
||||
await sleep(0);
|
||||
const styles = document.getElementsByTagName('style');
|
||||
@ -74,7 +106,11 @@ describe('Wave component', () => {
|
||||
});
|
||||
|
||||
it('read wave color from border firstly', async () => {
|
||||
const wrapper = mount(<Wave><div style={{ borderColor: 'yellow', backgroundColor: 'green' }}>button</div></Wave>);
|
||||
const wrapper = mount(
|
||||
<Wave>
|
||||
<div style={{ borderColor: 'yellow', backgroundColor: 'green' }}>button</div>
|
||||
</Wave>,
|
||||
);
|
||||
wrapper.find('div').getDOMNode().click();
|
||||
await sleep(0);
|
||||
const styles = document.getElementsByTagName('style');
|
||||
@ -84,7 +120,13 @@ describe('Wave component', () => {
|
||||
});
|
||||
|
||||
it('hidden element with -leave className', async () => {
|
||||
const wrapper = mount(<Wave><button type="button" className="xx-leave">button</button></Wave>);
|
||||
const wrapper = mount(
|
||||
<Wave>
|
||||
<button type="button" className="xx-leave">
|
||||
button
|
||||
</button>
|
||||
</Wave>,
|
||||
);
|
||||
wrapper.find('button').getDOMNode().click();
|
||||
await sleep(0);
|
||||
const styles = document.getElementsByTagName('style');
|
||||
@ -95,7 +137,9 @@ describe('Wave component', () => {
|
||||
it('ConfigProvider csp', async () => {
|
||||
const wrapper = mount(
|
||||
<ConfigProvider csp={{ nonce: 'YourNonceCode' }}>
|
||||
<Wave><button type="button">button</button></Wave>
|
||||
<Wave>
|
||||
<button type="button">button</button>
|
||||
</Wave>
|
||||
</ConfigProvider>,
|
||||
);
|
||||
wrapper.find('button').getDOMNode().click();
|
||||
|
@ -9,6 +9,7 @@ interface TransButtonProps extends React.HTMLAttributes<HTMLDivElement> {
|
||||
onClick?: (e?: React.MouseEvent<HTMLDivElement>) => void;
|
||||
noStyle?: boolean;
|
||||
autoFocus?: boolean;
|
||||
disabled?: boolean;
|
||||
}
|
||||
|
||||
const inlineStyle: React.CSSProperties = {
|
||||
@ -63,7 +64,24 @@ class TransButton extends React.Component<TransButtonProps> {
|
||||
}
|
||||
|
||||
render() {
|
||||
const { style, noStyle, ...restProps } = this.props;
|
||||
const { style, noStyle, disabled, ...restProps } = this.props;
|
||||
|
||||
let mergedStyle: React.CSSProperties = {};
|
||||
|
||||
if (!noStyle) {
|
||||
mergedStyle = {
|
||||
...inlineStyle,
|
||||
};
|
||||
}
|
||||
|
||||
if (disabled) {
|
||||
mergedStyle.pointerEvents = 'none';
|
||||
}
|
||||
|
||||
mergedStyle = {
|
||||
...mergedStyle,
|
||||
...style,
|
||||
};
|
||||
|
||||
return (
|
||||
<div
|
||||
@ -73,7 +91,7 @@ class TransButton extends React.Component<TransButtonProps> {
|
||||
{...restProps}
|
||||
onKeyDown={this.onKeyDown}
|
||||
onKeyUp={this.onKeyUp}
|
||||
style={{ ...(!noStyle ? inlineStyle : null), ...style }}
|
||||
style={mergedStyle}
|
||||
/>
|
||||
);
|
||||
}
|
||||
|
@ -40,19 +40,10 @@ describe('Avatar Render', () => {
|
||||
global.document.body.appendChild(div);
|
||||
|
||||
const wrapper = mount(<Avatar src="http://error.url">Fallback</Avatar>, { attachTo: div });
|
||||
wrapper.instance().setScale = jest.fn(() => {
|
||||
if (wrapper.state().scale === 0.5) {
|
||||
return;
|
||||
}
|
||||
wrapper.instance().setState({ scale: 0.5 });
|
||||
});
|
||||
wrapper.find('img').simulate('error');
|
||||
|
||||
const children = wrapper.find('.ant-avatar-string');
|
||||
expect(children.length).toBe(1);
|
||||
expect(children.text()).toBe('Fallback');
|
||||
expect(wrapper.instance().setScale).toHaveBeenCalled();
|
||||
expect(div.querySelector('.ant-avatar-string').style.transform).toContain('scale(0.5)');
|
||||
|
||||
wrapper.detach();
|
||||
global.document.body.removeChild(div);
|
||||
@ -136,6 +127,11 @@ describe('Avatar Render', () => {
|
||||
expect(wrapper.state().scale).toBe(0.32);
|
||||
});
|
||||
|
||||
it('should calculate scale of avatar children correctly with gap', () => {
|
||||
const wrapper = mount(<Avatar gap={2}>Avatar</Avatar>);
|
||||
expect(wrapper.state().scale).toBe(0.36);
|
||||
});
|
||||
|
||||
it('should warning when pass a string as icon props', () => {
|
||||
const warnSpy = jest.spyOn(console, 'error').mockImplementation(() => {});
|
||||
mount(<Avatar size={64} icon="aa" />);
|
||||
|
@ -454,7 +454,16 @@ Array [
|
||||
type="button"
|
||||
>
|
||||
<span>
|
||||
Change
|
||||
ChangeUser
|
||||
</span>
|
||||
</button>,
|
||||
<button
|
||||
class="ant-btn ant-btn-sm"
|
||||
style="vertical-align:middle"
|
||||
type="button"
|
||||
>
|
||||
<span>
|
||||
changeGap
|
||||
</span>
|
||||
</button>,
|
||||
]
|
||||
|
@ -7,11 +7,11 @@ title:
|
||||
|
||||
## zh-CN
|
||||
|
||||
对于字符型的头像,当字符串较长时,字体大小可以根据头像宽度自动调整。
|
||||
对于字符型的头像,当字符串较长时,字体大小可以根据头像宽度自动调整。也可使用 `gap` 来设置字符距离左右两侧边界单位像素。
|
||||
|
||||
## en-US
|
||||
|
||||
For letter type Avatar, when the letters are too long to display, the font size can be automatically adjusted according to the width of the Avatar.
|
||||
For letter type Avatar, when the letters are too long to display, the font size can be automatically adjusted according to the width of the Avatar. You can also use `gap` to set the unit distance between left and right sides.
|
||||
|
||||
```tsx
|
||||
import React, { useState } from 'react';
|
||||
@ -19,18 +19,24 @@ import { Avatar, Button } from 'antd';
|
||||
|
||||
const UserList = ['U', 'Lucy', 'Tom', 'Edward'];
|
||||
const ColorList = ['#f56a00', '#7265e6', '#ffbf00', '#00a2ae'];
|
||||
const GapList = [4, 3, 2, 1];
|
||||
|
||||
const Autoset: React.FC = () => {
|
||||
const [user, setUser] = useState(UserList[0]);
|
||||
const [color, setColor] = useState(ColorList[0]);
|
||||
const [gap, setGap] = useState(GapList[0]);
|
||||
const changeUser = () => {
|
||||
const index = UserList.indexOf(user);
|
||||
setUser(index < UserList.length - 1 ? UserList[index + 1] : UserList[0]);
|
||||
setColor(index < ColorList.length - 1 ? ColorList[index + 1] : ColorList[0]);
|
||||
};
|
||||
const changeGap = () => {
|
||||
const index = GapList.indexOf(gap);
|
||||
setGap(index < GapList.length - 1 ? GapList[index + 1] : GapList[0]);
|
||||
};
|
||||
return (
|
||||
<>
|
||||
<Avatar style={{ backgroundColor: color, verticalAlign: 'middle' }} size="large">
|
||||
<Avatar style={{ backgroundColor: color, verticalAlign: 'middle' }} size="large" gap={gap}>
|
||||
{user}
|
||||
</Avatar>
|
||||
<Button
|
||||
@ -38,7 +44,10 @@ const Autoset: React.FC = () => {
|
||||
style={{ margin: '0 16px', verticalAlign: 'middle' }}
|
||||
onClick={changeUser}
|
||||
>
|
||||
Change
|
||||
ChangeUser
|
||||
</Button>
|
||||
<Button size="small" style={{ verticalAlign: 'middle' }} onClick={changeGap}>
|
||||
changeGap
|
||||
</Button>
|
||||
</>
|
||||
);
|
||||
|
@ -17,3 +17,4 @@ Avatars can be used to represent people or objects. It supports images, `Icon`s,
|
||||
| srcSet | a list of sources to use for different screen resolutions | string | - | |
|
||||
| alt | This attribute defines the alternative text describing the image | string | - | |
|
||||
| onError | handler when img load error, return false to prevent default fallback behavior | () => boolean | - | |
|
||||
| gap | Letter type unit distance between left and right sides | number | 4 | 4.3.0 |
|
||||
|
@ -12,6 +12,7 @@ export interface AvatarProps {
|
||||
* or a custom number size
|
||||
* */
|
||||
size?: 'large' | 'small' | 'default' | number;
|
||||
gap?: number;
|
||||
/** Src of image avatar */
|
||||
src?: string;
|
||||
/** Srcset of image avatar */
|
||||
@ -61,10 +62,12 @@ export default class Avatar extends React.Component<AvatarProps, AvatarState> {
|
||||
}
|
||||
|
||||
componentDidUpdate(prevProps: AvatarProps) {
|
||||
this.setScale();
|
||||
if (prevProps.src !== this.props.src) {
|
||||
this.setState({ isImgExist: true, scale: 1 });
|
||||
}
|
||||
if (prevProps.children !== this.props.children || prevProps.gap !== this.props.gap) {
|
||||
this.setScale();
|
||||
}
|
||||
}
|
||||
|
||||
setScale = () => {
|
||||
@ -73,20 +76,22 @@ export default class Avatar extends React.Component<AvatarProps, AvatarState> {
|
||||
}
|
||||
const childrenWidth = this.avatarChildren.offsetWidth; // offsetWidth avoid affecting be transform scale
|
||||
const nodeWidth = this.avatarNode.offsetWidth;
|
||||
const { gap = 4 } = this.props;
|
||||
// denominator is 0 is no meaning
|
||||
if (
|
||||
childrenWidth === 0 ||
|
||||
nodeWidth === 0 ||
|
||||
(this.lastChildrenWidth === childrenWidth && this.lastNodeWidth === nodeWidth)
|
||||
childrenWidth !== 0 &&
|
||||
nodeWidth !== 0 &&
|
||||
(this.lastChildrenWidth !== childrenWidth || this.lastNodeWidth !== nodeWidth)
|
||||
) {
|
||||
return;
|
||||
this.lastChildrenWidth = childrenWidth;
|
||||
this.lastNodeWidth = nodeWidth;
|
||||
}
|
||||
|
||||
if (gap * 2 < nodeWidth) {
|
||||
this.setState({
|
||||
scale: nodeWidth - gap * 2 < childrenWidth ? (nodeWidth - gap * 2) / childrenWidth : 1,
|
||||
});
|
||||
}
|
||||
this.lastChildrenWidth = childrenWidth;
|
||||
this.lastNodeWidth = nodeWidth;
|
||||
// add 4px gap for each side to get better performance
|
||||
this.setState({
|
||||
scale: nodeWidth - 8 < childrenWidth ? (nodeWidth - 8) / childrenWidth : 1,
|
||||
});
|
||||
};
|
||||
|
||||
handleImgLoadError = () => {
|
||||
@ -204,7 +209,6 @@ export default class Avatar extends React.Component<AvatarProps, AvatarState> {
|
||||
|
||||
return (
|
||||
<span
|
||||
{...others}
|
||||
style={{ ...sizeStyle, ...others.style }}
|
||||
className={classString}
|
||||
ref={(node: HTMLElement) => (this.avatarNode = node)}
|
||||
|
@ -22,3 +22,4 @@ title: Avatar
|
||||
| srcSet | 设置图片类头像响应式资源地址 | string | - | |
|
||||
| alt | 图像无法显示时的替代文本 | string | - | |
|
||||
| onError | 图片加载失败的事件,返回 false 会关闭组件默认的 fallback 行为 | () => boolean | - | |
|
||||
| gap | 字符类型距离左右两侧边界单位像素 | number | 4 | 4.3.0 |
|
||||
|
@ -3,6 +3,7 @@ import Animate from 'rc-animate';
|
||||
import addEventListener from 'rc-util/lib/Dom/addEventListener';
|
||||
import classNames from 'classnames';
|
||||
import omit from 'omit.js';
|
||||
import VerticalAlignTopOutlined from '@ant-design/icons/VerticalAlignTopOutlined';
|
||||
import throttleByAnimationFrame from '../_util/throttleByAnimationFrame';
|
||||
import { ConfigContext } from '../config-provider';
|
||||
import getScroll from '../_util/getScroll';
|
||||
@ -80,7 +81,9 @@ const BackTop: React.FC<BackTopProps> = props => {
|
||||
const { children } = props;
|
||||
const defaultElement = (
|
||||
<div className={`${prefixCls}-content`}>
|
||||
<div className={`${prefixCls}-icon`} />
|
||||
<div className={`${prefixCls}-icon`}>
|
||||
<VerticalAlignTopOutlined />
|
||||
</div>
|
||||
</div>
|
||||
);
|
||||
return (
|
||||
|
@ -37,11 +37,8 @@
|
||||
}
|
||||
|
||||
&-icon {
|
||||
width: 14px;
|
||||
height: 16px;
|
||||
margin: 12px auto;
|
||||
background: url(data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAACQAAAAoCAYAAACWwljjAAAABGdBTUEAALGPC/xhBQAAAbtJREFUWAntmMtKw0AUhhMvS5cuxILgQlRUpIggIoKIIoigG1eC+AA+jo+i6FIXBfeuXIgoeKVeitVWJX5HWhhDksnUpp3FDPyZk3Nm5nycmZKkXhAEOXSA3lG7muTeRzmfy6HneUvIhnYkQK+Q9NhAA0Opg0vBEhjBKHiyb8iGMyQMOYuK41BcBSypAL+MYXSKjtFAW7EAGEO3qN4uMQbbAkXiSfRQJ1H6a+yhlkKRcAoVFYiweYNjtCVQJJpBz2GCiPt7fBOZQpFgDpUikse5HgnkM4Fi4QX0Fpc5wf9EbLqpUCy4jMoJSXWhFwbMNgWKhVbRhy5jirhs9fy/oFhgHVVTJEs7RLZ8sSEoJm6iz7SZDMbJ+/OKERQTttCXQRLToRUmrKWCYuA2+jbN0MB4OQobYShfdTCgn/sL1K36M7TLrN3n+758aPy2rrpR6+/od5E8tf/A1uLS9aId5T7J3CNYihkQ4D9PiMdMC7mp4rjB9kjFjZp8BlnVHJBuO1yFXIV0FdDF3RlyFdJVQBdv5AxVdIsq8apiZ2PyYO1EVykesGfZEESsCkweyR8MUW+V8uJ1gkYipmpdP1pm2aJVPEGzAAAAAElFTkSuQmCC)
|
||||
~'100%/100%' no-repeat;
|
||||
font-size: 24px;
|
||||
line-height: 40px;
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -485,12 +485,17 @@ exports[`renders ./components/badge/demo/change.md correctly 1`] = `
|
||||
`;
|
||||
|
||||
exports[`renders ./components/badge/demo/colorful.md correctly 1`] = `
|
||||
<div>
|
||||
<h4
|
||||
style="margin-bottom:16px"
|
||||
Array [
|
||||
<div
|
||||
class="ant-divider ant-divider-horizontal ant-divider-with-text ant-divider-with-text-left"
|
||||
role="separator"
|
||||
>
|
||||
Presets:
|
||||
</h4>
|
||||
<span
|
||||
class="ant-divider-inner-text"
|
||||
>
|
||||
Presets
|
||||
</span>
|
||||
</div>,
|
||||
<div>
|
||||
<div>
|
||||
<span
|
||||
@ -674,12 +679,17 @@ exports[`renders ./components/badge/demo/colorful.md correctly 1`] = `
|
||||
</span>
|
||||
</span>
|
||||
</div>
|
||||
</div>
|
||||
<h4
|
||||
style="margin:16px 0"
|
||||
</div>,
|
||||
<div
|
||||
class="ant-divider ant-divider-horizontal ant-divider-with-text ant-divider-with-text-left"
|
||||
role="separator"
|
||||
>
|
||||
Custom:
|
||||
</h4>
|
||||
<span
|
||||
class="ant-divider-inner-text"
|
||||
>
|
||||
Custom
|
||||
</span>
|
||||
</div>,
|
||||
<div>
|
||||
<span
|
||||
class="ant-badge ant-badge-status ant-badge-not-a-wrapper"
|
||||
@ -736,8 +746,8 @@ exports[`renders ./components/badge/demo/colorful.md correctly 1`] = `
|
||||
#108ee9
|
||||
</span>
|
||||
</span>
|
||||
</div>
|
||||
</div>
|
||||
</div>,
|
||||
]
|
||||
`;
|
||||
|
||||
exports[`renders ./components/badge/demo/dot.md correctly 1`] = `
|
||||
|
@ -14,7 +14,7 @@ title:
|
||||
We preset a series of colorful Badge styles for use in different situations. You can also set it to a hex color string for custom color.
|
||||
|
||||
```jsx
|
||||
import { Badge } from 'antd';
|
||||
import { Badge, Divider } from 'antd';
|
||||
|
||||
const colors = [
|
||||
'pink',
|
||||
@ -33,8 +33,8 @@ const colors = [
|
||||
];
|
||||
|
||||
ReactDOM.render(
|
||||
<div>
|
||||
<h4 style={{ marginBottom: 16 }}>Presets:</h4>
|
||||
<>
|
||||
<Divider orientation="left">Presets</Divider>
|
||||
<div>
|
||||
{colors.map(color => (
|
||||
<div key={color}>
|
||||
@ -42,7 +42,7 @@ ReactDOM.render(
|
||||
</div>
|
||||
))}
|
||||
</div>
|
||||
<h4 style={{ margin: '16px 0' }}>Custom:</h4>
|
||||
<Divider orientation="left">Custom</Divider>
|
||||
<div>
|
||||
<Badge color="#f50" text="#f50" />
|
||||
<br />
|
||||
@ -52,7 +52,7 @@ ReactDOM.render(
|
||||
<br />
|
||||
<Badge color="#108ee9" text="#108ee9" />
|
||||
</div>
|
||||
</div>,
|
||||
</>,
|
||||
mountNode,
|
||||
);
|
||||
```
|
||||
|
@ -1,40 +1,49 @@
|
||||
// Jest Snapshot v1, https://goo.gl/fbAQLP
|
||||
|
||||
exports[`renders ./components/button/demo/basic.md correctly 1`] = `
|
||||
<div>
|
||||
Array [
|
||||
<button
|
||||
class="ant-btn ant-btn-primary"
|
||||
type="button"
|
||||
>
|
||||
<span>
|
||||
Primary
|
||||
Primary Button
|
||||
</span>
|
||||
</button>
|
||||
</button>,
|
||||
<button
|
||||
class="ant-btn"
|
||||
type="button"
|
||||
>
|
||||
<span>
|
||||
Default
|
||||
Default Button
|
||||
</span>
|
||||
</button>
|
||||
</button>,
|
||||
<button
|
||||
class="ant-btn ant-btn-dashed"
|
||||
type="button"
|
||||
>
|
||||
<span>
|
||||
Dashed
|
||||
Dashed Button
|
||||
</span>
|
||||
</button>
|
||||
</button>,
|
||||
<br />,
|
||||
<button
|
||||
class="ant-btn ant-btn-text"
|
||||
type="button"
|
||||
>
|
||||
<span>
|
||||
Text Button
|
||||
</span>
|
||||
</button>,
|
||||
<button
|
||||
class="ant-btn ant-btn-link"
|
||||
type="button"
|
||||
>
|
||||
<span>
|
||||
Link
|
||||
Link Button
|
||||
</span>
|
||||
</button>
|
||||
</div>
|
||||
</button>,
|
||||
]
|
||||
`;
|
||||
|
||||
exports[`renders ./components/button/demo/block.md correctly 1`] = `
|
||||
@ -185,6 +194,24 @@ exports[`renders ./components/button/demo/disabled.md correctly 1`] = `
|
||||
</span>
|
||||
</button>
|
||||
<br />
|
||||
<button
|
||||
class="ant-btn ant-btn-text"
|
||||
type="button"
|
||||
>
|
||||
<span>
|
||||
Text
|
||||
</span>
|
||||
</button>
|
||||
<button
|
||||
class="ant-btn ant-btn-text"
|
||||
disabled=""
|
||||
type="button"
|
||||
>
|
||||
<span>
|
||||
Text(disabled)
|
||||
</span>
|
||||
</button>
|
||||
<br />
|
||||
<button
|
||||
class="ant-btn ant-btn-link ant-btn-dangerous"
|
||||
type="button"
|
||||
@ -272,6 +299,14 @@ exports[`renders ./components/button/demo/ghost.md correctly 1`] = `
|
||||
link
|
||||
</span>
|
||||
</button>
|
||||
<button
|
||||
class="ant-btn ant-btn-text ant-btn-background-ghost"
|
||||
type="button"
|
||||
>
|
||||
<span>
|
||||
Text Button
|
||||
</span>
|
||||
</button>
|
||||
<button
|
||||
class="ant-btn ant-btn-link ant-btn-background-ghost"
|
||||
type="button"
|
||||
|
@ -268,18 +268,6 @@ exports[`Button rtl render component should be rendered correctly in RTL directi
|
||||
/>
|
||||
`;
|
||||
|
||||
exports[`Button should has click wave effect 1`] = `
|
||||
<button
|
||||
ant-click-animating-without-extra-node="true"
|
||||
class="ant-btn ant-btn-primary"
|
||||
type="button"
|
||||
>
|
||||
<span>
|
||||
button
|
||||
</span>
|
||||
</button>
|
||||
`;
|
||||
|
||||
exports[`Button should merge text if children using variable 1`] = `
|
||||
<button
|
||||
class="ant-btn"
|
||||
@ -291,17 +279,6 @@ exports[`Button should merge text if children using variable 1`] = `
|
||||
</button>
|
||||
`;
|
||||
|
||||
exports[`Button should not insert space to link button 1`] = `
|
||||
<button
|
||||
class="ant-btn ant-btn-link"
|
||||
type="button"
|
||||
>
|
||||
<span>
|
||||
按钮
|
||||
</span>
|
||||
</button>
|
||||
`;
|
||||
|
||||
exports[`Button should not render as link button when href is undefined 1`] = `
|
||||
<button
|
||||
class="ant-btn ant-btn-primary"
|
||||
|
@ -95,8 +95,11 @@ describe('Button', () => {
|
||||
});
|
||||
|
||||
// https://github.com/ant-design/ant-design/issues/18118
|
||||
it('should not insert space to link button', () => {
|
||||
expect(<Button type="link">按钮</Button>).toMatchRenderedSnapshot();
|
||||
it('should not insert space to link or text button', () => {
|
||||
const wrapper1 = mount(<Button type="link">按钮</Button>);
|
||||
expect(wrapper1.text()).toBe('按钮');
|
||||
const wrapper2 = mount(<Button type="text">按钮</Button>);
|
||||
expect(wrapper2.text()).toBe('按钮');
|
||||
});
|
||||
|
||||
it('should render empty button without errors', () => {
|
||||
@ -188,11 +191,31 @@ describe('Button', () => {
|
||||
expect(<Button>{false}</Button>).toMatchRenderedSnapshot();
|
||||
});
|
||||
|
||||
it('should has click wave effect', async () => {
|
||||
it('should have click wave effect', async () => {
|
||||
const wrapper = mount(<Button type="primary">button</Button>);
|
||||
wrapper.find('.ant-btn').getDOMNode<HTMLButtonElement>().click();
|
||||
await new Promise(resolve => setTimeout(resolve, 0));
|
||||
expect(wrapper.render()).toMatchSnapshot();
|
||||
await sleep(0);
|
||||
expect(
|
||||
wrapper.find('.ant-btn').getDOMNode().hasAttribute('ant-click-animating-without-extra-node'),
|
||||
).toBe(true);
|
||||
});
|
||||
|
||||
it('should not have click wave effect for link type button', async () => {
|
||||
const wrapper = mount(<Button type="link">button</Button>);
|
||||
wrapper.find('.ant-btn').getDOMNode<HTMLButtonElement>().click();
|
||||
await sleep(0);
|
||||
expect(
|
||||
wrapper.find('.ant-btn').getDOMNode().hasAttribute('ant-click-animating-without-extra-node'),
|
||||
).toBe(false);
|
||||
});
|
||||
|
||||
it('should not have click wave effect for text type button', async () => {
|
||||
const wrapper = mount(<Button type="link">button</Button>);
|
||||
wrapper.find('.ant-btn').getDOMNode<HTMLButtonElement>().click();
|
||||
await sleep(0);
|
||||
expect(
|
||||
wrapper.find('.ant-btn').getDOMNode().hasAttribute('ant-click-animating-without-extra-node'),
|
||||
).toBe(false);
|
||||
});
|
||||
|
||||
it('should not render as link button when href is undefined', async () => {
|
||||
@ -212,7 +235,6 @@ describe('Button', () => {
|
||||
This {'is'} a test {1}
|
||||
</Button>,
|
||||
);
|
||||
|
||||
expect(wrapper.render()).toMatchSnapshot();
|
||||
});
|
||||
|
||||
|
@ -68,7 +68,7 @@ function spaceChildren(children: React.ReactNode, needInserted: boolean) {
|
||||
);
|
||||
}
|
||||
|
||||
const ButtonTypes = tuple('default', 'primary', 'ghost', 'dashed', 'link');
|
||||
const ButtonTypes = tuple('default', 'primary', 'ghost', 'dashed', 'link', 'text');
|
||||
export type ButtonType = typeof ButtonTypes[number];
|
||||
const ButtonShapes = tuple('circle', 'circle-outline', 'round');
|
||||
export type ButtonShape = typeof ButtonShapes[number];
|
||||
@ -131,7 +131,7 @@ const InternalButton: React.ForwardRefRenderFunction<unknown, ButtonProps> = (pr
|
||||
|
||||
const isNeedInserted = () => {
|
||||
const { icon, children, type } = props;
|
||||
return React.Children.count(children) === 1 && !icon && type !== 'link';
|
||||
return React.Children.count(children) === 1 && !icon && type !== 'link' && type !== 'text';
|
||||
};
|
||||
|
||||
const fixTwoCNChar = () => {
|
||||
@ -265,7 +265,7 @@ const InternalButton: React.ForwardRefRenderFunction<unknown, ButtonProps> = (pr
|
||||
</button>
|
||||
);
|
||||
|
||||
if (type === 'link') {
|
||||
if (type === 'link' || type === 'text') {
|
||||
return buttonNode;
|
||||
}
|
||||
|
||||
|
@ -17,12 +17,14 @@ There are `primary` button, `default` button, `dashed` button and `link` button
|
||||
import { Button } from 'antd';
|
||||
|
||||
ReactDOM.render(
|
||||
<div>
|
||||
<Button type="primary">Primary</Button>
|
||||
<Button>Default</Button>
|
||||
<Button type="dashed">Dashed</Button>
|
||||
<Button type="link">Link</Button>
|
||||
</div>,
|
||||
<>
|
||||
<Button type="primary">Primary Button</Button>
|
||||
<Button>Default Button</Button>
|
||||
<Button type="dashed">Dashed Button</Button>
|
||||
<br />
|
||||
<Button type="text">Text Button</Button>
|
||||
<Button type="link">Link Button</Button>
|
||||
</>,
|
||||
mountNode,
|
||||
);
|
||||
```
|
||||
|
@ -36,6 +36,11 @@ ReactDOM.render(
|
||||
Link(disabled)
|
||||
</Button>
|
||||
<br />
|
||||
<Button type="text">Text</Button>
|
||||
<Button type="text" disabled>
|
||||
Text(disabled)
|
||||
</Button>
|
||||
<br />
|
||||
<Button type="link" danger>
|
||||
Danger Link
|
||||
</Button>
|
||||
|
@ -25,6 +25,9 @@ ReactDOM.render(
|
||||
<Button type="dashed" ghost>
|
||||
link
|
||||
</Button>
|
||||
<Button type="text" ghost>
|
||||
Text Button
|
||||
</Button>
|
||||
<Button type="link" ghost>
|
||||
link
|
||||
</Button>
|
||||
|
@ -15,6 +15,7 @@ In Ant Design we provide 4 types of button.
|
||||
- Primary button: indicate the main action, one primary button at most in one section.
|
||||
- Default button: indicate a series of actions without priority.
|
||||
- Dashed button: used for adding action commonly.
|
||||
- Text button: used for the most secondary action.
|
||||
- Link button: used for external links.
|
||||
|
||||
And 4 other properties additionally.
|
||||
@ -39,7 +40,7 @@ To get a customized button, just set `type`/`shape`/`size`/`loading`/`disabled`.
|
||||
| shape | can be set to `circle`, `round` or omitted | string | - | |
|
||||
| size | set the size of button | `large` \| `middle` \| `small` | | |
|
||||
| target | same as target attribute of a, works when href is specified | string | - | |
|
||||
| type | can be set to `primary` `ghost` `dashed` `link` or omitted (meaning `default`) | string | `default` | |
|
||||
| type | can be set to `primary` `ghost` `dashed` `danger` `link` `text` or omitted (meaning `default`) | string | `default` | |
|
||||
| onClick | set the handler to handle `click` event | (event) => void | - | |
|
||||
| block | option to fit button width to its parent width | boolean | `false` | |
|
||||
| danger | set the danger status of button | boolean | `false` | |
|
||||
|
@ -16,7 +16,8 @@ subtitle: 按钮
|
||||
- 主按钮:用于主行动点,一个操作区域只能有一个主按钮。
|
||||
- 默认按钮:用于没有主次之分的一组行动点。
|
||||
- 虚线按钮:常用于添加操作。
|
||||
- 链接按钮:用于次要或外链的行动点。
|
||||
- 文本按钮:用于最次级的行动点。
|
||||
- 链接按钮:用于作为外链的行动点。
|
||||
|
||||
以及四种状态属性与上面配合使用。
|
||||
|
||||
@ -42,7 +43,7 @@ subtitle: 按钮
|
||||
| shape | 设置按钮形状,可选值为 `circle`、 `round` 或者不设 | string | - | |
|
||||
| size | 设置按钮大小 | `large` \| `middle` \| `small` | 无 | |
|
||||
| target | 相当于 a 链接的 target 属性,href 存在时生效 | string | - | |
|
||||
| type | 设置按钮类型,可选值为 `primary` `dashed` `link` 或者不设 | string | - | |
|
||||
| type | 设置按钮类型 | `primary` \| `ghost` \| `dashed` \| `danger` \| `link` \| `text` | - | |
|
||||
| onClick | 点击按钮时的回调 | (event) => void | - | |
|
||||
| block | 将按钮宽度调整为其父宽度的选项 | boolean | `false` | |
|
||||
| danger | 设置危险按钮 | boolean | `false` | |
|
||||
|
@ -79,6 +79,10 @@
|
||||
.btn-link;
|
||||
}
|
||||
|
||||
&-text {
|
||||
.btn-text;
|
||||
}
|
||||
|
||||
&-dangerous {
|
||||
.btn-danger-default;
|
||||
}
|
||||
|
@ -147,7 +147,7 @@
|
||||
}
|
||||
.button-color(@color; @background; @border) {
|
||||
color: @color;
|
||||
background-color: @background;
|
||||
background: @background;
|
||||
border-color: @border; // a inside Button which only work in Chrome
|
||||
// http://stackoverflow.com/a/17253457
|
||||
> a:only-child {
|
||||
@ -346,6 +346,9 @@
|
||||
.btn-link() {
|
||||
.button-variant-other(@link-color, transparent, transparent);
|
||||
box-shadow: none;
|
||||
&:hover {
|
||||
background: @btn-link-hover-bg;
|
||||
}
|
||||
&:hover,
|
||||
&:focus,
|
||||
&:active {
|
||||
@ -353,6 +356,25 @@
|
||||
}
|
||||
.button-disabled(@disabled-color; transparent; transparent);
|
||||
}
|
||||
// link button style
|
||||
.btn-text() {
|
||||
.button-variant-other(@text-color, transparent, transparent);
|
||||
box-shadow: none;
|
||||
&:hover,
|
||||
&:focus {
|
||||
color: @text-color;
|
||||
background: @btn-text-hover-bg;
|
||||
border-color: transparent;
|
||||
}
|
||||
|
||||
&:active {
|
||||
color: @text-color;
|
||||
background: fadein(@btn-text-hover-bg, 1%);
|
||||
border-color: transparent;
|
||||
}
|
||||
|
||||
.button-disabled(@disabled-color; transparent; transparent);
|
||||
}
|
||||
// round button
|
||||
.btn-round(@btnClassName: btn) {
|
||||
.button-size(@btn-circle-size; @btn-circle-size / 2; @font-size-base; @btn-circle-size);
|
||||
|
@ -0,0 +1,7 @@
|
||||
// Jest Snapshot v1, https://goo.gl/fbAQLP
|
||||
|
||||
exports[`Collapse rtl render component should be rendered correctly in RTL direction 1`] = `
|
||||
<div
|
||||
class="ant-collapse ant-collapse-icon-position-right ant-collapse-rtl"
|
||||
/>
|
||||
`;
|
@ -49,12 +49,6 @@ exports[`Collapse could override default openAnimation 1`] = `
|
||||
</div>
|
||||
`;
|
||||
|
||||
exports[`Collapse rtl render component should be rendered correctly in RTL direction 1`] = `
|
||||
<div
|
||||
class="ant-collapse ant-collapse-icon-position-right ant-collapse-rtl"
|
||||
/>
|
||||
`;
|
||||
|
||||
exports[`Collapse should render extra node of panel 1`] = `
|
||||
<div
|
||||
class="ant-collapse ant-collapse-icon-position-left"
|
||||
|
8
components/collapse/__tests__/common.test.js
Normal file
8
components/collapse/__tests__/common.test.js
Normal file
@ -0,0 +1,8 @@
|
||||
import mountTest from '../../../tests/shared/mountTest';
|
||||
import rtlTest from '../../../tests/shared/rtlTest';
|
||||
import Collapse from '..';
|
||||
|
||||
describe('Collapse', () => {
|
||||
mountTest(Collapse);
|
||||
rtlTest(Collapse);
|
||||
});
|
@ -1,7 +1,5 @@
|
||||
import React from 'react';
|
||||
import { mount } from 'enzyme';
|
||||
import mountTest from '../../../tests/shared/mountTest';
|
||||
import rtlTest from '../../../tests/shared/rtlTest';
|
||||
import { sleep } from '../../../tests/utils';
|
||||
|
||||
describe('Collapse', () => {
|
||||
@ -18,8 +16,6 @@ describe('Collapse', () => {
|
||||
|
||||
// eslint-disable-next-line global-require
|
||||
const Collapse = require('..').default;
|
||||
mountTest(Collapse);
|
||||
rtlTest(Collapse);
|
||||
|
||||
it('should support remove expandIcon', () => {
|
||||
const wrapper = mount(
|
||||
@ -65,11 +61,10 @@ describe('Collapse', () => {
|
||||
</Collapse>,
|
||||
);
|
||||
expect(wrapper.find('.ant-collapse-item').hasClass('ant-collapse-item-active')).toBe(false);
|
||||
wrapper
|
||||
.find('.ant-collapse-header')
|
||||
.at(0)
|
||||
.simulate('click');
|
||||
wrapper.find('.ant-collapse-header').at(0).simulate('click');
|
||||
wrapper.update();
|
||||
await sleep(400);
|
||||
wrapper.update();
|
||||
expect(wrapper.find('.ant-collapse-item').hasClass('ant-collapse-item-active')).toBe(true);
|
||||
});
|
||||
|
||||
@ -81,10 +76,7 @@ describe('Collapse', () => {
|
||||
</Collapse.Panel>
|
||||
</Collapse>,
|
||||
);
|
||||
wrapper
|
||||
.find('.ant-collapse-header')
|
||||
.at(0)
|
||||
.simulate('click');
|
||||
wrapper.find('.ant-collapse-header').at(0).simulate('click');
|
||||
expect(wrapper.render()).toMatchSnapshot();
|
||||
});
|
||||
});
|
||||
|
File diff suppressed because it is too large
Load Diff
@ -102,6 +102,16 @@ describe('ConfigProvider', () => {
|
||||
),
|
||||
).toMatchSnapshot();
|
||||
});
|
||||
|
||||
it('configProvider virtual and dropdownMatchSelectWidth', () => {
|
||||
expect(
|
||||
render(
|
||||
<ConfigProvider virtual={false} dropdownMatchSelectWidth={false}>
|
||||
{renderComponent({})}
|
||||
</ConfigProvider>,
|
||||
),
|
||||
).toMatchSnapshot();
|
||||
});
|
||||
});
|
||||
}
|
||||
|
||||
|
@ -26,6 +26,8 @@ export interface ConfigConsumerProps {
|
||||
space?: {
|
||||
size?: SizeType | number;
|
||||
};
|
||||
virtual?: boolean;
|
||||
dropdownMatchSelectWidth?: boolean;
|
||||
}
|
||||
|
||||
export const ConfigContext = React.createContext<ConfigConsumerProps>({
|
||||
|
@ -47,9 +47,11 @@ Some components use dynamic style to support wave effect. You can config `csp` p
|
||||
| getTargetContainer | Config Affix, Anchor scroll target container. | () => HTMLElement | () => window | 4.2.0 |
|
||||
| locale | language package setting, you can find the packages in [antd/es/locale](http://unpkg.com/antd/es/locale/) | object | |
|
||||
| prefixCls | set prefix class. `Note:` This will discard default styles from `antd`. | string | ant | |
|
||||
| pageHeader | Unify the ghost of PageHeader, ref [PageHeader](/components/page-header) | { ghost:boolean } | 'true' | |
|
||||
| pageHeader | Unify the ghost of PageHeader, ref [PageHeader](/components/page-header) | { ghost:boolean } | true | |
|
||||
| direction | set direction of layout. See [demo](#components-config-provider-demo-direction) | `ltr` \| `rtl` | `ltr` | |
|
||||
| space | set Space `size`, ref [Space](/components/space) | { size: `small` \| `middle` \| `large` \| `number` } | - | 4.1.0 |
|
||||
| virtual | Disable virtual scroll when set to `false` | boolean | - | 4.3.0 |
|
||||
| dropdownMatchSelectWidth | Determine whether the dropdown menu and the select input are the same width. Default set `min-width` same as input. `false` will disable virtual scroll | boolean \| number | - | 4.3.0 |
|
||||
|
||||
## FAQ
|
||||
|
||||
|
@ -9,6 +9,8 @@ import LocaleProvider, { Locale, ANT_MARK } from '../locale-provider';
|
||||
import LocaleReceiver from '../locale-provider/LocaleReceiver';
|
||||
import { ConfigConsumer, ConfigContext, CSPConfig, ConfigConsumerProps } from './context';
|
||||
import { SizeType, SizeContextProvider } from './SizeContext';
|
||||
import message from '../message';
|
||||
import notification from '../notification';
|
||||
|
||||
export { RenderEmptyHandler, ConfigContext, ConfigConsumer, CSPConfig, ConfigConsumerProps };
|
||||
|
||||
@ -47,12 +49,25 @@ export interface ConfigProviderProps {
|
||||
space?: {
|
||||
size?: SizeType | number;
|
||||
};
|
||||
virtual?: boolean;
|
||||
dropdownMatchSelectWidth?: boolean;
|
||||
}
|
||||
|
||||
class ConfigProvider extends React.Component<ConfigProviderProps> {
|
||||
getPrefixClsWrapper = (context: ConfigConsumerProps) => {
|
||||
const ConfigProvider: React.FC<ConfigProviderProps> = props => {
|
||||
React.useEffect(() => {
|
||||
if (props.direction) {
|
||||
message.config({
|
||||
rtl: props.direction === 'rtl',
|
||||
});
|
||||
notification.config({
|
||||
rtl: props.direction === 'rtl',
|
||||
});
|
||||
}
|
||||
}, [props.direction]);
|
||||
|
||||
const getPrefixClsWrapper = (context: ConfigConsumerProps) => {
|
||||
return (suffixCls: string, customizePrefixCls?: string) => {
|
||||
const { prefixCls } = this.props;
|
||||
const { prefixCls } = props;
|
||||
|
||||
if (customizePrefixCls) return customizePrefixCls;
|
||||
|
||||
@ -62,7 +77,7 @@ class ConfigProvider extends React.Component<ConfigProviderProps> {
|
||||
};
|
||||
};
|
||||
|
||||
renderProvider = (context: ConfigConsumerProps, legacyLocale: Locale) => {
|
||||
const renderProvider = (context: ConfigConsumerProps, legacyLocale: Locale) => {
|
||||
const {
|
||||
children,
|
||||
getTargetContainer,
|
||||
@ -77,16 +92,20 @@ class ConfigProvider extends React.Component<ConfigProviderProps> {
|
||||
componentSize,
|
||||
direction,
|
||||
space,
|
||||
} = this.props;
|
||||
virtual,
|
||||
dropdownMatchSelectWidth,
|
||||
} = props;
|
||||
|
||||
const config: ConfigConsumerProps = {
|
||||
...context,
|
||||
getPrefixCls: this.getPrefixClsWrapper(context),
|
||||
getPrefixCls: getPrefixClsWrapper(context),
|
||||
csp,
|
||||
autoInsertSpaceInButton,
|
||||
locale: locale || legacyLocale,
|
||||
direction,
|
||||
space,
|
||||
virtual,
|
||||
dropdownMatchSelectWidth,
|
||||
};
|
||||
|
||||
if (getTargetContainer) {
|
||||
@ -136,17 +155,15 @@ class ConfigProvider extends React.Component<ConfigProviderProps> {
|
||||
);
|
||||
};
|
||||
|
||||
render() {
|
||||
return (
|
||||
<LocaleReceiver>
|
||||
{(_, __, legacyLocale) => (
|
||||
<ConfigConsumer>
|
||||
{context => this.renderProvider(context, legacyLocale as Locale)}
|
||||
</ConfigConsumer>
|
||||
)}
|
||||
</LocaleReceiver>
|
||||
);
|
||||
}
|
||||
}
|
||||
return (
|
||||
<LocaleReceiver>
|
||||
{(_, __, legacyLocale) => (
|
||||
<ConfigConsumer>
|
||||
{context => renderProvider(context, legacyLocale as Locale)}
|
||||
</ConfigConsumer>
|
||||
)}
|
||||
</LocaleReceiver>
|
||||
);
|
||||
};
|
||||
|
||||
export default ConfigProvider;
|
||||
|
@ -48,9 +48,11 @@ return (
|
||||
| getTargetContainer | 配置 Affix、Anchor 滚动监听容器。 | () => HTMLElement | () => window | 4.2.0 |
|
||||
| locale | 语言包配置,语言包可到 [antd/es/locale](http://unpkg.com/antd/es/locale/) 目录下寻找 | object | - | |
|
||||
| prefixCls | 设置统一样式前缀。`注意:这将不会应用由 antd 提供的默认样式` | string | ant | |
|
||||
| pageHeader | 统一设置 PageHeader 的 ghost,参考 [PageHeader](/components/page-header) | { ghost: boolean } | 'true' | |
|
||||
| pageHeader | 统一设置 PageHeader 的 ghost,参考 [PageHeader](/components/page-header) | { ghost: boolean } | true | |
|
||||
| direction | 设置文本展示方向。 [示例](#components-config-provider-demo-direction) | `ltr` \| `rtl` | `ltr` | |
|
||||
| space | 设置 Space 的 `size`,参考 [Space](/components/space) | { size: `small` \| `middle` \| `large` \| `number` } | - | 4.1.0 |
|
||||
| virtual | 设置 `false` 时关闭虚拟滚动 | boolean | - | 4.3.0 |
|
||||
| dropdownMatchSelectWidth | 下拉菜单和选择器同宽。默认将设置 `min-width`。`false` 时会关闭虚拟滚动 | boolean \| number | - | 4.3.0 |
|
||||
|
||||
## FAQ
|
||||
|
||||
|
@ -144,6 +144,7 @@ Added in `4.1.0`.
|
||||
| Property | Description | Type | Default | Version |
|
||||
| --- | --- | --- | --- | --- |
|
||||
| allowEmpty | Allow start or end input leave empty | \[boolean, boolean] | \[false, false] | |
|
||||
| dateRender | Customize date cell. `info` argument is added in 4.3.0 | function(currentDate: moment, today: moment, info: { range: 'start' \| ''end }) => React.ReactNode | - | |
|
||||
| defaultValue | to set default date | \[[moment](http://momentjs.com/), [moment](http://momentjs.com/)] | - | |
|
||||
| defaultPickerValue | to set default picker date | \[[moment](http://momentjs.com/), [moment](http://momentjs.com/)\] | - | |
|
||||
| disabled | disable start or end | `[boolean, boolean]` | - | |
|
||||
|
@ -146,6 +146,7 @@ import 'moment/locale/zh-cn';
|
||||
| 参数 | 说明 | 类型 | 默认值 | 版本 |
|
||||
| --- | --- | --- | --- | --- |
|
||||
| allowEmpty | 允许起始项部分为空 | \[boolean, boolean] | \[false, false] | |
|
||||
| dateRender | 自定义日期单元格的内容。`info` 参数自 4.3.0 添加 | function(currentDate: moment, today: moment, info: { range: 'start' \| ''end }) => React.ReactNode | - | |
|
||||
| defaultValue | 默认日期 | [moment](http://momentjs.com/)\[] | 无 | |
|
||||
| defaultPickerValue | 默认面板日期 | [moment](http://momentjs.com/)\[] | 无 | |
|
||||
| disabled | 禁用起始项 | `[boolean, boolean]` | 无 | |
|
||||
|
@ -57,7 +57,7 @@ const Cell: React.FC<CellProps> = ({
|
||||
{label && (
|
||||
<span
|
||||
className={classNames(`${itemPrefixCls}-item-label`, {
|
||||
[`${itemPrefixCls}-item-colon`]: colon,
|
||||
[`${itemPrefixCls}-item-no-colon`]: !colon,
|
||||
})}
|
||||
>
|
||||
{label}
|
||||
|
@ -22,7 +22,7 @@ exports[`renders ./components/descriptions/demo/basic.md correctly 1`] = `
|
||||
colspan="1"
|
||||
>
|
||||
<span
|
||||
class="ant-descriptions-item-label ant-descriptions-item-colon"
|
||||
class="ant-descriptions-item-label"
|
||||
>
|
||||
UserName
|
||||
</span>
|
||||
@ -37,7 +37,7 @@ exports[`renders ./components/descriptions/demo/basic.md correctly 1`] = `
|
||||
colspan="1"
|
||||
>
|
||||
<span
|
||||
class="ant-descriptions-item-label ant-descriptions-item-colon"
|
||||
class="ant-descriptions-item-label"
|
||||
>
|
||||
Telephone
|
||||
</span>
|
||||
@ -52,7 +52,7 @@ exports[`renders ./components/descriptions/demo/basic.md correctly 1`] = `
|
||||
colspan="1"
|
||||
>
|
||||
<span
|
||||
class="ant-descriptions-item-label ant-descriptions-item-colon"
|
||||
class="ant-descriptions-item-label"
|
||||
>
|
||||
Live
|
||||
</span>
|
||||
@ -71,7 +71,7 @@ exports[`renders ./components/descriptions/demo/basic.md correctly 1`] = `
|
||||
colspan="1"
|
||||
>
|
||||
<span
|
||||
class="ant-descriptions-item-label ant-descriptions-item-colon"
|
||||
class="ant-descriptions-item-label"
|
||||
>
|
||||
Remark
|
||||
</span>
|
||||
@ -86,7 +86,7 @@ exports[`renders ./components/descriptions/demo/basic.md correctly 1`] = `
|
||||
colspan="2"
|
||||
>
|
||||
<span
|
||||
class="ant-descriptions-item-label ant-descriptions-item-colon"
|
||||
class="ant-descriptions-item-label"
|
||||
>
|
||||
Address
|
||||
</span>
|
||||
@ -626,7 +626,7 @@ exports[`renders ./components/descriptions/demo/size.md correctly 1`] = `
|
||||
colspan="1"
|
||||
>
|
||||
<span
|
||||
class="ant-descriptions-item-label ant-descriptions-item-colon"
|
||||
class="ant-descriptions-item-label"
|
||||
>
|
||||
Product
|
||||
</span>
|
||||
@ -641,7 +641,7 @@ exports[`renders ./components/descriptions/demo/size.md correctly 1`] = `
|
||||
colspan="1"
|
||||
>
|
||||
<span
|
||||
class="ant-descriptions-item-label ant-descriptions-item-colon"
|
||||
class="ant-descriptions-item-label"
|
||||
>
|
||||
Billing
|
||||
</span>
|
||||
@ -656,7 +656,7 @@ exports[`renders ./components/descriptions/demo/size.md correctly 1`] = `
|
||||
colspan="1"
|
||||
>
|
||||
<span
|
||||
class="ant-descriptions-item-label ant-descriptions-item-colon"
|
||||
class="ant-descriptions-item-label"
|
||||
>
|
||||
time
|
||||
</span>
|
||||
@ -675,7 +675,7 @@ exports[`renders ./components/descriptions/demo/size.md correctly 1`] = `
|
||||
colspan="1"
|
||||
>
|
||||
<span
|
||||
class="ant-descriptions-item-label ant-descriptions-item-colon"
|
||||
class="ant-descriptions-item-label"
|
||||
>
|
||||
Amount
|
||||
</span>
|
||||
@ -690,7 +690,7 @@ exports[`renders ./components/descriptions/demo/size.md correctly 1`] = `
|
||||
colspan="1"
|
||||
>
|
||||
<span
|
||||
class="ant-descriptions-item-label ant-descriptions-item-colon"
|
||||
class="ant-descriptions-item-label"
|
||||
>
|
||||
Discount
|
||||
</span>
|
||||
@ -705,7 +705,7 @@ exports[`renders ./components/descriptions/demo/size.md correctly 1`] = `
|
||||
colspan="1"
|
||||
>
|
||||
<span
|
||||
class="ant-descriptions-item-label ant-descriptions-item-colon"
|
||||
class="ant-descriptions-item-label"
|
||||
>
|
||||
Official
|
||||
</span>
|
||||
@ -745,7 +745,7 @@ exports[`renders ./components/descriptions/demo/vertical.md correctly 1`] = `
|
||||
colspan="1"
|
||||
>
|
||||
<span
|
||||
class="ant-descriptions-item-label ant-descriptions-item-colon"
|
||||
class="ant-descriptions-item-label"
|
||||
>
|
||||
UserName
|
||||
</span>
|
||||
@ -755,7 +755,7 @@ exports[`renders ./components/descriptions/demo/vertical.md correctly 1`] = `
|
||||
colspan="1"
|
||||
>
|
||||
<span
|
||||
class="ant-descriptions-item-label ant-descriptions-item-colon"
|
||||
class="ant-descriptions-item-label"
|
||||
>
|
||||
Telephone
|
||||
</span>
|
||||
@ -765,7 +765,7 @@ exports[`renders ./components/descriptions/demo/vertical.md correctly 1`] = `
|
||||
colspan="1"
|
||||
>
|
||||
<span
|
||||
class="ant-descriptions-item-label ant-descriptions-item-colon"
|
||||
class="ant-descriptions-item-label"
|
||||
>
|
||||
Live
|
||||
</span>
|
||||
@ -813,7 +813,7 @@ exports[`renders ./components/descriptions/demo/vertical.md correctly 1`] = `
|
||||
colspan="2"
|
||||
>
|
||||
<span
|
||||
class="ant-descriptions-item-label ant-descriptions-item-colon"
|
||||
class="ant-descriptions-item-label"
|
||||
>
|
||||
Address
|
||||
</span>
|
||||
@ -823,7 +823,7 @@ exports[`renders ./components/descriptions/demo/vertical.md correctly 1`] = `
|
||||
colspan="1"
|
||||
>
|
||||
<span
|
||||
class="ant-descriptions-item-label ant-descriptions-item-colon"
|
||||
class="ant-descriptions-item-label"
|
||||
>
|
||||
Remark
|
||||
</span>
|
||||
|
@ -17,7 +17,7 @@ exports[`Descriptions Descriptions support colon 1`] = `
|
||||
colspan="1"
|
||||
>
|
||||
<span
|
||||
class="ant-descriptions-item-label"
|
||||
class="ant-descriptions-item-label ant-descriptions-item-no-colon"
|
||||
>
|
||||
Product
|
||||
</span>
|
||||
@ -81,7 +81,7 @@ exports[`Descriptions Descriptions.Item support className 1`] = `
|
||||
colspan="1"
|
||||
>
|
||||
<span
|
||||
class="ant-descriptions-item-label ant-descriptions-item-colon"
|
||||
class="ant-descriptions-item-label"
|
||||
>
|
||||
Product
|
||||
</span>
|
||||
@ -115,7 +115,7 @@ exports[`Descriptions column is number 1`] = `
|
||||
colspan="1"
|
||||
>
|
||||
<span
|
||||
class="ant-descriptions-item-label ant-descriptions-item-colon"
|
||||
class="ant-descriptions-item-label"
|
||||
>
|
||||
Product
|
||||
</span>
|
||||
@ -130,7 +130,7 @@ exports[`Descriptions column is number 1`] = `
|
||||
colspan="1"
|
||||
>
|
||||
<span
|
||||
class="ant-descriptions-item-label ant-descriptions-item-colon"
|
||||
class="ant-descriptions-item-label"
|
||||
>
|
||||
Billing
|
||||
</span>
|
||||
@ -145,7 +145,7 @@ exports[`Descriptions column is number 1`] = `
|
||||
colspan="1"
|
||||
>
|
||||
<span
|
||||
class="ant-descriptions-item-label ant-descriptions-item-colon"
|
||||
class="ant-descriptions-item-label"
|
||||
>
|
||||
time
|
||||
</span>
|
||||
@ -164,7 +164,7 @@ exports[`Descriptions column is number 1`] = `
|
||||
colspan="3"
|
||||
>
|
||||
<span
|
||||
class="ant-descriptions-item-label ant-descriptions-item-colon"
|
||||
class="ant-descriptions-item-label"
|
||||
>
|
||||
Amount
|
||||
</span>
|
||||
@ -198,7 +198,7 @@ exports[`Descriptions should work with React Fragment 1`] = `
|
||||
colspan="1"
|
||||
>
|
||||
<span
|
||||
class="ant-descriptions-item-label ant-descriptions-item-colon"
|
||||
class="ant-descriptions-item-label"
|
||||
>
|
||||
bamboo
|
||||
</span>
|
||||
@ -217,7 +217,7 @@ exports[`Descriptions should work with React Fragment 1`] = `
|
||||
colspan="1"
|
||||
>
|
||||
<span
|
||||
class="ant-descriptions-item-label ant-descriptions-item-colon"
|
||||
class="ant-descriptions-item-label"
|
||||
>
|
||||
bamboo
|
||||
</span>
|
||||
@ -236,7 +236,7 @@ exports[`Descriptions should work with React Fragment 1`] = `
|
||||
colspan="1"
|
||||
>
|
||||
<span
|
||||
class="ant-descriptions-item-label ant-descriptions-item-colon"
|
||||
class="ant-descriptions-item-label"
|
||||
>
|
||||
bamboo
|
||||
</span>
|
||||
@ -270,7 +270,7 @@ exports[`Descriptions vertical layout 1`] = `
|
||||
colspan="1"
|
||||
>
|
||||
<span
|
||||
class="ant-descriptions-item-label ant-descriptions-item-colon"
|
||||
class="ant-descriptions-item-label"
|
||||
>
|
||||
Product
|
||||
</span>
|
||||
@ -298,7 +298,7 @@ exports[`Descriptions vertical layout 1`] = `
|
||||
colspan="1"
|
||||
>
|
||||
<span
|
||||
class="ant-descriptions-item-label ant-descriptions-item-colon"
|
||||
class="ant-descriptions-item-label"
|
||||
>
|
||||
Billing
|
||||
</span>
|
||||
@ -326,7 +326,7 @@ exports[`Descriptions vertical layout 1`] = `
|
||||
colspan="1"
|
||||
>
|
||||
<span
|
||||
class="ant-descriptions-item-label ant-descriptions-item-colon"
|
||||
class="ant-descriptions-item-label"
|
||||
>
|
||||
time
|
||||
</span>
|
||||
@ -354,7 +354,7 @@ exports[`Descriptions vertical layout 1`] = `
|
||||
colspan="1"
|
||||
>
|
||||
<span
|
||||
class="ant-descriptions-item-label ant-descriptions-item-colon"
|
||||
class="ant-descriptions-item-label"
|
||||
>
|
||||
Amount
|
||||
</span>
|
||||
@ -397,7 +397,7 @@ exports[`Descriptions when item is rendered conditionally 1`] = `
|
||||
colspan="1"
|
||||
>
|
||||
<span
|
||||
class="ant-descriptions-item-label ant-descriptions-item-colon"
|
||||
class="ant-descriptions-item-label"
|
||||
>
|
||||
Product
|
||||
</span>
|
||||
@ -416,7 +416,7 @@ exports[`Descriptions when item is rendered conditionally 1`] = `
|
||||
colspan="1"
|
||||
>
|
||||
<span
|
||||
class="ant-descriptions-item-label ant-descriptions-item-colon"
|
||||
class="ant-descriptions-item-label"
|
||||
>
|
||||
Billing
|
||||
</span>
|
||||
@ -435,7 +435,7 @@ exports[`Descriptions when item is rendered conditionally 1`] = `
|
||||
colspan="1"
|
||||
>
|
||||
<span
|
||||
class="ant-descriptions-item-label ant-descriptions-item-colon"
|
||||
class="ant-descriptions-item-label"
|
||||
>
|
||||
time
|
||||
</span>
|
||||
@ -454,7 +454,7 @@ exports[`Descriptions when item is rendered conditionally 1`] = `
|
||||
colspan="1"
|
||||
>
|
||||
<span
|
||||
class="ant-descriptions-item-label ant-descriptions-item-colon"
|
||||
class="ant-descriptions-item-label"
|
||||
>
|
||||
Amount
|
||||
</span>
|
||||
|
@ -39,16 +39,21 @@
|
||||
line-height: @line-height-base;
|
||||
|
||||
&::after {
|
||||
& when (@descriptions-item-trailing-colon=true) {
|
||||
content: ':';
|
||||
}
|
||||
& when not (@descriptions-item-trailing-colon=true) {
|
||||
content: ' ';
|
||||
}
|
||||
|
||||
position: relative;
|
||||
top: -0.5px;
|
||||
margin: 0 8px 0 2px;
|
||||
content: ' ';
|
||||
margin: 0 @descriptions-item-label-colon-margin-right 0
|
||||
@descriptions-item-label-colon-margin-left;
|
||||
}
|
||||
}
|
||||
|
||||
&-item-colon {
|
||||
&::after {
|
||||
content: ':';
|
||||
&.@{descriptions-prefix-cls}-item-no-colon::after {
|
||||
content: ' ';
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -34,6 +34,7 @@ const menu = (
|
||||
3rd menu item
|
||||
</a>
|
||||
</Menu.Item>
|
||||
<Menu.Item danger>a danger item</Menu.Item>
|
||||
</Menu>
|
||||
);
|
||||
|
||||
|
@ -1,5 +1,6 @@
|
||||
@import '../../style/themes/index';
|
||||
@import '../../style/mixins/index';
|
||||
@import './status';
|
||||
|
||||
@dropdown-prefix-cls: ~'@{ant-prefix}-dropdown';
|
||||
|
||||
|
12
components/dropdown/style/status.less
Normal file
12
components/dropdown/style/status.less
Normal file
@ -0,0 +1,12 @@
|
||||
@import './index';
|
||||
|
||||
.@{dropdown-prefix-cls}-menu-item {
|
||||
&&-danger {
|
||||
color: @error-color;
|
||||
|
||||
&:hover {
|
||||
color: @text-color-inverse;
|
||||
background-color: @error-color;
|
||||
}
|
||||
}
|
||||
}
|
@ -286,16 +286,34 @@ exports[`renders ./components/empty/demo/config-provider.md correctly 1`] = `
|
||||
/>
|
||||
</span>
|
||||
</label>
|
||||
<span
|
||||
aria-label="down"
|
||||
class="anticon anticon-down ant-dropdown-trigger ant-transfer-list-header-dropdown"
|
||||
role="img"
|
||||
>
|
||||
<svg
|
||||
aria-hidden="true"
|
||||
class=""
|
||||
data-icon="down"
|
||||
fill="currentColor"
|
||||
focusable="false"
|
||||
height="1em"
|
||||
viewBox="64 64 896 896"
|
||||
width="1em"
|
||||
>
|
||||
<path
|
||||
d="M884 256h-75c-5.1 0-9.9 2.5-12.9 6.6L512 654.2 227.9 262.6c-3-4.1-7.8-6.6-12.9-6.6h-75c-6.5 0-10.3 7.4-6.5 12.7l352.6 486.1c12.8 17.6 39 17.6 51.7 0l352.6-486.1c3.9-5.3.1-12.7-6.4-12.7z"
|
||||
/>
|
||||
</svg>
|
||||
</span>
|
||||
<span
|
||||
class="ant-transfer-list-header-selected"
|
||||
>
|
||||
<span>
|
||||
0 item
|
||||
</span>
|
||||
<span
|
||||
class="ant-transfer-list-header-title"
|
||||
/>
|
||||
0 item
|
||||
</span>
|
||||
<span
|
||||
class="ant-transfer-list-header-title"
|
||||
/>
|
||||
</div>
|
||||
<div
|
||||
class="ant-transfer-list-body"
|
||||
@ -429,16 +447,34 @@ exports[`renders ./components/empty/demo/config-provider.md correctly 1`] = `
|
||||
/>
|
||||
</span>
|
||||
</label>
|
||||
<span
|
||||
aria-label="down"
|
||||
class="anticon anticon-down ant-dropdown-trigger ant-transfer-list-header-dropdown"
|
||||
role="img"
|
||||
>
|
||||
<svg
|
||||
aria-hidden="true"
|
||||
class=""
|
||||
data-icon="down"
|
||||
fill="currentColor"
|
||||
focusable="false"
|
||||
height="1em"
|
||||
viewBox="64 64 896 896"
|
||||
width="1em"
|
||||
>
|
||||
<path
|
||||
d="M884 256h-75c-5.1 0-9.9 2.5-12.9 6.6L512 654.2 227.9 262.6c-3-4.1-7.8-6.6-12.9-6.6h-75c-6.5 0-10.3 7.4-6.5 12.7l352.6 486.1c12.8 17.6 39 17.6 51.7 0l352.6-486.1c3.9-5.3.1-12.7-6.4-12.7z"
|
||||
/>
|
||||
</svg>
|
||||
</span>
|
||||
<span
|
||||
class="ant-transfer-list-header-selected"
|
||||
>
|
||||
<span>
|
||||
0 item
|
||||
</span>
|
||||
<span
|
||||
class="ant-transfer-list-header-title"
|
||||
/>
|
||||
0 item
|
||||
</span>
|
||||
<span
|
||||
class="ant-transfer-list-header-title"
|
||||
/>
|
||||
</div>
|
||||
<div
|
||||
class="ant-transfer-list-body"
|
||||
|
@ -47,7 +47,7 @@ export interface FormItemProps extends FormItemLabelProps, FormItemInputProps, R
|
||||
required?: boolean;
|
||||
|
||||
/** Auto passed by List render props. User should not use this. */
|
||||
fieldKey?: number;
|
||||
fieldKey?: React.Key | React.Key[];
|
||||
}
|
||||
|
||||
function hasValidName(name?: NamePath): Boolean {
|
||||
@ -192,6 +192,7 @@ function FormItem(props: FormItemProps): React.ReactElement {
|
||||
'htmlFor',
|
||||
'id', // It is deprecated because `htmlFor` is its replacement.
|
||||
'initialValue',
|
||||
'isListField',
|
||||
'label',
|
||||
'labelAlign',
|
||||
'labelCol',
|
||||
@ -256,7 +257,8 @@ function FormItem(props: FormItemProps): React.ReactElement {
|
||||
if (noStyle) {
|
||||
nameRef.current = [...mergedName];
|
||||
if (fieldKey) {
|
||||
nameRef.current[nameRef.current.length - 1] = fieldKey;
|
||||
const fieldKeys = Array.isArray(fieldKey) ? fieldKey : [fieldKey];
|
||||
nameRef.current = [...mergedName.slice(-1), ...fieldKeys];
|
||||
}
|
||||
updateItemErrors(nameRef.current.join('__SPLIT__'), errors);
|
||||
}
|
||||
|
@ -1015,6 +1015,89 @@ exports[`renders ./components/form/demo/dynamic-form-item.md correctly 1`] = `
|
||||
</form>
|
||||
`;
|
||||
|
||||
exports[`renders ./components/form/demo/dynamic-form-items.md correctly 1`] = `
|
||||
<form
|
||||
autocomplete="off"
|
||||
class="ant-form ant-form-horizontal"
|
||||
id="dynamic_form_nest_item"
|
||||
>
|
||||
<div>
|
||||
<div
|
||||
class="ant-row ant-form-item"
|
||||
>
|
||||
<div
|
||||
class="ant-col ant-form-item-control"
|
||||
>
|
||||
<div
|
||||
class="ant-form-item-control-input"
|
||||
>
|
||||
<div
|
||||
class="ant-form-item-control-input-content"
|
||||
>
|
||||
<button
|
||||
class="ant-btn ant-btn-dashed ant-btn-block"
|
||||
type="button"
|
||||
>
|
||||
<span
|
||||
aria-label="plus"
|
||||
class="anticon anticon-plus"
|
||||
role="img"
|
||||
>
|
||||
<svg
|
||||
aria-hidden="true"
|
||||
class=""
|
||||
data-icon="plus"
|
||||
fill="currentColor"
|
||||
focusable="false"
|
||||
height="1em"
|
||||
viewBox="64 64 896 896"
|
||||
width="1em"
|
||||
>
|
||||
<defs />
|
||||
<path
|
||||
d="M482 152h60q8 0 8 8v704q0 8-8 8h-60q-8 0-8-8V160q0-8 8-8z"
|
||||
/>
|
||||
<path
|
||||
d="M176 474h672q8 0 8 8v60q0 8-8 8H176q-8 0-8-8v-60q0-8 8-8z"
|
||||
/>
|
||||
</svg>
|
||||
</span>
|
||||
<span>
|
||||
Add field
|
||||
</span>
|
||||
</button>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div
|
||||
class="ant-row ant-form-item"
|
||||
>
|
||||
<div
|
||||
class="ant-col ant-form-item-control"
|
||||
>
|
||||
<div
|
||||
class="ant-form-item-control-input"
|
||||
>
|
||||
<div
|
||||
class="ant-form-item-control-input-content"
|
||||
>
|
||||
<button
|
||||
class="ant-btn ant-btn-primary"
|
||||
type="submit"
|
||||
>
|
||||
<span>
|
||||
Submit
|
||||
</span>
|
||||
</button>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</form>
|
||||
`;
|
||||
|
||||
exports[`renders ./components/form/demo/dynamic-rule.md correctly 1`] = `
|
||||
<form
|
||||
class="ant-form ant-form-horizontal"
|
||||
|
@ -7,11 +7,11 @@ title:
|
||||
|
||||
## zh-CN
|
||||
|
||||
动态增加、减少表单项。如果需要动态支持多项字段时,可以参考[此处](https://codesandbox.io/s/wonderful-lichterman-br63z)。
|
||||
动态增加、减少表单项。
|
||||
|
||||
## en-US
|
||||
|
||||
Add or remove form items dynamically. You can ref [this example](https://codesandbox.io/s/wonderful-lichterman-br63z) if you want to support mutiple fields.
|
||||
Add or remove form items dynamically.
|
||||
|
||||
```jsx
|
||||
import { Form, Input, Button } from 'antd';
|
||||
|
84
components/form/demo/dynamic-form-items.md
Normal file
84
components/form/demo/dynamic-form-items.md
Normal file
@ -0,0 +1,84 @@
|
||||
---
|
||||
order: 4.1
|
||||
title:
|
||||
zh-CN: 动态增减嵌套字段
|
||||
en-US: Dynamic Form nest Items
|
||||
---
|
||||
|
||||
## zh-CN
|
||||
|
||||
嵌套表单字段需要对 `field` 进行拓展,将 `field.name` 和 `field.fieldKey` 应用于控制字段。
|
||||
|
||||
## en-US
|
||||
|
||||
Nest dynamic field need extends `field`. Pass `field.name` and `field.fieldKey` to nest item.
|
||||
|
||||
```jsx
|
||||
import { Form, Input, Button, Space } from 'antd';
|
||||
import { MinusCircleOutlined, PlusOutlined } from '@ant-design/icons';
|
||||
|
||||
const Demo = () => {
|
||||
const onFinish = values => {
|
||||
console.log('Received values of form:', values);
|
||||
};
|
||||
|
||||
return (
|
||||
<Form name="dynamic_form_nest_item" onFinish={onFinish} autoComplete="off">
|
||||
<Form.List name="users">
|
||||
{(fields, { add, remove }) => {
|
||||
return (
|
||||
<div>
|
||||
{fields.map(field => (
|
||||
<Space key={field.key} style={{ display: 'flex', marginBottom: 8 }} align="start">
|
||||
<Form.Item
|
||||
{...field}
|
||||
name={[field.name, 'first']}
|
||||
fieldKey={[field.fieldKey, 'first']}
|
||||
rules={[{ required: true, message: 'Missing first name' }]}
|
||||
>
|
||||
<Input placeholder="First Name" />
|
||||
</Form.Item>
|
||||
<Form.Item
|
||||
{...field}
|
||||
name={[field.name, 'last']}
|
||||
fieldKey={[field.fieldKey, 'last']}
|
||||
rules={[{ required: true, message: 'Missing last name' }]}
|
||||
>
|
||||
<Input placeholder="Last Name" />
|
||||
</Form.Item>
|
||||
|
||||
<MinusCircleOutlined
|
||||
onClick={() => {
|
||||
remove(field.name);
|
||||
}}
|
||||
/>
|
||||
</Space>
|
||||
))}
|
||||
|
||||
<Form.Item>
|
||||
<Button
|
||||
type="dashed"
|
||||
onClick={() => {
|
||||
add();
|
||||
}}
|
||||
block
|
||||
>
|
||||
<PlusOutlined /> Add field
|
||||
</Button>
|
||||
</Form.Item>
|
||||
</div>
|
||||
);
|
||||
}}
|
||||
</Form.List>
|
||||
|
||||
<Form.Item>
|
||||
<Button type="primary" htmlType="submit">
|
||||
Submit
|
||||
</Button>
|
||||
</Form.Item>
|
||||
</Form>
|
||||
);
|
||||
};
|
||||
|
||||
ReactDOM.render(<Demo />, mountNode);
|
||||
```
|
@ -16,26 +16,27 @@ High performance Form component with data scope management. Including data colle
|
||||
|
||||
### Form
|
||||
|
||||
| Property | Description | Type | Default |
|
||||
| --- | --- | --- | --- |
|
||||
| component | Set the Form rendering element. Do not create a DOM node for `false` | ComponentType \| false | form |
|
||||
| colon | Configure the default value of `colon` for Form.Item. Indicates whether the colon after the label is displayed (only effective when prop layout is horizontal) | boolean | true |
|
||||
| fields | Control of form fields through state management (such as redux). Not recommended for non-strong demand. View [example](#components-form-demo-global-state) | [FieldData](#FieldData)\[] | - |
|
||||
| form | Form control instance created by `Form.useForm()`. Automatically created when not provided | [FormInstance](#FormInstance) | - |
|
||||
| hideRequiredMark | Hide required mark for all form items | boolean | false |
|
||||
| initialValues | Set value by Form initialization or reset | object | - |
|
||||
| labelAlign | text align of label of all items | `left` \| `right` | `right` |
|
||||
| labelCol | label layout, like `<Col>` component. Set `span` `offset` value like `{span: 3, offset: 12}` or `sm: {span: 3, offset: 12}` | [object](/components/grid/#Col) | - |
|
||||
| layout | Form layout | `horizontal` \| `vertical` \| `inline` | `horizontal` |
|
||||
| name | Form name. Will be the prefix of Field `id` | string | - |
|
||||
| scrollToFirstError | Auto scroll to first failed field when submit | false | - |
|
||||
| size | Set field component size (antd components only) | `small` \| `middle` \| `large` | - |
|
||||
| validateMessages | Validation prompt template, description [see below](#validateMessages) | [ValidateMessages](https://github.com/react-component/field-form/blob/master/src/utils/messages.ts) | - |
|
||||
| wrapperCol | The layout for input controls, same as `labelCol` | [object](/components/grid/#Col) | - |
|
||||
| onFinish | Trigger after submitting the form and verifying data successfully | Function(values) | - |
|
||||
| onFinishFailed | Trigger after submitting the form and verifying data failed | Function({ values, errorFields, outOfDate }) | - |
|
||||
| onFieldsChange | Trigger when field updated | Function(changedFields, allFields) | - |
|
||||
| onValuesChange | Trigger when value updated | Function(changedValues, allValues) | - |
|
||||
| Property | Description | Type | Default | Version |
|
||||
| --- | --- | --- | --- | --- |
|
||||
| component | Set the Form rendering element. Do not create a DOM node for `false` | ComponentType \| false | form | |
|
||||
| colon | Configure the default value of `colon` for Form.Item. Indicates whether the colon after the label is displayed (only effective when prop layout is horizontal) | boolean | true | |
|
||||
| fields | Control of form fields through state management (such as redux). Not recommended for non-strong demand. View [example](#components-form-demo-global-state) | [FieldData](#FieldData)\[] | - | |
|
||||
| form | Form control instance created by `Form.useForm()`. Automatically created when not provided | [FormInstance](#FormInstance) | - | |
|
||||
| hideRequiredMark | Hide required mark for all form items | boolean | false | |
|
||||
| initialValues | Set value by Form initialization or reset | object | - | |
|
||||
| labelAlign | text align of label of all items | `left` \| `right` | `right` | |
|
||||
| labelCol | label layout, like `<Col>` component. Set `span` `offset` value like `{span: 3, offset: 12}` or `sm: {span: 3, offset: 12}` | [object](/components/grid/#Col) | - | |
|
||||
| layout | Form layout | `horizontal` \| `vertical` \| `inline` | `horizontal` | |
|
||||
| name | Form name. Will be the prefix of Field `id` | string | - | |
|
||||
| scrollToFirstError | Auto scroll to first failed field when submit | false | - | |
|
||||
| size | Set field component size (antd components only) | `small` \| `middle` \| `large` | - | |
|
||||
| validateMessages | Validation prompt template, description [see below](#validateMessages) | [ValidateMessages](https://github.com/react-component/field-form/blob/master/src/utils/messages.ts) | - | |
|
||||
| validateTrigger | Config field validate trigger | string \| string[] | 'onChange' | 4.3.0 |
|
||||
| wrapperCol | The layout for input controls, same as `labelCol` | [object](/components/grid/#Col) | - | |
|
||||
| onFinish | Trigger after submitting the form and verifying data successfully | Function(values) | - | |
|
||||
| onFinishFailed | Trigger after submitting the form and verifying data failed | Function({ values, errorFields, outOfDate }) | - | |
|
||||
| onFieldsChange | Trigger when field updated | Function(changedFields, allFields) | - | |
|
||||
| onValuesChange | Trigger when value updated | Function(changedValues, allValues) | - | |
|
||||
|
||||
### validateMessages
|
||||
|
||||
|
@ -17,26 +17,27 @@ title: Form
|
||||
|
||||
### Form
|
||||
|
||||
| 参数 | 说明 | 类型 | 默认值 |
|
||||
| --- | --- | --- | --- |
|
||||
| component | 设置 Form 渲染元素,为 `false` 则不创建 DOM 节点 | ComponentType \| false | form |
|
||||
| colon | 配置 Form.Item 的 `colon` 的默认值。表示是否显示 label 后面的冒号 (只有在属性 layout 为 horizontal 时有效) | boolean | true |
|
||||
| fields | 通过状态管理(如 redux)控制表单字段,如非强需求不推荐使用。查看[示例](#components-form-demo-global-state) | [FieldData](#FieldData)\[] | - |
|
||||
| form | 经 `Form.useForm()` 创建的 form 控制实例,不提供时会自动创建 | [FormInstance](#FormInstance) | - |
|
||||
| hideRequiredMark | 隐藏所有表单项的必选标记 | boolean | false |
|
||||
| initialValues | 表单默认值,只有初始化以及重置时生效 | object | - |
|
||||
| labelAlign | label 标签的文本对齐方式 | `left` \| `right` | `right` |
|
||||
| labelCol | label 标签布局,同 `<Col>` 组件,设置 `span` `offset` 值,如 `{span: 3, offset: 12}` 或 `sm: {span: 3, offset: 12}` | [object](/components/grid/#Col) | - |
|
||||
| layout | 表单布局 | `horizontal` \| `vertical` \| `inline` | `horizontal` |
|
||||
| name | 表单名称,会作为表单字段 `id` 前缀使用 | string | - |
|
||||
| scrollToFirstError | 提交失败自动滚动到第一个错误字段 | false | - |
|
||||
| size | 设置字段组件的尺寸(仅限 antd 组件) | `small` \| `middle` \| `large` | - |
|
||||
| validateMessages | 验证提示模板,说明[见下](#validateMessages) | [ValidateMessages](https://github.com/react-component/field-form/blob/master/src/utils/messages.ts) | - |
|
||||
| wrapperCol | 需要为输入控件设置布局样式时,使用该属性,用法同 labelCol | [object](/components/grid/#Col) | - |
|
||||
| onFinish | 提交表单且数据验证成功后回调事件 | Function(values) | - |
|
||||
| onFinishFailed | 提交表单且数据验证失败后回调事件 | Function({ values, errorFields, outOfDate }) | - |
|
||||
| onFieldsChange | 字段更新时触发回调事件 | Function(changedFields, allFields) | - |
|
||||
| onValuesChange | 字段值更新时触发回调事件 | Function(changedValues, allValues) | - |
|
||||
| 参数 | 说明 | 类型 | 默认值 | 版本 |
|
||||
| --- | --- | --- | --- | --- |
|
||||
| component | 设置 Form 渲染元素,为 `false` 则不创建 DOM 节点 | ComponentType \| false | form | |
|
||||
| colon | 配置 Form.Item 的 `colon` 的默认值。表示是否显示 label 后面的冒号 (只有在属性 layout 为 horizontal 时有效) | boolean | true | |
|
||||
| fields | 通过状态管理(如 redux)控制表单字段,如非强需求不推荐使用。查看[示例](#components-form-demo-global-state) | [FieldData](#FieldData)\[] | - | |
|
||||
| form | 经 `Form.useForm()` 创建的 form 控制实例,不提供时会自动创建 | [FormInstance](#FormInstance) | - | |
|
||||
| hideRequiredMark | 隐藏所有表单项的必选标记 | boolean | false | |
|
||||
| initialValues | 表单默认值,只有初始化以及重置时生效 | object | - | |
|
||||
| labelAlign | label 标签的文本对齐方式 | `left` \| `right` | `right` | |
|
||||
| labelCol | label 标签布局,同 `<Col>` 组件,设置 `span` `offset` 值,如 `{span: 3, offset: 12}` 或 `sm: {span: 3, offset: 12}` | [object](/components/grid/#Col) | - | |
|
||||
| layout | 表单布局 | `horizontal` \| `vertical` \| `inline` | `horizontal` | |
|
||||
| name | 表单名称,会作为表单字段 `id` 前缀使用 | string | - | |
|
||||
| scrollToFirstError | 提交失败自动滚动到第一个错误字段 | false | - | |
|
||||
| size | 设置字段组件的尺寸(仅限 antd 组件) | `small` \| `middle` \| `large` | - | |
|
||||
| validateMessages | 验证提示模板,说明[见下](#validateMessages) | [ValidateMessages](https://github.com/react-component/field-form/blob/master/src/utils/messages.ts) | - | |
|
||||
| validateTrigger | 统一设置字段校验规则 | string \| string[] | 'onChange' | 4.3.0 |
|
||||
| wrapperCol | 需要为输入控件设置布局样式时,使用该属性,用法同 labelCol | [object](/components/grid/#Col) | - | |
|
||||
| onFinish | 提交表单且数据验证成功后回调事件 | Function(values) | - | |
|
||||
| onFinishFailed | 提交表单且数据验证失败后回调事件 | Function({ values, errorFields, outOfDate }) | - | |
|
||||
| onFieldsChange | 字段更新时触发回调事件 | Function(changedFields, allFields) | - | |
|
||||
| onValuesChange | 字段值更新时触发回调事件 | Function(changedValues, allValues) | - | |
|
||||
|
||||
### validateMessages
|
||||
|
||||
|
@ -11,6 +11,7 @@ export interface PasswordProps extends InputProps {
|
||||
readonly inputPrefixCls?: string;
|
||||
readonly action?: string;
|
||||
visibilityToggle?: boolean;
|
||||
iconRender?: (visible: boolean) => React.ReactNode;
|
||||
}
|
||||
|
||||
export interface PasswordState {
|
||||
@ -28,6 +29,7 @@ export default class Password extends React.Component<PasswordProps, PasswordSta
|
||||
static defaultProps = {
|
||||
action: 'click',
|
||||
visibilityToggle: true,
|
||||
iconRender: (visible: boolean) => (visible ? <EyeOutlined /> : <EyeInvisibleOutlined />),
|
||||
};
|
||||
|
||||
state: PasswordState = {
|
||||
@ -44,9 +46,10 @@ export default class Password extends React.Component<PasswordProps, PasswordSta
|
||||
};
|
||||
|
||||
getIcon = (prefixCls: string) => {
|
||||
const { action } = this.props;
|
||||
const { action, iconRender = () => null } = this.props;
|
||||
const { visible } = this.state;
|
||||
const iconTrigger = ActionMap[action!] || '';
|
||||
const icon = this.state.visible ? EyeOutlined : EyeInvisibleOutlined;
|
||||
const icon = iconRender(visible);
|
||||
const iconProps = {
|
||||
[iconTrigger]: this.onVisibleChange,
|
||||
className: `${prefixCls}-icon`,
|
||||
@ -62,7 +65,7 @@ export default class Password extends React.Component<PasswordProps, PasswordSta
|
||||
e.preventDefault();
|
||||
},
|
||||
};
|
||||
return React.createElement(icon as React.ComponentType, iconProps);
|
||||
return React.cloneElement(React.isValidElement(icon) ? icon : <span>{icon}</span>, iconProps);
|
||||
};
|
||||
|
||||
saveInput = (instance: Input) => {
|
||||
@ -102,7 +105,7 @@ export default class Password extends React.Component<PasswordProps, PasswordSta
|
||||
});
|
||||
|
||||
const props = {
|
||||
...omit(restProps, ['suffix']),
|
||||
...omit(restProps, ['suffix', 'iconRender']),
|
||||
type: this.state.visible ? 'text' : 'password',
|
||||
className: inputClassName,
|
||||
prefixCls: inputPrefixCls,
|
||||
|
@ -1918,45 +1918,97 @@ exports[`renders ./components/input/demo/group.md correctly 1`] = `
|
||||
`;
|
||||
|
||||
exports[`renders ./components/input/demo/password-input.md correctly 1`] = `
|
||||
<span
|
||||
class="ant-input-password ant-input-affix-wrapper"
|
||||
<div
|
||||
class="ant-space ant-space-vertical"
|
||||
>
|
||||
<input
|
||||
action="click"
|
||||
class="ant-input"
|
||||
placeholder="input password"
|
||||
type="password"
|
||||
value=""
|
||||
/>
|
||||
<span
|
||||
class="ant-input-suffix"
|
||||
<div
|
||||
class="ant-space-item"
|
||||
style="margin-bottom:8px"
|
||||
>
|
||||
<span
|
||||
aria-label="eye-invisible"
|
||||
class="anticon anticon-eye-invisible ant-input-password-icon"
|
||||
role="img"
|
||||
tabindex="-1"
|
||||
class="ant-input-password ant-input-affix-wrapper"
|
||||
>
|
||||
<svg
|
||||
aria-hidden="true"
|
||||
class=""
|
||||
data-icon="eye-invisible"
|
||||
fill="currentColor"
|
||||
focusable="false"
|
||||
height="1em"
|
||||
viewBox="64 64 896 896"
|
||||
width="1em"
|
||||
<input
|
||||
action="click"
|
||||
class="ant-input"
|
||||
placeholder="input password"
|
||||
type="password"
|
||||
value=""
|
||||
/>
|
||||
<span
|
||||
class="ant-input-suffix"
|
||||
>
|
||||
<path
|
||||
d="M942.2 486.2Q889.47 375.11 816.7 305l-50.88 50.88C807.31 395.53 843.45 447.4 874.7 512 791.5 684.2 673.4 766 512 766q-72.67 0-133.87-22.38L323 798.75Q408 838 512 838q288.3 0 430.2-300.3a60.29 60.29 0 000-51.5zm-63.57-320.64L836 122.88a8 8 0 00-11.32 0L715.31 232.2Q624.86 186 512 186q-288.3 0-430.2 300.3a60.3 60.3 0 000 51.5q56.69 119.4 136.5 191.41L112.48 835a8 8 0 000 11.31L155.17 889a8 8 0 0011.31 0l712.15-712.12a8 8 0 000-11.32zM149.3 512C232.6 339.8 350.7 258 512 258c54.54 0 104.13 9.36 149.12 28.39l-70.3 70.3a176 176 0 00-238.13 238.13l-83.42 83.42C223.1 637.49 183.3 582.28 149.3 512zm246.7 0a112.11 112.11 0 01146.2-106.69L401.31 546.2A112 112 0 01396 512z"
|
||||
/>
|
||||
<path
|
||||
d="M508 624c-3.46 0-6.87-.16-10.25-.47l-52.82 52.82a176.09 176.09 0 00227.42-227.42l-52.82 52.82c.31 3.38.47 6.79.47 10.25a111.94 111.94 0 01-112 112z"
|
||||
/>
|
||||
</svg>
|
||||
<span
|
||||
aria-label="eye-invisible"
|
||||
class="anticon anticon-eye-invisible ant-input-password-icon"
|
||||
role="img"
|
||||
tabindex="-1"
|
||||
>
|
||||
<svg
|
||||
aria-hidden="true"
|
||||
class=""
|
||||
data-icon="eye-invisible"
|
||||
fill="currentColor"
|
||||
focusable="false"
|
||||
height="1em"
|
||||
viewBox="64 64 896 896"
|
||||
width="1em"
|
||||
>
|
||||
<path
|
||||
d="M942.2 486.2Q889.47 375.11 816.7 305l-50.88 50.88C807.31 395.53 843.45 447.4 874.7 512 791.5 684.2 673.4 766 512 766q-72.67 0-133.87-22.38L323 798.75Q408 838 512 838q288.3 0 430.2-300.3a60.29 60.29 0 000-51.5zm-63.57-320.64L836 122.88a8 8 0 00-11.32 0L715.31 232.2Q624.86 186 512 186q-288.3 0-430.2 300.3a60.3 60.3 0 000 51.5q56.69 119.4 136.5 191.41L112.48 835a8 8 0 000 11.31L155.17 889a8 8 0 0011.31 0l712.15-712.12a8 8 0 000-11.32zM149.3 512C232.6 339.8 350.7 258 512 258c54.54 0 104.13 9.36 149.12 28.39l-70.3 70.3a176 176 0 00-238.13 238.13l-83.42 83.42C223.1 637.49 183.3 582.28 149.3 512zm246.7 0a112.11 112.11 0 01146.2-106.69L401.31 546.2A112 112 0 01396 512z"
|
||||
/>
|
||||
<path
|
||||
d="M508 624c-3.46 0-6.87-.16-10.25-.47l-52.82 52.82a176.09 176.09 0 00227.42-227.42l-52.82 52.82c.31 3.38.47 6.79.47 10.25a111.94 111.94 0 01-112 112z"
|
||||
/>
|
||||
</svg>
|
||||
</span>
|
||||
</span>
|
||||
</span>
|
||||
</span>
|
||||
</span>
|
||||
</div>
|
||||
<div
|
||||
class="ant-space-item"
|
||||
>
|
||||
<span
|
||||
class="ant-input-password ant-input-affix-wrapper"
|
||||
>
|
||||
<input
|
||||
action="click"
|
||||
class="ant-input"
|
||||
placeholder="input password"
|
||||
type="password"
|
||||
value=""
|
||||
/>
|
||||
<span
|
||||
class="ant-input-suffix"
|
||||
>
|
||||
<span
|
||||
aria-label="eye-invisible"
|
||||
class="anticon anticon-eye-invisible ant-input-password-icon"
|
||||
role="img"
|
||||
tabindex="-1"
|
||||
>
|
||||
<svg
|
||||
aria-hidden="true"
|
||||
class=""
|
||||
data-icon="eye-invisible"
|
||||
fill="currentColor"
|
||||
focusable="false"
|
||||
height="1em"
|
||||
viewBox="64 64 896 896"
|
||||
width="1em"
|
||||
>
|
||||
<path
|
||||
d="M942.2 486.2Q889.47 375.11 816.7 305l-50.88 50.88C807.31 395.53 843.45 447.4 874.7 512 791.5 684.2 673.4 766 512 766q-72.67 0-133.87-22.38L323 798.75Q408 838 512 838q288.3 0 430.2-300.3a60.29 60.29 0 000-51.5zm-63.57-320.64L836 122.88a8 8 0 00-11.32 0L715.31 232.2Q624.86 186 512 186q-288.3 0-430.2 300.3a60.3 60.3 0 000 51.5q56.69 119.4 136.5 191.41L112.48 835a8 8 0 000 11.31L155.17 889a8 8 0 0011.31 0l712.15-712.12a8 8 0 000-11.32zM149.3 512C232.6 339.8 350.7 258 512 258c54.54 0 104.13 9.36 149.12 28.39l-70.3 70.3a176 176 0 00-238.13 238.13l-83.42 83.42C223.1 637.49 183.3 582.28 149.3 512zm246.7 0a112.11 112.11 0 01146.2-106.69L401.31 546.2A112 112 0 01396 512z"
|
||||
/>
|
||||
<path
|
||||
d="M508 624c-3.46 0-6.87-.16-10.25-.47l-52.82 52.82a176.09 176.09 0 00227.42-227.42l-52.82 52.82c.31 3.38.47 6.79.47 10.25a111.94 111.94 0 01-112 112z"
|
||||
/>
|
||||
</svg>
|
||||
</span>
|
||||
</span>
|
||||
</span>
|
||||
</div>
|
||||
</div>
|
||||
`;
|
||||
|
||||
exports[`renders ./components/input/demo/presuffix.md correctly 1`] = `
|
||||
|
@ -14,7 +14,17 @@ title:
|
||||
Input type of password.
|
||||
|
||||
```jsx
|
||||
import { Input } from 'antd';
|
||||
import { Input, Space } from 'antd';
|
||||
import { EyeInvisibleOutlined, EyeTwoTone } from '@ant-design/icons';
|
||||
|
||||
ReactDOM.render(<Input.Password placeholder="input password" />, mountNode);
|
||||
ReactDOM.render(
|
||||
<Space direction="vertical">
|
||||
<Input.Password placeholder="input password" />
|
||||
<Input.Password
|
||||
placeholder="input password"
|
||||
iconRender={visible => (visible ? <EyeTwoTone /> : <EyeInvisibleOutlined />)}
|
||||
/>
|
||||
</Space>,
|
||||
mountNode,
|
||||
);
|
||||
```
|
||||
|
@ -34,7 +34,7 @@
|
||||
}
|
||||
|
||||
.disabled() {
|
||||
color: @disabled-color;
|
||||
color: @input-disabled-color;
|
||||
background-color: @input-disabled-bg;
|
||||
cursor: not-allowed;
|
||||
opacity: 1;
|
||||
|
File diff suppressed because it is too large
Load Diff
@ -44,6 +44,12 @@ const localeValues: Locale = {
|
||||
searchPlaceholder: 'Search here',
|
||||
itemUnit: 'item',
|
||||
itemsUnit: 'items',
|
||||
remove: 'Remove',
|
||||
selectCurrent: 'Select current page',
|
||||
removeCurrent: 'Remove current page',
|
||||
selectAll: 'Select all data',
|
||||
removeAll: 'Remove all data',
|
||||
selectInvert: 'Invert current page',
|
||||
},
|
||||
Upload: {
|
||||
uploading: 'Uploading...',
|
||||
|
@ -44,6 +44,12 @@ const localeValues: Locale = {
|
||||
searchPlaceholder: '请输入搜索内容',
|
||||
itemUnit: '项',
|
||||
itemsUnit: '项',
|
||||
remove: '删除',
|
||||
selectCurrent: '全选当页',
|
||||
removeCurrent: '删除当页',
|
||||
selectAll: '全选所有',
|
||||
removeAll: '删除全部',
|
||||
selectInvert: '反选当页',
|
||||
},
|
||||
Upload: {
|
||||
uploading: '文件上传中',
|
||||
|
@ -17,6 +17,7 @@ export interface MenuItemProps
|
||||
disabled?: boolean;
|
||||
level?: number;
|
||||
icon?: React.ReactNode;
|
||||
danger?: boolean;
|
||||
title?: React.ReactNode;
|
||||
children?: React.ReactNode;
|
||||
className?: string;
|
||||
@ -56,7 +57,7 @@ export default class MenuItem extends React.Component<MenuItemProps> {
|
||||
|
||||
renderItem = ({ siderCollapsed }: SiderContextProps) => {
|
||||
const { level, className, children, rootPrefixCls } = this.props;
|
||||
const { title, icon, ...rest } = this.props;
|
||||
const { title, icon, danger, ...rest } = this.props;
|
||||
|
||||
return (
|
||||
<MenuContext.Consumer>
|
||||
@ -87,6 +88,7 @@ export default class MenuItem extends React.Component<MenuItemProps> {
|
||||
<Item
|
||||
{...rest}
|
||||
className={classNames(className, {
|
||||
[`${rootPrefixCls}-item-danger`]: danger,
|
||||
[`${rootPrefixCls}-item-only-child`]:
|
||||
(icon ? childrenLength + 1 : childrenLength) === 1,
|
||||
})}
|
||||
|
@ -1156,7 +1156,7 @@ Array [
|
||||
Option 3
|
||||
</li>
|
||||
<li
|
||||
class="ant-menu-item ant-menu-item-only-child"
|
||||
class="ant-menu-item ant-menu-item-danger ant-menu-item-only-child"
|
||||
role="menuitem"
|
||||
style="padding-left:48px"
|
||||
>
|
||||
|
@ -61,7 +61,9 @@ class Sider extends React.Component {
|
||||
<Menu.Item key="1">Option 1</Menu.Item>
|
||||
<Menu.Item key="2">Option 2</Menu.Item>
|
||||
<Menu.Item key="3">Option 3</Menu.Item>
|
||||
<Menu.Item key="4">Option 4</Menu.Item>
|
||||
<Menu.Item key="4" danger>
|
||||
Option 4
|
||||
</Menu.Item>
|
||||
</SubMenu>
|
||||
<SubMenu key="sub2" icon={<AppstoreOutlined />} title="Navigation Two">
|
||||
<Menu.Item key="5">Option 5</Menu.Item>
|
||||
|
@ -58,6 +58,7 @@ More layouts with navigation: [Layout](/components/layout).
|
||||
| key | Unique ID of the menu item | string | | |
|
||||
| title | Set display title for collapsed item | string | | |
|
||||
| icon | icon of the menu item | ReactNode | | 4.2.0 |
|
||||
| danger | Display the danger style | boolean | false | 4.3.0 |
|
||||
|
||||
> Note: `icon` is a newly added prop in`4.2.0`. For previous versions, please use the following method to define the icon.
|
||||
>
|
||||
|
@ -59,6 +59,7 @@ subtitle: 导航菜单
|
||||
| key | item 的唯一标志 | string | | |
|
||||
| title | 设置收缩时展示的悬浮标题 | string | | |
|
||||
| icon | 菜单图标 | ReactNode | | 4.2.0 |
|
||||
| danger | 展示错误状态样式 | boolean | false | 4.3.0 |
|
||||
|
||||
> 注意:`icon` 是 `4.2.0` 新增的属性,之前的版本请使用下面的方式定义图标。
|
||||
>
|
||||
|
@ -1,5 +1,6 @@
|
||||
@import '../../style/themes/index';
|
||||
@import '../../style/mixins/index';
|
||||
@import './status';
|
||||
|
||||
@menu-prefix-cls: ~'@{ant-prefix}-menu';
|
||||
|
||||
|
47
components/menu/style/status.less
Normal file
47
components/menu/style/status.less
Normal file
@ -0,0 +1,47 @@
|
||||
@import './index';
|
||||
|
||||
.@{menu-prefix-cls} {
|
||||
// Danger
|
||||
&-item-danger&-item {
|
||||
color: @menu-highlight-danger-color;
|
||||
|
||||
&:hover,
|
||||
&-active {
|
||||
color: @menu-highlight-danger-color;
|
||||
}
|
||||
|
||||
&:active {
|
||||
background: @menu-item-active-danger-bg;
|
||||
}
|
||||
|
||||
&-selected {
|
||||
color: @menu-highlight-danger-color;
|
||||
> a,
|
||||
> a:hover {
|
||||
color: @menu-highlight-danger-color;
|
||||
}
|
||||
}
|
||||
|
||||
.@{menu-prefix-cls}:not(.@{menu-prefix-cls}-horizontal) &-selected {
|
||||
background-color: @menu-item-active-danger-bg;
|
||||
}
|
||||
|
||||
.@{menu-prefix-cls}-inline &::after {
|
||||
border-right-color: @menu-highlight-danger-color;
|
||||
}
|
||||
}
|
||||
|
||||
// ==================== Dark ====================
|
||||
&-dark &-item-danger&-item {
|
||||
&,
|
||||
&:hover,
|
||||
& > a {
|
||||
color: @menu-dark-danger-color;
|
||||
}
|
||||
}
|
||||
|
||||
&-dark&-dark:not(&-horizontal) &-item-danger&-item-selected {
|
||||
color: @menu-dark-highlight-color;
|
||||
background-color: @menu-dark-item-active-danger-bg;
|
||||
}
|
||||
}
|
@ -1,5 +1,16 @@
|
||||
// Jest Snapshot v1, https://goo.gl/fbAQLP
|
||||
|
||||
exports[`renders ./components/message/demo/custom-style.md correctly 1`] = `
|
||||
<button
|
||||
class="ant-btn"
|
||||
type="button"
|
||||
>
|
||||
<span>
|
||||
Customized style
|
||||
</span>
|
||||
</button>
|
||||
`;
|
||||
|
||||
exports[`renders ./components/message/demo/duration.md correctly 1`] = `
|
||||
<button
|
||||
class="ant-btn"
|
||||
|
30
components/message/demo/custom-style.md
Normal file
30
components/message/demo/custom-style.md
Normal file
@ -0,0 +1,30 @@
|
||||
---
|
||||
order: 6
|
||||
title:
|
||||
zh-CN: 自定义样式
|
||||
en-US: Customized style
|
||||
---
|
||||
|
||||
## zh-CN
|
||||
|
||||
使用 `style` 和 `className` 来定义样式。
|
||||
|
||||
## en-US
|
||||
|
||||
The `style` and `className` are available to customize Message.
|
||||
|
||||
```jsx
|
||||
import { message, Button } from 'antd';
|
||||
|
||||
const success = () => {
|
||||
message.success({
|
||||
content: 'This is a prompt message with custom className and style',
|
||||
className: 'custom-class',
|
||||
style: {
|
||||
marginTop: '50%',
|
||||
},
|
||||
});
|
||||
};
|
||||
|
||||
ReactDOM.render(<Button onClick={success}>Customized style</Button>, mountNode);
|
||||
```
|
@ -55,6 +55,8 @@ The properties of config are as follows:
|
||||
| onClose | Specify a function that will be called when the message is closed | function | - |
|
||||
| icon | Customized Icon | ReactNode | - |
|
||||
| key | The unique identifier of the Message | string\|number | - |
|
||||
| className | Customized CSS class | string | - |
|
||||
| style | Customized inline style | [React.CSSProperties](https://github.com/DefinitelyTyped/DefinitelyTyped/blob/e434515761b36830c3e58a970abf5186f005adac/types/react/index.d.ts#L794) | - |
|
||||
|
||||
### Global static methods
|
||||
|
||||
@ -65,6 +67,10 @@ Methods for global configuration and destruction are also provided:
|
||||
|
||||
#### message.config
|
||||
|
||||
> When you use `ConfigProvider` for global configuration, the system will automatically start RTL mode by default.(4.3.0+)
|
||||
>
|
||||
> When you want to use it alone, you can start the RTL mode through the following settings.
|
||||
|
||||
```js
|
||||
message.config({
|
||||
top: 100,
|
||||
|
@ -60,6 +60,8 @@ export interface ArgsProps {
|
||||
onClose?: () => void;
|
||||
icon?: React.ReactNode;
|
||||
key?: string | number;
|
||||
style?: React.CSSProperties;
|
||||
className?: string;
|
||||
}
|
||||
|
||||
const iconMap = {
|
||||
@ -91,7 +93,8 @@ function notice(args: ArgsProps): MessageType {
|
||||
instance.notice({
|
||||
key: target,
|
||||
duration,
|
||||
style: {},
|
||||
style: args.style || {},
|
||||
className: args.className,
|
||||
content: (
|
||||
<div className={messageClass}>
|
||||
{args.icon || (IconComponent && <IconComponent />)}
|
||||
|
@ -49,13 +49,15 @@ title: Message
|
||||
|
||||
`config` 对象属性如下:
|
||||
|
||||
| 参数 | 说明 | 类型 | 默认值 |
|
||||
| -------- | --------------------------------------------- | -------------- | ------ |
|
||||
| content | 提示内容 | ReactNode | - |
|
||||
| duration | 自动关闭的延时,单位秒。设为 0 时不自动关闭。 | number | 3 |
|
||||
| onClose | 关闭时触发的回调函数 | Function | - |
|
||||
| icon | 自定义图标 | ReactNode | - |
|
||||
| key | 当前提示的唯一标志 | string\|number | - |
|
||||
| 参数 | 说明 | 类型 | 默认值 |
|
||||
| --- | --- | --- | --- |
|
||||
| content | 提示内容 | ReactNode | - |
|
||||
| duration | 自动关闭的延时,单位秒。设为 0 时不自动关闭。 | number | 3 |
|
||||
| onClose | 关闭时触发的回调函数 | Function | - |
|
||||
| icon | 自定义图标 | ReactNode | - |
|
||||
| key | 当前提示的唯一标志 | string\|number | - |
|
||||
| className | 自定义 CSS class | string | - |
|
||||
| style | 自定义内联样式 | [React.CSSProperties](https://github.com/DefinitelyTyped/DefinitelyTyped/blob/e434515761b36830c3e58a970abf5186f005adac/types/react/index.d.ts#L794) | - |
|
||||
|
||||
### 全局方法
|
||||
|
||||
@ -66,6 +68,10 @@ title: Message
|
||||
|
||||
#### message.config
|
||||
|
||||
> 当你使用 `ConfigProvider` 进行全局化配置时,系统会默认自动开启 RTL 模式。(4.3.0+)
|
||||
>
|
||||
> 当你想单独使用,可通过如下设置开启 RTL 模式。
|
||||
|
||||
```js
|
||||
message.config({
|
||||
top: 100,
|
||||
|
@ -98,6 +98,21 @@ describe('notification', () => {
|
||||
expect(document.querySelectorAll('.ant-notification-rtl').length).toBe(1);
|
||||
});
|
||||
|
||||
it('should be able to config prefixCls', () => {
|
||||
notification.config({
|
||||
prefixCls: 'prefix-test',
|
||||
});
|
||||
notification.open({
|
||||
message: 'Notification Title',
|
||||
duration: 0,
|
||||
});
|
||||
expect(document.querySelectorAll('.ant-notification-notice').length).toBe(0);
|
||||
expect(document.querySelectorAll('.prefix-test-notice').length).toBe(1);
|
||||
notification.config({
|
||||
prefixCls: 'ant-notification',
|
||||
});
|
||||
});
|
||||
|
||||
it('should be able to open with icon', async () => {
|
||||
const openNotificationWithIcon = async type => {
|
||||
const iconPrefix = '.ant-notification-notice-icon';
|
||||
|
@ -50,6 +50,10 @@ The properties of config are as follows:
|
||||
|
||||
- `notification.config(options)`
|
||||
|
||||
> When you use `ConfigProvider` for global configuration, the system will automatically start RTL mode by default.(4.3.0+)
|
||||
>
|
||||
> When you want to use it alone, you can start the RTL mode through the following settings.
|
||||
|
||||
```js
|
||||
notification.config({
|
||||
placement: 'bottomRight',
|
||||
|
@ -19,6 +19,7 @@ const notificationInstance: {
|
||||
let defaultDuration = 4.5;
|
||||
let defaultTop = 24;
|
||||
let defaultBottom = 24;
|
||||
let defaultPrefixCls = 'ant-notification';
|
||||
let defaultPlacement: NotificationPlacement = 'topRight';
|
||||
let defaultGetContainer: () => HTMLElement;
|
||||
let defaultCloseIcon: React.ReactNode;
|
||||
@ -27,6 +28,7 @@ export interface ConfigProps {
|
||||
top?: number;
|
||||
bottom?: number;
|
||||
duration?: number;
|
||||
prefixCls?: string;
|
||||
placement?: NotificationPlacement;
|
||||
getContainer?: () => HTMLElement;
|
||||
closeIcon?: React.ReactNode;
|
||||
@ -35,7 +37,10 @@ export interface ConfigProps {
|
||||
|
||||
let rtl = false;
|
||||
function setNotificationConfig(options: ConfigProps) {
|
||||
const { duration, placement, bottom, top, getContainer, closeIcon } = options;
|
||||
const { duration, placement, bottom, top, getContainer, closeIcon, prefixCls } = options;
|
||||
if (prefixCls !== undefined) {
|
||||
defaultPrefixCls = prefixCls;
|
||||
}
|
||||
if (duration !== undefined) {
|
||||
defaultDuration = duration;
|
||||
}
|
||||
@ -109,7 +114,7 @@ function getNotificationInstance(
|
||||
getContainer = defaultGetContainer,
|
||||
closeIcon = defaultCloseIcon,
|
||||
} = args;
|
||||
const outerPrefixCls = args.prefixCls || 'ant-notification';
|
||||
const outerPrefixCls = args.prefixCls || defaultPrefixCls;
|
||||
const prefixCls = `${outerPrefixCls}-notice`;
|
||||
|
||||
const cacheKey = `${outerPrefixCls}-${placement}`;
|
||||
|
@ -51,6 +51,10 @@ config 参数如下:
|
||||
|
||||
- `notification.config(options)`
|
||||
|
||||
> 当你使用 `ConfigProvider` 进行全局化配置时,系统会默认自动开启 RTL 模式。(4.3.0+)
|
||||
>
|
||||
> 当你想单独使用,可通过如下设置开启 RTL 模式。
|
||||
|
||||
```js
|
||||
notification.config({
|
||||
placement: 'bottomRight',
|
||||
|
@ -104,7 +104,7 @@ exports[`renders ./components/page-header/demo/actions.md correctly 1`] = `
|
||||
colspan="1"
|
||||
>
|
||||
<span
|
||||
class="ant-descriptions-item-label ant-descriptions-item-colon"
|
||||
class="ant-descriptions-item-label"
|
||||
>
|
||||
Created
|
||||
</span>
|
||||
@ -119,7 +119,7 @@ exports[`renders ./components/page-header/demo/actions.md correctly 1`] = `
|
||||
colspan="1"
|
||||
>
|
||||
<span
|
||||
class="ant-descriptions-item-label ant-descriptions-item-colon"
|
||||
class="ant-descriptions-item-label"
|
||||
>
|
||||
Association
|
||||
</span>
|
||||
@ -136,7 +136,7 @@ exports[`renders ./components/page-header/demo/actions.md correctly 1`] = `
|
||||
colspan="1"
|
||||
>
|
||||
<span
|
||||
class="ant-descriptions-item-label ant-descriptions-item-colon"
|
||||
class="ant-descriptions-item-label"
|
||||
>
|
||||
Creation Time
|
||||
</span>
|
||||
@ -155,7 +155,7 @@ exports[`renders ./components/page-header/demo/actions.md correctly 1`] = `
|
||||
colspan="1"
|
||||
>
|
||||
<span
|
||||
class="ant-descriptions-item-label ant-descriptions-item-colon"
|
||||
class="ant-descriptions-item-label"
|
||||
>
|
||||
Effective Time
|
||||
</span>
|
||||
@ -170,7 +170,7 @@ exports[`renders ./components/page-header/demo/actions.md correctly 1`] = `
|
||||
colspan="2"
|
||||
>
|
||||
<span
|
||||
class="ant-descriptions-item-label ant-descriptions-item-colon"
|
||||
class="ant-descriptions-item-label"
|
||||
>
|
||||
Remarks
|
||||
</span>
|
||||
@ -828,7 +828,7 @@ exports[`renders ./components/page-header/demo/ghost.md correctly 1`] = `
|
||||
colspan="1"
|
||||
>
|
||||
<span
|
||||
class="ant-descriptions-item-label ant-descriptions-item-colon"
|
||||
class="ant-descriptions-item-label"
|
||||
>
|
||||
Created
|
||||
</span>
|
||||
@ -843,7 +843,7 @@ exports[`renders ./components/page-header/demo/ghost.md correctly 1`] = `
|
||||
colspan="1"
|
||||
>
|
||||
<span
|
||||
class="ant-descriptions-item-label ant-descriptions-item-colon"
|
||||
class="ant-descriptions-item-label"
|
||||
>
|
||||
Association
|
||||
</span>
|
||||
@ -860,7 +860,7 @@ exports[`renders ./components/page-header/demo/ghost.md correctly 1`] = `
|
||||
colspan="1"
|
||||
>
|
||||
<span
|
||||
class="ant-descriptions-item-label ant-descriptions-item-colon"
|
||||
class="ant-descriptions-item-label"
|
||||
>
|
||||
Creation Time
|
||||
</span>
|
||||
@ -879,7 +879,7 @@ exports[`renders ./components/page-header/demo/ghost.md correctly 1`] = `
|
||||
colspan="1"
|
||||
>
|
||||
<span
|
||||
class="ant-descriptions-item-label ant-descriptions-item-colon"
|
||||
class="ant-descriptions-item-label"
|
||||
>
|
||||
Effective Time
|
||||
</span>
|
||||
@ -894,7 +894,7 @@ exports[`renders ./components/page-header/demo/ghost.md correctly 1`] = `
|
||||
colspan="2"
|
||||
>
|
||||
<span
|
||||
class="ant-descriptions-item-label ant-descriptions-item-colon"
|
||||
class="ant-descriptions-item-label"
|
||||
>
|
||||
Remarks
|
||||
</span>
|
||||
@ -1024,7 +1024,7 @@ exports[`renders ./components/page-header/demo/responsive.md correctly 1`] = `
|
||||
colspan="1"
|
||||
>
|
||||
<span
|
||||
class="ant-descriptions-item-label ant-descriptions-item-colon"
|
||||
class="ant-descriptions-item-label"
|
||||
>
|
||||
Created
|
||||
</span>
|
||||
@ -1039,7 +1039,7 @@ exports[`renders ./components/page-header/demo/responsive.md correctly 1`] = `
|
||||
colspan="1"
|
||||
>
|
||||
<span
|
||||
class="ant-descriptions-item-label ant-descriptions-item-colon"
|
||||
class="ant-descriptions-item-label"
|
||||
>
|
||||
Association
|
||||
</span>
|
||||
@ -1060,7 +1060,7 @@ exports[`renders ./components/page-header/demo/responsive.md correctly 1`] = `
|
||||
colspan="1"
|
||||
>
|
||||
<span
|
||||
class="ant-descriptions-item-label ant-descriptions-item-colon"
|
||||
class="ant-descriptions-item-label"
|
||||
>
|
||||
Creation Time
|
||||
</span>
|
||||
@ -1075,7 +1075,7 @@ exports[`renders ./components/page-header/demo/responsive.md correctly 1`] = `
|
||||
colspan="1"
|
||||
>
|
||||
<span
|
||||
class="ant-descriptions-item-label ant-descriptions-item-colon"
|
||||
class="ant-descriptions-item-label"
|
||||
>
|
||||
Effective Time
|
||||
</span>
|
||||
@ -1094,7 +1094,7 @@ exports[`renders ./components/page-header/demo/responsive.md correctly 1`] = `
|
||||
colspan="2"
|
||||
>
|
||||
<span
|
||||
class="ant-descriptions-item-label ant-descriptions-item-colon"
|
||||
class="ant-descriptions-item-label"
|
||||
>
|
||||
Remarks
|
||||
</span>
|
||||
|
@ -2,8 +2,8 @@
|
||||
|
||||
exports[`Popconfirm rtl render component should be rendered correctly in RTL direction 1`] = `<span />`;
|
||||
|
||||
exports[`Popconfirm should show overlay when trigger is clicked 1`] = `"<div class=\\"ant-popover-content\\"><div class=\\"ant-popover-arrow\\"></div><div class=\\"ant-popover-inner\\" role=\\"tooltip\\"><div class=\\"ant-popover-inner-content\\"><div class=\\"ant-popover-message\\"><span role=\\"img\\" aria-label=\\"exclamation-circle\\" class=\\"anticon anticon-exclamation-circle\\"><svg viewBox=\\"64 64 896 896\\" focusable=\\"false\\" class=\\"\\" data-icon=\\"exclamation-circle\\" width=\\"1em\\" height=\\"1em\\" fill=\\"currentColor\\" aria-hidden=\\"true\\"><path d=\\"M512 64C264.6 64 64 264.6 64 512s200.6 448 448 448 448-200.6 448-448S759.4 64 512 64zm-32 232c0-4.4 3.6-8 8-8h48c4.4 0 8 3.6 8 8v272c0 4.4-3.6 8-8 8h-48c-4.4 0-8-3.6-8-8V296zm32 440a48.01 48.01 0 010-96 48.01 48.01 0 010 96z\\"></path></svg></span><div class=\\"ant-popover-message-title\\">code</div></div><div class=\\"ant-popover-buttons\\"><button type=\\"button\\" class=\\"ant-btn ant-btn-sm\\"><span>Cancel</span></button><button type=\\"button\\" class=\\"ant-btn ant-btn-primary ant-btn-sm\\"><span>OK</span></button></div></div></div></div>"`;
|
||||
exports[`Popconfirm should show overlay when trigger is clicked 1`] = `"<div class=\\"ant-popover-content\\"><div class=\\"ant-popover-arrow\\"><span class=\\"ant-popover-arrow-content\\"></span></div><div class=\\"ant-popover-inner\\" role=\\"tooltip\\"><div class=\\"ant-popover-inner-content\\"><div class=\\"ant-popover-message\\"><span role=\\"img\\" aria-label=\\"exclamation-circle\\" class=\\"anticon anticon-exclamation-circle\\"><svg viewBox=\\"64 64 896 896\\" focusable=\\"false\\" class=\\"\\" data-icon=\\"exclamation-circle\\" width=\\"1em\\" height=\\"1em\\" fill=\\"currentColor\\" aria-hidden=\\"true\\"><path d=\\"M512 64C264.6 64 64 264.6 64 512s200.6 448 448 448 448-200.6 448-448S759.4 64 512 64zm-32 232c0-4.4 3.6-8 8-8h48c4.4 0 8 3.6 8 8v272c0 4.4-3.6 8-8 8h-48c-4.4 0-8-3.6-8-8V296zm32 440a48.01 48.01 0 010-96 48.01 48.01 0 010 96z\\"></path></svg></span><div class=\\"ant-popover-message-title\\">code</div></div><div class=\\"ant-popover-buttons\\"><button type=\\"button\\" class=\\"ant-btn ant-btn-sm\\"><span>Cancel</span></button><button type=\\"button\\" class=\\"ant-btn ant-btn-primary ant-btn-sm\\"><span>OK</span></button></div></div></div></div>"`;
|
||||
|
||||
exports[`Popconfirm should show overlay when trigger is clicked 2`] = `"<div class=\\"ant-popover-content\\"><div class=\\"ant-popover-arrow\\"></div><div class=\\"ant-popover-inner\\" role=\\"tooltip\\"><div class=\\"ant-popover-inner-content\\"><div class=\\"ant-popover-message\\"><span role=\\"img\\" aria-label=\\"exclamation-circle\\" class=\\"anticon anticon-exclamation-circle\\"><svg viewBox=\\"64 64 896 896\\" focusable=\\"false\\" class=\\"\\" data-icon=\\"exclamation-circle\\" width=\\"1em\\" height=\\"1em\\" fill=\\"currentColor\\" aria-hidden=\\"true\\"><path d=\\"M512 64C264.6 64 64 264.6 64 512s200.6 448 448 448 448-200.6 448-448S759.4 64 512 64zm-32 232c0-4.4 3.6-8 8-8h48c4.4 0 8 3.6 8 8v272c0 4.4-3.6 8-8 8h-48c-4.4 0-8-3.6-8-8V296zm32 440a48.01 48.01 0 010-96 48.01 48.01 0 010 96z\\"></path></svg></span><div class=\\"ant-popover-message-title\\">code</div></div><div class=\\"ant-popover-buttons\\"><button type=\\"button\\" class=\\"ant-btn ant-btn-sm\\"><span>Cancel</span></button><button type=\\"button\\" class=\\"ant-btn ant-btn-primary ant-btn-sm\\"><span>OK</span></button></div></div></div></div>"`;
|
||||
exports[`Popconfirm should show overlay when trigger is clicked 2`] = `"<div class=\\"ant-popover-content\\"><div class=\\"ant-popover-arrow\\"><span class=\\"ant-popover-arrow-content\\"></span></div><div class=\\"ant-popover-inner\\" role=\\"tooltip\\"><div class=\\"ant-popover-inner-content\\"><div class=\\"ant-popover-message\\"><span role=\\"img\\" aria-label=\\"exclamation-circle\\" class=\\"anticon anticon-exclamation-circle\\"><svg viewBox=\\"64 64 896 896\\" focusable=\\"false\\" class=\\"\\" data-icon=\\"exclamation-circle\\" width=\\"1em\\" height=\\"1em\\" fill=\\"currentColor\\" aria-hidden=\\"true\\"><path d=\\"M512 64C264.6 64 64 264.6 64 512s200.6 448 448 448 448-200.6 448-448S759.4 64 512 64zm-32 232c0-4.4 3.6-8 8-8h48c4.4 0 8 3.6 8 8v272c0 4.4-3.6 8-8 8h-48c-4.4 0-8-3.6-8-8V296zm32 440a48.01 48.01 0 010-96 48.01 48.01 0 010 96z\\"></path></svg></span><div class=\\"ant-popover-message-title\\">code</div></div><div class=\\"ant-popover-buttons\\"><button type=\\"button\\" class=\\"ant-btn ant-btn-sm\\"><span>Cancel</span></button><button type=\\"button\\" class=\\"ant-btn ant-btn-primary ant-btn-sm\\"><span>OK</span></button></div></div></div></div>"`;
|
||||
|
||||
exports[`Popconfirm shows content for render functions 1`] = `"<div class=\\"ant-popover-content\\"><div class=\\"ant-popover-arrow\\"></div><div class=\\"ant-popover-inner\\" role=\\"tooltip\\"><div class=\\"ant-popover-inner-content\\"><div class=\\"ant-popover-message\\"><span role=\\"img\\" aria-label=\\"exclamation-circle\\" class=\\"anticon anticon-exclamation-circle\\"><svg viewBox=\\"64 64 896 896\\" focusable=\\"false\\" class=\\"\\" data-icon=\\"exclamation-circle\\" width=\\"1em\\" height=\\"1em\\" fill=\\"currentColor\\" aria-hidden=\\"true\\"><path d=\\"M512 64C264.6 64 64 264.6 64 512s200.6 448 448 448 448-200.6 448-448S759.4 64 512 64zm-32 232c0-4.4 3.6-8 8-8h48c4.4 0 8 3.6 8 8v272c0 4.4-3.6 8-8 8h-48c-4.4 0-8-3.6-8-8V296zm32 440a48.01 48.01 0 010-96 48.01 48.01 0 010 96z\\"></path></svg></span><div class=\\"ant-popover-message-title\\">some-title</div></div><div class=\\"ant-popover-buttons\\"><button type=\\"button\\" class=\\"ant-btn ant-btn-sm\\"><span>Cancel</span></button><button type=\\"button\\" class=\\"ant-btn ant-btn-primary ant-btn-sm\\"><span>OK</span></button></div></div></div></div>"`;
|
||||
exports[`Popconfirm shows content for render functions 1`] = `"<div class=\\"ant-popover-content\\"><div class=\\"ant-popover-arrow\\"><span class=\\"ant-popover-arrow-content\\"></span></div><div class=\\"ant-popover-inner\\" role=\\"tooltip\\"><div class=\\"ant-popover-inner-content\\"><div class=\\"ant-popover-message\\"><span role=\\"img\\" aria-label=\\"exclamation-circle\\" class=\\"anticon anticon-exclamation-circle\\"><svg viewBox=\\"64 64 896 896\\" focusable=\\"false\\" class=\\"\\" data-icon=\\"exclamation-circle\\" width=\\"1em\\" height=\\"1em\\" fill=\\"currentColor\\" aria-hidden=\\"true\\"><path d=\\"M512 64C264.6 64 64 264.6 64 512s200.6 448 448 448 448-200.6 448-448S759.4 64 512 64zm-32 232c0-4.4 3.6-8 8-8h48c4.4 0 8 3.6 8 8v272c0 4.4-3.6 8-8 8h-48c-4.4 0-8-3.6-8-8V296zm32 440a48.01 48.01 0 010-96 48.01 48.01 0 010 96z\\"></path></svg></span><div class=\\"ant-popover-message-title\\">some-title</div></div><div class=\\"ant-popover-buttons\\"><button type=\\"button\\" class=\\"ant-btn ant-btn-sm\\"><span>Cancel</span></button><button type=\\"button\\" class=\\"ant-btn ant-btn-primary ant-btn-sm\\"><span>OK</span></button></div></div></div></div>"`;
|
||||
|
@ -176,4 +176,23 @@ describe('Popconfirm', () => {
|
||||
triggerNode.simulate('click');
|
||||
expect(ref.current.getPopupDomNode()).toBeFalsy();
|
||||
});
|
||||
|
||||
it('should be closed by pressing ESC', () => {
|
||||
const onVisibleChange = jest.fn();
|
||||
const wrapper = mount(
|
||||
<Popconfirm
|
||||
title="title"
|
||||
mouseEnterDelay={0}
|
||||
mouseLeaveDelay={0}
|
||||
onVisibleChange={onVisibleChange}
|
||||
>
|
||||
<span>Delete</span>
|
||||
</Popconfirm>,
|
||||
);
|
||||
const triggerNode = wrapper.find('span').at(0);
|
||||
triggerNode.simulate('click');
|
||||
expect(onVisibleChange).toHaveBeenLastCalledWith(true, undefined);
|
||||
triggerNode.simulate('keydown', { key: 'Escape', keyCode: 27 });
|
||||
expect(onVisibleChange).toHaveBeenLastCalledWith(false, eventObject);
|
||||
});
|
||||
});
|
||||
|
@ -1,5 +1,6 @@
|
||||
import * as React from 'react';
|
||||
import ExclamationCircleFilled from '@ant-design/icons/ExclamationCircleFilled';
|
||||
import KeyCode from 'rc-util/lib/KeyCode';
|
||||
import Tooltip, { AbstractTooltipProps } from '../tooltip';
|
||||
import Button from '../button';
|
||||
import { LegacyButtonType, NativeButtonProps, convertLegacyProps } from '../button/button';
|
||||
@ -7,6 +8,7 @@ import LocaleReceiver from '../locale-provider/LocaleReceiver';
|
||||
import defaultLocale from '../locale/default';
|
||||
import { ConfigContext } from '../config-provider';
|
||||
import { getRenderPropValue, RenderFunction } from '../_util/getRenderPropValue';
|
||||
import { cloneElement } from '../_util/reactNode';
|
||||
|
||||
export interface PopconfirmProps extends AbstractTooltipProps {
|
||||
title: React.ReactNode | RenderFunction;
|
||||
@ -19,7 +21,10 @@ export interface PopconfirmProps extends AbstractTooltipProps {
|
||||
okButtonProps?: NativeButtonProps;
|
||||
cancelButtonProps?: NativeButtonProps;
|
||||
icon?: React.ReactNode;
|
||||
onVisibleChange?: (visible: boolean, e?: React.MouseEvent<HTMLElement>) => void;
|
||||
onVisibleChange?: (
|
||||
visible: boolean,
|
||||
e?: React.MouseEvent<HTMLElement> | React.KeyboardEvent<HTMLDivElement>,
|
||||
) => void;
|
||||
}
|
||||
|
||||
export interface PopconfirmState {
|
||||
@ -46,7 +51,10 @@ const Popconfirm = React.forwardRef<unknown, PopconfirmProps>((props, ref) => {
|
||||
}
|
||||
}, [props.defaultVisible]);
|
||||
|
||||
const settingVisible = (value: boolean, e?: React.MouseEvent<HTMLButtonElement>) => {
|
||||
const settingVisible = (
|
||||
value: boolean,
|
||||
e?: React.MouseEvent<HTMLButtonElement> | React.KeyboardEvent<HTMLDivElement>,
|
||||
) => {
|
||||
if (!('visible' in props)) {
|
||||
setVisible(value);
|
||||
}
|
||||
@ -72,6 +80,12 @@ const Popconfirm = React.forwardRef<unknown, PopconfirmProps>((props, ref) => {
|
||||
}
|
||||
};
|
||||
|
||||
const onKeyDown = (e: React.KeyboardEvent<HTMLDivElement>) => {
|
||||
if (e.keyCode === KeyCode.ESC && visible) {
|
||||
settingVisible(false, e);
|
||||
}
|
||||
};
|
||||
|
||||
const onVisibleChange = (value: boolean) => {
|
||||
const { disabled } = props;
|
||||
if (disabled) {
|
||||
@ -107,7 +121,7 @@ const Popconfirm = React.forwardRef<unknown, PopconfirmProps>((props, ref) => {
|
||||
|
||||
const { getPrefixCls } = React.useContext(ConfigContext);
|
||||
|
||||
const { prefixCls: customizePrefixCls, placement, ...restProps } = props;
|
||||
const { prefixCls: customizePrefixCls, placement, children, ...restProps } = props;
|
||||
const prefixCls = getPrefixCls('popover', customizePrefixCls);
|
||||
|
||||
const overlay = (
|
||||
@ -125,7 +139,14 @@ const Popconfirm = React.forwardRef<unknown, PopconfirmProps>((props, ref) => {
|
||||
visible={visible}
|
||||
overlay={overlay}
|
||||
ref={ref as any}
|
||||
/>
|
||||
>
|
||||
{cloneElement(children, {
|
||||
onKeyDown: (e: React.KeyboardEvent<any>) => {
|
||||
children?.props.onKeyDown?.(e);
|
||||
onKeyDown(e);
|
||||
},
|
||||
})}
|
||||
</Tooltip>
|
||||
);
|
||||
});
|
||||
|
||||
|
@ -1,6 +1,6 @@
|
||||
// Jest Snapshot v1, https://goo.gl/fbAQLP
|
||||
|
||||
exports[`Popover handles empty title/content props safely 1`] = `"<div class=\\"ant-popover-content\\"><div class=\\"ant-popover-arrow\\"></div><div class=\\"ant-popover-inner\\" role=\\"tooltip\\"><div class=\\"ant-popover-inner-content\\"></div></div></div>"`;
|
||||
exports[`Popover handles empty title/content props safely 1`] = `"<div class=\\"ant-popover-content\\"><div class=\\"ant-popover-arrow\\"><span class=\\"ant-popover-arrow-content\\"></span></div><div class=\\"ant-popover-inner\\" role=\\"tooltip\\"><div class=\\"ant-popover-inner-content\\"></div></div></div>"`;
|
||||
|
||||
exports[`Popover should be rendered correctly in RTL direction 1`] = `
|
||||
Array [
|
||||
@ -19,7 +19,11 @@ Array [
|
||||
>
|
||||
<div
|
||||
class="ant-popover-arrow"
|
||||
/>
|
||||
>
|
||||
<span
|
||||
class="ant-popover-arrow-content"
|
||||
/>
|
||||
</div>
|
||||
<div
|
||||
class="ant-popover-inner"
|
||||
role="tooltip"
|
||||
@ -39,6 +43,6 @@ Array [
|
||||
]
|
||||
`;
|
||||
|
||||
exports[`Popover should show overlay when trigger is clicked 1`] = `"<div class=\\"ant-popover-content\\"><div class=\\"ant-popover-arrow\\"></div><div class=\\"ant-popover-inner\\" role=\\"tooltip\\"><div class=\\"ant-popover-title\\">code</div><div class=\\"ant-popover-inner-content\\">console.log('hello world')</div></div></div>"`;
|
||||
exports[`Popover should show overlay when trigger is clicked 1`] = `"<div class=\\"ant-popover-content\\"><div class=\\"ant-popover-arrow\\"><span class=\\"ant-popover-arrow-content\\"></span></div><div class=\\"ant-popover-inner\\" role=\\"tooltip\\"><div class=\\"ant-popover-title\\">code</div><div class=\\"ant-popover-inner-content\\">console.log('hello world')</div></div></div>"`;
|
||||
|
||||
exports[`Popover shows content for render functions 1`] = `"<div class=\\"ant-popover-content\\"><div class=\\"ant-popover-arrow\\"></div><div class=\\"ant-popover-inner\\" role=\\"tooltip\\"><div class=\\"ant-popover-title\\">some-title</div><div class=\\"ant-popover-inner-content\\">some-content</div></div></div>"`;
|
||||
exports[`Popover shows content for render functions 1`] = `"<div class=\\"ant-popover-content\\"><div class=\\"ant-popover-arrow\\"><span class=\\"ant-popover-arrow-content\\"></span></div><div class=\\"ant-popover-inner\\" role=\\"tooltip\\"><div class=\\"ant-popover-title\\">some-title</div><div class=\\"ant-popover-inner-content\\">some-content</div></div></div>"`;
|
||||
|
@ -81,6 +81,8 @@ class Select<ValueType extends SelectValue = SelectValue> extends React.Componen
|
||||
getPrefixCls,
|
||||
renderEmpty,
|
||||
direction,
|
||||
virtual,
|
||||
dropdownMatchSelectWidth,
|
||||
}: ConfigConsumerProps) => {
|
||||
const {
|
||||
prefixCls: customizePrefixCls,
|
||||
@ -142,6 +144,8 @@ class Select<ValueType extends SelectValue = SelectValue> extends React.Componen
|
||||
return (
|
||||
<RcSelect<ValueType>
|
||||
ref={this.selectRef}
|
||||
virtual={virtual}
|
||||
dropdownMatchSelectWidth={dropdownMatchSelectWidth}
|
||||
{...selectProps}
|
||||
listHeight={listHeight}
|
||||
listItemHeight={listItemHeight}
|
||||
|
@ -21,6 +21,7 @@ export interface SkeletonProps {
|
||||
avatar?: SkeletonAvatarProps | boolean;
|
||||
title?: SkeletonTitleProps | boolean;
|
||||
paragraph?: SkeletonParagraphProps | boolean;
|
||||
round?: boolean;
|
||||
}
|
||||
|
||||
function getComponentProps<T>(prop: T | boolean | undefined): T | {} {
|
||||
@ -80,6 +81,7 @@ const Skeleton = (props: SkeletonProps) => {
|
||||
title,
|
||||
paragraph,
|
||||
active,
|
||||
round,
|
||||
} = props;
|
||||
|
||||
const prefixCls = getPrefixCls('skeleton', customizePrefixCls);
|
||||
@ -143,6 +145,7 @@ const Skeleton = (props: SkeletonProps) => {
|
||||
[`${prefixCls}-with-avatar`]: hasAvatar,
|
||||
[`${prefixCls}-active`]: active,
|
||||
[`${prefixCls}-rtl`]: direction === 'rtl',
|
||||
[`${prefixCls}-round`]: round,
|
||||
});
|
||||
|
||||
return (
|
||||
|
@ -450,6 +450,30 @@ exports[`Skeleton rtl render component should be rendered correctly in RTL direc
|
||||
</div>
|
||||
`;
|
||||
|
||||
exports[`Skeleton should round title and paragraph 1`] = `
|
||||
<div
|
||||
class="ant-skeleton ant-skeleton-round"
|
||||
>
|
||||
<div
|
||||
class="ant-skeleton-content"
|
||||
>
|
||||
<h3
|
||||
class="ant-skeleton-title"
|
||||
style="width: 38%;"
|
||||
/>
|
||||
<ul
|
||||
class="ant-skeleton-paragraph"
|
||||
>
|
||||
<li />
|
||||
<li />
|
||||
<li
|
||||
style="width: 61%;"
|
||||
/>
|
||||
</ul>
|
||||
</div>
|
||||
</div>
|
||||
`;
|
||||
|
||||
exports[`Skeleton should square avatar 1`] = `
|
||||
<div
|
||||
class="ant-skeleton ant-skeleton-with-avatar"
|
||||
|
@ -28,6 +28,11 @@ describe('Skeleton', () => {
|
||||
expect(wrapperSmall.render()).toMatchSnapshot();
|
||||
});
|
||||
|
||||
it('should round title and paragraph', () => {
|
||||
const wrapperSmall = genSkeleton({ round: true, title: true, paragraph: true });
|
||||
expect(wrapperSmall.render()).toMatchSnapshot();
|
||||
})
|
||||
|
||||
describe('avatar', () => {
|
||||
it('size', () => {
|
||||
const wrapperSmall = genSkeleton({ avatar: { size: 'small' } });
|
||||
|
@ -25,6 +25,7 @@ Provide a placeholder while you wait for content to load, or to visualise conten
|
||||
| loading | Display the skeleton when `true` | boolean | - |
|
||||
| paragraph | Show paragraph placeholder | boolean \| [SkeletonParagraphProps](#SkeletonParagraphProps) | true |
|
||||
| title | Show title placeholder | boolean \| [SkeletonTitleProps](#SkeletonTitleProps) | true |
|
||||
| round | Show paragraph and title radius when `true` | boolean | false |
|
||||
|
||||
### SkeletonAvatarProps
|
||||
|
||||
|
@ -26,6 +26,7 @@ cols: 1
|
||||
| loading | 为 `true` 时,显示占位图。反之则直接展示子组件 | boolean | - |
|
||||
| paragraph | 是否显示段落占位图 | boolean \| [SkeletonParagraphProps](#SkeletonParagraphProps) | true |
|
||||
| title | 是否显示标题占位图 | boolean \| [SkeletonTitleProps](#SkeletonTitleProps) | true |
|
||||
| round | 为 `true` 时,段落和标题显示圆角 | boolean | false |
|
||||
|
||||
### SkeletonAvatarProps
|
||||
|
||||
|
@ -72,6 +72,13 @@
|
||||
}
|
||||
}
|
||||
|
||||
&-round &-content {
|
||||
.@{skeleton-title-prefix-cls},
|
||||
.@{skeleton-paragraph-prefix-cls} > li {
|
||||
border-radius: 100px;
|
||||
}
|
||||
}
|
||||
|
||||
// With active animation
|
||||
&.@{skeleton-prefix-cls}-active {
|
||||
& .@{skeleton-prefix-cls}-content {
|
||||
|
@ -964,7 +964,11 @@ exports[`renders ./components/slider/demo/show-tooltip.md correctly 1`] = `
|
||||
>
|
||||
<div
|
||||
class="ant-tooltip-arrow"
|
||||
/>
|
||||
>
|
||||
<span
|
||||
class="ant-tooltip-arrow-content"
|
||||
/>
|
||||
</div>
|
||||
<div
|
||||
class="ant-tooltip-inner"
|
||||
role="tooltip"
|
||||
|
@ -64,7 +64,11 @@ exports[`Slider should render in RTL direction 1`] = `
|
||||
>
|
||||
<div
|
||||
class="ant-tooltip-arrow"
|
||||
/>
|
||||
>
|
||||
<span
|
||||
class="ant-tooltip-arrow-content"
|
||||
/>
|
||||
</div>
|
||||
<div
|
||||
class="ant-tooltip-inner"
|
||||
role="tooltip"
|
||||
@ -91,7 +95,11 @@ exports[`Slider should show tooltip when hovering slider handler 1`] = `
|
||||
>
|
||||
<div
|
||||
class="ant-tooltip-arrow"
|
||||
/>
|
||||
>
|
||||
<span
|
||||
class="ant-tooltip-arrow-content"
|
||||
/>
|
||||
</div>
|
||||
<div
|
||||
class="ant-tooltip-inner"
|
||||
role="tooltip"
|
||||
@ -113,7 +121,11 @@ exports[`Slider should show tooltip when hovering slider handler 2`] = `
|
||||
>
|
||||
<div
|
||||
class="ant-tooltip-arrow"
|
||||
/>
|
||||
>
|
||||
<span
|
||||
class="ant-tooltip-arrow-content"
|
||||
/>
|
||||
</div>
|
||||
<div
|
||||
class="ant-tooltip-inner"
|
||||
role="tooltip"
|
||||
|
@ -1,516 +1,17 @@
|
||||
/* stylelint-disable at-rule-no-unknown */
|
||||
|
||||
// Reboot
|
||||
//
|
||||
// Normalization of HTML elements, manually forked from Normalize.css to remove
|
||||
// styles targeting irrelevant browsers while applying new styles.
|
||||
//
|
||||
// Normalize is licensed MIT. https://github.com/necolas/normalize.css
|
||||
|
||||
// HTML & Body reset
|
||||
@{html-selector},
|
||||
body {
|
||||
.square(100%);
|
||||
}
|
||||
|
||||
// remove the clear button of a text input control in IE10+
|
||||
input::-ms-clear,
|
||||
input::-ms-reveal {
|
||||
display: none;
|
||||
}
|
||||
|
||||
// Document
|
||||
//
|
||||
// 1. Change from `box-sizing: content-box` so that `width` is not affected by `padding` or `border`.
|
||||
// 2. Change the default font family in all browsers.
|
||||
// 3. Correct the line height in all browsers.
|
||||
// 4. Prevent adjustments of font size after orientation changes in IE on Windows Phone and in iOS.
|
||||
// 5. Setting @viewport causes scrollbars to overlap content in IE11 and Edge, so
|
||||
// we force a non-overlapping, non-auto-hiding scrollbar to counteract.
|
||||
// 6. Change the default tap highlight to be completely transparent in iOS.
|
||||
|
||||
*,
|
||||
*::before,
|
||||
*::after {
|
||||
box-sizing: border-box; // 1
|
||||
}
|
||||
|
||||
@{html-selector} {
|
||||
font-family: sans-serif; // 2
|
||||
line-height: 1.15; // 3
|
||||
-webkit-text-size-adjust: 100%; // 4
|
||||
-ms-text-size-adjust: 100%; // 4
|
||||
-ms-overflow-style: scrollbar; // 5
|
||||
-webkit-tap-highlight-color: fade(@black, 0%); // 6
|
||||
}
|
||||
|
||||
// IE10+ doesn't honor `<meta name="viewport">` in some cases.
|
||||
@-ms-viewport {
|
||||
width: device-width;
|
||||
}
|
||||
|
||||
// Shim for "new" HTML5 structural elements to display correctly (IE10, older browsers)
|
||||
article,
|
||||
aside,
|
||||
dialog,
|
||||
figcaption,
|
||||
figure,
|
||||
footer,
|
||||
header,
|
||||
hgroup,
|
||||
main,
|
||||
nav,
|
||||
section {
|
||||
display: block;
|
||||
}
|
||||
|
||||
// Body
|
||||
//
|
||||
// 1. remove the margin in all browsers.
|
||||
// 2. As a best practice, apply a default `body-background`.
|
||||
|
||||
body {
|
||||
margin: 0; // 1
|
||||
color: @text-color;
|
||||
font-size: @font-size-base;
|
||||
font-family: @font-family;
|
||||
font-variant: @font-variant-base;
|
||||
line-height: @line-height-base;
|
||||
background-color: @body-background; // 2
|
||||
font-feature-settings: @font-feature-settings-base;
|
||||
}
|
||||
|
||||
// Suppress the focus outline on elements that cannot be accessed via keyboard.
|
||||
// This prevents an unwanted focus outline from appearing around elements that
|
||||
// might still respond to pointer events.
|
||||
//
|
||||
// Credit: https://github.com/suitcss/base
|
||||
[tabindex='-1']:focus {
|
||||
outline: none !important;
|
||||
}
|
||||
|
||||
// Content grouping
|
||||
//
|
||||
// 1. Add the correct box sizing in Firefox.
|
||||
// 2. Show the overflow in Edge and IE.
|
||||
|
||||
hr {
|
||||
box-sizing: content-box; // 1
|
||||
height: 0; // 1
|
||||
overflow: visible; // 2
|
||||
}
|
||||
|
||||
//
|
||||
// Typography
|
||||
//
|
||||
|
||||
// remove top margins from headings
|
||||
//
|
||||
// By default, `<h1>`-`<h6>` all receive top and bottom margins. We nuke the top
|
||||
// margin for easier control within type scales as it avoids margin collapsing.
|
||||
h1,
|
||||
h2,
|
||||
h3,
|
||||
h4,
|
||||
h5,
|
||||
h6 {
|
||||
margin-top: 0;
|
||||
margin-bottom: 0.5em;
|
||||
color: @heading-color;
|
||||
font-weight: 500;
|
||||
}
|
||||
|
||||
// Reset margins on paragraphs
|
||||
//
|
||||
// Similarly, the top margin on `<p>`s get reset. However, we also reset the
|
||||
// bottom margin to use `em` units instead of `em`.
|
||||
p {
|
||||
margin-top: 0;
|
||||
margin-bottom: 1em;
|
||||
}
|
||||
|
||||
// Abbreviations
|
||||
//
|
||||
// 1. remove the bottom border in Firefox 39-.
|
||||
// 2. Add the correct text decoration in Chrome, Edge, IE, Opera, and Safari.
|
||||
// 3. Add explicit cursor to indicate changed behavior.
|
||||
// 4. Duplicate behavior to the data-* attribute for our tooltip plugin
|
||||
|
||||
abbr[title],
|
||||
abbr[data-original-title] {
|
||||
// 4
|
||||
text-decoration: underline; // 2
|
||||
text-decoration: underline dotted; // 2
|
||||
border-bottom: 0; // 1
|
||||
cursor: help; // 3
|
||||
}
|
||||
|
||||
address {
|
||||
margin-bottom: 1em;
|
||||
font-style: normal;
|
||||
line-height: inherit;
|
||||
}
|
||||
|
||||
input[type='text'],
|
||||
input[type='password'],
|
||||
input[type='number'],
|
||||
textarea {
|
||||
-webkit-appearance: none;
|
||||
}
|
||||
|
||||
ol,
|
||||
ul,
|
||||
dl {
|
||||
margin-top: 0;
|
||||
margin-bottom: 1em;
|
||||
}
|
||||
|
||||
ol ol,
|
||||
ul ul,
|
||||
ol ul,
|
||||
ul ol {
|
||||
margin-bottom: 0;
|
||||
}
|
||||
|
||||
dt {
|
||||
font-weight: 500;
|
||||
}
|
||||
|
||||
dd {
|
||||
margin-bottom: 0.5em;
|
||||
margin-left: 0; // Undo browser default
|
||||
}
|
||||
|
||||
blockquote {
|
||||
margin: 0 0 1em;
|
||||
}
|
||||
|
||||
dfn {
|
||||
font-style: italic; // Add the correct font style in Android 4.3-
|
||||
}
|
||||
|
||||
b,
|
||||
strong {
|
||||
font-weight: bolder; // Add the correct font weight in Chrome, Edge, and Safari
|
||||
}
|
||||
|
||||
small {
|
||||
font-size: 80%; // Add the correct font size in all browsers
|
||||
}
|
||||
|
||||
//
|
||||
// Prevent `sub` and `sup` elements from affecting the line height in
|
||||
// all browsers.
|
||||
//
|
||||
|
||||
sub,
|
||||
sup {
|
||||
position: relative;
|
||||
font-size: 75%;
|
||||
line-height: 0;
|
||||
vertical-align: baseline;
|
||||
}
|
||||
|
||||
sub {
|
||||
bottom: -0.25em;
|
||||
}
|
||||
sup {
|
||||
top: -0.5em;
|
||||
}
|
||||
|
||||
//
|
||||
// Links
|
||||
//
|
||||
|
||||
a {
|
||||
color: @link-color;
|
||||
text-decoration: @link-decoration;
|
||||
background-color: transparent; // remove the gray background on active links in IE 10.
|
||||
outline: none;
|
||||
cursor: pointer;
|
||||
transition: color 0.3s;
|
||||
-webkit-text-decoration-skip: objects; // remove gaps in links underline in iOS 8+ and Safari 8+.
|
||||
|
||||
&:hover {
|
||||
color: @link-hover-color;
|
||||
// Config global less under antd
|
||||
[class^=~'@{ant-prefix}-'],
|
||||
[class*=~' @{ant-prefix}-'] {
|
||||
// remove the clear button of a text input control in IE10+
|
||||
&::-ms-clear,
|
||||
input::-ms-clear,
|
||||
input::-ms-reveal {
|
||||
display: none;
|
||||
}
|
||||
|
||||
&:active {
|
||||
color: @link-active-color;
|
||||
}
|
||||
|
||||
&:active,
|
||||
&:hover {
|
||||
text-decoration: @link-hover-decoration;
|
||||
outline: 0;
|
||||
}
|
||||
|
||||
// https://github.com/ant-design/ant-design/issues/22503
|
||||
&:focus {
|
||||
text-decoration: @link-focus-decoration;
|
||||
outline: @link-focus-outline;
|
||||
}
|
||||
|
||||
&[disabled] {
|
||||
color: @disabled-color;
|
||||
cursor: not-allowed;
|
||||
pointer-events: none;
|
||||
&,
|
||||
*,
|
||||
*::before,
|
||||
*::after {
|
||||
box-sizing: border-box; // 1
|
||||
}
|
||||
}
|
||||
|
||||
//
|
||||
// Code
|
||||
//
|
||||
|
||||
pre,
|
||||
code,
|
||||
kbd,
|
||||
samp {
|
||||
font-size: 1em; // Correct the odd `em` font sizing in all browsers.
|
||||
font-family: @code-family;
|
||||
}
|
||||
|
||||
pre {
|
||||
// remove browser default top margin
|
||||
margin-top: 0;
|
||||
// Reset browser default of `1em` to use `em`s
|
||||
margin-bottom: 1em;
|
||||
// Don't allow content to break outside
|
||||
overflow: auto;
|
||||
}
|
||||
|
||||
//
|
||||
// Figures
|
||||
//
|
||||
figure {
|
||||
// Apply a consistent margin strategy (matches our type styles).
|
||||
margin: 0 0 1em;
|
||||
}
|
||||
|
||||
//
|
||||
// Images and content
|
||||
//
|
||||
|
||||
img {
|
||||
vertical-align: middle;
|
||||
border-style: none; // remove the border on images inside links in IE 10-.
|
||||
}
|
||||
|
||||
svg:not(:root) {
|
||||
overflow: hidden; // Hide the overflow in IE
|
||||
}
|
||||
|
||||
// Avoid 300ms click delay on touch devices that support the `touch-action` CSS property.
|
||||
//
|
||||
// In particular, unlike most other browsers, IE11+Edge on Windows 10 on touch devices and IE Mobile 10-11
|
||||
// DON'T remove the click delay when `<meta name="viewport" content="width=device-width">` is present.
|
||||
// However, they DO support emoving the click delay via `touch-action: manipulation`.
|
||||
// See:
|
||||
// * https://getbootstrap.com/docs/4.0/content/reboot/#click-delay-optimization-for-touch
|
||||
// * http://caniuse.com/#feat=css-touch-action
|
||||
// * https://patrickhlauke.github.io/touch/tests/results/#suppressing-300ms-delay
|
||||
|
||||
a,
|
||||
area,
|
||||
button,
|
||||
[role='button'],
|
||||
input:not([type='range']),
|
||||
label,
|
||||
select,
|
||||
summary,
|
||||
textarea {
|
||||
touch-action: manipulation;
|
||||
}
|
||||
|
||||
//
|
||||
// Tables
|
||||
//
|
||||
|
||||
table {
|
||||
border-collapse: collapse; // Prevent double borders
|
||||
}
|
||||
|
||||
caption {
|
||||
padding-top: 0.75em;
|
||||
padding-bottom: 0.3em;
|
||||
color: @text-color-secondary;
|
||||
text-align: left;
|
||||
caption-side: bottom;
|
||||
}
|
||||
|
||||
th {
|
||||
// Matches default `<td>` alignment by inheriting from the `<body>`, or the
|
||||
// closest parent with a set `text-align`.
|
||||
text-align: inherit;
|
||||
}
|
||||
|
||||
//
|
||||
// Forms
|
||||
//
|
||||
|
||||
input,
|
||||
button,
|
||||
select,
|
||||
optgroup,
|
||||
textarea {
|
||||
margin: 0; // remove the margin in Firefox and Safari
|
||||
color: inherit;
|
||||
font-size: inherit;
|
||||
font-family: inherit;
|
||||
line-height: inherit;
|
||||
}
|
||||
|
||||
button,
|
||||
input {
|
||||
overflow: visible; // Show the overflow in Edge
|
||||
}
|
||||
|
||||
button,
|
||||
select {
|
||||
text-transform: none; // remove the inheritance of text transform in Firefox
|
||||
}
|
||||
|
||||
// 1. Prevent a WebKit bug where (2) destroys native `audio` and `video`
|
||||
// controls in Android 4.
|
||||
// 2. Correct the inability to style clickable types in iOS and Safari.
|
||||
button,
|
||||
@{html-selector} [type="button"], /* 1 */
|
||||
[type="reset"],
|
||||
[type="submit"] {
|
||||
-webkit-appearance: button; // 2
|
||||
}
|
||||
|
||||
// remove inner border and padding from Firefox, but don't restore the outline like Normalize.
|
||||
button::-moz-focus-inner,
|
||||
[type='button']::-moz-focus-inner,
|
||||
[type='reset']::-moz-focus-inner,
|
||||
[type='submit']::-moz-focus-inner {
|
||||
padding: 0;
|
||||
border-style: none;
|
||||
}
|
||||
|
||||
input[type='radio'],
|
||||
input[type='checkbox'] {
|
||||
box-sizing: border-box; // 1. Add the correct box sizing in IE 10-
|
||||
padding: 0; // 2. remove the padding in IE 10-
|
||||
}
|
||||
|
||||
input[type='date'],
|
||||
input[type='time'],
|
||||
input[type='datetime-local'],
|
||||
input[type='month'] {
|
||||
// remove the default appearance of temporal inputs to avoid a Mobile Safari
|
||||
// bug where setting a custom line-height prevents text from being vertically
|
||||
// centered within the input.
|
||||
// See https://bugs.webkit.org/show_bug.cgi?id=139848
|
||||
// and https://github.com/twbs/bootstrap/issues/11266
|
||||
-webkit-appearance: listbox;
|
||||
}
|
||||
|
||||
textarea {
|
||||
overflow: auto; // remove the default vertical scrollbar in IE.
|
||||
// Textareas should really only resize vertically so they don't break their (horizontal) containers.
|
||||
resize: vertical;
|
||||
}
|
||||
|
||||
fieldset {
|
||||
// Browsers set a default `min-width: min-content;` on fieldsets,
|
||||
// unlike e.g. `<div>`s, which have `min-width: 0;` by default.
|
||||
// So we reset that to ensure fieldsets behave more like a standard block element.
|
||||
// See https://github.com/twbs/bootstrap/issues/12359
|
||||
// and https://html.spec.whatwg.org/multipage/#the-fieldset-and-legend-elements
|
||||
min-width: 0;
|
||||
margin: 0;
|
||||
// Reset the default outline behavior of fieldsets so they don't affect page layout.
|
||||
padding: 0;
|
||||
border: 0;
|
||||
}
|
||||
|
||||
// 1. Correct the text wrapping in Edge and IE.
|
||||
// 2. Correct the color inheritance from `fieldset` elements in IE.
|
||||
legend {
|
||||
display: block;
|
||||
width: 100%;
|
||||
max-width: 100%; // 1
|
||||
margin-bottom: 0.5em;
|
||||
padding: 0;
|
||||
color: inherit; // 2
|
||||
font-size: 1.5em;
|
||||
line-height: inherit;
|
||||
white-space: normal; // 1
|
||||
}
|
||||
|
||||
progress {
|
||||
vertical-align: baseline; // Add the correct vertical alignment in Chrome, Firefox, and Opera.
|
||||
}
|
||||
|
||||
// Correct the cursor style of incement and decement buttons in Chrome.
|
||||
[type='number']::-webkit-inner-spin-button,
|
||||
[type='number']::-webkit-outer-spin-button {
|
||||
height: auto;
|
||||
}
|
||||
|
||||
[type='search'] {
|
||||
// This overrides the extra rounded corners on search inputs in iOS so that our
|
||||
// `.form-control` class can properly style them. Note that this cannot simply
|
||||
// be added to `.form-control` as it's not specific enough. For details, see
|
||||
// https://github.com/twbs/bootstrap/issues/11586.
|
||||
outline-offset: -2px; // 2. Correct the outline style in Safari.
|
||||
-webkit-appearance: none;
|
||||
}
|
||||
|
||||
//
|
||||
// remove the inner padding and cancel buttons in Chrome and Safari on macOS.
|
||||
//
|
||||
|
||||
[type='search']::-webkit-search-cancel-button,
|
||||
[type='search']::-webkit-search-decoration {
|
||||
-webkit-appearance: none;
|
||||
}
|
||||
|
||||
//
|
||||
// 1. Correct the inability to style clickable types in iOS and Safari.
|
||||
// 2. Change font properties to `inherit` in Safari.
|
||||
//
|
||||
|
||||
::-webkit-file-upload-button {
|
||||
font: inherit; // 2
|
||||
-webkit-appearance: button; // 1
|
||||
}
|
||||
|
||||
//
|
||||
// Correct element displays
|
||||
//
|
||||
|
||||
output {
|
||||
display: inline-block;
|
||||
}
|
||||
|
||||
summary {
|
||||
display: list-item; // Add the correct display in all browsers
|
||||
}
|
||||
|
||||
template {
|
||||
display: none; // Add the correct display in IE
|
||||
}
|
||||
|
||||
// Always hide an element with the `hidden` HTML attribute (from PureCSS).
|
||||
// Needed for proper display in IE 10-.
|
||||
[hidden] {
|
||||
display: none !important;
|
||||
}
|
||||
|
||||
mark {
|
||||
padding: 0.2em;
|
||||
background-color: @yellow-1;
|
||||
}
|
||||
|
||||
::selection {
|
||||
color: @text-color-inverse;
|
||||
background: @text-selection-bg;
|
||||
}
|
||||
|
||||
// Utility classes
|
||||
.clearfix {
|
||||
.clearfix();
|
||||
}
|
||||
|
501
components/style/core/global.less
Normal file
501
components/style/core/global.less
Normal file
@ -0,0 +1,501 @@
|
||||
/* stylelint-disable at-rule-no-unknown */
|
||||
|
||||
// Reboot
|
||||
//
|
||||
// Normalization of HTML elements, manually forked from Normalize.css to remove
|
||||
// styles targeting irrelevant browsers while applying new styles.
|
||||
//
|
||||
// Normalize is licensed MIT. https://github.com/necolas/normalize.css
|
||||
|
||||
// HTML & Body reset
|
||||
@{html-selector},
|
||||
body {
|
||||
.square(100%);
|
||||
}
|
||||
|
||||
// remove the clear button of a text input control in IE10+
|
||||
input::-ms-clear,
|
||||
input::-ms-reveal {
|
||||
display: none;
|
||||
}
|
||||
|
||||
// Document
|
||||
//
|
||||
// 1. Change from `box-sizing: content-box` so that `width` is not affected by `padding` or `border`.
|
||||
// 2. Change the default font family in all browsers.
|
||||
// 3. Correct the line height in all browsers.
|
||||
// 4. Prevent adjustments of font size after orientation changes in IE on Windows Phone and in iOS.
|
||||
// 5. Setting @viewport causes scrollbars to overlap content in IE11 and Edge, so
|
||||
// we force a non-overlapping, non-auto-hiding scrollbar to counteract.
|
||||
// 6. Change the default tap highlight to be completely transparent in iOS.
|
||||
|
||||
*,
|
||||
*::before,
|
||||
*::after {
|
||||
box-sizing: border-box; // 1
|
||||
}
|
||||
|
||||
@{html-selector} {
|
||||
font-family: sans-serif; // 2
|
||||
line-height: 1.15; // 3
|
||||
-webkit-text-size-adjust: 100%; // 4
|
||||
-ms-text-size-adjust: 100%; // 4
|
||||
-ms-overflow-style: scrollbar; // 5
|
||||
-webkit-tap-highlight-color: fade(@black, 0%); // 6
|
||||
}
|
||||
|
||||
// IE10+ doesn't honor `<meta name="viewport">` in some cases.
|
||||
@-ms-viewport {
|
||||
width: device-width;
|
||||
}
|
||||
|
||||
// Body
|
||||
//
|
||||
// 1. remove the margin in all browsers.
|
||||
// 2. As a best practice, apply a default `body-background`.
|
||||
|
||||
body {
|
||||
margin: 0; // 1
|
||||
color: @text-color;
|
||||
font-size: @font-size-base;
|
||||
font-family: @font-family;
|
||||
font-variant: @font-variant-base;
|
||||
line-height: @line-height-base;
|
||||
background-color: @body-background; // 2
|
||||
font-feature-settings: @font-feature-settings-base;
|
||||
}
|
||||
|
||||
// Suppress the focus outline on elements that cannot be accessed via keyboard.
|
||||
// This prevents an unwanted focus outline from appearing around elements that
|
||||
// might still respond to pointer events.
|
||||
//
|
||||
// Credit: https://github.com/suitcss/base
|
||||
[tabindex='-1']:focus {
|
||||
outline: none !important;
|
||||
}
|
||||
|
||||
// Content grouping
|
||||
//
|
||||
// 1. Add the correct box sizing in Firefox.
|
||||
// 2. Show the overflow in Edge and IE.
|
||||
|
||||
hr {
|
||||
box-sizing: content-box; // 1
|
||||
height: 0; // 1
|
||||
overflow: visible; // 2
|
||||
}
|
||||
|
||||
//
|
||||
// Typography
|
||||
//
|
||||
|
||||
// remove top margins from headings
|
||||
//
|
||||
// By default, `<h1>`-`<h6>` all receive top and bottom margins. We nuke the top
|
||||
// margin for easier control within type scales as it avoids margin collapsing.
|
||||
h1,
|
||||
h2,
|
||||
h3,
|
||||
h4,
|
||||
h5,
|
||||
h6 {
|
||||
margin-top: 0;
|
||||
margin-bottom: 0.5em;
|
||||
color: @heading-color;
|
||||
font-weight: 500;
|
||||
}
|
||||
|
||||
// Reset margins on paragraphs
|
||||
//
|
||||
// Similarly, the top margin on `<p>`s get reset. However, we also reset the
|
||||
// bottom margin to use `em` units instead of `em`.
|
||||
p {
|
||||
margin-top: 0;
|
||||
margin-bottom: 1em;
|
||||
}
|
||||
|
||||
// Abbreviations
|
||||
//
|
||||
// 1. remove the bottom border in Firefox 39-.
|
||||
// 2. Add the correct text decoration in Chrome, Edge, IE, Opera, and Safari.
|
||||
// 3. Add explicit cursor to indicate changed behavior.
|
||||
// 4. Duplicate behavior to the data-* attribute for our tooltip plugin
|
||||
|
||||
abbr[title],
|
||||
abbr[data-original-title] {
|
||||
// 4
|
||||
text-decoration: underline; // 2
|
||||
text-decoration: underline dotted; // 2
|
||||
border-bottom: 0; // 1
|
||||
cursor: help; // 3
|
||||
}
|
||||
|
||||
address {
|
||||
margin-bottom: 1em;
|
||||
font-style: normal;
|
||||
line-height: inherit;
|
||||
}
|
||||
|
||||
input[type='text'],
|
||||
input[type='password'],
|
||||
input[type='number'],
|
||||
textarea {
|
||||
-webkit-appearance: none;
|
||||
}
|
||||
|
||||
ol,
|
||||
ul,
|
||||
dl {
|
||||
margin-top: 0;
|
||||
margin-bottom: 1em;
|
||||
}
|
||||
|
||||
ol ol,
|
||||
ul ul,
|
||||
ol ul,
|
||||
ul ol {
|
||||
margin-bottom: 0;
|
||||
}
|
||||
|
||||
dt {
|
||||
font-weight: 500;
|
||||
}
|
||||
|
||||
dd {
|
||||
margin-bottom: 0.5em;
|
||||
margin-left: 0; // Undo browser default
|
||||
}
|
||||
|
||||
blockquote {
|
||||
margin: 0 0 1em;
|
||||
}
|
||||
|
||||
dfn {
|
||||
font-style: italic; // Add the correct font style in Android 4.3-
|
||||
}
|
||||
|
||||
b,
|
||||
strong {
|
||||
font-weight: bolder; // Add the correct font weight in Chrome, Edge, and Safari
|
||||
}
|
||||
|
||||
small {
|
||||
font-size: 80%; // Add the correct font size in all browsers
|
||||
}
|
||||
|
||||
//
|
||||
// Prevent `sub` and `sup` elements from affecting the line height in
|
||||
// all browsers.
|
||||
//
|
||||
|
||||
sub,
|
||||
sup {
|
||||
position: relative;
|
||||
font-size: 75%;
|
||||
line-height: 0;
|
||||
vertical-align: baseline;
|
||||
}
|
||||
|
||||
sub {
|
||||
bottom: -0.25em;
|
||||
}
|
||||
sup {
|
||||
top: -0.5em;
|
||||
}
|
||||
|
||||
//
|
||||
// Links
|
||||
//
|
||||
|
||||
a {
|
||||
color: @link-color;
|
||||
text-decoration: @link-decoration;
|
||||
background-color: transparent; // remove the gray background on active links in IE 10.
|
||||
outline: none;
|
||||
cursor: pointer;
|
||||
transition: color 0.3s;
|
||||
-webkit-text-decoration-skip: objects; // remove gaps in links underline in iOS 8+ and Safari 8+.
|
||||
|
||||
&:hover {
|
||||
color: @link-hover-color;
|
||||
}
|
||||
|
||||
&:active {
|
||||
color: @link-active-color;
|
||||
}
|
||||
|
||||
&:active,
|
||||
&:hover {
|
||||
text-decoration: @link-hover-decoration;
|
||||
outline: 0;
|
||||
}
|
||||
|
||||
// https://github.com/ant-design/ant-design/issues/22503
|
||||
&:focus {
|
||||
text-decoration: @link-focus-decoration;
|
||||
outline: @link-focus-outline;
|
||||
}
|
||||
|
||||
&[disabled] {
|
||||
color: @disabled-color;
|
||||
cursor: not-allowed;
|
||||
pointer-events: none;
|
||||
}
|
||||
}
|
||||
|
||||
//
|
||||
// Code
|
||||
//
|
||||
|
||||
pre,
|
||||
code,
|
||||
kbd,
|
||||
samp {
|
||||
font-size: 1em; // Correct the odd `em` font sizing in all browsers.
|
||||
font-family: @code-family;
|
||||
}
|
||||
|
||||
pre {
|
||||
// remove browser default top margin
|
||||
margin-top: 0;
|
||||
// Reset browser default of `1em` to use `em`s
|
||||
margin-bottom: 1em;
|
||||
// Don't allow content to break outside
|
||||
overflow: auto;
|
||||
}
|
||||
|
||||
//
|
||||
// Figures
|
||||
//
|
||||
figure {
|
||||
// Apply a consistent margin strategy (matches our type styles).
|
||||
margin: 0 0 1em;
|
||||
}
|
||||
|
||||
//
|
||||
// Images and content
|
||||
//
|
||||
|
||||
img {
|
||||
vertical-align: middle;
|
||||
border-style: none; // remove the border on images inside links in IE 10-.
|
||||
}
|
||||
|
||||
svg:not(:root) {
|
||||
overflow: hidden; // Hide the overflow in IE
|
||||
}
|
||||
|
||||
// Avoid 300ms click delay on touch devices that support the `touch-action` CSS property.
|
||||
//
|
||||
// In particular, unlike most other browsers, IE11+Edge on Windows 10 on touch devices and IE Mobile 10-11
|
||||
// DON'T remove the click delay when `<meta name="viewport" content="width=device-width">` is present.
|
||||
// However, they DO support emoving the click delay via `touch-action: manipulation`.
|
||||
// See:
|
||||
// * https://getbootstrap.com/docs/4.0/content/reboot/#click-delay-optimization-for-touch
|
||||
// * http://caniuse.com/#feat=css-touch-action
|
||||
// * https://patrickhlauke.github.io/touch/tests/results/#suppressing-300ms-delay
|
||||
|
||||
a,
|
||||
area,
|
||||
button,
|
||||
[role='button'],
|
||||
input:not([type='range']),
|
||||
label,
|
||||
select,
|
||||
summary,
|
||||
textarea {
|
||||
touch-action: manipulation;
|
||||
}
|
||||
|
||||
//
|
||||
// Tables
|
||||
//
|
||||
|
||||
table {
|
||||
border-collapse: collapse; // Prevent double borders
|
||||
}
|
||||
|
||||
caption {
|
||||
padding-top: 0.75em;
|
||||
padding-bottom: 0.3em;
|
||||
color: @text-color-secondary;
|
||||
text-align: left;
|
||||
caption-side: bottom;
|
||||
}
|
||||
|
||||
th {
|
||||
// Matches default `<td>` alignment by inheriting from the `<body>`, or the
|
||||
// closest parent with a set `text-align`.
|
||||
text-align: inherit;
|
||||
}
|
||||
|
||||
//
|
||||
// Forms
|
||||
//
|
||||
|
||||
input,
|
||||
button,
|
||||
select,
|
||||
optgroup,
|
||||
textarea {
|
||||
margin: 0; // remove the margin in Firefox and Safari
|
||||
color: inherit;
|
||||
font-size: inherit;
|
||||
font-family: inherit;
|
||||
line-height: inherit;
|
||||
}
|
||||
|
||||
button,
|
||||
input {
|
||||
overflow: visible; // Show the overflow in Edge
|
||||
}
|
||||
|
||||
button,
|
||||
select {
|
||||
text-transform: none; // remove the inheritance of text transform in Firefox
|
||||
}
|
||||
|
||||
// 1. Prevent a WebKit bug where (2) destroys native `audio` and `video`
|
||||
// controls in Android 4.
|
||||
// 2. Correct the inability to style clickable types in iOS and Safari.
|
||||
button,
|
||||
@{html-selector} [type="button"], /* 1 */
|
||||
[type="reset"],
|
||||
[type="submit"] {
|
||||
-webkit-appearance: button; // 2
|
||||
}
|
||||
|
||||
// remove inner border and padding from Firefox, but don't restore the outline like Normalize.
|
||||
button::-moz-focus-inner,
|
||||
[type='button']::-moz-focus-inner,
|
||||
[type='reset']::-moz-focus-inner,
|
||||
[type='submit']::-moz-focus-inner {
|
||||
padding: 0;
|
||||
border-style: none;
|
||||
}
|
||||
|
||||
input[type='radio'],
|
||||
input[type='checkbox'] {
|
||||
box-sizing: border-box; // 1. Add the correct box sizing in IE 10-
|
||||
padding: 0; // 2. remove the padding in IE 10-
|
||||
}
|
||||
|
||||
input[type='date'],
|
||||
input[type='time'],
|
||||
input[type='datetime-local'],
|
||||
input[type='month'] {
|
||||
// remove the default appearance of temporal inputs to avoid a Mobile Safari
|
||||
// bug where setting a custom line-height prevents text from being vertically
|
||||
// centered within the input.
|
||||
// See https://bugs.webkit.org/show_bug.cgi?id=139848
|
||||
// and https://github.com/twbs/bootstrap/issues/11266
|
||||
-webkit-appearance: listbox;
|
||||
}
|
||||
|
||||
textarea {
|
||||
overflow: auto; // remove the default vertical scrollbar in IE.
|
||||
// Textareas should really only resize vertically so they don't break their (horizontal) containers.
|
||||
resize: vertical;
|
||||
}
|
||||
|
||||
fieldset {
|
||||
// Browsers set a default `min-width: min-content;` on fieldsets,
|
||||
// unlike e.g. `<div>`s, which have `min-width: 0;` by default.
|
||||
// So we reset that to ensure fieldsets behave more like a standard block element.
|
||||
// See https://github.com/twbs/bootstrap/issues/12359
|
||||
// and https://html.spec.whatwg.org/multipage/#the-fieldset-and-legend-elements
|
||||
min-width: 0;
|
||||
margin: 0;
|
||||
// Reset the default outline behavior of fieldsets so they don't affect page layout.
|
||||
padding: 0;
|
||||
border: 0;
|
||||
}
|
||||
|
||||
// 1. Correct the text wrapping in Edge and IE.
|
||||
// 2. Correct the color inheritance from `fieldset` elements in IE.
|
||||
legend {
|
||||
display: block;
|
||||
width: 100%;
|
||||
max-width: 100%; // 1
|
||||
margin-bottom: 0.5em;
|
||||
padding: 0;
|
||||
color: inherit; // 2
|
||||
font-size: 1.5em;
|
||||
line-height: inherit;
|
||||
white-space: normal; // 1
|
||||
}
|
||||
|
||||
progress {
|
||||
vertical-align: baseline; // Add the correct vertical alignment in Chrome, Firefox, and Opera.
|
||||
}
|
||||
|
||||
// Correct the cursor style of incement and decement buttons in Chrome.
|
||||
[type='number']::-webkit-inner-spin-button,
|
||||
[type='number']::-webkit-outer-spin-button {
|
||||
height: auto;
|
||||
}
|
||||
|
||||
[type='search'] {
|
||||
// This overrides the extra rounded corners on search inputs in iOS so that our
|
||||
// `.form-control` class can properly style them. Note that this cannot simply
|
||||
// be added to `.form-control` as it's not specific enough. For details, see
|
||||
// https://github.com/twbs/bootstrap/issues/11586.
|
||||
outline-offset: -2px; // 2. Correct the outline style in Safari.
|
||||
-webkit-appearance: none;
|
||||
}
|
||||
|
||||
//
|
||||
// remove the inner padding and cancel buttons in Chrome and Safari on macOS.
|
||||
//
|
||||
|
||||
[type='search']::-webkit-search-cancel-button,
|
||||
[type='search']::-webkit-search-decoration {
|
||||
-webkit-appearance: none;
|
||||
}
|
||||
|
||||
//
|
||||
// 1. Correct the inability to style clickable types in iOS and Safari.
|
||||
// 2. Change font properties to `inherit` in Safari.
|
||||
//
|
||||
|
||||
::-webkit-file-upload-button {
|
||||
font: inherit; // 2
|
||||
-webkit-appearance: button; // 1
|
||||
}
|
||||
|
||||
//
|
||||
// Correct element displays
|
||||
//
|
||||
|
||||
output {
|
||||
display: inline-block;
|
||||
}
|
||||
|
||||
summary {
|
||||
display: list-item; // Add the correct display in all browsers
|
||||
}
|
||||
|
||||
template {
|
||||
display: none; // Add the correct display in IE
|
||||
}
|
||||
|
||||
// Always hide an element with the `hidden` HTML attribute (from PureCSS).
|
||||
// Needed for proper display in IE 10-.
|
||||
[hidden] {
|
||||
display: none !important;
|
||||
}
|
||||
|
||||
mark {
|
||||
padding: 0.2em;
|
||||
background-color: @yellow-1;
|
||||
}
|
||||
|
||||
::selection {
|
||||
color: @text-color-inverse;
|
||||
background: @text-selection-bg;
|
||||
}
|
||||
|
||||
// Utility classes
|
||||
.clearfix {
|
||||
.clearfix();
|
||||
}
|
@ -1,4 +1,5 @@
|
||||
@import '../mixins/index';
|
||||
@import 'base';
|
||||
@import 'global';
|
||||
@import 'iconfont';
|
||||
@import 'motion';
|
||||
|
@ -221,6 +221,7 @@
|
||||
@btn-default-ghost-border: fade(@white, 25%);
|
||||
|
||||
@btn-link-ghost-color: @text-color;
|
||||
@btn-text-hover-bg: rgba(255, 255, 255, 0.03);
|
||||
|
||||
// Checkbox
|
||||
// ---
|
||||
|
@ -219,6 +219,8 @@
|
||||
@btn-group-border: @primary-5;
|
||||
|
||||
@btn-link-ghost-color: @component-background;
|
||||
@btn-link-hover-bg: transparent;
|
||||
@btn-text-hover-bg: rgba(0, 0, 0, 0.018);
|
||||
|
||||
// Checkbox
|
||||
@checkbox-size: 16px;
|
||||
@ -235,6 +237,9 @@
|
||||
@descriptions-middle-padding: @padding-sm @padding-lg;
|
||||
@descriptions-small-padding: @padding-xs @padding-md;
|
||||
@descriptions-item-padding-bottom: @padding-md;
|
||||
@descriptions-item-trailing-colon: true;
|
||||
@descriptions-item-label-colon-margin-right: 8px;
|
||||
@descriptions-item-label-colon-margin-left: 2px;
|
||||
|
||||
// Dropdown
|
||||
@dropdown-selected-color: @primary-color;
|
||||
@ -395,6 +400,7 @@
|
||||
@input-disabled-bg: @disabled-bg;
|
||||
@input-outline-offset: 0 0;
|
||||
@input-icon-hover-color: fade(@black, 85%);
|
||||
@input-disabled-color: @disabled-color;
|
||||
|
||||
// Mentions
|
||||
// ---
|
||||
@ -512,7 +518,9 @@
|
||||
@menu-popup-bg: @component-background;
|
||||
@menu-item-color: @text-color;
|
||||
@menu-highlight-color: @primary-color;
|
||||
@menu-highlight-danger-color: @error-color;
|
||||
@menu-item-active-bg: @primary-1;
|
||||
@menu-item-active-danger-bg: @red-1;
|
||||
@menu-item-active-border-width: 3px;
|
||||
@menu-item-group-title-color: @text-color-secondary;
|
||||
@menu-item-vertical-margin: 4px;
|
||||
@ -527,11 +535,13 @@
|
||||
|
||||
// dark theme
|
||||
@menu-dark-color: @text-color-secondary-dark;
|
||||
@menu-dark-danger-color: @error-color;
|
||||
@menu-dark-bg: @layout-header-background;
|
||||
@menu-dark-arrow-color: #fff;
|
||||
@menu-dark-submenu-bg: #000c17;
|
||||
@menu-dark-highlight-color: #fff;
|
||||
@menu-dark-item-active-bg: @primary-color;
|
||||
@menu-dark-item-active-danger-bg: @error-color;
|
||||
@menu-dark-selected-item-icon-color: @white;
|
||||
@menu-dark-selected-item-text-color: @white;
|
||||
@menu-dark-item-hover-bg: transparent;
|
||||
|
@ -76,12 +76,7 @@ describe('Table', () => {
|
||||
};
|
||||
const wrapper = mount(<Table loading={loading} />);
|
||||
expect(wrapper.find('.ant-spin')).toHaveLength(0);
|
||||
expect(
|
||||
wrapper
|
||||
.find('.ant-table-placeholder')
|
||||
.hostNodes()
|
||||
.text(),
|
||||
).not.toEqual('');
|
||||
expect(wrapper.find('.ant-table-placeholder').hostNodes().text()).not.toEqual('');
|
||||
|
||||
loading.spinning = true;
|
||||
wrapper.setProps({ loading });
|
||||
@ -179,4 +174,51 @@ describe('Table', () => {
|
||||
);
|
||||
wrapper.simulate('touchmove');
|
||||
});
|
||||
|
||||
it('renders ellipsis by showTitle option', () => {
|
||||
const data = [
|
||||
{
|
||||
id: '1',
|
||||
age: 32,
|
||||
},
|
||||
{
|
||||
id: '2',
|
||||
age: 42,
|
||||
},
|
||||
];
|
||||
const columns = [
|
||||
{ title: 'id', dataKey: 'id', ellipsis: { showTitle: false } },
|
||||
{ title: 'age', dataKey: 'age', ellipsis: { showTitle: false } },
|
||||
];
|
||||
const wrapper = mount(<Table columns={columns} dataSource={data} />);
|
||||
wrapper.find('td').forEach(td => {
|
||||
expect(td.hasClass('ant-table-cell-ellipsis')).toBeTruthy();
|
||||
});
|
||||
});
|
||||
|
||||
it('not renders ellipsis origin html title', () => {
|
||||
const data = [
|
||||
{
|
||||
id: '1',
|
||||
age: 32,
|
||||
},
|
||||
{
|
||||
id: '2',
|
||||
age: 42,
|
||||
},
|
||||
];
|
||||
const columns = [
|
||||
{ title: 'id', dataKey: 'id', ellipsis: { showTitle: true } },
|
||||
{ title: 'age', dataKey: 'age', ellipsis: { showTitle: true } },
|
||||
];
|
||||
const wrapper = mount(<Table columns={columns} dataSource={data} />);
|
||||
|
||||
wrapper.find('.ant-table-thead th').forEach(td => {
|
||||
expect(td.getDOMNode().attributes.getNamedItem('title')).toBeTruthy();
|
||||
});
|
||||
|
||||
wrapper.find('.ant-table-tbody td').forEach(td => {
|
||||
expect(td.getDOMNode().attributes.getNamedItem('title')).toBeFalsy();
|
||||
});
|
||||
});
|
||||
});
|
||||
|
@ -233,7 +233,11 @@ exports[`Table.filter renders custom filter icon with right Tooltip title 1`] =
|
||||
>
|
||||
<div
|
||||
class="ant-tooltip-arrow"
|
||||
/>
|
||||
>
|
||||
<span
|
||||
class="ant-tooltip-arrow-content"
|
||||
/>
|
||||
</div>
|
||||
<div
|
||||
class="ant-tooltip-inner"
|
||||
role="tooltip"
|
||||
|
@ -4674,6 +4674,300 @@ exports[`renders ./components/table/demo/ellipsis.md correctly 1`] = `
|
||||
</div>
|
||||
`;
|
||||
|
||||
exports[`renders ./components/table/demo/ellipsis-custom-tooltip.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:fixed"
|
||||
>
|
||||
<colgroup>
|
||||
<col
|
||||
style="width:150px;min-width:150px"
|
||||
/>
|
||||
<col
|
||||
style="width:80px;min-width:80px"
|
||||
/>
|
||||
</colgroup>
|
||||
<thead
|
||||
class="ant-table-thead"
|
||||
>
|
||||
<tr>
|
||||
<th
|
||||
class="ant-table-cell"
|
||||
>
|
||||
Name
|
||||
</th>
|
||||
<th
|
||||
class="ant-table-cell"
|
||||
>
|
||||
Age
|
||||
</th>
|
||||
<th
|
||||
class="ant-table-cell ant-table-cell-ellipsis"
|
||||
title="Address"
|
||||
>
|
||||
Address
|
||||
</th>
|
||||
<th
|
||||
class="ant-table-cell ant-table-cell-ellipsis"
|
||||
title="Long Column Long Column Long Column"
|
||||
>
|
||||
Long Column Long Column Long Column
|
||||
</th>
|
||||
<th
|
||||
class="ant-table-cell ant-table-cell-ellipsis"
|
||||
title="Long Column Long Column"
|
||||
>
|
||||
Long Column Long Column
|
||||
</th>
|
||||
<th
|
||||
class="ant-table-cell ant-table-cell-ellipsis"
|
||||
title="Long Column"
|
||||
>
|
||||
Long Column
|
||||
</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>
|
||||
<td
|
||||
class="ant-table-cell"
|
||||
>
|
||||
32
|
||||
</td>
|
||||
<td
|
||||
class="ant-table-cell ant-table-cell-ellipsis"
|
||||
>
|
||||
<span>
|
||||
New York No. 1 Lake Park, New York No. 1 Lake Park
|
||||
</span>
|
||||
</td>
|
||||
<td
|
||||
class="ant-table-cell ant-table-cell-ellipsis"
|
||||
>
|
||||
<span>
|
||||
New York No. 1 Lake Park, New York No. 1 Lake Park
|
||||
</span>
|
||||
</td>
|
||||
<td
|
||||
class="ant-table-cell ant-table-cell-ellipsis"
|
||||
>
|
||||
<span>
|
||||
New York No. 1 Lake Park, New York No. 1 Lake Park
|
||||
</span>
|
||||
</td>
|
||||
<td
|
||||
class="ant-table-cell ant-table-cell-ellipsis"
|
||||
>
|
||||
<span>
|
||||
New York No. 1 Lake Park, New York No. 1 Lake Park
|
||||
</span>
|
||||
</td>
|
||||
</tr>
|
||||
<tr
|
||||
class="ant-table-row ant-table-row-level-0"
|
||||
data-row-key="2"
|
||||
>
|
||||
<td
|
||||
class="ant-table-cell"
|
||||
>
|
||||
<a>
|
||||
Jim Green
|
||||
</a>
|
||||
</td>
|
||||
<td
|
||||
class="ant-table-cell"
|
||||
>
|
||||
42
|
||||
</td>
|
||||
<td
|
||||
class="ant-table-cell ant-table-cell-ellipsis"
|
||||
>
|
||||
<span>
|
||||
London No. 2 Lake Park, London No. 2 Lake Park
|
||||
</span>
|
||||
</td>
|
||||
<td
|
||||
class="ant-table-cell ant-table-cell-ellipsis"
|
||||
>
|
||||
<span>
|
||||
London No. 2 Lake Park, London No. 2 Lake Park
|
||||
</span>
|
||||
</td>
|
||||
<td
|
||||
class="ant-table-cell ant-table-cell-ellipsis"
|
||||
>
|
||||
<span>
|
||||
London No. 2 Lake Park, London No. 2 Lake Park
|
||||
</span>
|
||||
</td>
|
||||
<td
|
||||
class="ant-table-cell ant-table-cell-ellipsis"
|
||||
>
|
||||
<span>
|
||||
London No. 2 Lake Park, London No. 2 Lake Park
|
||||
</span>
|
||||
</td>
|
||||
</tr>
|
||||
<tr
|
||||
class="ant-table-row ant-table-row-level-0"
|
||||
data-row-key="3"
|
||||
>
|
||||
<td
|
||||
class="ant-table-cell"
|
||||
>
|
||||
<a>
|
||||
Joe Black
|
||||
</a>
|
||||
</td>
|
||||
<td
|
||||
class="ant-table-cell"
|
||||
>
|
||||
32
|
||||
</td>
|
||||
<td
|
||||
class="ant-table-cell ant-table-cell-ellipsis"
|
||||
>
|
||||
<span>
|
||||
Sidney No. 1 Lake Park, Sidney No. 1 Lake Park
|
||||
</span>
|
||||
</td>
|
||||
<td
|
||||
class="ant-table-cell ant-table-cell-ellipsis"
|
||||
>
|
||||
<span>
|
||||
Sidney No. 1 Lake Park, Sidney No. 1 Lake Park
|
||||
</span>
|
||||
</td>
|
||||
<td
|
||||
class="ant-table-cell ant-table-cell-ellipsis"
|
||||
>
|
||||
<span>
|
||||
Sidney No. 1 Lake Park, Sidney No. 1 Lake Park
|
||||
</span>
|
||||
</td>
|
||||
<td
|
||||
class="ant-table-cell ant-table-cell-ellipsis"
|
||||
>
|
||||
<span>
|
||||
Sidney No. 1 Lake Park, Sidney No. 1 Lake Park
|
||||
</span>
|
||||
</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/expand.md correctly 1`] = `
|
||||
<div
|
||||
class="ant-table-wrapper"
|
||||
|
109
components/table/demo/ellipsis-custom-tooltip.md
Normal file
109
components/table/demo/ellipsis-custom-tooltip.md
Normal file
@ -0,0 +1,109 @@
|
||||
---
|
||||
order: 29
|
||||
title:
|
||||
en-US: ellipsis column custom tooltip
|
||||
zh-CN: 自定义单元格省略提示
|
||||
---
|
||||
|
||||
## zh-CN
|
||||
|
||||
设置 `column.ellipsis.showTitle` 关闭单元格内容自动省略后默认的 `title` 提示, 使用 `Tooltip` 替代。
|
||||
|
||||
## en-US
|
||||
|
||||
Ellipsis cell content via setting `column.ellipsis.showTitle`, use `Tooltip` instead of the html title attribute.
|
||||
|
||||
```jsx
|
||||
import { Table, Tooltip } from 'antd';
|
||||
|
||||
const columns = [
|
||||
{
|
||||
title: 'Name',
|
||||
dataIndex: 'name',
|
||||
key: 'name',
|
||||
render: text => <a>{text}</a>,
|
||||
width: 150,
|
||||
},
|
||||
{
|
||||
title: 'Age',
|
||||
dataIndex: 'age',
|
||||
key: 'age',
|
||||
width: 80,
|
||||
},
|
||||
{
|
||||
title: 'Address',
|
||||
dataIndex: 'address',
|
||||
key: 'address 1',
|
||||
ellipsis: {
|
||||
showTitle: false,
|
||||
},
|
||||
render: address => (
|
||||
<Tooltip placement="topLeft" title={address}>
|
||||
{address}
|
||||
</Tooltip>
|
||||
),
|
||||
},
|
||||
{
|
||||
title: 'Long Column Long Column Long Column',
|
||||
dataIndex: 'address',
|
||||
key: 'address 2',
|
||||
ellipsis: {
|
||||
showTitle: false,
|
||||
},
|
||||
render: address => (
|
||||
<Tooltip placement="topLeft" title={address}>
|
||||
{address}
|
||||
</Tooltip>
|
||||
),
|
||||
},
|
||||
{
|
||||
title: 'Long Column Long Column',
|
||||
dataIndex: 'address',
|
||||
key: 'address 3',
|
||||
ellipsis: {
|
||||
showTitle: false,
|
||||
},
|
||||
render: address => (
|
||||
<Tooltip placement="topLeft" title={address}>
|
||||
{address}
|
||||
</Tooltip>
|
||||
),
|
||||
},
|
||||
{
|
||||
title: 'Long Column',
|
||||
dataIndex: 'address',
|
||||
key: 'address 4',
|
||||
ellipsis: {
|
||||
showTitle: false,
|
||||
},
|
||||
render: address => (
|
||||
<Tooltip placement="topLeft" title={address}>
|
||||
{address}
|
||||
</Tooltip>
|
||||
),
|
||||
},
|
||||
];
|
||||
|
||||
const data = [
|
||||
{
|
||||
key: '1',
|
||||
name: 'John Brown',
|
||||
age: 32,
|
||||
address: 'New York No. 1 Lake Park, New York No. 1 Lake Park',
|
||||
},
|
||||
{
|
||||
key: '2',
|
||||
name: 'Jim Green',
|
||||
age: 42,
|
||||
address: 'London No. 2 Lake Park, London No. 2 Lake Park',
|
||||
},
|
||||
{
|
||||
key: '3',
|
||||
name: 'Joe Black',
|
||||
age: 32,
|
||||
address: 'Sidney No. 1 Lake Park, Sidney No. 1 Lake Park',
|
||||
},
|
||||
];
|
||||
|
||||
ReactDOM.render(<Table columns={columns} dataSource={data} />, mountNode);
|
||||
```
|
@ -111,36 +111,37 @@ Same as `onRow` `onHeaderRow` `onCell` `onHeaderCell`
|
||||
|
||||
One of the Table `columns` prop for describing the table's columns, Column has the same API.
|
||||
|
||||
| Property | Description | Type | Default |
|
||||
| --- | --- | --- | --- |
|
||||
| align | specify which way that column is aligned | `left` \| `right` \| `center` | `left` |
|
||||
| ellipsis | ellipsis cell content, not working with sorter and filters for now.<br />tableLayout would be `fixed` when `ellipsis` is true. | boolean | false |
|
||||
| className | className of this column | string | - |
|
||||
| colSpan | Span of this column's title | number | - |
|
||||
| dataIndex | Display field of the data record, support nest path by string array | string \| string\[] | - |
|
||||
| defaultFilteredValue | Default filtered values | string\[] | - | |
|
||||
| defaultSortOrder | Default order of sorted values | `ascend` \| `descend` | - |
|
||||
| filterDropdown | Customized filter overlay | React.ReactNode \| (props: [FilterDropdownProps](https://git.io/fjP5h)) => React.ReactNode | - |
|
||||
| filterDropdownVisible | Whether `filterDropdown` is visible | boolean | - |
|
||||
| filtered | Whether the `dataSource` is filtered | boolean | `false` |
|
||||
| filteredValue | Controlled filtered value, filter icon will highlight | string\[] | - |
|
||||
| filterIcon | Customized filter icon | ReactNode\|(filtered: boolean) => ReactNode | `false` |
|
||||
| filterMultiple | Whether multiple filters can be selected | boolean | `true` |
|
||||
| filters | Filter menu config | object\[] | - |
|
||||
| fixed | (IE not support) Set column to be fixed: `true`(same as left) `'left'` `'right'` | boolean\|string | `false` |
|
||||
| key | Unique key of this column, you can ignore this prop if you've set a unique `dataIndex` | string | - |
|
||||
| render | Renderer of the table cell. The return value should be a ReactNode, or an object for [colSpan/rowSpan config](#components-table-demo-colspan-rowspan) | Function(text, record, index) {} | - |
|
||||
| responsive | The list of breakpoints at which to display this column. Always visible if not set. | [Breakpoint](https://github.com/ant-design/ant-design/blob/015109b42b85c63146371b4e32b883cf97b088e8/components/_util/responsiveObserve.ts#L1)\[] | - |
|
||||
| sorter | Sort function for local sort, see [Array.sort](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Array/sort)'s compareFunction. If you need sort buttons only, set to `true` | Function\|boolean | - |
|
||||
| sortOrder | Order of sorted values: `'ascend'` `'descend'` `false` | boolean\|string | - |
|
||||
| sortDirections | supported sort way, override `sortDirections` in `Table`, could be `'ascend'`, `'descend'` | Array | `['ascend', 'descend']` |
|
||||
| title | Title of this column | ReactNode\|({ sortOrder, sortColumn, filters }) => ReactNode | - |
|
||||
| width | Width of this column ([width not working?](https://github.com/ant-design/ant-design/issues/13825#issuecomment-449889241)) | string\|number | - |
|
||||
| onCell | Set props on per cell | Function(record, rowIndex) | - |
|
||||
| onFilter | Callback executed when the confirm filter button is clicked | Function | - |
|
||||
| onFilterDropdownVisibleChange | Callback executed when `filterDropdownVisible` is changed | function(visible) {} | - |
|
||||
| onHeaderCell | Set props on per header cell | Function(column) | - |
|
||||
| showSorterTooltip | header show next sorter direction tooltip, override `showSorterTooltip` in table | boolean | `true` |
|
||||
| Property | Description | Type | Default | Version |
|
||||
| --- | --- | --- | --- | --- |
|
||||
| align | specify which way that column is aligned | `left` \| `right` \| `center` | `left` | |
|
||||
| ellipsis | ellipsis cell content, not working with sorter and filters for now.<br />tableLayout would be `fixed` when `ellipsis` is `true` or `{ showTitle?: boolean }`. | boolean \| { showTitle?: boolean } | false | showTitle: 4.3.0 |
|
||||
| className | className of this column | string | - | |
|
||||
| colSpan | Span of this column's title | number | - | |
|
||||
| dataIndex | Display field of the data record, support nest path by string array | string \| string\[] | - | |
|
||||
| defaultFilteredValue | Default filtered values | string\[] | - | | |
|
||||
| defaultSortOrder | Default order of sorted values | `ascend` \| `descend` | - | |
|
||||
| filterDropdown | Customized filter overlay | React.ReactNode \| (props: [FilterDropdownProps](https://git.io/fjP5h)) => React.ReactNode | - | |
|
||||
| filterDropdownVisible | Whether `filterDropdown` is visible | boolean | - | |
|
||||
| filtered | Whether the `dataSource` is filtered | boolean | `false` | |
|
||||
| filteredValue | Controlled filtered value, filter icon will highlight | string\[] | - | |
|
||||
| filterIcon | Customized filter icon | ReactNode\|(filtered: boolean) => ReactNode | `false` | |
|
||||
| filterMultiple | Whether multiple filters can be selected | boolean | `true` | |
|
||||
| filters | Filter menu config | object\[] | - | |
|
||||
| fixed | (IE not support) Set column to be fixed: `true`(same as left) `'left'` `'right'` | boolean\|string | `false` | |
|
||||
| key | Unique key of this column, you can ignore this prop if you've set a unique `dataIndex` | string | - | |
|
||||
| render | Renderer of the table cell. The return value should be a ReactNode, or an object for [colSpan/rowSpan config](#components-table-demo-colspan-rowspan) | Function(text, record, index) {} | - | |
|
||||
| responsive | The list of breakpoints at which to display this column. Always visible if not set. | [Breakpoint](https://github.com/ant-design/ant-design/blob/015109b42b85c63146371b4e32b883cf97b088e8/components/_util/responsiveObserve.ts#L1)\[] | - | 4.2.0 |
|
||||
| shouldCellUpdate | Control cell render logic | (record) => boolean | - | 4.3.0 |
|
||||
| sorter | Sort function for local sort, see [Array.sort](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Array/sort)'s compareFunction. If you need sort buttons only, set to `true` | Function\|boolean | - | |
|
||||
| sortOrder | Order of sorted values: `'ascend'` `'descend'` `false` | boolean\|string | - | |
|
||||
| sortDirections | supported sort way, override `sortDirections` in `Table`, could be `'ascend'`, `'descend'` | Array | `['ascend', 'descend']` | |
|
||||
| title | Title of this column | ReactNode\|({ sortOrder, sortColumn, filters }) => ReactNode | - | |
|
||||
| width | Width of this column ([width not working?](https://github.com/ant-design/ant-design/issues/13825#issuecomment-449889241)) | string\|number | - | |
|
||||
| onCell | Set props on per cell | Function(record, rowIndex) | - | |
|
||||
| onFilter | Callback executed when the confirm filter button is clicked | Function | - | |
|
||||
| onFilterDropdownVisibleChange | Callback executed when `filterDropdownVisible` is changed | function(visible) {} | - | |
|
||||
| onHeaderCell | Set props on per header cell | Function(column) | - | |
|
||||
| showSorterTooltip | header show next sorter direction tooltip, override `showSorterTooltip` in table | boolean | `true` | |
|
||||
|
||||
### ColumnGroup
|
||||
|
||||
@ -293,4 +294,4 @@ In order to improve user experience, Pagination show size changer by default whe
|
||||
|
||||
### Why Table fully render when state change?
|
||||
|
||||
Table can not tell what state used in `columns.render`, so it always need fully render to avoid sync issue. But you can use `components` to customize component for conditional render. ref [#23763](https://github.com/ant-design/ant-design/issues/23763).
|
||||
Table can not tell what state used in `columns.render`, so it always need fully render to avoid sync issue. You can use `column.shouldCellUpdate` to control render.
|
||||
|
@ -116,36 +116,37 @@ const columns = [
|
||||
|
||||
列描述数据对象,是 columns 中的一项,Column 使用相同的 API。
|
||||
|
||||
| 参数 | 说明 | 类型 | 默认值 |
|
||||
| --- | --- | --- | --- |
|
||||
| align | 设置列的对齐方式 | `left` \| `right` \| `center` | `left` |
|
||||
| ellipsis | 超过宽度将自动省略,暂不支持和排序筛选一起使用。<br />设置为 `true` 时,表格布局将变成 `tableLayout="fixed"`。 | boolean | false |
|
||||
| className | 列样式类名 | string | - |
|
||||
| colSpan | 表头列合并,设置为 0 时,不渲染 | number | - |
|
||||
| dataIndex | 列数据在数据项中对应的路径,支持通过数组查询嵌套路径 | string \| string\[] | - |
|
||||
| defaultFilteredValue | 默认筛选值 | string\[] | - |
|
||||
| defaultSortOrder | 默认排序顺序 | `ascend` \| `descend` | - |
|
||||
| filterDropdown | 可以自定义筛选菜单,此函数只负责渲染图层,需要自行编写各种交互 | React.ReactNode \| (props: [FilterDropdownProps](https://git.io/fjP5h)) => React.ReactNode | - |
|
||||
| filterDropdownVisible | 用于控制自定义筛选菜单是否可见 | boolean | - |
|
||||
| filtered | 标识数据是否经过过滤,筛选图标会高亮 | boolean | false |
|
||||
| filteredValue | 筛选的受控属性,外界可用此控制列的筛选状态,值为已筛选的 value 数组 | string\[] | - |
|
||||
| filterIcon | 自定义 filter 图标。 | ReactNode\|(filtered: boolean) => ReactNode | false |
|
||||
| filterMultiple | 是否多选 | boolean | true |
|
||||
| filters | 表头的筛选菜单项 | object\[] | - |
|
||||
| fixed | (IE 下无效)列是否固定,可选 `true`(等效于 left) `'left'` `'right'` | boolean\|string | false |
|
||||
| key | React 需要的 key,如果已经设置了唯一的 `dataIndex`,可以忽略这个属性 | string | - |
|
||||
| render | 生成复杂数据的渲染函数,参数分别为当前行的值,当前行数据,行索引,@return 里面可以设置表格[行/列合并](#components-table-demo-colspan-rowspan) | Function(text, record, index) {} | - |
|
||||
| responsive | 响应式 breakpoint 配置列表。未设置则始终可见。 | [Breakpoint](https://github.com/ant-design/ant-design/blob/015109b42b85c63146371b4e32b883cf97b088e8/components/_util/responsiveObserve.ts#L1)\[] | - |
|
||||
| sorter | 排序函数,本地排序使用一个函数(参考 [Array.sort](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Array/sort) 的 compareFunction),需要服务端排序可设为 true | Function\|boolean | - |
|
||||
| sortOrder | 排序的受控属性,外界可用此控制列的排序,可设置为 `'ascend'` `'descend'` `false` | boolean\|string | - |
|
||||
| sortDirections | 支持的排序方式,覆盖`Table`中`sortDirections`, 取值为 `'ascend'` `'descend'` | Array | `['ascend', 'descend']` |
|
||||
| title | 列头显示文字(函数用法 `3.10.0` 后支持) | ReactNode\|({ sortOrder, sortColumn, filters }) => ReactNode | - |
|
||||
| width | 列宽度([指定了也不生效?](https://github.com/ant-design/ant-design/issues/13825#issuecomment-449889241)) | string\|number | - |
|
||||
| onCell | 设置单元格属性 | Function(record, rowIndex) | - |
|
||||
| onFilter | 本地模式下,确定筛选的运行函数 | Function | - |
|
||||
| onFilterDropdownVisibleChange | 自定义筛选菜单可见变化时调用 | function(visible) {} | - |
|
||||
| onHeaderCell | 设置头部单元格属性 | Function(column) | - |
|
||||
| showSorterTooltip | 表头显示下一次排序的 tooltip 提示, 覆盖 table 中`showSorterTooltip` | boolean | `true` |
|
||||
| 参数 | 说明 | 类型 | 默认值 | 版本 |
|
||||
| --- | --- | --- | --- | --- |
|
||||
| align | 设置列的对齐方式 | `left` \| `right` \| `center` | `left` | |
|
||||
| ellipsis | 超过宽度将自动省略,暂不支持和排序筛选一起使用。<br />设置为 `true` 或 `{ showTitle?: boolean }` 时,表格布局将变成 `tableLayout="fixed"`。 | boolean \| { showTitle?: boolean } | false | showTitle: 4.3.0 |
|
||||
| className | 列样式类名 | string | - | |
|
||||
| colSpan | 表头列合并,设置为 0 时,不渲染 | number | - | |
|
||||
| dataIndex | 列数据在数据项中对应的路径,支持通过数组查询嵌套路径 | string \| string\[] | - | |
|
||||
| defaultFilteredValue | 默认筛选值 | string\[] | - | |
|
||||
| defaultSortOrder | 默认排序顺序 | `ascend` \| `descend` | - | |
|
||||
| filterDropdown | 可以自定义筛选菜单,此函数只负责渲染图层,需要自行编写各种交互 | React.ReactNode \| (props: [FilterDropdownProps](https://git.io/fjP5h)) => React.ReactNode | - | |
|
||||
| filterDropdownVisible | 用于控制自定义筛选菜单是否可见 | boolean | - | |
|
||||
| filtered | 标识数据是否经过过滤,筛选图标会高亮 | boolean | false | |
|
||||
| filteredValue | 筛选的受控属性,外界可用此控制列的筛选状态,值为已筛选的 value 数组 | string\[] | - | |
|
||||
| filterIcon | 自定义 filter 图标。 | ReactNode\|(filtered: boolean) => ReactNode | false | |
|
||||
| filterMultiple | 是否多选 | boolean | true | |
|
||||
| filters | 表头的筛选菜单项 | object\[] | - | |
|
||||
| fixed | (IE 下无效)列是否固定,可选 `true`(等效于 left) `'left'` `'right'` | boolean\|string | false | |
|
||||
| key | React 需要的 key,如果已经设置了唯一的 `dataIndex`,可以忽略这个属性 | string | - | |
|
||||
| render | 生成复杂数据的渲染函数,参数分别为当前行的值,当前行数据,行索引,@return 里面可以设置表格[行/列合并](#components-table-demo-colspan-rowspan) | Function(text, record, index) {} | - | |
|
||||
| responsive | 响应式 breakpoint 配置列表。未设置则始终可见。 | [Breakpoint](https://github.com/ant-design/ant-design/blob/015109b42b85c63146371b4e32b883cf97b088e8/components/_util/responsiveObserve.ts#L1)\[] | - | 4.2.0 |
|
||||
| shouldCellUpdate | 自定义单元格渲染时机 | (record) => boolean | - | 4.3.0 |
|
||||
| sorter | 排序函数,本地排序使用一个函数(参考 [Array.sort](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Array/sort) 的 compareFunction),需要服务端排序可设为 true | Function\|boolean | - | |
|
||||
| sortOrder | 排序的受控属性,外界可用此控制列的排序,可设置为 `'ascend'` `'descend'` `false` | boolean\|string | - | |
|
||||
| sortDirections | 支持的排序方式,覆盖`Table`中`sortDirections`, 取值为 `'ascend'` `'descend'` | Array | `['ascend', 'descend']` | |
|
||||
| title | 列头显示文字(函数用法 `3.10.0` 后支持) | ReactNode\|({ sortOrder, sortColumn, filters }) => ReactNode | - | |
|
||||
| width | 列宽度([指定了也不生效?](https://github.com/ant-design/ant-design/issues/13825#issuecomment-449889241)) | string\|number | - | |
|
||||
| onCell | 设置单元格属性 | Function(record, rowIndex) | - | |
|
||||
| onFilter | 本地模式下,确定筛选的运行函数 | Function | - | |
|
||||
| onFilterDropdownVisibleChange | 自定义筛选菜单可见变化时调用 | function(visible) {} | - | |
|
||||
| onHeaderCell | 设置头部单元格属性 | Function(column) | - | |
|
||||
| showSorterTooltip | 表头显示下一次排序的 tooltip 提示, 覆盖 table 中`showSorterTooltip` | boolean | `true` | |
|
||||
|
||||
### ColumnGroup
|
||||
|
||||
@ -297,4 +298,4 @@ Table 移除了在 v3 中废弃的 `onRowClick`、`onRowDoubleClick`、`onRowMou
|
||||
|
||||
### 为什么 更新 state 会导致全表渲染?
|
||||
|
||||
由于 `columns` 支持 `render` 方法,因而 Table 无法知道哪些单元会受到影响。你可以通过 `components` 属性来精确控制子元素的渲染,请参考 [#23763](https://github.com/ant-design/ant-design/issues/23763)。
|
||||
由于 `columns` 支持 `render` 方法,因而 Table 无法知道哪些单元会受到影响。你可以通过 `column.shouldCellUpdate` 来控制单元格的渲染。
|
||||
|
@ -1251,15 +1251,15 @@ exports[`renders ./components/tabs/demo/editable-card.md correctly 1`] = `
|
||||
<div>
|
||||
Tab 1
|
||||
<span
|
||||
aria-label="close"
|
||||
class="anticon anticon-close ant-tabs-close-x"
|
||||
aria-label="close-circle"
|
||||
class="anticon anticon-close-circle ant-tabs-close-x"
|
||||
role="img"
|
||||
tabindex="-1"
|
||||
>
|
||||
<svg
|
||||
aria-hidden="true"
|
||||
class=""
|
||||
data-icon="close"
|
||||
data-icon="close-circle"
|
||||
fill="currentColor"
|
||||
focusable="false"
|
||||
height="1em"
|
||||
@ -1267,7 +1267,10 @@ exports[`renders ./components/tabs/demo/editable-card.md correctly 1`] = `
|
||||
width="1em"
|
||||
>
|
||||
<path
|
||||
d="M563.8 512l262.5-312.9c4.4-5.2.7-13.1-6.1-13.1h-79.8c-4.7 0-9.2 2.1-12.3 5.7L511.6 449.8 295.1 191.7c-3-3.6-7.5-5.7-12.3-5.7H203c-6.8 0-10.5 7.9-6.1 13.1L459.4 512 196.9 824.9A7.95 7.95 0 00203 838h79.8c4.7 0 9.2-2.1 12.3-5.7l216.5-258.1 216.5 258.1c3 3.6 7.5 5.7 12.3 5.7h79.8c6.8 0 10.5-7.9 6.1-13.1L563.8 512z"
|
||||
d="M685.4 354.8c0-4.4-3.6-8-8-8l-66 .3L512 465.6l-99.3-118.4-66.1-.3c-4.4 0-8 3.5-8 8 0 1.9.7 3.7 1.9 5.2l130.1 155L340.5 670a8.32 8.32 0 00-1.9 5.2c0 4.4 3.6 8 8 8l66.1-.3L512 564.4l99.3 118.4 66 .3c4.4 0 8-3.5 8-8 0-1.9-.7-3.7-1.9-5.2L553.5 515l130.1-155c1.2-1.4 1.8-3.3 1.8-5.2z"
|
||||
/>
|
||||
<path
|
||||
d="M512 65C264.6 65 64 265.6 64 513s200.6 448 448 448 448-200.6 448-448S759.4 65 512 65zm0 820c-205.4 0-372-166.6-372-372s166.6-372 372-372 372 166.6 372 372-166.6 372-372 372z"
|
||||
/>
|
||||
</svg>
|
||||
</span>
|
||||
@ -1285,15 +1288,15 @@ exports[`renders ./components/tabs/demo/editable-card.md correctly 1`] = `
|
||||
<div>
|
||||
Tab 2
|
||||
<span
|
||||
aria-label="close"
|
||||
class="anticon anticon-close ant-tabs-close-x"
|
||||
aria-label="close-circle"
|
||||
class="anticon anticon-close-circle ant-tabs-close-x"
|
||||
role="img"
|
||||
tabindex="-1"
|
||||
>
|
||||
<svg
|
||||
aria-hidden="true"
|
||||
class=""
|
||||
data-icon="close"
|
||||
data-icon="close-circle"
|
||||
fill="currentColor"
|
||||
focusable="false"
|
||||
height="1em"
|
||||
@ -1301,7 +1304,10 @@ exports[`renders ./components/tabs/demo/editable-card.md correctly 1`] = `
|
||||
width="1em"
|
||||
>
|
||||
<path
|
||||
d="M563.8 512l262.5-312.9c4.4-5.2.7-13.1-6.1-13.1h-79.8c-4.7 0-9.2 2.1-12.3 5.7L511.6 449.8 295.1 191.7c-3-3.6-7.5-5.7-12.3-5.7H203c-6.8 0-10.5 7.9-6.1 13.1L459.4 512 196.9 824.9A7.95 7.95 0 00203 838h79.8c4.7 0 9.2-2.1 12.3-5.7l216.5-258.1 216.5 258.1c3 3.6 7.5 5.7 12.3 5.7h79.8c6.8 0 10.5-7.9 6.1-13.1L563.8 512z"
|
||||
d="M685.4 354.8c0-4.4-3.6-8-8-8l-66 .3L512 465.6l-99.3-118.4-66.1-.3c-4.4 0-8 3.5-8 8 0 1.9.7 3.7 1.9 5.2l130.1 155L340.5 670a8.32 8.32 0 00-1.9 5.2c0 4.4 3.6 8 8 8l66.1-.3L512 564.4l99.3 118.4 66 .3c4.4 0 8-3.5 8-8 0-1.9-.7-3.7-1.9-5.2L553.5 515l130.1-155c1.2-1.4 1.8-3.3 1.8-5.2z"
|
||||
/>
|
||||
<path
|
||||
d="M512 65C264.6 65 64 265.6 64 513s200.6 448 448 448 448-200.6 448-448S759.4 65 512 65zm0 820c-205.4 0-372-166.6-372-372s166.6-372 372-372 372 166.6 372 372-166.6 372-372 372z"
|
||||
/>
|
||||
</svg>
|
||||
</span>
|
||||
|
@ -15,6 +15,7 @@ Only card type Tabs support adding & closable. +Use `closable={false}` to disabl
|
||||
|
||||
```jsx
|
||||
import { Tabs } from 'antd';
|
||||
import { CloseCircleOutlined } from '@ant-design/icons';
|
||||
|
||||
const { TabPane } = Tabs;
|
||||
|
||||
@ -81,7 +82,12 @@ class Demo extends React.Component {
|
||||
onEdit={this.onEdit}
|
||||
>
|
||||
{this.state.panes.map(pane => (
|
||||
<TabPane tab={pane.title} key={pane.key} closable={pane.closable}>
|
||||
<TabPane
|
||||
tab={pane.title}
|
||||
key={pane.key}
|
||||
closable={pane.closable}
|
||||
closeIcon={<CloseCircleOutlined />}
|
||||
>
|
||||
{pane.content}
|
||||
</TabPane>
|
||||
))}
|
||||
|
Some files were not shown because too many files have changed in this diff Show More
Loading…
Reference in New Issue
Block a user