upgrade to 3.8.2

This commit is contained in:
HeskeyBaozi 2018-08-20 14:00:51 +08:00
commit 65600c8a95
51 changed files with 858 additions and 755 deletions

View File

@ -1,7 +1,6 @@
components/**/*.js
components/**/*.jsx
components/*/__tests__/type.tsx
!.eslintrc.js
!components/*/__tests__/**/*.js
!components/*/demo/*
!.*.js

View File

@ -14,6 +14,41 @@ timeline: true
* Major version release is not included in this schedule for breaking change and new features.
---
## 3.8.2
`2018-8-18`
- 🐞 Fixed Tag still visible when initially setting `visible` prop to false. [#11757](https://github.com/ant-design/ant-design/issues/11757)
- 🐞 Fixed Modal text got selected when opened by double click. [#11777](https://github.com/ant-design/ant-design/issues/11777)
- 🐞 Fixed style of Rate component while getting clicked. [#11736](https://github.com/ant-design/ant-design/issues/11736)
- 🐞 Fixed style of Badge component when its children is `display:block`. [#84119d8](https://github.com/ant-design/ant-design/commit/84119d8959d55edf535a9cac5ff532e61b6ee698)
- Drawer
- 🐞 Fixed Drawer not compatible with IE10 and IE9. [#11583](https://github.com/ant-design/ant-design/issues/11583)
- 🐞 Fixed Drawer not being able to be scrolled vertically on mobile device. [#11443](https://github.com/ant-design/ant-design/issues/11443)
- TypeScript
- 🐞 Fixed `selectable` prop is missing in TreeNode props. [#11604](https://github.com/ant-design/ant-design/issues/11604) [@apieceofbart](https://github.com/apieceofbart)
- 🐞 Fixed `autosize` prop is missing in Input props. [#11697](https://github.com/ant-design/ant-design/issues/11697)
## 3.8.1
`2018-08-12`
- 🐞 Fixed TimePicker unexpected long width. [80f8267](https://github.com/ant-design/ant-design/commit/80f82674fb63b068d047651ccba772999139f1b7)
- 🐞 Fixed Tabs that focusable element in inactive panel cause tabs disappear. [#11261](https://github.com/ant-design/ant-design/issues/11261)
- 🐞 Fixed Badge `offset` x y axis order error. [#11648](https://github.com/ant-design/ant-design/pull/11648) [@tangjinzhou](https://github.com/tangjinzhou)
- Upload
- 🐞 Fixed detete button missing in Upload. [#10454](https://github.com/ant-design/ant-design/issues/10454)
- 🐞 Fixed Upload thumbnail which url has no extension. [#11684](https://github.com/ant-design/ant-design/pull/11684) [@elantion](https://github.com/elantion)
- 🐞 Fixed Anchor with `affix=true` doesn't work inside inner scrollable. [#11688](https://github.com/ant-design/ant-design/pull/11688) [@vitaliymaz](https://github.com/vitaliymaz)
- 🐞 Fixed card width in List.Grid. [!11712](https://github.com/ant-design/ant-design/issues/11712)
- 🐞 Fixed Radio align problem in safari. [754a22c](https://github.com/ant-design/ant-design/commit/754a22ca24dee685666554778f53a5fe700959ff)
- 💄 Apply wave click animation to components Switch, Radio.Button and Tag. [9cf6ae6](https://github.com/ant-design/ant-design/commit/9cf6ae601010acbf665d575d34c0cc0918e604e7)
- TypeScript
- 🐞 Fixed missing prop signature `destroyInactivePanel` of Collapse. [#11646](https://github.com/ant-design/ant-design/pull/11646) [@zheeeng](https://github.com/zheeeng)
- 🐞 Fixed missing prop `getPopupContainer` signature of AutoComplete. [#11690](https://github.com/ant-design/ant-design/pull/11690) [@Huanghuiying0624](https://github.com/Huanghuiying0624)
- 🐞 Fixed Upload `lastModifiedDate` signature. [#11709](https://github.com/ant-design/ant-design/pull/11709) [@andycall](https://github.com/andycall)
- 💄 Migrate to new lifecycle methods, include components TimePicker, Upload, CheckboxGroup, Layout.Sider, Tooltip, Popconfirm. [#11666](https://github.com/ant-design/ant-design/pull/11666) [@dancerphil](https://github.com/dancerphil) [#11682](https://github.com/ant-design/ant-design/pull/11682) [@dancerphil](https://github.com/dancerphil)
## 3.8.0

View File

@ -15,6 +15,40 @@ timeline: true
---
## 3.8.2
`2018-8-18`
- 🐞 修复 Tag 组件 `visible` 属性初始值为 false 时仍然可见的问题。[#11757](https://github.com/ant-design/ant-design/issues/11757)
- 🐞 修复 Modal 文本在双击打开的时候会被选中的问题。[#11777](https://github.com/ant-design/ant-design/issues/11777)
- 🐞 修复 Rate 组件点击时的样式问题。[#11736](https://github.com/ant-design/ant-design/issues/11736)
- 🐞 修复 Badge 组件在子元素为 `display:block` 时的样式问题。[#84119d8](https://github.com/ant-design/ant-design/commit/84119d8959d55edf535a9cac5ff532e61b6ee698)
- Drawer
- 🐞 修复 Drawer 组件不兼容 IE10 和 IE9 的问题。[#11583](https://github.com/ant-design/ant-design/issues/11583)
- 🐞 修复 Drawer 组件在移动设备上无法垂直滚动的问题。 [#11443](https://github.com/ant-design/ant-design/issues/11443)
- TypeScript
- 🐞 修复 TreeNode 组件缺少的 `selectable` 属性定义。[#11604](https://github.com/ant-design/ant-design/issues/11604) [@apieceofbart](https://github.com/apieceofbart)
- 🐞 修复 Input 组件缺失 `autosize` 属性的类型错误。[#11697](https://github.com/ant-design/ant-design/issues/11697)
## 3.8.1
`2018-08-12`
- 🐞 修复 TimePicker 面板输入框宽度过长的问题。[80f8267](https://github.com/ant-design/ant-design/commit/80f82674fb63b068d047651ccba772999139f1b7)
- 🐞 修复 Tabs 中隐藏的输入框可能被聚焦的问题。[#11261](https://github.com/ant-design/ant-design/issues/11261)
- 🐞 修复 Badge 组件属性 `offset` 的坐标设置顺序问题。[#11648](https://github.com/ant-design/ant-design/pull/11648) [@tangjinzhou](https://github.com/tangjinzhou)
- Upload
- 🐞 修复 Upload 组件删除按钮可能不展示的问题。[#10454](https://github.com/ant-design/ant-design/issues/10454)
- 🐞 修复 Upload 组件缩略图地址没有文件扩展名时的显示问题。[#11684](https://github.com/ant-design/ant-design/pull/11684) [@elantion](https://github.com/elantion)
- 🐞 修复 Anchor 组件当 `affix=true` 时无法在滚动的窗口中固定的问题。[#11688](https://github.com/ant-design/ant-design/pull/11688) [@vitaliymaz](https://github.com/vitaliymaz)
- 🐞 修复 List.Grid 组件中的卡片宽度问题。[!11712](https://github.com/ant-design/ant-design/issues/11712)
- 🐞 修复 Radio 在 safari 下对齐的问题。[754a22c](https://github.com/ant-design/ant-design/commit/754a22ca24dee685666554778f53a5fe700959ff)
- 💄 添加点击动画效果到组件 Switch, Radio.Button 和 Tag。[9cf6ae6](https://github.com/ant-design/ant-design/commit/9cf6ae601010acbf665d575d34c0cc0918e604e7)
- TypeScript
- 🐞 修复 Collapse 组件缺少的 `destroyInactivePanel` 定义。[#11646](https://github.com/ant-design/ant-design/pull/11646) [@zheeeng](https://github.com/zheeeng)
- 💄 修复 AutoComplete 没有 `getPopupContainer` 属性定义的问题。[#11690](https://github.com/ant-design/ant-design/pull/11690) [@Huanghuiying0624](https://github.com/Huanghuiying0624)
- 🐞 修复 Upload 组件的 `lastModifiedDate` 定义。[#11709](https://github.com/ant-design/ant-design/pull/11709) [@andycall](https://github.com/andycall)
- 💄 使用新的 React 生命周期函数,包括组件 Upload, CheckboxGroup, Layout.Sider, Tooltip, Popconfirm。[#11666](https://github.com/ant-design/ant-design/pull/11666) [@dancerphil](https://github.com/dancerphil) [#11682](https://github.com/ant-design/ant-design/pull/11682) [@dancerphil](https://github.com/dancerphil)
## 3.8.0
`2018-08-05`

103
components/_util/wave.tsx Normal file
View File

@ -0,0 +1,103 @@
import * as React from 'react';
import { findDOMNode } from 'react-dom';
import TransitionEvents from 'css-animation/lib/Event';
export default class Wave extends React.Component<{insertExtraNode?: boolean}> {
private instance?: {
cancel: () => void;
};
private styleForPesudo: HTMLStyleElement | null;
isNotGrey(color: string) {
const match = (color || '').match(/rgba?\((\d*), (\d*), (\d*)(, [\.\d]*)?\)/);
if (match && match[1] && match[2] && match[3]) {
return !(match[1] === match[2] && match[2] === match[3]);
}
return true;
}
onClick = (node: HTMLElement) => {
if (node.className.indexOf('-leave') >= 0) {
return;
}
this.removeExtraStyleNode();
const { insertExtraNode } = this.props;
const extraNode = document.createElement('div');
extraNode.className = 'ant-click-animating-node';
const attributeName = insertExtraNode ? 'ant-click-animating' : 'ant-click-animating-without-extra-node';
node.removeAttribute(attributeName);
node.setAttribute(attributeName, 'true');
// Get wave color from target
const waveColor =
getComputedStyle(node).getPropertyValue('border-top-color') || // Firefox Compatible
getComputedStyle(node).getPropertyValue('border-color') ||
getComputedStyle(node).getPropertyValue('background-color');
// Not white or transparnt or grey
if (waveColor &&
waveColor !== '#ffffff' &&
waveColor !== 'rgb(255, 255, 255)' &&
this.isNotGrey(waveColor) &&
!/rgba\(\d*, \d*, \d*, 0\)/.test(waveColor) && // any transparent rgba color
waveColor !== 'transparent') {
extraNode.style.borderColor = waveColor;
this.styleForPesudo = document.createElement('style');
this.styleForPesudo.innerHTML =
`[ant-click-animating-without-extra-node]:after { border-color: ${waveColor}; }`;
document.body.appendChild(this.styleForPesudo);
}
if (insertExtraNode) {
node.appendChild(extraNode);
}
const transitionEnd = () => {
node.removeAttribute(attributeName);
this.removeExtraStyleNode();
if (insertExtraNode) {
node.removeChild(extraNode);
}
TransitionEvents.removeEndEventListener(node, transitionEnd);
};
TransitionEvents.addEndEventListener(node, transitionEnd);
}
bindAnimationEvent = (node: HTMLElement) => {
if (node.getAttribute('disabled') ||
node.className.indexOf('disabled') >= 0) {
return;
}
const onClick = (e: MouseEvent) => {
// Fix radio button click twice
if ((e.target as HTMLElement).tagName === 'INPUT') {
return;
}
setTimeout(() => this.onClick(node), 0);
};
node.addEventListener('click', onClick, true);
return {
cancel: () => {
node.removeEventListener('click', onClick, true);
},
};
}
removeExtraStyleNode() {
if (this.styleForPesudo && document.body.contains(this.styleForPesudo)) {
document.body.removeChild(this.styleForPesudo);
this.styleForPesudo = null;
}
}
componentDidMount() {
this.instance = this.bindAnimationEvent(findDOMNode(this) as HTMLElement);
}
componentWillUnmount() {
if (this.instance) {
this.instance.cancel();
}
}
render() {
return this.props.children;
}
}

View File

@ -62,11 +62,8 @@ describe('Anchor Render', () => {
wrapper.instance().handleScrollTo('##API');
expect(wrapper.instance().state.activeLink).toBe('##API');
expect(scrollToSpy).not.toHaveBeenCalled();
await new Promise(resolve => setTimeout(resolve, 50));
expect(scrollToSpy).toHaveBeenCalled();
expect(wrapper.instance().animating).toBe(true);
await new Promise(resolve => setTimeout(resolve, 1000));
expect(wrapper.instance().animating).toBe(false);
expect(scrollToSpy).toHaveBeenCalled();
});
it('should remove listener when unmount', async () => {

View File

@ -63,6 +63,8 @@ export default class BackTop extends React.Component<BackTopProps, any> {
this.setScrollTop(easeInOutCubic(time, scrollTop, 0, 450));
if (time < 450) {
raf(frameFunc);
} else {
this.setScrollTop(0);
}
};
raf(frameFunc);

View File

@ -10,11 +10,13 @@
display: inline-block;
line-height: 1;
vertical-align: middle;
color: unset;
&-count {
position: absolute;
transform: translateX(-50%);
top: -@badge-height / 2;
transform: translate(50%, -50%);
top: 0;
right: 0;
height: @badge-height;
border-radius: @badge-height / 2;
min-width: @badge-height;
@ -26,7 +28,7 @@
font-size: @badge-font-size;
font-weight: @badge-font-weight;
white-space: nowrap;
transform-origin: -10% center;
transform-origin: 0 center;
box-shadow: 0 0 0 1px #fff;
a,
a:hover {
@ -40,9 +42,10 @@
&-dot {
position: absolute;
transform: translateX(-50%);
transform: translate(50%, -50%);
transform-origin: 0 center;
top: -@badge-dot-size / 2;
top: 0;
right: 0;
height: @badge-dot-size;
width: @badge-dot-size;
border-radius: 100%;

View File

@ -2,7 +2,7 @@ import * as React from 'react';
import { findDOMNode } from 'react-dom';
import * as PropTypes from 'prop-types';
import classNames from 'classnames';
import clickAnimation from './clickAnimation';
import Wave from '../_util/wave';
import Icon from '../icon';
import Group from './button-group';
@ -87,10 +87,7 @@ export default class Button extends React.Component<ButtonProps, any> {
block: PropTypes.bool,
};
delayTimeout: number;
clickAnimation: {
cancel: () => void;
};
private delayTimeout: number;
constructor(props: ButtonProps) {
super(props);
@ -102,7 +99,6 @@ export default class Button extends React.Component<ButtonProps, any> {
componentDidMount() {
this.fixTwoCNChar();
this.clickAnimation = clickAnimation(findDOMNode(this) as HTMLElement);
}
componentWillReceiveProps(nextProps: ButtonProps) {
@ -128,9 +124,6 @@ export default class Button extends React.Component<ButtonProps, any> {
if (this.delayTimeout) {
clearTimeout(this.delayTimeout);
}
if (this.clickAnimation) {
this.clickAnimation.cancel();
}
}
fixTwoCNChar() {
@ -213,14 +206,16 @@ export default class Button extends React.Component<ButtonProps, any> {
const { htmlType, ...otherProps } = rest;
return (
<button
{...otherProps}
type={htmlType || 'button'}
className={classes}
onClick={this.handleClick}
>
{iconNode}{kids}
</button>
<Wave>
<button
{...otherProps}
type={htmlType || 'button'}
className={classes}
onClick={this.handleClick}
>
{iconNode}{kids}
</button>
</Wave>
);
}
}

View File

@ -1,20 +0,0 @@
import TransitionEvents from 'css-animation/lib/Event';
const clickAnimation = (node: HTMLElement) => {
function handler() {
node.removeAttribute('ant-click-animating');
node.setAttribute('ant-click-animating', 'true');
TransitionEvents.addEndEventListener(node, () => {
node.removeAttribute('ant-click-animating');
TransitionEvents.removeEndEventListener(node);
});
}
node.addEventListener('click', handler, false);
return {
cancel: () => {
node.removeEventListener('click', handler, false);
},
};
};
export default clickAnimation;

View File

@ -8,7 +8,6 @@
@btn-ghost-color: @text-color;
@btn-ghost-bg: transparent;
@btn-ghost-border: @border-color-base;
@btn-animation-width: 6px;
// Button styles
// -----------------------------
@ -132,10 +131,6 @@
margin-left: 8px;
}
&-danger[ant-click-animating]:after {
border-color: @btn-danger-color;
}
&-background-ghost {
background: transparent !important;
border-color: #fff;
@ -164,17 +159,6 @@
}
}
@keyframes buttonEffect {
to {
opacity: 0;
top: -@btn-animation-width;
left: -@btn-animation-width;
bottom: -@btn-animation-width;
right: -@btn-animation-width;
border-width: @btn-animation-width;
}
}
a.@{btn-prefix-cls} {
line-height: @btn-height-base - 2px;
&-lg {
@ -184,17 +168,3 @@ a.@{btn-prefix-cls} {
line-height: @btn-height-sm - 2px;
}
}
[ant-click-animating]:after {
content: '';
position: absolute;
top: -1px;
left: -1px;
bottom: -1px;
right: -1px;
border-radius: inherit;
border: 0 solid @primary-color;
opacity: 0.4;
animation: buttonEffect .4s cubic-bezier(.25, .8, .25, 1);
display: block;
}

View File

@ -1,5 +1,6 @@
import * as React from 'react';
import * as PropTypes from 'prop-types';
import { polyfill } from 'react-lifecycles-compat';
import classNames from 'classnames';
import shallowEqual from 'shallowequal';
import Checkbox from './Checkbox';
@ -38,7 +39,7 @@ export interface CheckboxGroupContext {
};
}
export default class CheckboxGroup extends React.Component<CheckboxGroupProps, CheckboxGroupState> {
class CheckboxGroup extends React.Component<CheckboxGroupProps, CheckboxGroupState> {
static defaultProps = {
options: [],
prefixCls: 'ant-checkbox',
@ -55,6 +56,15 @@ export default class CheckboxGroup extends React.Component<CheckboxGroupProps, C
checkboxGroup: PropTypes.any,
};
static getDerivedStateFromProps(nextProps: CheckboxGroupProps) {
if ('value' in nextProps) {
return {
value: nextProps.value || [],
};
}
return null;
}
constructor(props: CheckboxGroupProps) {
super(props);
this.state = {
@ -72,13 +82,6 @@ export default class CheckboxGroup extends React.Component<CheckboxGroupProps, C
};
}
componentWillReceiveProps(nextProps: CheckboxGroupProps) {
if ('value' in nextProps) {
this.setState({
value: nextProps.value || [],
});
}
}
shouldComponentUpdate(nextProps: CheckboxGroupProps, nextState: CheckboxGroupState) {
return !shallowEqual(this.props, nextProps) ||
!shallowEqual(this.state, nextState);
@ -141,3 +144,7 @@ export default class CheckboxGroup extends React.Component<CheckboxGroupProps, C
);
}
}
polyfill(CheckboxGroup);
export default CheckboxGroup;

View File

@ -64,4 +64,19 @@ describe('CheckboxGroup', () => {
expect(wrapper).toMatchSnapshot();
});
it('should be controlled by value', () => {
const options = [
{ label: 'Apple', value: 'Apple' },
{ label: 'Orange', value: 'Orange' },
];
const wrapper = mount(
<Checkbox.Group options={options} />
);
expect(wrapper.instance().state.value).toEqual([]);
wrapper.setProps({ value: ['Apple'] });
expect(wrapper.instance().state.value).toEqual(['Apple']);
});
});

View File

@ -65,7 +65,8 @@
border-top: 0;
border-left: 0;
content: ' ';
transition: all .1s @ease-in-back;
transition: all .1s @ease-in-back, opacity .1s;
opacity: 0;
}
}
@ -85,15 +86,17 @@
// 半选状态
.@{checkbox-prefix-cls}-indeterminate .@{checkbox-inner-prefix-cls}:after {
@indeterminate-width: (@checkbox-size / 14) * 8px;
@indeterminate-height: (@checkbox-size / 14) * 1px;
@indeterminate-width: @checkbox-size - 7px;
@indeterminate-height: @checkbox-size - 7px;
content: ' ';
transform: scale(1);
position: absolute;
left: (@checkbox-size - 2 - @indeterminate-width) / 2;
top: (@checkbox-size - 3 - @indeterminate-height) / 2;
transform: translate(-50%, -50%) scale(1);
border: 0;
left: 50%;
top: 50%;
width: @indeterminate-width;
height: @indeterminate-height;
background-color: @checkbox-color;
opacity: 1;
}
.@{checkbox-prefix-cls}-indeterminate.@{checkbox-prefix-cls}-disabled .@{checkbox-inner-prefix-cls}:after {
@ -110,10 +113,10 @@
border-left: 0;
content: ' ';
transition: all .2s @ease-out-back .1s;
opacity: 1;
}
.@{checkbox-prefix-cls}-checked,
.@{checkbox-prefix-cls}-indeterminate {
.@{checkbox-prefix-cls}-checked {
.@{checkbox-inner-prefix-cls} {
background-color: @checkbox-color;
border-color: @checkbox-color;

View File

@ -12,7 +12,7 @@ exports[`Drawer className is test_drawer 1`] = `
/>
<div
class="ant-drawer-content-wrapper"
style="transform:translateX(100%);width:256px"
style="transform:translateX(100%);-ms-transform:translateX(100%);width:256px"
>
<div
class="ant-drawer-content"
@ -71,7 +71,7 @@ exports[`Drawer closable is false 1`] = `
/>
<div
class="ant-drawer-content-wrapper"
style="transform:translateX(100%);width:256px"
style="transform:translateX(100%);-ms-transform:translateX(100%);width:256px"
>
<div
class="ant-drawer-content"
@ -104,7 +104,7 @@ exports[`Drawer destroyOnClose is true 1`] = `
/>
<div
class="ant-drawer-content-wrapper"
style="transform:translateX(100%);width:256px"
style="transform:translateX(100%);-ms-transform:translateX(100%);width:256px"
>
<div
class="ant-drawer-content"
@ -163,7 +163,7 @@ exports[`Drawer have a title 1`] = `
/>
<div
class="ant-drawer-content-wrapper"
style="transform:translateX(100%);width:256px"
style="transform:translateX(100%);-ms-transform:translateX(100%);width:256px"
>
<div
class="ant-drawer-content"
@ -231,7 +231,7 @@ exports[`Drawer render correctly 1`] = `
/>
<div
class="ant-drawer-content-wrapper"
style="transform:translateX(100%);width:400px"
style="transform:translateX(100%);-ms-transform:translateX(100%);width:400px"
>
<div
class="ant-drawer-content"

View File

@ -5,25 +5,32 @@
.@{dawer-prefix-cls} {
position: fixed;
top: 0;
width: 100%;
height: 100%;
pointer-events: none;
width: 0%;
z-index: @zindex-modal;
transition: transform 0.3s @ease-in-out-circ;
transition: transform @animation-duration-slow @ease-base-in;
> * {
transition: transform 0.3s @ease-in-out-circ;
transition: transform @animation-duration-slow @ease-base-in;
}
&-content-wrapper {
position: absolute;
position: fixed;
}
.@{dawer-prefix-cls}-content {
width: 100%;
height: 100%;
opacity: 0;
transition: opacity @animation-duration-slow linear;
}
&-left,
&-right {
.@{dawer-prefix-cls}-content-wrapper,
.@{dawer-prefix-cls}-content {
width: 0%;
height: 100%;
.@{dawer-prefix-cls}-content-wrapper {
height: 100%;
}
&.@{dawer-prefix-cls}-open {
width: 100%;
}
}
&-left {
&.@{dawer-prefix-cls}-open {
@ -44,13 +51,44 @@
}
}
}
&.@{dawer-prefix-cls}-open {
> * {
pointer-events: auto;
&-top,
&-bottom {
.@{dawer-prefix-cls}-content-wrapper,
.@{dawer-prefix-cls}-content {
width: 100%;
}
}
&-top {
&.@{dawer-prefix-cls}-open {
.@{dawer-prefix-cls}-content-wrapper {
box-shadow: @shadow-1-down;
}
}
}
&-bottom {
.@{dawer-prefix-cls} {
&-content-wrapper {
bottom: 0;
}
}
&.@{dawer-prefix-cls}-open {
.@{dawer-prefix-cls}-content-wrapper {
box-shadow: @shadow-1-up;
}
}
}
&.@{dawer-prefix-cls}-open {
.@{dawer-prefix-cls} {
&-content {
opacity: 1;
}
&-mask {
opacity: 0.3;
height: 100%;
animation: antdDrawerFadeIn @animation-duration-slow @ease-base-out;
transition: none;
}
}
}
@ -82,7 +120,7 @@
font-weight: 700;
line-height: 1;
text-decoration: none;
transition: color 0.3s;
transition: color @animation-duration-slow;
color: @text-color-secondary;
outline: 0;
padding: 0;
@ -123,21 +161,29 @@
&-mask {
position: fixed;
top: 0;
right: 0;
left: 0;
bottom: 0;
width: 100%;
height: 0;
opacity: 0;
background-color: @modal-mask-bg;
height: 100%;
transition: opacity 0.3s @ease-in-out-circ;
filter: ~"alpha(opacity=50)";
transition: opacity @animation-duration-slow linear, height 0s ease @animation-duration-slow;
}
&-open {
overflow: hidden;
transition: transform @animation-duration-slow @ease-base-out;
> * {
transition: transform @animation-duration-slow @ease-base-out;
}
&-content {
box-shadow: @shadow-2;
}
}
}
@keyframes antdDrawerFadeIn {
0% {
opacity: 0;
}
100% {
opacity: 0.3;
}
}

View File

@ -18,21 +18,9 @@ We provide semantic name for every icon, and naming rules are as follows:
See more design detail at [here](/docs/spec/icon).
## How To Use
Use tag <Icon /> to create an icon and set its type in the type prop, for example:
```html
<Icon type="link" />
```
## Local deployment
By default, icons are deployed at [iconfont.cn](http://iconfont.cn), publicly available repository of a huge set of icons. In case you need to use a locally deployed version of the icon font, you can refer to [this example](https://github.com/ant-design/antd-init/tree/master/examples/local-iconfont)。
## List of icons
> Click the icon and copy the code
> Click the icon and copy the code.
### Directional Icons
@ -62,16 +50,95 @@ import IconSet from 'site/theme/template/IconSet';
ReactDOM.render(<IconSet className="icons" catigory="logo" />, mountNode);
```
## API
You can set `style` and `className` for size and color of icons because they are still fonts in essence.
```jsx
<Icon type="question" style={{ fontSize: 16, color: '#08c' }} />
```
### Icon
| Property | Description | Type | Default |
| -------- | ----------- | ---- | ------- |
| spin | Rotate icon with animation | boolean | false |
| style | style properties of icon, like fontSize and color | object | - |
| --- | --- | --- | --- |
| type | Type of ant design icon | string | - |
| style | Style properties of icon, like `fontSize` and `color` | CSSProperties | - |
| svgStyle | Inline style to apply to the SVG element | CSSProperties | - |
| svgClassName | Extra class name for the SVG element | string | - |
| spin | Rotate icon with animation | boolean | false |
| component | The component used for the root node. This will override the **`type`** property. | ComponentType<CustomIconComponentProps\> | - |
All the icons will render to `<svg>`. You can still set `style` and `className` for size and color of icons.
```jsx
<Icon type="message" style={{ fontSize: '16px', color: '#08c' }} />
```
You can import svg icon as an react component by using `webpack` and [`@svgr/webpack`](https://www.npmjs.com/package/@svgr/webpack). `@svgr/webpack`'s `options` [reference](https://github.com/smooth-code/svgr#options).
```js
// webpack.config.js
{
test: /\.svg(\?v=\d+\.\d+\.\d+)?$/,
use: [
{
loader: 'babel-loader',
},
{
loader: '@svgr/webpack',
options: {
babel: false,
icon: true,
},
},
],
}
```
```jsx
import { Icon } from 'antd';
import MessageSvg from 'path/to/message.svg'; // path to your '*.svg' file.
ReactDOM.render(
<Icon component={MessageSvg} />,
mountNode
);
```
#### CustomIconComponentProps
The following properties are available fot the component:
| Property | Description | Type | Default |
| --- | --- | --- | --- |
| width | The width of the `svg` element | string \| number | '1em' |
| height | The height of the `svg` element | string \| number | '1em' |
| fill | Define the color used to paint the `svg` element | string | 'currentColor' |
| className | The computed class name of the `svg` element | string | - |
| style | The computed style of the `svg` element | CSSProperties | - |
### Icon.createFromIconfontCN(options)
This method is
```js
const MyIcon = Icon.createFromIconfontCN({
namespace: 'foo', // identifier
url: 'at.alicdn.com/t/font_8d5l8fzk5b87iudi', // generated by iconfont.cn
prefix: 'icon-',
});
ReactDOM.render(<MyIcon type="example" />, mountedNode);
```
其本质上是创建了一个使用 `<use>` 标签来渲染图标的组件。
The following options are available:
| Property | Description | Type | Default |
| --- | --- | --- | --- |
| prefix | 设置图标的前缀,通常以短横线结尾,如 `icon-`、`foo-` | string | '' |
| extraCommonProps | 给所有的 `svg` 图标 `<Icon />` 组件设置额外的属性 | `{ [key: string]: any }` | {} |
| namespace | 图标集合的名字空间,在 `url` 也设置的情况下有效,用于区分已导入的图标符号集合 | string | - |
| url | [iconfont.cn](http://iconfont.cn/) 项目在线生成的 `js` 地址,在 `namespace` 也设置的情况下有效 | string | - |
`namespace``url` 都设置有效的情况下,组件在渲染前会自动引入 [iconfont.cn](http://iconfont.cn/) 项目中的图标符号集,无需手动引入。
见 [iconfont.cn 使用帮助](http://iconfont.cn/help/detail?spm=a313x.7781069.1998910419.15&helptype=code) 查看如何生成 `js` 地址。

View File

@ -91,9 +91,6 @@ ReactDOM.render(<IconSet className="icons" catigory="logo" />, mountNode);
}
```
之后直接导入即可
```jsx
import { Icon } from 'antd';
import MessageSvg from 'path/to/message.svg'; // path to your '*.svg' file.
@ -119,7 +116,7 @@ ReactDOM.render(
### Icon.createFromIconfontCN(options)
使用方式如下:
这个方法适用于 `iconfont.cn` 的用户
```js
const MyIcon = Icon.createFromIconfontCN({

View File

@ -53,7 +53,6 @@ export default class Input extends React.Component<InputProps, any> {
addonBefore: PropTypes.node,
addonAfter: PropTypes.node,
prefixCls: PropTypes.string,
autosize: PropTypes.oneOfType([PropTypes.bool, PropTypes.object]),
onPressEnter: PropTypes.func,
onKeyDown: PropTypes.func,
onKeyUp: PropTypes.func,

View File

@ -54,7 +54,7 @@ The rest of the props of `Input.TextArea` are the same as the original [textarea
| Property | Description | Type | Default |
| -------- | ----------- | ---- | ------- |
| enterButton | to show a enter button after input | boolean\|ReactNode | false |
| enterButton | to show an enter button after input | boolean\|ReactNode | false |
| onSearch | The callback function that is triggered when you click on the search-icon or press Enter key. | function(value, event) | |
Supports all props of `Input`.

View File

@ -15,6 +15,7 @@ if (typeof window !== 'undefined') {
}
import * as React from 'react';
import { polyfill } from 'react-lifecycles-compat';
import classNames from 'classnames';
import omit from 'omit.js';
import * as PropTypes from 'prop-types';
@ -67,7 +68,7 @@ const generateId = (() => {
};
})();
export default class Sider extends React.Component<SiderProps, SiderState> {
class Sider extends React.Component<SiderProps, SiderState> {
static __ANT_LAYOUT_SIDER: any = true;
static defaultProps = {
@ -90,6 +91,15 @@ export default class Sider extends React.Component<SiderProps, SiderState> {
siderHook: PropTypes.object,
};
static getDerivedStateFromProps(nextProps: SiderProps) {
if ('collapsed' in nextProps) {
return {
collapsed: nextProps.collapsed,
};
}
return null;
}
private mql: MediaQueryList;
private uniqueId: string;
@ -122,14 +132,6 @@ export default class Sider extends React.Component<SiderProps, SiderState> {
};
}
componentWillReceiveProps(nextProps: SiderProps) {
if ('collapsed' in nextProps) {
this.setState({
collapsed: nextProps.collapsed,
});
}
}
componentDidMount() {
if (this.mql) {
this.mql.addListener(this.responsiveHandler);
@ -234,3 +236,7 @@ export default class Sider extends React.Component<SiderProps, SiderState> {
);
}
}
polyfill(Sider);
export default Sider;

View File

@ -76,6 +76,15 @@ describe('Layout', () => {
);
expect(wrapper).toMatchSnapshot();
});
it('should be controlled by collapsed', () => {
const wrapper = mount(
<Sider>Sider</Sider>
);
expect(wrapper.instance().state.collapsed).toBe(false);
wrapper.setProps({ collapsed: true });
expect(wrapper.instance().state.collapsed).toBe(true);
});
});
describe('Sider onBreakpoint', () => {

View File

@ -199,6 +199,7 @@
margin-bottom: 16px;
&-content {
display: block;
max-width: 100%;
}
}
}

View File

@ -62,6 +62,7 @@ title: Modal
| 参数 | 说明 | 类型 | 默认值 |
| --- | --- | --- | --- |
| cancelText | 取消按钮文字 | string | 取消 |
| centered | 垂直居中展示 Modal | Boolean | `false` |
| className | 容器类名 | string | - |
| content | 内容 | string\|ReactNode | 无 |
| iconType | 图标 Icon 类型 | string | question-circle |

View File

@ -105,6 +105,7 @@
animation-duration: @animation-duration-slow;
transform: none; // reset scale avoid mousePosition bug
opacity: 0;
user-select: none; // https://github.com/ant-design/ant-design/issues/11777
}
&-mask {

View File

@ -1,4 +1,5 @@
import * as React from 'react';
import { polyfill } from 'react-lifecycles-compat';
import Tooltip, { AbstractTooltipProps } from '../tooltip';
import Icon from '../icon';
import Button from '../button';
@ -25,7 +26,7 @@ export interface PopconfirmLocale {
cancelText: string;
}
export default class Popconfirm extends React.Component<PopconfirmProps, PopconfirmState> {
class Popconfirm extends React.Component<PopconfirmProps, PopconfirmState> {
static defaultProps = {
prefixCls: 'ant-popover',
transitionName: 'zoom-big',
@ -35,6 +36,13 @@ export default class Popconfirm extends React.Component<PopconfirmProps, Popconf
icon: <Icon type="exclamation-circle" />,
};
static getDerivedStateFromProps(nextProps: PopconfirmProps) {
if ('visible' in nextProps) {
return { visible: nextProps.visible };
}
return null;
}
private tooltip: any;
constructor(props: PopconfirmProps) {
@ -45,12 +53,6 @@ export default class Popconfirm extends React.Component<PopconfirmProps, Popconf
};
}
componentWillReceiveProps(nextProps: PopconfirmProps) {
if ('visible' in nextProps) {
this.setState({ visible: nextProps.visible });
}
}
getPopupDomNode() {
return this.tooltip.getPopupDomNode();
}
@ -140,3 +142,7 @@ export default class Popconfirm extends React.Component<PopconfirmProps, Popconf
);
}
}
polyfill(Popconfirm);
export default Popconfirm;

View File

@ -3,6 +3,7 @@ import * as PropTypes from 'prop-types';
import { AbstractCheckboxProps } from '../checkbox/Checkbox';
import Radio from './radio';
import { RadioChangeEvent } from './interface';
import Wave from '../_util/wave';
export type RadioButtonProps = AbstractCheckboxProps<RadioChangeEvent>;
@ -24,7 +25,9 @@ export default class RadioButton extends React.Component<RadioButtonProps, any>
}
return (
<Radio {...radioProps} />
<Wave>
<Radio {...radioProps} />
</Wave>
);
}
}

View File

@ -30,7 +30,7 @@
display: inline-block;
position: relative;
line-height: 1;
vertical-align: text-bottom;
vertical-align: sub;
cursor: pointer;
.@{radio-prefix-cls}-wrapper:hover &,
&:hover,
@ -295,3 +295,10 @@ span.@{radio-prefix-cls} + * {
opacity: 0;
}
}
// Firefox hack
@supports (-moz-appearance:meterbar) and (background-blend-mode:difference,normal) {
.@{radio-prefix-cls} {
vertical-align: text-bottom;
}
}

View File

@ -31,6 +31,10 @@
color: inherit;
cursor: pointer;
&:focus {
outline: 0;
}
&-first,
&-second {
user-select: none;
@ -38,7 +42,8 @@
color: @rate-star-bg;
}
&-focused, &:hover {
&:hover,
&:focus {
transform: scale(1.1);
}

View File

@ -1,5 +1,5 @@
import React from 'react';
import { shallow, render } from 'enzyme';
import { shallow, render, mount } from 'enzyme';
import Spin from '..';
describe('Spin', () => {
@ -27,4 +27,13 @@ describe('Spin', () => {
);
expect(wrapper.find('.ant-spin').at(0).hasClass('ant-spin-spinning')).toEqual(false);
});
it('should be controlled by spinning', () => {
const wrapper = mount(
<Spin spinning={false} />
);
expect(wrapper.instance().state.spinning).toBe(false);
wrapper.setProps({ spinning: true });
expect(wrapper.instance().state.spinning).toBe(true);
});
});

View File

@ -26,7 +26,7 @@
display: block;
position: absolute;
height: 100%;
max-height: 320px;
max-height: 360px;
width: 100%;
z-index: 4;
.@{spin-prefix-cls}-dot {
@ -74,6 +74,7 @@
&-container {
position: relative;
transition: opacity .3s;
.clearfix;
}
@ -81,7 +82,7 @@
pointer-events: none;
user-select: none;
overflow: hidden;
opacity: 0.7;
opacity: 0.5;
-webkit-filter: blur(0.5px);
filter: blur(0.5px);

View File

@ -3,3 +3,34 @@
transform: rotate(360deg);
}
}
[ant-click-animating],
[ant-click-animating-without-extra-node] {
position: relative;
}
[ant-click-animating-without-extra-node]:after,
.ant-click-animating-node {
content: '';
position: absolute;
top: -1px;
left: -1px;
bottom: -1px;
right: -1px;
border-radius: inherit;
border: 0 solid @primary-color;
opacity: 0.4;
animation: waveEffect .4s cubic-bezier(.25, .8, .25, 1);
display: block;
}
@keyframes waveEffect {
to {
opacity: 0;
top: -@wave-animation-width;
left: -@wave-animation-width;
bottom: -@wave-animation-width;
right: -@wave-animation-width;
border-width: @wave-animation-width;
}
}

View File

@ -77,6 +77,8 @@
@link-hover-decoration : none;
// Animation
@ease-base-out : cubic-bezier(0.7, 0.3, 0.1, 1);
@ease-base-in : cubic-bezier(0.9, 0, 0.3, 0.7);
@ease-out : cubic-bezier(0.215, 0.61, 0.355, 1);
@ease-in : cubic-bezier(0.55, 0.055, 0.675, 0.19);
@ease-in-out : cubic-bezier(0.645, 0.045, 0.355, 1);
@ -486,4 +488,8 @@
// ---
@message-notice-content-padding: 10px 16px;
// Motion
// ---
@wave-animation-width: 6px;
@import "./default.deperated.less";

View File

@ -3,6 +3,7 @@ import * as PropTypes from 'prop-types';
import RcSwitch from 'rc-switch';
import classNames from 'classnames';
import omit from 'omit.js';
import Wave from '../_util/wave';
import Icon from '../icon';
export interface SwitchProps {
@ -59,12 +60,14 @@ export default class Switch extends React.Component<SwitchProps, {}> {
/>
) : null;
return (
<RcSwitch
{...omit(this.props, ['loading'])}
className={classes}
ref={this.saveSwitch}
loadingIcon={loadingIcon}
/>
<Wave insertExtraNode>
<RcSwitch
{...omit(this.props, ['loading'])}
className={classes}
ref={this.saveSwitch}
loadingIcon={loadingIcon}
/>
</Wave>
);
}
}

View File

@ -70,25 +70,7 @@ exports[`renders ./components/table/demo/ajax.md correctly 1`] = `
<i
class="anticon anticon-filter ant-dropdown-trigger"
title="Filter menu"
>
<svg
aria-hidden="true"
class=""
data-icon="filter"
fill="currentColor"
height="1em"
viewBox="0 0 1024 1024"
width="1em"
>
<path
class="st0"
d="M411 561.4l9.5 16.6h183l9.5-16.6L811.3 226H212.7zM420.6 642h182.9v156H420.6z"
/>
<path
d="M880.1 154H143.9c-24.5 0-39.8 26.7-27.5 48L349 597.4V838c0 17.7 14.2 32 31.8 32h262.4c17.6 0 31.8-14.3 31.8-32V597.4L907.7 202c12.2-21.3-3.1-48-27.6-48zM603.4 798H420.6V642h182.9v156zm9.6-236.6l-9.5 16.6h-183l-9.5-16.6L212.7 226h598.6L613 561.4z"
/>
</svg>
</i>
/>
</span>
</th>
<th
@ -144,6 +126,7 @@ exports[`renders ./components/table/demo/basic.md correctly 1`] = `
<col />
<col />
<col />
<col />
</colgroup>
<thead
class="ant-table-thead"
@ -170,6 +153,13 @@ exports[`renders ./components/table/demo/basic.md correctly 1`] = `
Address
</span>
</th>
<th
class=""
>
<span>
Tags
</span>
</th>
<th
class=""
>
@ -209,6 +199,24 @@ exports[`renders ./components/table/demo/basic.md correctly 1`] = `
>
New York No. 1 Lake Park
</td>
<td
class=""
>
<span>
<div
class="ant-tag ant-tag-blue"
data-show="true"
>
nice
</div>
<div
class="ant-tag ant-tag-blue"
data-show="true"
>
developer
</div>
</span>
</td>
<td
class=""
>
@ -216,7 +224,7 @@ exports[`renders ./components/table/demo/basic.md correctly 1`] = `
<a
href="javascript:;"
>
Action 一 John Brown
Invite John Brown
</a>
<div
class="ant-divider ant-divider-vertical"
@ -226,32 +234,6 @@ exports[`renders ./components/table/demo/basic.md correctly 1`] = `
>
Delete
</a>
<div
class="ant-divider ant-divider-vertical"
/>
<a
class="ant-dropdown-link"
href="javascript:;"
>
More actions
<i
class="anticon anticon-down"
>
<svg
aria-hidden="true"
class=""
data-icon="down"
fill="currentColor"
height="1em"
viewBox="0 0 1024 1024"
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>
</i>
</a>
</span>
</td>
</tr>
@ -282,6 +264,18 @@ exports[`renders ./components/table/demo/basic.md correctly 1`] = `
>
London No. 1 Lake Park
</td>
<td
class=""
>
<span>
<div
class="ant-tag ant-tag-blue"
data-show="true"
>
loser
</div>
</span>
</td>
<td
class=""
>
@ -289,7 +283,7 @@ exports[`renders ./components/table/demo/basic.md correctly 1`] = `
<a
href="javascript:;"
>
Action 一 Jim Green
Invite Jim Green
</a>
<div
class="ant-divider ant-divider-vertical"
@ -299,32 +293,6 @@ exports[`renders ./components/table/demo/basic.md correctly 1`] = `
>
Delete
</a>
<div
class="ant-divider ant-divider-vertical"
/>
<a
class="ant-dropdown-link"
href="javascript:;"
>
More actions
<i
class="anticon anticon-down"
>
<svg
aria-hidden="true"
class=""
data-icon="down"
fill="currentColor"
height="1em"
viewBox="0 0 1024 1024"
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>
</i>
</a>
</span>
</td>
</tr>
@ -355,6 +323,24 @@ exports[`renders ./components/table/demo/basic.md correctly 1`] = `
>
Sidney No. 1 Lake Park
</td>
<td
class=""
>
<span>
<div
class="ant-tag ant-tag-blue"
data-show="true"
>
cool
</div>
<div
class="ant-tag ant-tag-blue"
data-show="true"
>
teacher
</div>
</span>
</td>
<td
class=""
>
@ -362,7 +348,7 @@ exports[`renders ./components/table/demo/basic.md correctly 1`] = `
<a
href="javascript:;"
>
Action 一 Joe Black
Invite Joe Black
</a>
<div
class="ant-divider ant-divider-vertical"
@ -372,32 +358,6 @@ exports[`renders ./components/table/demo/basic.md correctly 1`] = `
>
Delete
</a>
<div
class="ant-divider ant-divider-vertical"
/>
<a
class="ant-dropdown-link"
href="javascript:;"
>
More actions
<i
class="anticon anticon-down"
>
<svg
aria-hidden="true"
class=""
data-icon="down"
fill="currentColor"
height="1em"
viewBox="0 0 1024 1024"
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>
</i>
</a>
</span>
</td>
</tr>
@ -970,25 +930,7 @@ exports[`renders ./components/table/demo/custom-filter-panel.md correctly 1`] =
<i
class="anticon anticon-filter ant-dropdown-trigger"
title="Filter menu"
>
<svg
aria-hidden="true"
class=""
data-icon="filter"
fill="currentColor"
height="1em"
viewBox="0 0 1024 1024"
width="1em"
>
<path
class="st0"
d="M411 561.4l9.5 16.6h183l9.5-16.6L811.3 226H212.7zM420.6 642h182.9v156H420.6z"
/>
<path
d="M880.1 154H143.9c-24.5 0-39.8 26.7-27.5 48L349 597.4V838c0 17.7 14.2 32 31.8 32h262.4c17.6 0 31.8-14.3 31.8-32V597.4L907.7 202c12.2-21.3-3.1-48-27.6-48zM603.4 798H420.6V642h182.9v156zm9.6-236.6l-9.5 16.6h-183l-9.5-16.6L212.7 226h598.6L613 561.4z"
/>
</svg>
</i>
/>
</span>
</th>
</tr>
@ -1895,21 +1837,7 @@ exports[`renders ./components/table/demo/dynamic-settings.md correctly 1`] = `
More actions
<i
class="anticon anticon-down"
>
<svg
aria-hidden="true"
class=""
data-icon="down"
fill="currentColor"
height="1em"
viewBox="0 0 1024 1024"
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>
</i>
/>
</a>
</span>
</td>
@ -1992,21 +1920,7 @@ exports[`renders ./components/table/demo/dynamic-settings.md correctly 1`] = `
More actions
<i
class="anticon anticon-down"
>
<svg
aria-hidden="true"
class=""
data-icon="down"
fill="currentColor"
height="1em"
viewBox="0 0 1024 1024"
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>
</i>
/>
</a>
</span>
</td>
@ -2089,21 +2003,7 @@ exports[`renders ./components/table/demo/dynamic-settings.md correctly 1`] = `
More actions
<i
class="anticon anticon-down"
>
<svg
aria-hidden="true"
class=""
data-icon="down"
fill="currentColor"
height="1em"
viewBox="0 0 1024 1024"
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>
</i>
/>
</a>
</span>
</td>
@ -2186,21 +2086,7 @@ exports[`renders ./components/table/demo/dynamic-settings.md correctly 1`] = `
More actions
<i
class="anticon anticon-down"
>
<svg
aria-hidden="true"
class=""
data-icon="down"
fill="currentColor"
height="1em"
viewBox="0 0 1024 1024"
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>
</i>
/>
</a>
</span>
</td>
@ -2283,21 +2169,7 @@ exports[`renders ./components/table/demo/dynamic-settings.md correctly 1`] = `
More actions
<i
class="anticon anticon-down"
>
<svg
aria-hidden="true"
class=""
data-icon="down"
fill="currentColor"
height="1em"
viewBox="0 0 1024 1024"
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>
</i>
/>
</a>
</span>
</td>
@ -2380,21 +2252,7 @@ exports[`renders ./components/table/demo/dynamic-settings.md correctly 1`] = `
More actions
<i
class="anticon anticon-down"
>
<svg
aria-hidden="true"
class=""
data-icon="down"
fill="currentColor"
height="1em"
viewBox="0 0 1024 1024"
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>
</i>
/>
</a>
</span>
</td>
@ -2477,21 +2335,7 @@ exports[`renders ./components/table/demo/dynamic-settings.md correctly 1`] = `
More actions
<i
class="anticon anticon-down"
>
<svg
aria-hidden="true"
class=""
data-icon="down"
fill="currentColor"
height="1em"
viewBox="0 0 1024 1024"
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>
</i>
/>
</a>
</span>
</td>
@ -2574,21 +2418,7 @@ exports[`renders ./components/table/demo/dynamic-settings.md correctly 1`] = `
More actions
<i
class="anticon anticon-down"
>
<svg
aria-hidden="true"
class=""
data-icon="down"
fill="currentColor"
height="1em"
viewBox="0 0 1024 1024"
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>
</i>
/>
</a>
</span>
</td>
@ -2671,21 +2501,7 @@ exports[`renders ./components/table/demo/dynamic-settings.md correctly 1`] = `
More actions
<i
class="anticon anticon-down"
>
<svg
aria-hidden="true"
class=""
data-icon="down"
fill="currentColor"
height="1em"
viewBox="0 0 1024 1024"
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>
</i>
/>
</a>
</span>
</td>
@ -2768,21 +2584,7 @@ exports[`renders ./components/table/demo/dynamic-settings.md correctly 1`] = `
More actions
<i
class="anticon anticon-down"
>
<svg
aria-hidden="true"
class=""
data-icon="down"
fill="currentColor"
height="1em"
viewBox="0 0 1024 1024"
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>
</i>
/>
</a>
</span>
</td>
@ -7237,7 +7039,7 @@ exports[`renders ./components/table/demo/grouping-columns.md correctly 1`] = `
<col />
<col />
<col
style="width:60px;min-width:60px"
style="width:80px;min-width:80px"
/>
</colgroup>
<thead
@ -7253,25 +7055,7 @@ exports[`renders ./components/table/demo/grouping-columns.md correctly 1`] = `
<i
class="anticon anticon-filter ant-dropdown-trigger"
title="Filter menu"
>
<svg
aria-hidden="true"
class=""
data-icon="filter"
fill="currentColor"
height="1em"
viewBox="0 0 1024 1024"
width="1em"
>
<path
class="st0"
d="M411 561.4l9.5 16.6h183l9.5-16.6L811.3 226H212.7zM420.6 642h182.9v156H420.6z"
/>
<path
d="M880.1 154H143.9c-24.5 0-39.8 26.7-27.5 48L349 597.4V838c0 17.7 14.2 32 31.8 32h262.4c17.6 0 31.8-14.3 31.8-32V597.4L907.7 202c12.2-21.3-3.1-48-27.6-48zM603.4 798H420.6V642h182.9v156zm9.6-236.6l-9.5 16.6h-183l-9.5-16.6L212.7 226h598.6L613 561.4z"
/>
</svg>
</i>
/>
</span>
</th>
<th
@ -7417,7 +7201,7 @@ exports[`renders ./components/table/demo/grouping-columns.md correctly 1`] = `
<col />
<col />
<col
style="width:60px;min-width:60px"
style="width:80px;min-width:80px"
/>
</colgroup>
<tbody
@ -7944,25 +7728,7 @@ exports[`renders ./components/table/demo/grouping-columns.md correctly 1`] = `
<i
class="anticon anticon-filter ant-dropdown-trigger"
title="Filter menu"
>
<svg
aria-hidden="true"
class=""
data-icon="filter"
fill="currentColor"
height="1em"
viewBox="0 0 1024 1024"
width="1em"
>
<path
class="st0"
d="M411 561.4l9.5 16.6h183l9.5-16.6L811.3 226H212.7zM420.6 642h182.9v156H420.6z"
/>
<path
d="M880.1 154H143.9c-24.5 0-39.8 26.7-27.5 48L349 597.4V838c0 17.7 14.2 32 31.8 32h262.4c17.6 0 31.8-14.3 31.8-32V597.4L907.7 202c12.2-21.3-3.1-48-27.6-48zM603.4 798H420.6V642h182.9v156zm9.6-236.6l-9.5 16.6h-183l-9.5-16.6L212.7 226h598.6L613 561.4z"
/>
</svg>
</i>
/>
</span>
</th>
</tr>
@ -8144,7 +7910,7 @@ exports[`renders ./components/table/demo/grouping-columns.md correctly 1`] = `
>
<colgroup>
<col
style="width:60px;min-width:60px"
style="width:80px;min-width:80px"
/>
</colgroup>
<thead
@ -8176,7 +7942,7 @@ exports[`renders ./components/table/demo/grouping-columns.md correctly 1`] = `
>
<colgroup>
<col
style="width:60px;min-width:60px"
style="width:80px;min-width:80px"
/>
</colgroup>
<tbody
@ -8440,25 +8206,7 @@ exports[`renders ./components/table/demo/head.md correctly 1`] = `
<i
class="anticon anticon-filter ant-dropdown-trigger"
title="Filter menu"
>
<svg
aria-hidden="true"
class=""
data-icon="filter"
fill="currentColor"
height="1em"
viewBox="0 0 1024 1024"
width="1em"
>
<path
class="st0"
d="M411 561.4l9.5 16.6h183l9.5-16.6L811.3 226H212.7zM420.6 642h182.9v156H420.6z"
/>
<path
d="M880.1 154H143.9c-24.5 0-39.8 26.7-27.5 48L349 597.4V838c0 17.7 14.2 32 31.8 32h262.4c17.6 0 31.8-14.3 31.8-32V597.4L907.7 202c12.2-21.3-3.1-48-27.6-48zM603.4 798H420.6V642h182.9v156zm9.6-236.6l-9.5 16.6h-183l-9.5-16.6L212.7 226h598.6L613 561.4z"
/>
</svg>
</i>
/>
</span>
</th>
<th
@ -8516,25 +8264,7 @@ exports[`renders ./components/table/demo/head.md correctly 1`] = `
<i
class="anticon anticon-filter ant-dropdown-trigger"
title="Filter menu"
>
<svg
aria-hidden="true"
class=""
data-icon="filter"
fill="currentColor"
height="1em"
viewBox="0 0 1024 1024"
width="1em"
>
<path
class="st0"
d="M411 561.4l9.5 16.6h183l9.5-16.6L811.3 226H212.7zM420.6 642h182.9v156H420.6z"
/>
<path
d="M880.1 154H143.9c-24.5 0-39.8 26.7-27.5 48L349 597.4V838c0 17.7 14.2 32 31.8 32h262.4c17.6 0 31.8-14.3 31.8-32V597.4L907.7 202c12.2-21.3-3.1-48-27.6-48zM603.4 798H420.6V642h182.9v156zm9.6-236.6l-9.5 16.6h-183l-9.5-16.6L212.7 226h598.6L613 561.4z"
/>
</svg>
</i>
/>
</span>
</th>
</tr>
@ -8708,6 +8438,7 @@ exports[`renders ./components/table/demo/jsx.md correctly 1`] = `
<col />
<col />
<col />
<col />
</colgroup>
<thead
class="ant-table-thead"
@ -8737,6 +8468,14 @@ exports[`renders ./components/table/demo/jsx.md correctly 1`] = `
Address
</span>
</th>
<th
class=""
rowspan="2"
>
<span>
Tags
</span>
</th>
<th
class=""
rowspan="2"
@ -8794,6 +8533,24 @@ exports[`renders ./components/table/demo/jsx.md correctly 1`] = `
>
New York No. 1 Lake Park
</td>
<td
class=""
>
<span>
<div
class="ant-tag ant-tag-blue"
data-show="true"
>
nice
</div>
<div
class="ant-tag ant-tag-blue"
data-show="true"
>
developer
</div>
</span>
</td>
<td
class=""
>
@ -8801,7 +8558,7 @@ exports[`renders ./components/table/demo/jsx.md correctly 1`] = `
<a
href="javascript:;"
>
Action 一
Invite Brown
</a>
<div
class="ant-divider ant-divider-vertical"
@ -8811,32 +8568,6 @@ exports[`renders ./components/table/demo/jsx.md correctly 1`] = `
>
Delete
</a>
<div
class="ant-divider ant-divider-vertical"
/>
<a
class="ant-dropdown-link"
href="javascript:;"
>
More actions
<i
class="anticon anticon-down"
>
<svg
aria-hidden="true"
class=""
data-icon="down"
fill="currentColor"
height="1em"
viewBox="0 0 1024 1024"
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>
</i>
</a>
</span>
</td>
</tr>
@ -8868,6 +8599,18 @@ exports[`renders ./components/table/demo/jsx.md correctly 1`] = `
>
London No. 1 Lake Park
</td>
<td
class=""
>
<span>
<div
class="ant-tag ant-tag-blue"
data-show="true"
>
loser
</div>
</span>
</td>
<td
class=""
>
@ -8875,7 +8618,7 @@ exports[`renders ./components/table/demo/jsx.md correctly 1`] = `
<a
href="javascript:;"
>
Action 一
Invite Green
</a>
<div
class="ant-divider ant-divider-vertical"
@ -8885,32 +8628,6 @@ exports[`renders ./components/table/demo/jsx.md correctly 1`] = `
>
Delete
</a>
<div
class="ant-divider ant-divider-vertical"
/>
<a
class="ant-dropdown-link"
href="javascript:;"
>
More actions
<i
class="anticon anticon-down"
>
<svg
aria-hidden="true"
class=""
data-icon="down"
fill="currentColor"
height="1em"
viewBox="0 0 1024 1024"
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>
</i>
</a>
</span>
</td>
</tr>
@ -8942,6 +8659,24 @@ exports[`renders ./components/table/demo/jsx.md correctly 1`] = `
>
Sidney No. 1 Lake Park
</td>
<td
class=""
>
<span>
<div
class="ant-tag ant-tag-blue"
data-show="true"
>
cool
</div>
<div
class="ant-tag ant-tag-blue"
data-show="true"
>
teacher
</div>
</span>
</td>
<td
class=""
>
@ -8949,7 +8684,7 @@ exports[`renders ./components/table/demo/jsx.md correctly 1`] = `
<a
href="javascript:;"
>
Action 一
Invite Black
</a>
<div
class="ant-divider ant-divider-vertical"
@ -8959,32 +8694,6 @@ exports[`renders ./components/table/demo/jsx.md correctly 1`] = `
>
Delete
</a>
<div
class="ant-divider ant-divider-vertical"
/>
<a
class="ant-dropdown-link"
href="javascript:;"
>
More actions
<i
class="anticon anticon-down"
>
<svg
aria-hidden="true"
class=""
data-icon="down"
fill="currentColor"
height="1em"
viewBox="0 0 1024 1024"
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>
</i>
</a>
</span>
</td>
</tr>
@ -9410,25 +9119,7 @@ exports[`renders ./components/table/demo/reset-filter.md correctly 1`] = `
<i
class="anticon anticon-filter ant-dropdown-trigger"
title="Filter menu"
>
<svg
aria-hidden="true"
class=""
data-icon="filter"
fill="currentColor"
height="1em"
viewBox="0 0 1024 1024"
width="1em"
>
<path
class="st0"
d="M411 561.4l9.5 16.6h183l9.5-16.6L811.3 226H212.7zM420.6 642h182.9v156H420.6z"
/>
<path
d="M880.1 154H143.9c-24.5 0-39.8 26.7-27.5 48L349 597.4V838c0 17.7 14.2 32 31.8 32h262.4c17.6 0 31.8-14.3 31.8-32V597.4L907.7 202c12.2-21.3-3.1-48-27.6-48zM603.4 798H420.6V642h182.9v156zm9.6-236.6l-9.5 16.6h-183l-9.5-16.6L212.7 226h598.6L613 561.4z"
/>
</svg>
</i>
/>
</span>
</th>
<th
@ -9486,25 +9177,7 @@ exports[`renders ./components/table/demo/reset-filter.md correctly 1`] = `
<i
class="anticon anticon-filter ant-dropdown-trigger"
title="Filter menu"
>
<svg
aria-hidden="true"
class=""
data-icon="filter"
fill="currentColor"
height="1em"
viewBox="0 0 1024 1024"
width="1em"
>
<path
class="st0"
d="M411 561.4l9.5 16.6h183l9.5-16.6L811.3 226H212.7zM420.6 642h182.9v156H420.6z"
/>
<path
d="M880.1 154H143.9c-24.5 0-39.8 26.7-27.5 48L349 597.4V838c0 17.7 14.2 32 31.8 32h262.4c17.6 0 31.8-14.3 31.8-32V597.4L907.7 202c12.2-21.3-3.1-48-27.6-48zM603.4 798H420.6V642h182.9v156zm9.6-236.6l-9.5 16.6h-183l-9.5-16.6L212.7 226h598.6L613 561.4z"
/>
</svg>
</i>
/>
</span>
</th>
</tr>
@ -10919,21 +10592,7 @@ exports[`renders ./components/table/demo/row-selection-custom.md correctly 1`] =
>
<i
class="anticon anticon-down"
>
<svg
aria-hidden="true"
class=""
data-icon="down"
fill="currentColor"
height="1em"
viewBox="0 0 1024 1024"
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>
</i>
/>
</div>
</div>
</span>

View File

@ -14,7 +14,7 @@ title:
Simple table with actions.
````jsx
import { Table, Icon, Divider } from 'antd';
import { Table, Divider, Tag } from 'antd';
const columns = [{
title: 'Name',
@ -29,18 +29,23 @@ const columns = [{
title: 'Address',
dataIndex: 'address',
key: 'address',
}, {
title: 'Tags',
key: 'tags',
dataIndex: 'tags',
render: tags => (
<span>
{tags.map(tag => <Tag color="blue" key={tag}>{tag}</Tag>)}
</span>
),
}, {
title: 'Action',
key: 'action',
render: (text, record) => (
<span>
<a href="javascript:;">Action 一 {record.name}</a>
<a href="javascript:;">Invite {record.name}</a>
<Divider type="vertical" />
<a href="javascript:;">Delete</a>
<Divider type="vertical" />
<a href="javascript:;" className="ant-dropdown-link">
More actions <Icon type="down" />
</a>
</span>
),
}];
@ -50,16 +55,19 @@ const data = [{
name: 'John Brown',
age: 32,
address: 'New York No. 1 Lake Park',
tags: ['nice', 'developer'],
}, {
key: '2',
name: 'Jim Green',
age: 42,
address: 'London No. 1 Lake Park',
tags: ['loser'],
}, {
key: '3',
name: 'Joe Black',
age: 32,
address: 'Sidney No. 1 Lake Park',
tags: ['cool', 'teacher'],
}];
ReactDOM.render(<Table columns={columns} dataSource={data} />, mountNode);

View File

@ -75,7 +75,7 @@ const columns = [{
title: 'Gender',
dataIndex: 'gender',
key: 'gender',
width: 60,
width: 80,
fixed: 'right',
}];

View File

@ -18,7 +18,7 @@ Using JSX style API (introduced in 2.5.0)
> Since this is just a syntax sugar for the prop `columns`, you can't compose `Column` and `ColumnGroup` with other Components.
````jsx
import { Table, Icon, Divider } from 'antd';
import { Table, Divider, Tag } from 'antd';
const { Column, ColumnGroup } = Table;
@ -28,18 +28,21 @@ const data = [{
lastName: 'Brown',
age: 32,
address: 'New York No. 1 Lake Park',
tags: ['nice', 'developer'],
}, {
key: '2',
firstName: 'Jim',
lastName: 'Green',
age: 42,
address: 'London No. 1 Lake Park',
tags: ['loser'],
}, {
key: '3',
firstName: 'Joe',
lastName: 'Black',
age: 32,
address: 'Sidney No. 1 Lake Park',
tags: ['cool', 'teacher'],
}];
ReactDOM.render(
@ -66,18 +69,24 @@ ReactDOM.render(
dataIndex="address"
key="address"
/>
<Column
title="Tags"
dataIndex="tags"
key="tags"
render={tags => (
<span>
{tags.map(tag => <Tag color="blue" key={tag}>{tag}</Tag>)}
</span>
)}
/>
<Column
title="Action"
key="action"
render={(text, record) => (
<span>
<a href="javascript:;">Action 一 {record.name}</a>
<a href="javascript:;">Invite {record.lastName}</a>
<Divider type="vertical" />
<a href="javascript:;">Delete</a>
<Divider type="vertical" />
<a href="javascript:;" className="ant-dropdown-link">
More actions <Icon type="down" />
</a>
</span>
)}
/>

View File

@ -23,6 +23,12 @@ export default class CheckableTag extends React.Component<CheckableTagProps> {
}, className);
delete (restProps as any).onChange; // TypeScript cannot check delete now.
return <div {...restProps as any} className={cls} onClick={this.handleClick} />;
return (
<div
{...restProps as any}
className={cls}
onClick={this.handleClick}
/>
);
}
}

View File

@ -1,17 +1,37 @@
// Jest Snapshot v1, https://goo.gl/fbAQLP
exports[`Tag can be controlled by visible 1`] = `
exports[`Tag visibility can be controlled by visible with hidden as initial value 1`] = `<div />`;
exports[`Tag visibility can be controlled by visible with hidden as initial value 2`] = `
<div
class="ant-tag"
data-show="true"
/>
`;
exports[`Tag visibility can be controlled by visible with hidden as initial value 3`] = `
<div
style="width: 0px;"
/>
`;
exports[`Tag visibility can be controlled by visible with visible as initial value 1`] = `
<div
class="ant-tag ant-tag-zoom-appear"
data-show="true"
/>
`;
exports[`Tag can be controlled by visible 2`] = `null`;
exports[`Tag visibility can be controlled by visible with visible as initial value 2`] = `
<div
style="width: 0px;"
/>
`;
exports[`Tag can be controlled by visible 3`] = `
exports[`Tag visibility can be controlled by visible with visible as initial value 3`] = `
<div
class="ant-tag"
data-show="true"
style="width: 0px;"
/>
`;

View File

@ -39,16 +39,31 @@ describe('Tag', () => {
expect(wrapper.find('.ant-tag').length).toBe(1);
});
it('can be controlled by visible', () => {
const wrapper = mount(
<Tag visible />
);
expect(wrapper.render()).toMatchSnapshot();
wrapper.setProps({ visible: false });
jest.runAllTimers();
expect(wrapper.render()).toMatchSnapshot();
wrapper.setProps({ visible: true });
jest.runAllTimers();
expect(wrapper.render()).toMatchSnapshot();
describe('visibility', () => {
it('can be controlled by visible with visible as initial value', () => {
const wrapper = mount(
<Tag visible />
);
expect(wrapper.render()).toMatchSnapshot();
wrapper.setProps({ visible: false });
jest.runAllTimers();
expect(wrapper.render()).toMatchSnapshot();
wrapper.setProps({ visible: true });
jest.runAllTimers();
expect(wrapper.render()).toMatchSnapshot();
});
it('can be controlled by visible with hidden as initial value', () => {
const wrapper = mount(
<Tag visible={false} />
);
expect(wrapper.render()).toMatchSnapshot();
wrapper.setProps({ visible: true });
jest.runAllTimers();
expect(wrapper.render()).toMatchSnapshot();
wrapper.setProps({ visible: false });
jest.runAllTimers();
expect(wrapper.render()).toMatchSnapshot();
});
});
});

View File

@ -6,6 +6,7 @@ import omit from 'omit.js';
import { polyfill } from 'react-lifecycles-compat';
import Icon from '../icon';
import CheckableTag from './CheckableTag';
import Wave from '../_util/wave';
export { CheckableTagProps } from './CheckableTag';
@ -27,6 +28,7 @@ export interface TagState {
closing: boolean;
closed: boolean;
visible: boolean;
mounted: boolean;
}
class Tag extends React.Component<TagProps, TagState> {
@ -36,14 +38,30 @@ class Tag extends React.Component<TagProps, TagState> {
closable: false,
};
static getDerivedStateFromProps(nextProps: TagProps) {
return ('visible' in nextProps) ? { visible: nextProps.visible } : null;
static getDerivedStateFromProps(nextProps: TagProps, state: TagState) {
if ('visible' in nextProps) {
let newState: Partial<TagState> = {
visible: nextProps.visible,
mounted: true,
};
if (!state.mounted) {
newState = {
...newState,
closed: !nextProps.visible,
};
}
return newState;
}
return null;
}
state = {
closing: false,
closed: false,
visible: true,
mounted: false,
};
componentDidUpdate(_prevProps: TagProps, prevState: TagState) {
@ -129,7 +147,7 @@ class Tag extends React.Component<TagProps, TagState> {
backgroundColor: (color && !isPresetColor) ? color : null,
...style,
};
const tag = this.state.closed ? null : (
const tag = this.state.closed ? <div /> : (
<div
data-show={!this.state.closing}
{...divProps}
@ -140,16 +158,19 @@ class Tag extends React.Component<TagProps, TagState> {
{closeIcon}
</div>
);
return (
<Animate
component=""
showProp="data-show"
transitionName={`${prefixCls}-zoom`}
transitionAppear
onEnd={this.animationEnd}
>
{tag}
</Animate>
<Wave>
<Animate
component=""
showProp="data-show"
transitionName={`${prefixCls}-zoom`}
transitionAppear
onEnd={this.animationEnd}
>
{tag}
</Animate>
</Wave>
);
}
}

View File

@ -1,5 +1,6 @@
import * as React from 'react';
import { cloneElement } from 'react';
import { polyfill } from 'react-lifecycles-compat';
import RcTooltip from 'rc-tooltip';
import classNames from 'classnames';
import getPlacements, { AdjustOverflow, PlacementsConfig } from './placements';
@ -56,7 +57,7 @@ const splitObject = (obj: any, keys: string[]) => {
return { picked, omitted };
};
export default class Tooltip extends React.Component<TooltipProps, any> {
class Tooltip extends React.Component<TooltipProps, any> {
static defaultProps = {
prefixCls: 'ant-tooltip',
placement: 'top' as TooltipPlacement,
@ -67,6 +68,13 @@ export default class Tooltip extends React.Component<TooltipProps, any> {
autoAdjustOverflow: true,
};
static getDerivedStateFromProps(nextProps: TooltipProps) {
if ('visible' in nextProps) {
return { visible: nextProps.visible };
}
return null;
}
private tooltip: typeof RcTooltip;
constructor(props: TooltipProps) {
@ -77,12 +85,6 @@ export default class Tooltip extends React.Component<TooltipProps, any> {
};
}
componentWillReceiveProps(nextProps: TooltipProps) {
if ('visible' in nextProps) {
this.setState({ visible: nextProps.visible });
}
}
onVisibleChange = (visible: boolean) => {
const { onVisibleChange } = this.props;
if (!('visible' in this.props)) {
@ -226,3 +228,7 @@ export default class Tooltip extends React.Component<TooltipProps, any> {
);
}
}
polyfill(Tooltip);
export default Tooltip;

View File

@ -36,6 +36,7 @@ export interface AntTreeNodeProps {
expanded?: boolean;
loading?: boolean;
selected?: boolean;
selectable?: boolean;
icon?: ((treeNode: AntdTreeNodeAttribute) => React.ReactNode) | React.ReactNode;
children?: React.ReactNode;
}

View File

@ -1,4 +1,5 @@
import * as React from 'react';
import { polyfill } from 'react-lifecycles-compat';
import RcUpload from 'rc-upload';
import classNames from 'classnames';
import uniqBy from 'lodash/uniqBy';
@ -20,7 +21,7 @@ import { T, fileToObject, genPercentAdd, getFileItem, removeFileItem } from './u
export { UploadProps };
export default class Upload extends React.Component<UploadProps, UploadState> {
class Upload extends React.Component<UploadProps, UploadState> {
static Dragger: typeof Dragger;
static defaultProps = {
@ -38,6 +39,15 @@ export default class Upload extends React.Component<UploadProps, UploadState> {
supportServerRender: true,
};
static getDerivedStateFromProps(nextProps: UploadProps) {
if ('fileList' in nextProps) {
return {
fileList: nextProps.fileList || [],
};
}
return null;
}
recentUploadStatus: boolean | PromiseLike<any>;
progressTimer: any;
@ -174,14 +184,6 @@ export default class Upload extends React.Component<UploadProps, UploadState> {
}
}
componentWillReceiveProps(nextProps: UploadProps) {
if ('fileList' in nextProps) {
this.setState({
fileList: nextProps.fileList || [],
});
}
}
onFileDrop = (e: React.DragEvent<HTMLDivElement>) => {
this.setState({
dragState: e.type,
@ -317,3 +319,7 @@ export default class Upload extends React.Component<UploadProps, UploadState> {
);
}
}
polyfill(Upload);
export default Upload;

View File

@ -161,6 +161,21 @@ describe('Upload', () => {
});
});
it('should be controlled by fileList', () => {
const fileList = [{
uid: '-1',
name: 'foo.png',
status: 'done',
url: 'http://www.baidu.com/xxx.png',
}];
const wrapper = mount(
<Upload />
);
expect(wrapper.instance().state.fileList).toEqual([]);
wrapper.setProps({ fileList });
expect(wrapper.instance().state.fileList).toEqual(fileList);
});
describe('util', () => {
it('should be able to copy file instance', () => {
const file = new File([], 'aaa.zip');

View File

@ -8,7 +8,7 @@ export interface HttpRequestHeader {
export interface RcFile extends File {
uid: string;
lastModifiedDate?: Date;
lastModifiedDate: Date;
}
export interface UploadFile {

View File

@ -20,8 +20,9 @@ title: 设计价值观
作为一份子,自然界的方方面面都会对用户行为产生深远影响,设计者应该从其中汲取灵感,并运用到当下的设计工作中。我们已做了部分探索,并将追求『自然』作为我们未来持之以恒的方向。
- 在行为的执行中,利用[行为分析](https://zhuanlan.zhihu.com/p/41952711)、人工智能、传感器等一系列方式,辅助用户有效决策、减少用户额外操作,从而节省用户脑力和体力,让人机交互行为更自然。
- 在感知和认知中,视觉系统扮演着最重要的角色,通过提炼自然界中的客观规律并运用到界面设计中,从而创建更有层次产品体验;同时,适时加入听觉系统、触觉系统等,创建更多维、更真实的产品体验。详见视觉语言
- 在行为的执行中,利用行为分析、人工智能、传感器等一系列方式,辅助用户有效决策、减少用户额外操作,从而节省用户脑力和体力,让人机交互行为更自然。
## 确定

View File

@ -1,6 +1,6 @@
{
"name": "antd",
"version": "3.8.0",
"version": "3.8.2",
"title": "Ant Design",
"description": "An enterprise-class UI design language and React-based implementation",
"homepage": "http://ant.design/",
@ -61,7 +61,7 @@
"rc-checkbox": "~2.1.5",
"rc-collapse": "~1.9.0",
"rc-dialog": "~7.2.0",
"rc-drawer": "~1.6.2",
"rc-drawer": "~1.7.3",
"rc-dropdown": "~2.2.0",
"rc-editor-mention": "^1.0.2",
"rc-form": "^2.1.0",
@ -80,7 +80,7 @@
"rc-time-picker": "~3.4.0",
"rc-tooltip": "~3.7.0",
"rc-tree": "~1.14.3",
"rc-tree-select": "~2.0.14",
"rc-tree-select": "~2.1.0",
"rc-trigger": "^2.5.4",
"rc-upload": "~2.5.0",
"rc-util": "^4.0.4",
@ -195,7 +195,7 @@
"lint:style": "stylelint \"{site,components}/**/*.less\" --syntax less",
"lint-fix:ts": "npm run tsc && antd-tools run ts-lint-fix",
"lint-fix": "npm run lint-fix:code && npm run lint-fix:demo",
"lint-fix:code": "eslint --fix tests site scripts components ./.eslintrc.js ./webpack.config.js --ext '.js,.jsx'",
"lint-fix:code": "eslint --fix tests site scripts components ./.*.js ./webpack.config.js --ext '.js,.jsx'",
"lint-fix:demo": "eslint-tinker ./components/*/demo/*.md",
"sort-api": "node ./scripts/sort-api-table.js",
"dist": "antd-tools run dist",
@ -212,7 +212,7 @@
"authors": "git log --format='%aN <%aE>' | sort -u | grep -v 'users.noreply.github.com' | grep -v 'gitter.im' | grep -v '.local>' | grep -v 'alibaba-inc.com' | grep -v 'alipay.com' | grep -v 'taobao.com' > AUTHORS.txt",
"lint-staged": "lint-staged",
"lint-staged:ts": "tsc && node node_modules/tslint/bin/tslint",
"lint-staged:es": "eslint ./.eslintrc.js ./webpack.config.js",
"lint-staged:es": "eslint ./.*.js ./webpack.config.js",
"lint-staged:demo": "cross-env RUN_ENV=DEMO eslint --ext '.md'"
},
"lint-staged": {

View File

@ -6,11 +6,28 @@
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<meta name="description" content="An enterprise-class UI design language and React-based implementation with a set of high-quality React components, one of best React UI library for enterprises">
<title>Ant Design - A UI Design Language</title>
<!-- Polyfills -->
<!--[if IE]>
<script src="https://as.alipayobjects.com/g/component/??es6-shim/0.35.1/es6-sham.min.js,es6-shim/0.35.1/es6-shim.min.js"></script>
<link rel="icon" href="https://gw.alipayobjects.com/zos/rmsportal/rlpTLlbMzTNYuZGGCVYM.png" type="image/x-icon">
<link rel="stylesheet" type="text/css" href="{{ root }}index-1.css"/>
<link rel="stylesheet" type="text/css" href="{{ root }}index-2.css"/>
<style id="nprogress-style">
#nprogress { display: none }
</style>
</head>
<body>
<div id="react-content">
{{ content | safe }}
</div>
<link rel="stylesheet/less" type="text/css" href="{{ root }}color.less"/>
<script src="https://gw.alipayobjects.com/os/lib/??es6-shim/0.35.3/es6-sham.min.js,es6-shim/0.35.3/es6-shim.min.js"></script>
<!--[if lte IE 10]>
<script src="https://as.alipayobjects.com/g/component/??console-polyfill/0.2.2/index.js,media-match/2.0.2/media.match.min.js"></script>
<![endif]-->
<script>
if (!window.Intl) {
document.writeln('<script src="https://as.alipayobjects.com/g/component/intl/1.0.1/??Intl.js,locale-data/jsonp/en.js,locale-data/jsonp/zh.js">' + '<' + '/script>');
}
</script>
<script>
(function() {
function isLocalStorageNameSupported() {
var testKey = 'test';
@ -61,16 +78,8 @@
document.documentElement.className += isZhCN(pathname) ? 'zh-cn' : 'en-us';
})()
</script>
<link rel="icon" href="https://gw.alipayobjects.com/zos/rmsportal/rlpTLlbMzTNYuZGGCVYM.png" type="image/x-icon">
<link rel="stylesheet" type="text/css" href="{{ root }}index-1.css"/>
<link rel="stylesheet" type="text/css" href="{{ root }}index-2.css"/>
<style id="nprogress-style">
#nprogress { display: none }
</style>
<!--[if lte IE 10]>
<script
src="https://as.alipayobjects.com/g/component/??console-polyfill/0.2.2/index.js,media-match/2.0.2/media.match.min.js"></script>
<![endif]-->
<script src="{{ root }}common.js"></script>
<script src="{{ root }}index.js"></script>
<!-- Global site tag (gtag.js) - Google Analytics -->
<script async src="https://www.googletagmanager.com/gtag/js?id=UA-72788897-1"></script>
<script>
@ -82,14 +91,6 @@
gtag('config', 'UA-72788897-1');
}
</script>
<script>
if (!window.Intl) {
document.writeln('<script src="https://as.alipayobjects.com/g/component/intl/1.0.1/??Intl.js,locale-data/jsonp/en.js,locale-data/jsonp/zh.js">' + '<' + '/script>');
}
if (!window.Promise) {
document.writeln('<script src="https://as.alipayobjects.com/g/component/es6-promise/3.2.2/es6-promise.min.js"' + '>' + '<' + '/' + 'script>');
}
</script>
<!-- Hotjar Tracking Code for ant.design -->
<script>
(function(h,o,t,j,a,r){
@ -101,13 +102,5 @@
a.appendChild(r);
})(window,document,'//static.hotjar.com/c/hotjar-','.js?sv=');
</script>
</head>
<body>
<div id="react-content">
{{ content | safe }}
</div>
<link rel="stylesheet/less" type="text/css" href="{{ root }}color.less"/>
<script src="{{ root }}common.js"></script>
<script src="{{ root }}index.js"></script>
</body>
</html>

View File

@ -1,6 +1,6 @@
import React from 'react';
import { FormattedMessage, injectIntl } from 'react-intl';
import { Modal, message, Row, Col } from 'antd';
import { Modal, message, Row, Col, Badge } from 'antd';
import { isLocalStorageNameSupported, loadScript } from '../utils';
import ColorPicker from '../Color/ColorPicker';
@ -108,9 +108,11 @@ class Footer extends React.Component {
</a>
</div>
<div>
<a target="_blank" rel="noopener noreferrer" href="http://kitchen.alipay.com">Kitchen</a>
<span> - </span>
<FormattedMessage id="app.footer.kitchen" />
<Badge dot offset={[3, 0]}>
<a target="_blank" rel="noopener noreferrer" href="http://kitchen.alipay.com">Kitchen</a>
<span> - </span>
<FormattedMessage id="app.footer.kitchen" />
</Badge>
</div>
<div>
<a href="http://scaffold.ant.design">Scaffolds</a>

View File

@ -25,7 +25,7 @@ module.exports = {
'app.demo.codesandbox': '在 CodeSandbox 中打开',
'app.demo.riddle': '在 Riddle 中打开',
'app.home.slogan': '一个 UI 设计语言',
'app.home.introduce': '一个服务于企业级产品的设计体系,基于『确定』和『自然』的设计价值观和模块化的解决方案,让设计者专注于更好的用户体验。',
'app.home.introduce': '服务于企业级产品的设计体系,基于确定和自然的设计价值观上的模块化解决方案,让设计者和开发者专注于更好的用户体验。',
'app.home.design-language': '设计语言',
'app.home.solution': '解决方案',
'app.home.components-explain': '基于 Ant Design 设计语言,我们提供了一套开箱即用的高质量 React 组件,用于开发和服务于企业级中后台产品,除官方的 React 实现,还有 Angular、Vue 的实现',