Merge remote-tracking branch 'ant-design/master'

This commit is contained in:
liekkas 2016-08-26 10:28:38 +08:00
commit 6dae3aebf1
158 changed files with 1572 additions and 3139 deletions

View File

@ -28,7 +28,9 @@ const eslintrc = {
'react/sort-comp': 0, 'react/sort-comp': 0,
'react/prop-types': 0, 'react/prop-types': 0,
'react/jsx-first-prop-new-line': 0, 'react/jsx-first-prop-new-line': 0,
"react/jsx-filename-extension": [1, { extensions: ['.js', '.jsx', '.md'] }],
'import/no-unresolved': 0, 'import/no-unresolved': 0,
'import/no-extraneous-dependencies': 0,
'no-param-reassign': 0, 'no-param-reassign': 0,
'no-return-assign': 0, 'no-return-assign': 0,
'max-len': 0, 'max-len': 0,
@ -50,6 +52,8 @@ if (process.env.RUN_ENV === 'DEMO') {
'prefer-rest-params': 0, 'prefer-rest-params': 0,
'react/no-multi-comp': 0, 'react/no-multi-comp': 0,
'react/prefer-es6-class': 0, 'react/prefer-es6-class': 0,
'jsx-a11y/href-no-hash': 0,
'import/newline-after-import': 0,
}); });
} }

View File

@ -9,11 +9,22 @@ timeline: true
--- ---
## 1.10.0
`2016-08-20`
- Affix 和 BackTop 新增 `target` 属性,支持指定滚动容器。[#2718](https://github.com/ant-design/ant-design/issues/2718)
- 文档页面加上编辑按钮,方便社区贡献。[#2325](https://github.com/ant-design/ant-design/issues/2325)
- 升级 rc-cascader 依赖,修复一个 `loadData` 属性和表单结合使用的问题。[#2767](https://github.com/ant-design/ant-design/issues/2767)
- 修复 `editable-card` 类型的 Tabs 没有关闭图标的问题。[#2747](https://github.com/ant-design/ant-design/issues/2747)
- Menu 修正默认 `z-index`。[#2762](https://github.com/ant-design/ant-design/issues/2762)
- 修正 Select 组件在 IE 下的一些样式问题。[#2741](https://github.com/ant-design/ant-design/issues/2741)
## 1.9.1 ## 1.9.1
`2016-08-16` `2016-08-16`
- 修复 Tabs 的 `type="editable-card"` 模式activeKey 错误的问题。[#2725](https://github.com/ant-design/ant-design/issues/2725) - 修复 `editable-card` 类型的 Tabs 设置 `activeKey` 无效的问题。[#2725](https://github.com/ant-design/ant-design/issues/2725)
- 修复一个 Table 的样式兼容性问题。[#2723](https://github.com/ant-design/ant-design/issues/2723) - 修复一个 Table 的样式兼容性问题。[#2723](https://github.com/ant-design/ant-design/issues/2723)
- 更新 axure 部件库。[#2714](https://github.com/ant-design/ant-design/issues/2714) - 更新 axure 部件库。[#2714](https://github.com/ant-design/ant-design/issues/2714)

View File

@ -0,0 +1,29 @@
---
order: 4
title: 参考对象
---
`target` 设置 `Affix` 需要监听其滚动事件的元素,默认为 `window`
````jsx
import { Affix, Button } from 'antd';
const Demo = () => {
return (
<div style={{ height: 100, overflow: 'hidden' }}>
<div style={{ height: '100%', overflowY: 'scroll' }} id="affix-target">
<div style={{ height: 300, backgroundImage: 'url(https://zos.alipayobjects.com/rmsportal/RmjwQiJorKyobvI.jpg)' }}>
<br />
<br />
<br />
<Affix target={() => document.getElementById('affix-target')} offsetTop={20}>
<Button type="primary">固定在容器顶部</Button>
</Affix>
</div>
</div>
</div>
);
};
ReactDOM.render(<Demo />, mountNode);
````

View File

@ -6,32 +6,42 @@ import warning from 'warning';
import assign from 'object-assign'; import assign from 'object-assign';
import shallowequal from 'shallowequal'; import shallowequal from 'shallowequal';
function getScroll(w, top?: boolean) { function getScroll(target, top) {
let ret = w[`page${top ? 'Y' : 'X'}Offset`]; const prop = top ? 'pageYOffset' : 'pageXOffset';
const method = `scroll${top ? 'Top' : 'Left'}`; const method = top ? 'scrollTop' : 'scrollLeft';
if (typeof ret !== 'number') { const isWindow = target === window;
const d = w.document;
let ret = isWindow ? target[prop] : target[method];
// ie6,7,8 standard mode // ie6,7,8 standard mode
ret = d.documentElement[method]; if (isWindow && typeof ret !== 'number') {
if (typeof ret !== 'number') { ret = window.document.documentElement[method];
// quirks mode
ret = d.body[method];
}
} }
return ret; return ret;
} }
function getOffset(element) { function getTargetRect(target): any {
const rect = element.getBoundingClientRect(); return target !== window ?
const body = document.body; target.getBoundingClientRect() :
const clientTop = element.clientTop || body.clientTop || 0; { top: 0, left: 0, bottom: 0 };
const clientLeft = element.clientLeft || body.clientLeft || 0; }
const scrollTop = getScroll(window, true);
const scrollLeft = getScroll(window); function getOffset(element, target) {
const elemRect = element.getBoundingClientRect();
const targetRect = getTargetRect(target);
const scrollTop = getScroll(target, true);
const scrollLeft = getScroll(target, false);
const docElem = window.document.body;
const clientTop = docElem.clientTop || 0;
const clientLeft = docElem.clientLeft || 0;
return { return {
top: rect.top + scrollTop - clientTop, top: elemRect.top - targetRect.top +
left: rect.left + scrollLeft - clientLeft, scrollTop - clientTop,
left: elemRect.left - targetRect.left +
scrollLeft - clientLeft,
}; };
} }
@ -45,15 +55,20 @@ export interface AffixProps {
offsetBottom?: number; offsetBottom?: number;
style?: React.CSSProperties; style?: React.CSSProperties;
onChange?: (affixed?: boolean) => any; onChange?: (affixed?: boolean) => any;
target?: () => Window | HTMLElement;
} }
export default class Affix extends React.Component<AffixProps, any> { export default class Affix extends React.Component<AffixProps, any> {
static propTypes = { static propTypes = {
offsetTop: React.PropTypes.number, offsetTop: React.PropTypes.number,
offsetBottom: React.PropTypes.number, offsetBottom: React.PropTypes.number,
target: React.PropTypes.func,
}; };
static defaultProps = { static defaultProps = {
target() {
return window;
},
onChange() {}, onChange() {},
}; };
@ -73,8 +88,10 @@ export default class Affix extends React.Component<AffixProps, any> {
} }
setAffixStyle(e, affixStyle) { setAffixStyle(e, affixStyle) {
const { onChange, target } = this.props;
const originalAffixStyle = this.state.affixStyle; const originalAffixStyle = this.state.affixStyle;
if (e.type === 'scroll' && originalAffixStyle && affixStyle) { const isWindow = target() === window;
if (e.type === 'scroll' && originalAffixStyle && affixStyle && isWindow) {
return; return;
} }
if (shallowequal(affixStyle, originalAffixStyle)) { if (shallowequal(affixStyle, originalAffixStyle)) {
@ -84,7 +101,7 @@ export default class Affix extends React.Component<AffixProps, any> {
const affixed = !!this.state.affixStyle; const affixed = !!this.state.affixStyle;
if ((affixStyle && !originalAffixStyle) || if ((affixStyle && !originalAffixStyle) ||
(!affixStyle && originalAffixStyle)) { (!affixStyle && originalAffixStyle)) {
this.props.onChange(affixed); onChange(affixed);
} }
}); });
} }
@ -100,24 +117,25 @@ export default class Affix extends React.Component<AffixProps, any> {
this.setState({ placeholderStyle }); this.setState({ placeholderStyle });
} }
handleScroll = (e) => { updatePosition = (e) => {
let { offsetTop, offsetBottom, offset } = this.props; let { offsetTop, offsetBottom, offset, target } = this.props;
const targetNode = target();
// Backwards support // Backwards support
offsetTop = offsetTop || offset; offsetTop = offsetTop || offset;
const scrollTop = getScroll(window, true); const scrollTop = getScroll(targetNode, true);
const affixNode = ReactDOM.findDOMNode(this) as HTMLElement; const affixNode = ReactDOM.findDOMNode(this) as HTMLElement;
const fixedNode = ReactDOM.findDOMNode(this.refs.fixedNode) as HTMLElement; const elemOffset = getOffset(affixNode, targetNode);
const elemOffset = getOffset(affixNode);
const elemSize = { const elemSize = {
width: fixedNode.offsetWidth, width: this.refs.fixedNode.offsetWidth,
height: fixedNode.offsetHeight, height: this.refs.fixedNode.offsetHeight,
}; };
const offsetMode = { const offsetMode = {
top: null as boolean, top: null as boolean,
bottom: null as boolean, bottom: null as boolean,
}; };
// Default to `offsetTop=0`.
if (typeof offsetTop !== 'number' && typeof offsetBottom !== 'number') { if (typeof offsetTop !== 'number' && typeof offsetBottom !== 'number') {
offsetMode.top = true; offsetMode.top = true;
offsetTop = 0; offsetTop = 0;
@ -126,25 +144,31 @@ export default class Affix extends React.Component<AffixProps, any> {
offsetMode.bottom = typeof offsetBottom === 'number'; offsetMode.bottom = typeof offsetBottom === 'number';
} }
const targetRect = getTargetRect(targetNode);
const targetInnerHeight =
(targetNode as Window).innerHeight || (targetNode as HTMLElement).clientHeight;
if (scrollTop > elemOffset.top - offsetTop && offsetMode.top) { if (scrollTop > elemOffset.top - offsetTop && offsetMode.top) {
// Fixed Top // Fixed Top
this.setAffixStyle(e, { this.setAffixStyle(e, {
position: 'fixed', position: 'fixed',
top: offsetTop, top: targetRect.top + offsetTop,
left: elemOffset.left, left: targetRect.left + elemOffset.left,
width: affixNode.offsetWidth, width: affixNode.offsetWidth,
}); });
this.setPlaceholderStyle(e, { this.setPlaceholderStyle(e, {
width: affixNode.offsetWidth, width: affixNode.offsetWidth,
height: affixNode.offsetHeight, height: affixNode.offsetHeight,
}); });
} else if (scrollTop < elemOffset.top + elemSize.height + offsetBottom - window.innerHeight && } else if (
offsetMode.bottom) { scrollTop < elemOffset.top + elemSize.height + offsetBottom - targetInnerHeight &&
offsetMode.bottom
) {
// Fixed Bottom // Fixed Bottom
const targetBottomOffet = targetNode === window ? 0 : (window.innerHeight - targetRect.bottom);
this.setAffixStyle(e, { this.setAffixStyle(e, {
position: 'fixed', position: 'fixed',
bottom: offsetBottom, bottom: targetBottomOffet + offsetBottom,
left: elemOffset.left, left: targetRect.left + elemOffset.left,
width: affixNode.offsetWidth, width: affixNode.offsetWidth,
}); });
this.setPlaceholderStyle(e, { this.setPlaceholderStyle(e, {
@ -159,17 +183,37 @@ export default class Affix extends React.Component<AffixProps, any> {
componentDidMount() { componentDidMount() {
warning(!('offset' in this.props), '`offset` prop of Affix is deprecated, use `offsetTop` instead.'); warning(!('offset' in this.props), '`offset` prop of Affix is deprecated, use `offsetTop` instead.');
this.scrollEvent = addEventListener(window, 'scroll', this.handleScroll);
this.resizeEvent = addEventListener(window, 'resize', this.handleScroll); const target = this.props.target;
this.setTargetEventListeners(target);
}
componentWillReceiveProps(nextProps) {
if (this.props.target !== nextProps.target) {
this.clearScrollEventListeners();
this.setTargetEventListeners(nextProps.target);
// Mock Event object.
this.updatePosition({});
}
} }
componentWillUnmount() { componentWillUnmount() {
if (this.scrollEvent) { this.clearScrollEventListeners();
this.scrollEvent.remove();
} }
if (this.resizeEvent) {
this.resizeEvent.remove(); setTargetEventListeners(getTarget) {
const target = getTarget();
this.scrollEvent = addEventListener(target, 'scroll', this.updatePosition);
this.resizeEvent = addEventListener(target, 'resize', this.updatePosition);
} }
clearScrollEventListeners() {
['scrollEvent', 'resizeEvent'].forEach((name) => {
if (this[name]) {
this[name].remove();
}
});
} }
render() { render() {
@ -180,6 +224,7 @@ export default class Affix extends React.Component<AffixProps, any> {
const props = assign({}, this.props); const props = assign({}, this.props);
delete props.offsetTop; delete props.offsetTop;
delete props.offsetBottom; delete props.offsetBottom;
delete props.target;
return ( return (
<div {...props} style={this.state.placeholderStyle}> <div {...props} style={this.state.placeholderStyle}>

View File

@ -20,4 +20,5 @@ english: Affix
|-------------|----------------|--------------------|--------------| |-------------|----------------|--------------------|--------------|
| offsetTop | 距离窗口顶部达到指定偏移量后触发 | Number | | | offsetTop | 距离窗口顶部达到指定偏移量后触发 | Number | |
| offsetBottom | 距离窗口底部达到指定偏移量后触发 | Number | | | offsetBottom | 距离窗口底部达到指定偏移量后触发 | Number | |
| target | 设置 `Affix` 需要监听其滚动事件的元素,值为一个返回对应 DOM 元素的函数 | Function | () => window |
| onChange | 固定状态改变时触发的回调函数 | Function(affixed) | 无 | | onChange | 固定状态改变时触发的回调函数 | Function(affixed) | 无 |

View File

@ -16,6 +16,7 @@ Items in dataSource could be an `AutoComplete.Option`.
````jsx ````jsx
import { AutoComplete } from 'antd'; import { AutoComplete } from 'antd';
const Option = AutoComplete.Option; const Option = AutoComplete.Option;
const Complete = React.createClass({ const Complete = React.createClass({

View File

@ -3,7 +3,7 @@ import Select, { Option, OptGroup } from '../select';
import classNames from 'classnames'; import classNames from 'classnames';
export interface AutoCompleteProps { export interface AutoCompleteProps {
size?: string; size?: 'large' | 'small' | 'default';
className?: string; className?: string;
notFoundContent?: Element; notFoundContent?: Element;
dataSource: Array<any>; dataSource: Array<any>;

View File

@ -5,24 +5,28 @@ import addEventListener from 'rc-util/lib/Dom/addEventListener';
import classNames from 'classnames'; import classNames from 'classnames';
import omit from 'object.omit'; import omit from 'object.omit';
function getScroll(w, top) { function getScroll(target, top) {
let ret = w[`page${top ? 'Y' : 'X'}Offset`]; if (typeof window === 'undefined') {
const method = `scroll${top ? 'Top' : 'Left'}`; return 0;
if (typeof ret !== 'number') { }
const d = w.document;
const prop = top ? 'pageYOffset' : 'pageXOffset';
const method = top ? 'scrollTop' : 'scrollLeft';
const isWindow = target === window;
let ret = isWindow ? target[prop] : target[method];
// ie6,7,8 standard mode // ie6,7,8 standard mode
ret = d.documentElement[method]; if (isWindow && typeof ret !== 'number') {
if (typeof ret !== 'number') { ret = window.document.documentElement[method];
// quirks mode
ret = d.body[method];
}
} }
return ret; return ret;
} }
interface BackTopProps { interface BackTopProps {
visibilityHeight?: number; visibilityHeight?: number;
onClick?: (event) => void; onClick?: (event) => void;
target?: () => HTMLElement | Window;
prefixCls?: string; prefixCls?: string;
className?: string; className?: string;
} }
@ -31,6 +35,9 @@ export default class BackTop extends React.Component<BackTopProps, any> {
static defaultProps = { static defaultProps = {
onClick() {}, onClick() {},
visibilityHeight: 400, visibilityHeight: 400,
target() {
return window;
},
prefixCls: 'ant-back-top', prefixCls: 'ant-back-top',
}; };
@ -38,9 +45,9 @@ export default class BackTop extends React.Component<BackTopProps, any> {
constructor(props) { constructor(props) {
super(props); super(props);
const scrollTop = getScroll(window, true); const scrollTop = getScroll(props.target(), true);
this.state = { this.state = {
visible: scrollTop > this.props.visibilityHeight, visible: scrollTop > props.visibilityHeight,
}; };
} }
@ -53,19 +60,25 @@ export default class BackTop extends React.Component<BackTopProps, any> {
} }
setScrollTop(value) { setScrollTop(value) {
const targetNode = this.props.target();
if (targetNode === window) {
document.body.scrollTop = value; document.body.scrollTop = value;
document.documentElement.scrollTop = value; document.documentElement.scrollTop = value;
} else {
(targetNode as HTMLElement).scrollTop = value;
}
} }
handleScroll = () => { handleScroll = () => {
const scrollTop = getScroll(window, true); const { visibilityHeight, target } = this.props;
const scrollTop = getScroll(target(), true);
this.setState({ this.setState({
visible: scrollTop > this.props.visibilityHeight, visible: scrollTop > visibilityHeight,
}); });
} }
componentDidMount() { componentDidMount() {
this.scrollEvent = addEventListener(window, 'scroll', this.handleScroll); this.scrollEvent = addEventListener(this.props.target(), 'scroll', this.handleScroll);
} }
componentWillUnmount() { componentWillUnmount() {

View File

@ -18,10 +18,10 @@ import { Badge } from 'antd';
ReactDOM.render(<div> ReactDOM.render(<div>
<Badge count={99}> <Badge count={99}>
<a href="#" className="head-example"></a> <a href="#" className="head-example" />
</Badge> </Badge>
<Badge count={200}> <Badge count={200}>
<a href="#" className="head-example"></a> <a href="#" className="head-example" />
</Badge> </Badge>
</div>, mountNode); </div>, mountNode);
```` ````

View File

@ -18,7 +18,7 @@ import { Badge } from 'antd';
ReactDOM.render( ReactDOM.render(
<Badge count={5}> <Badge count={5}>
<a href="#" className="head-example"></a> <a href="#" className="head-example" />
</Badge> </Badge>
, mountNode); , mountNode);
```` ````

View File

@ -44,10 +44,10 @@ const Test = React.createClass({
return ( return (
<div> <div>
<Badge count={this.state.count}> <Badge count={this.state.count}>
<a href="#" className="head-example"></a> <a href="#" className="head-example" />
</Badge> </Badge>
<Badge dot={this.state.show}> <Badge dot={this.state.show}>
<a href="#" className="head-example"></a> <a href="#" className="head-example" />
</Badge> </Badge>
<div style={{ marginTop: 10 }}> <div style={{ marginTop: 10 }}>
<ButtonGroup> <ButtonGroup>

View File

@ -19,7 +19,7 @@ import { Badge } from 'antd';
ReactDOM.render( ReactDOM.render(
<a href="#"> <a href="#">
<Badge count={5}> <Badge count={5}>
<span className="head-example"></span> <span className="head-example" />
</Badge> </Badge>
</a> </a>
, mountNode); , mountNode);

View File

@ -18,10 +18,10 @@ import { Badge } from 'antd';
ReactDOM.render(<div> ReactDOM.render(<div>
<Badge count={99} overflowCount={10}> <Badge count={99} overflowCount={10}>
<a href="#" className="head-example"></a> <a href="#" className="head-example" />
</Badge> </Badge>
<Badge count={1000} overflowCount={999}> <Badge count={1000} overflowCount={999}>
<a href="#" className="head-example"></a> <a href="#" className="head-example" />
</Badge> </Badge>
</div>, mountNode); </div>, mountNode);
```` ````

View File

@ -0,0 +1,36 @@
---
order: 7
title:
zh-CN: 状态点
en-US: Status
---
## zh-CN
用于表示状态的小圆点。
## en-US
Standalone badge with status.
````jsx
import { Badge } from 'antd';
ReactDOM.render(
<div>
<div>Status: &nbsp;</div>
<Badge status="success" />
<Badge status="error" />
<Badge status="default" />
<Badge status="processing" />
<Badge status="warning" />
<br />
<Badge status="success" text="Success" /><br />
<Badge status="error" text="Error" /><br />
<Badge status="default" text="Default" /><br />
<Badge status="processing" text="Processing" /><br />
<Badge status="warning" text="Warning" />
</div>,
mountNode
);
````

View File

@ -14,7 +14,7 @@ Badge normally appears in proximity to notification or head picture with eye-cat
```jsx ```jsx
<Badge count={5}> <Badge count={5}>
<a href="#" className="head-example"></a> <a href="#" className="head-example" />
</Badge> </Badge>
``` ```
@ -28,3 +28,5 @@ Badge normally appears in proximity to notification or head picture with eye-cat
| count | Number to show in badge | Number | | | count | Number to show in badge | Number | |
| overflowCount | Max count to show | Number | 99 | | overflowCount | Max count to show | Number | 99 |
| dot | whether to show red dot without number | Boolean | false | | dot | whether to show red dot without number | Boolean | false |
| status | Set Badge as a status dot | Enum{ 'success', 'processing, 'default', 'error', 'warning' } | '' |
| text | If `status` is set, `text` is to set the text of status dot | String | '' |

View File

@ -13,6 +13,8 @@ interface BadgeProps {
style?: React.CSSProperties; style?: React.CSSProperties;
prefixCls?: string; prefixCls?: string;
className?: string; className?: string;
status?: 'success' | 'processing' | 'default' | 'error' | 'warning';
text?: string;
} }
export default class Badge extends React.Component<BadgeProps, any> { export default class Badge extends React.Component<BadgeProps, any> {
@ -21,6 +23,7 @@ export default class Badge extends React.Component<BadgeProps, any> {
count: null, count: null,
dot: false, dot: false,
overflowCount: 99, overflowCount: 99,
// status: 'default',
}; };
static propTypes = { static propTypes = {
@ -33,18 +36,25 @@ export default class Badge extends React.Component<BadgeProps, any> {
}; };
render() { render() {
let { count, prefixCls, overflowCount, className, style, children, dot } = this.props; let { count, prefixCls, overflowCount, className, style, children, dot, status, text } = this.props;
const isDot = dot || status;
count = count > overflowCount ? `${overflowCount}+` : count; count = count > overflowCount ? `${overflowCount}+` : count;
// dot mode don't need count // dot mode don't need count
if (dot) { if (isDot) {
count = ''; count = '';
} }
// null undefined "" "0" 0 // null undefined "" "0" 0
const hidden = (!count || count === '0') && !dot; const hidden = (!count || count === '0') && !isDot;
const scrollNumberCls = prefixCls + (dot ? '-dot' : '-count'); const scrollNumberCls = classNames({
[`${prefixCls}-dot`]: isDot,
[`${prefixCls}-count`]: !isDot,
[`${prefixCls}-status`]: status,
[`${prefixCls}-status-${status}`]: status,
[`${prefixCls}-status-with-text`]: text,
});
const badgeCls = classNames({ const badgeCls = classNames({
[className]: !!className, [className]: !!className,
[prefixCls]: true, [prefixCls]: true,
@ -70,6 +80,10 @@ export default class Badge extends React.Component<BadgeProps, any> {
/> />
} }
</Animate> </Animate>
{
hidden || !text ? null :
<span className={`${prefixCls}-status-text`}>{text}</span>
}
</span> </span>
); );
} }

View File

@ -15,7 +15,7 @@ english: Badge
```jsx ```jsx
<Badge count={5}> <Badge count={5}>
<a href="#" className="head-example"></a> <a href="#" className="head-example" />
</Badge> </Badge>
``` ```
@ -28,4 +28,6 @@ english: Badge
|----------------|----------------------------------|------------|---------|--------| |----------------|----------------------------------|------------|---------|--------|
| count | 展示的数字,大于 overflowCount 时显示为 `${overflowCount}+`,为 0 时隐藏 | Number | | | | count | 展示的数字,大于 overflowCount 时显示为 `${overflowCount}+`,为 0 时隐藏 | Number | | |
| overflowCount | 展示封顶的数字值 | Number | | 99 | | overflowCount | 展示封顶的数字值 | Number | | 99 |
| dot | 不展示数字,只有一个小红点 | boolean | | false | | dot | 不展示数字,只有一个小红点 | Boolean | | false |
| status | 设置 Badge 为状态点 | Enum | 'success'、'processing'、'default'、'error'、'warning' | '' |
| text | 在设置了 `status` 的前提下有效,设置状态点的文本 | String | | '' |

View File

@ -47,6 +47,38 @@
box-shadow: 0 0 0 1px #fff; box-shadow: 0 0 0 1px #fff;
} }
&-status {
width: 6px;
height: 6px;
&-success {
background-color: @success-color;
}
&-processing {
background-color: @primary-color;
animation: antStatusProcessing 1.2s infinite ease-in-out;
}
&-default {
background-color: @normal-color;
}
&-error {
background-color: @error-color;
}
&-warning {
background-color: @warning-color;
}
&-with-text {
top: 5px;
}
&-text {
color: @text-color;
font-size: @font-size-base;
margin-left: 8px; // 8 - (6 / 2) === 5
}
}
&-zoom-appear, &-zoom-appear,
&-zoom-enter { &-zoom-enter {
animation: antZoomBadgeIn .3s @ease-out-back; animation: antZoomBadgeIn .3s @ease-out-back;
@ -66,6 +98,16 @@
} }
} }
@keyframes antStatusProcessing {
0%,
100% {
opacity: 1;
}
50% {
opacity: 0;
}
}
a & { a & {
&-count:hover { &-count:hover {
background: tint(@error-color, 20%); background: tint(@error-color, 20%);

View File

@ -35,6 +35,7 @@ interface ButtonProps {
shape?: ButtonShape; shape?: ButtonShape;
size?: ButtonSize; size?: ButtonSize;
onClick?: React.FormEventHandler; onClick?: React.FormEventHandler;
onMouseUp?: React.FormEventHandler;
loading?: boolean; loading?: boolean;
disabled?: boolean; disabled?: boolean;
style?: React.CSSProperties; style?: React.CSSProperties;

View File

@ -7,7 +7,19 @@ const Option = Select.Option;
function noop() {} function noop() {}
export default class Header extends React.Component { export interface HeaderProps {
prefixCls?: string;
locale?: any;
fullscreen?: boolean;
yearSelectOffset?: number;
yearSelectTotal?: number;
type?: string;
onValueChange?: (value) => void;
onTypeChange?: (type: string) => void;
value: any;
}
export default class Header extends React.Component<HeaderProps, any> {
static defaultProps = { static defaultProps = {
prefixCls: `${PREFIX_CLS}-header`, prefixCls: `${PREFIX_CLS}-header`,
yearSelectOffset: 10, yearSelectOffset: 10,

View File

@ -16,7 +16,27 @@ function zerofixed(v) {
return `${v}`; return `${v}`;
} }
export default class Calendar extends React.Component { interface CalendarContext {
antLocale?: {
Calendar?: any
};
}
export interface CalendarProps {
prefixCls?: string;
className?: string;
value?: Date;
defaultValue?: Date;
mode?: 'month' | 'year';
fullscreen?: boolean;
dateCellRender?: (date) => React.ReactNode;
monthCellRender?: (month) => React.ReactNode;
locale?: any;
style?: React.CSSProperties;
onPanelChange?: (date: Date, mode: string) => void;
}
export default class Calendar extends React.Component<CalendarProps, any> {
static defaultProps = { static defaultProps = {
monthCellRender: noop, monthCellRender: noop,
dateCellRender: noop, dateCellRender: noop,
@ -43,6 +63,8 @@ export default class Calendar extends React.Component {
antLocale: PropTypes.object, antLocale: PropTypes.object,
}; };
context: CalendarContext;
constructor(props) { constructor(props) {
super(props); super(props);
this.state = { this.state = {

View File

@ -1 +1,2 @@
module.exports = require('../../date-picker/locale/en_US'); import en_US from '../../date-picker/locale/en_US';
export default en_US;

View File

@ -1 +1,2 @@
module.exports = require('../../date-picker/locale/ru_RU'); import ru_RU from '../../date-picker/locale/ru_RU';
export default ru_RU;

View File

@ -1 +1,2 @@
module.exports = require('../../date-picker/locale/zh_CN'); import zh_CN from '../../date-picker/locale/zh_CN';
export default zh_CN;

View File

@ -2,8 +2,9 @@
// https://github.com/WickyNilliams/enquire.js/issues/82 // https://github.com/WickyNilliams/enquire.js/issues/82
import assign from 'object-assign'; import assign from 'object-assign';
if (typeof window !== 'undefined') { if (typeof window !== 'undefined') {
const matchMediaPolyfill = function matchMediaPolyfill() { const matchMediaPolyfill = function matchMediaPolyfill(mediaQuery: string): MediaQueryList {
return { return {
media: mediaQuery,
matches: false, matches: false,
addListener() { addListener() {
}, },
@ -23,7 +24,7 @@ export interface CarouselProps {
/** 动画效果函数,可取 scrollx, fade */ /** 动画效果函数,可取 scrollx, fade */
effect?: CarouselEffect; effect?: CarouselEffect;
/** 是否显示面板指示点 */ /** 是否显示面板指示点 */
dots?: SlickCarouselboolean; dots?: boolean;
/** 垂直显示 */ /** 垂直显示 */
vertical?: boolean; vertical?: boolean;
/** 是否自动切换 */ /** 是否自动切换 */

View File

@ -59,12 +59,13 @@ export default class CheckboxGroup extends React.Component<CheckboxGroupProps, C
} }
getOptions() { getOptions() {
const { options } = this.props; const { options } = this.props;
return options.map(option => { // https://github.com/Microsoft/TypeScript/issues/7960
return (options as Array<any>).map(option => {
if (typeof option === 'string') { if (typeof option === 'string') {
return { return {
label: option, label: option,
value: option, value: option,
}; } as CheckboxOptionType;
} }
return option; return option;
}); });

View File

@ -2,7 +2,7 @@ import * as React from 'react';
import CalendarLocale from 'rc-calendar/lib/locale/zh_CN'; import CalendarLocale from 'rc-calendar/lib/locale/zh_CN';
import RcCalendar from 'rc-calendar'; import RcCalendar from 'rc-calendar';
export default class Calendar extends React.Component { export default class Calendar extends React.Component<any, any> {
static defaultProps = { static defaultProps = {
locale: CalendarLocale, locale: CalendarLocale,
prefixCls: 'ant-calendar', prefixCls: 'ant-calendar',

View File

@ -5,7 +5,7 @@ import RcDatePicker from 'rc-calendar/lib/Picker';
import classNames from 'classnames'; import classNames from 'classnames';
import Icon from '../icon'; import Icon from '../icon';
export default class RangePicker extends React.Component { export default class RangePicker extends React.Component<any, any> {
static defaultProps = { static defaultProps = {
defaultValue: [], defaultValue: [],
}; };
@ -74,7 +74,7 @@ export default class RangePicker extends React.Component {
let pickerChangeHandler = { let pickerChangeHandler = {
onChange: this.handleChange, onChange: this.handleChange,
}; };
let calendarHandler = { let calendarHandler: Object = {
onOk: this.handleChange, onOk: this.handleChange,
}; };
if (props.timePicker) { if (props.timePicker) {

View File

@ -6,6 +6,11 @@ import classNames from 'classnames';
import assign from 'object-assign'; import assign from 'object-assign';
import Icon from '../icon'; import Icon from '../icon';
export interface PickerProps {
parseDateFromValue?: Function;
value?: string | Date;
}
export default function createPicker(TheCalendar) { export default function createPicker(TheCalendar) {
// use class typescript error // use class typescript error
const CalenderWrapper = React.createClass({ const CalenderWrapper = React.createClass({
@ -16,7 +21,7 @@ export default function createPicker(TheCalendar) {
}; };
}, },
componentWillReceiveProps(nextProps) { componentWillReceiveProps(nextProps: PickerProps) {
if ('value' in nextProps) { if ('value' in nextProps) {
this.setState({ this.setState({
value: nextProps.parseDateFromValue(nextProps.value), value: nextProps.parseDateFromValue(nextProps.value),
@ -60,10 +65,10 @@ export default function createPicker(TheCalendar) {
}); });
// 需要选择时间时,点击 ok 时才触发 onChange // 需要选择时间时,点击 ok 时才触发 onChange
let pickerChangeHandler = { let pickerChangeHandler: Object = {
onChange: this.handleChange, onChange: this.handleChange,
}; };
let calendarHandler = { let calendarHandler: Object = {
onOk: this.handleChange, onOk: this.handleChange,
// fix https://github.com/ant-design/ant-design/issues/1902 // fix https://github.com/ant-design/ant-design/issues/1902
onSelect: (value, cause) => { onSelect: (value, cause) => {
@ -95,7 +100,7 @@ export default function createPicker(TheCalendar) {
); );
// default width for showTime // default width for showTime
const pickerStyle = {}; const pickerStyle = { width: undefined };
if (props.showTime) { if (props.showTime) {
pickerStyle.width = 180; pickerStyle.width = 180;
} }

View File

@ -7,11 +7,11 @@ title:
## zh-CN ## zh-CN
通过 `locale` 配置时区、语言等, 默认支持 `en_US``zh_CN`。 通过 `locale` 配置时区、语言等, 默认支持 `en_US``zh_CN`。不同版本带有不同的时区配置,如果所在时区与默认配置不同,需要自行设置。上面的 demo 就是在东八区使用 en_US 版本的例子。
## en-US ## en-US
Use locale to set the properties like time zone, language and etc. en_US, zh_CN are supported by default. Use locale to set the properties like time zone, language and etc. `en_US`, `zh_CN` are supported by default. There are different time zone configuration in different versions, you must set it by yourself if your time zone does not match the default setting. The example above is to show how to use the `en_US` version at GMT+8 time zone.
````jsx ````jsx
@ -19,7 +19,7 @@ import { DatePicker } from 'antd';
import enUS from 'antd/lib/date-picker/locale/en_US'; import enUS from 'antd/lib/date-picker/locale/en_US';
const customLocale = { const customLocale = {
timezoneOffset: 0 * 60, timezoneOffset: 8 * 60,
firstDayOfWeek: 0, firstDayOfWeek: 0,
minimalDaysInFirstWeek: 1, minimalDaysInFirstWeek: 1,
}; };

View File

@ -1,15 +1,49 @@
import * as React from 'react';
import assign from 'object-assign';
import RcCalendar from 'rc-calendar'; import RcCalendar from 'rc-calendar';
import MonthCalendar from 'rc-calendar/lib/MonthCalendar'; import MonthCalendar from 'rc-calendar/lib/MonthCalendar';
import createPicker from './createPicker'; import createPicker from './createPicker';
import wrapPicker from './wrapPicker'; import wrapPicker from './wrapPicker';
import RangePicker from './RangePicker'; import RangePicker from './RangePicker';
import Calendar from './Calendar'; import Calendar from './Calendar';
import { TimePickerProps } from '../time-picker';
const DatePicker = wrapPicker(createPicker(RcCalendar)); interface PickerProps {
const MonthPicker = wrapPicker(createPicker(MonthCalendar), 'yyyy-MM'); format?: string;
disabled?: boolean;
style?: React.CSSProperties;
popupStyle?: React.CSSProperties;
locale?: any;
size?: 'large' | 'small' | 'default';
getCalendarContainer?: (trigger) => React.ReactNode;
}
DatePicker.Calendar = Calendar; interface SinglePickerProps {
DatePicker.RangePicker = wrapPicker(RangePicker); value?: string | Date;
DatePicker.MonthPicker = MonthPicker; defaultValue?: string | Date;
onChange?: (date: Date, dateString: string) => void;
}
export interface DatePickerProps extends PickerProps, SinglePickerProps {
showTime?: TimePickerProps;
}
const DatePicker = wrapPicker(createPicker(RcCalendar)) as React.ClassicComponentClass<DatePickerProps>;
export interface MonthPickerProps extends PickerProps, SinglePickerProps {
}
const MonthPicker = wrapPicker(createPicker(MonthCalendar), 'yyyy-MM') as React.ClassicComponentClass<MonthPickerProps>;
export interface RangePickerProps extends PickerProps {
value?: [string | Date, string | Date];
defaultValue?: [string | Date, string | Date];
onChange?: (dates: [Date, Date], dateStrings: [String, String]) => void;
showTime?: TimePickerProps;
}
assign(DatePicker, {
RangePicker: wrapPicker(RangePicker) as React.ClassicComponentClass<RangePickerProps>,
Calendar,
MonthPicker,
});
export default DatePicker; export default DatePicker;

View File

@ -7,7 +7,7 @@ import classNames from 'classnames';
import defaultLocale from './locale/zh_CN'; import defaultLocale from './locale/zh_CN';
import assign from 'object-assign'; import assign from 'object-assign';
export default function wrapPicker(Picker, defaultFormat) { export default function wrapPicker(Picker, defaultFormat?) {
const PickerWrapper = React.createClass({ const PickerWrapper = React.createClass({
getDefaultProps() { getDefaultProps() {
return { return {
@ -46,7 +46,7 @@ export default function wrapPicker(Picker, defaultFormat) {
getFormatter() { getFormatter() {
const format = this.props.format; const format = this.props.format;
const formatter = new DateTimeFormat(format, this.getLocale().lang.format); const formatter = new DateTimeFormat(format as string, this.getLocale().lang.format);
return formatter; return formatter;
}, },

View File

@ -19,13 +19,13 @@ import { Menu, Dropdown, Icon } from 'antd';
const menu = ( const menu = (
<Menu> <Menu>
<Menu.Item> <Menu.Item>
<a target="_blank" href="http://www.alipay.com/">第一个菜单项</a> <a target="_blank" rel="noopener noreferrer" href="http://www.alipay.com/">第一个菜单项</a>
</Menu.Item> </Menu.Item>
<Menu.Item> <Menu.Item>
<a target="_blank" href="http://www.taobao.com/">第二个菜单项</a> <a target="_blank" rel="noopener noreferrer" href="http://www.taobao.com/">第二个菜单项</a>
</Menu.Item> </Menu.Item>
<Menu.Item> <Menu.Item>
<a target="_blank" href="http://www.tmall.com/">第三个菜单项</a> <a target="_blank" rel="noopener noreferrer" href="http://www.tmall.com/">第三个菜单项</a>
</Menu.Item> </Menu.Item>
</Menu> </Menu>
); );

View File

@ -19,10 +19,10 @@ import { Menu, Dropdown, Icon } from 'antd';
const menu = ( const menu = (
<Menu> <Menu>
<Menu.Item key="0"> <Menu.Item key="0">
<a target="_blank" href="http://www.alipay.com/">第一个菜单项</a> <a target="_blank" rel="noopener noreferrer" href="http://www.alipay.com/">第一个菜单项</a>
</Menu.Item> </Menu.Item>
<Menu.Item key="1"> <Menu.Item key="1">
<a target="_blank" href="http://www.taobao.com/">第二个菜单项</a> <a target="_blank" rel="noopener noreferrer" href="http://www.taobao.com/">第二个菜单项</a>
</Menu.Item> </Menu.Item>
<Menu.Divider /> <Menu.Divider />
<Menu.Item key="3" disabled>第三个菜单项(不可用)</Menu.Item> <Menu.Item key="3" disabled>第三个菜单项(不可用)</Menu.Item>

View File

@ -5,7 +5,18 @@ import Dropdown from './dropdown';
const ButtonGroup = Button.Group; const ButtonGroup = Button.Group;
import classNames from 'classnames'; import classNames from 'classnames';
import splitObject from '../_util/splitObject'; import splitObject from '../_util/splitObject';
export default class DropdownButton extends React.Component {
export interface DropdownButtonProps {
type?: 'primary' | 'ghost' | 'dash';
onClick?: React.FormEventHandler;
trigger?: 'click' | 'hover';
overlay: React.ReactNode;
visible?: boolean;
onVisibleChange?: (visible: boolean) => void;
style?: React.CSSProperties;
}
export default class DropdownButton extends React.Component<DropdownButtonProps, any> {
static defaultProps = { static defaultProps = {
align: { align: {
points: ['tr', 'br'], points: ['tr', 'br'],

View File

@ -2,13 +2,16 @@ import * as React from 'react';
import RcDropdown from 'rc-dropdown'; import RcDropdown from 'rc-dropdown';
export interface DropDownProps { export interface DropDownProps {
trigger: string[]; trigger?: Array<'click' | 'hover'>;
overlay: React.ReactNode; overlay: React.ReactNode;
visible: boolean; style?: React.CSSProperties;
onVisibleChange: (visible: boolean) => void; onVisibleChange?: (visible: boolean) => void;
visible?: boolean;
align?: Object;
} }
export default class Dropdown extends React.Component<DropDownProps, any> { export default class Dropdown extends React.Component<DropDownProps, any> {
static Button: React.ReactNode;
static defaultProps = { static defaultProps = {
transitionName: 'slide-up', transitionName: 'slide-up',
prefixCls: 'ant-dropdown', prefixCls: 'ant-dropdown',

View File

@ -31,9 +31,9 @@ english: Dropdown
| 参数 | 说明 | 类型 | 默认值 | | 参数 | 说明 | 类型 | 默认值 |
|-------------|------------------|--------------------|--------------| |-------------|------------------|--------------------|--------------|
| type | 按钮类型,和 [Button](/components/button) 一致 | String | 'default' | | type | 按钮类型,和 [Button](/components/button/) 一致 | String | 'default' |
| onClick | 点击左侧按钮的回调,和 [Button](/components/button) 一致 | Function | - | | onClick | 点击左侧按钮的回调,和 [Button](/components/button/) 一致 | Function | - |
| trigger | 触发下拉的行为 | ['click'] or ['hover'] | ['hover'] | | trigger | 触发下拉的行为 | ['click'] or ['hover'] | ['hover'] |
| overlay | 菜单 | [Menu](/components/menu) | - | | overlay | 菜单 | [Menu](/components/menu/) | - |
| visible | 菜单是否显示 | Boolean | - | | visible | 菜单是否显示 | Boolean | - |
| onVisibleChange | 菜单显示状态改变时调用,参数为 { visible } | Function | - | | onVisibleChange | 菜单显示状态改变时调用,参数为 { visible } | Function | - |

View File

@ -1,10 +1,83 @@
import * as React from 'react'; import * as React from 'react';
import { PropTypes } from 'react';
import classNames from 'classnames'; import classNames from 'classnames';
import PureRenderMixin from 'react-addons-pure-render-mixin'; import PureRenderMixin from 'react-addons-pure-render-mixin';
import omit from 'object.omit'; import omit from 'object.omit';
import warning from 'warning'; import warning from 'warning';
import assign from 'object-assign';
import FormItem from './FormItem';
import createDOMForm from 'rc-form/lib/createDOMForm';
import { FIELD_META_PROP } from './constants';
export default class Form extends React.Component { export interface FormCreateOption {
onFieldsChange?: (props: any, fields: Array<any>) => void;
mapPropsToFields?: (props: any) => void;
}
export interface FormProps {
horizontal?: boolean;
inline?: boolean;
vertical?: boolean;
form?: Object;
onSubmit?: React.FormEventHandler;
style?: React.CSSProperties;
className?: string;
prefixCls?: string;
}
// function create
export type WrappedFormUtils = {
/** 获取一组输入控件的值,如不传入参数,则获取全部组件的值 */
getFieldsValue(fieldNames?: Array<string>): Object;
/** 获取一个输入控件的值*/
getFieldValue(fieldName: string): any;
/** 设置一组输入控件的值*/
setFieldsValue(obj: Object): void;
/** 设置一组输入控件的值*/
setFields(obj: Object): void;
/** 校验并获取一组输入域的值与 Error */
validateFields(fieldNames?: Array<string>, options?: Object, callback?: (erros: any, values: any) => void): any;
/** 与 `validateFields` 相似,但校验完后,如果校验不通过的菜单域不在可见范围内,则自动滚动进可见范围 */
validateFieldsAndScroll(
fieldNames?: Array<string>,
options?: Object,
callback?: (erros: any, values: any) => void
): void;
/** 获取某个输入控件的 Error */
getFieldError(name: string): Object[];
/** 判断一个输入控件是否在校验状态*/
isFieldValidating(name: string): boolean;
/** 重置一组输入控件的值与状态,如不传入参数,则重置所有组件 */
resetFields(names?: Array<string>): void;
getFieldProps(id: string, options: {
/** 子节点的值的属性,如 Checkbox 的是 'checked' */
valuePropName?: string;
/** 子节点的初始值,类型、可选值均由子节点决定 */
initialValue?: any;
/** 收集子节点的值的时机 */
trigger?: string;
/** 校验子节点值的时机 */
validateTrigger?: string;
/** 校验规则,参见 [async-validator](https://github.com/yiminghe/async-validator) */
rules?: Array<any>;
/** 必填输入控件唯一标志 */
id?: string;
}): Array<any>;
}
export interface FormComponentProps {
form: WrappedFormUtils;
}
class FormComponent extends React.Component<FormComponentProps, {}> {
}
export interface ComponentDecorator {
<T extends (typeof FormComponent)>(component: T): T;
}
export default class Form extends React.Component<FormProps, any> {
static defaultProps = { static defaultProps = {
prefixCls: 'ant-form', prefixCls: 'ant-form',
onSubmit(e) { onSubmit(e) {
@ -21,6 +94,33 @@ export default class Form extends React.Component {
onSubmit: React.PropTypes.func, onSubmit: React.PropTypes.func,
}; };
static Item = FormItem;
static create = (options?: FormCreateOption): ComponentDecorator => {
const formWrapper = createDOMForm(assign({}, options, {
fieldNameProp: 'id',
fieldMetaProp: FIELD_META_PROP,
}));
/* eslint-disable react/prefer-es6-class */
return (Component) => formWrapper(React.createClass({
propTypes: {
form: PropTypes.object.isRequired,
},
childContextTypes: {
form: PropTypes.object.isRequired,
},
getChildContext() {
return {
form: this.props.form,
};
},
render() {
return <Component {...this.props} />;
},
}));
};
constructor(props) { constructor(props) {
super(props); super(props);

View File

@ -3,9 +3,35 @@ import classNames from 'classnames';
import PureRenderMixin from 'react-addons-pure-render-mixin'; import PureRenderMixin from 'react-addons-pure-render-mixin';
import Row from '../row'; import Row from '../row';
import Col from '../col'; import Col from '../col';
import { WrappedFormUtils } from './Form';
import { FIELD_META_PROP } from './constants'; import { FIELD_META_PROP } from './constants';
export default class FormItem extends React.Component { export interface FormItemLabelColOption {
span: number;
offset: number;
}
export interface FormItemProps {
prefixCls?: string;
id?: string;
label?: string;
labelCol?: FormItemLabelColOption;
wrapperCol?: FormItemLabelColOption;
help?: React.ReactNode;
extra?: string;
validateStatus?: 'success' | 'warning' | 'error' | 'validating';
hasFeedback?: boolean;
className?: string;
required?: boolean;
style?: React.CSSProperties;
colon?: boolean;
}
export interface FormItemContext {
form: WrappedFormUtils;
}
export default class FormItem extends React.Component<FormItemProps, any> {
static defaultProps = { static defaultProps = {
hasFeedback: false, hasFeedback: false,
prefixCls: 'ant-form', prefixCls: 'ant-form',
@ -14,7 +40,7 @@ export default class FormItem extends React.Component {
static propTypes = { static propTypes = {
prefixCls: React.PropTypes.string, prefixCls: React.PropTypes.string,
label: React.PropTypes.node, label: React.PropTypes.string,
labelCol: React.PropTypes.object, labelCol: React.PropTypes.object,
help: React.PropTypes.oneOfType([React.PropTypes.node, React.PropTypes.bool]), help: React.PropTypes.oneOfType([React.PropTypes.node, React.PropTypes.bool]),
validateStatus: React.PropTypes.oneOf(['', 'success', 'warning', 'error', 'validating']), validateStatus: React.PropTypes.oneOf(['', 'success', 'warning', 'error', 'validating']),
@ -30,6 +56,8 @@ export default class FormItem extends React.Component {
form: React.PropTypes.object, form: React.PropTypes.object,
}; };
context: FormItemContext;
shouldComponentUpdate(...args) { shouldComponentUpdate(...args) {
return PureRenderMixin.shouldComponentUpdate.apply(this, args); return PureRenderMixin.shouldComponentUpdate.apply(this, args);
} }
@ -46,14 +74,14 @@ export default class FormItem extends React.Component {
getOnlyControl() { getOnlyControl() {
const children = React.Children.toArray(this.props.children); const children = React.Children.toArray(this.props.children);
const child = children.filter((c) => { const child = children.filter((c: React.ReactElement<any>) => {
return c.props && FIELD_META_PROP in c.props; return c.props && FIELD_META_PROP in c.props;
})[0]; })[0];
return child !== undefined ? child : null; return child !== undefined ? child : null;
} }
getChildProp(prop) { getChildProp(prop) {
const child = this.getOnlyControl(); const child = this.getOnlyControl() as React.ReactElement<any>;
return child && child.props && child.props[prop]; return child && child.props && child.props[prop];
} }
@ -173,7 +201,7 @@ export default class FormItem extends React.Component {
renderChildren() { renderChildren() {
const props = this.props; const props = this.props;
const children = React.Children.map(props.children, (child) => { const children = React.Children.map(props.children, (child: React.ReactElement<any>) => {
if (child && typeof child.type === 'function' && !child.props.size) { if (child && typeof child.type === 'function' && !child.props.size) {
return React.cloneElement(child, { size: 'large' }); return React.cloneElement(child, { size: 'large' });
} }

View File

@ -1,22 +0,0 @@
import assign from 'object-assign';
const ValueMixin = {
setValue(field, e) {
let v = e;
const target = e && e.target;
if (target) {
if ((`${target.nodeName}`).toLowerCase() === 'input' &&
target.type === 'checkbox') {
v = target.checked;
} else {
v = e.target.value;
}
}
const newFormData = {};
newFormData[field] = v;
this.setState({
formData: assign({}, this.state.formData, newFormData),
});
},
};
export default ValueMixin;

View File

@ -31,7 +31,7 @@ let BasicDemo = React.createClass({
handleSubmit(e) { handleSubmit(e) {
e.preventDefault(); e.preventDefault();
this.props.form.validateFields((errors, values) => { this.props.form.validateFields((errors, values) => {
if (!!errors) { if (errors) {
console.log('Errors in form!!!'); console.log('Errors in form!!!');
return; return;
} }

View File

@ -40,7 +40,7 @@ let Demo = React.createClass({
handleSubmit() { handleSubmit() {
this.props.form.validateFields((errors, values) => { this.props.form.validateFields((errors, values) => {
if (!!errors) { if (errors) {
console.log('Errors in form!!!'); console.log('Errors in form!!!');
return; return;
} }
@ -60,17 +60,14 @@ let Demo = React.createClass({
} else { } else {
strength = 'H'; strength = 'H';
} }
if (type === 'pass') { this.setState({
this.setState({ passBarShow: true, passStrength: strength }); [`${type}BarShow`]: true,
[`${type}Strength`]: strength,
});
} else { } else {
this.setState({ rePassBarShow: true, rePassStrength: strength }); this.setState({
} [`${type}BarShow`]: false,
} else { });
if (type === 'pass') {
this.setState({ passBarShow: false });
} else {
this.setState({ rePassBarShow: false });
}
} }
}, },
@ -113,9 +110,9 @@ let Demo = React.createClass({
return ( return (
<div> <div>
<ul className={classSet}> <ul className={classSet}>
<li className="ant-pwd-strength-item ant-pwd-strength-item-1"></li> <li className="ant-pwd-strength-item ant-pwd-strength-item-1" />
<li className="ant-pwd-strength-item ant-pwd-strength-item-2"></li> <li className="ant-pwd-strength-item ant-pwd-strength-item-2" />
<li className="ant-pwd-strength-item ant-pwd-strength-item-3"></li> <li className="ant-pwd-strength-item ant-pwd-strength-item-3" />
<span className="ant-form-text"> <span className="ant-form-text">
{level[strength]} {level[strength]}
</span> </span>

View File

@ -37,7 +37,7 @@ let Demo = React.createClass({
handleSubmit(e) { handleSubmit(e) {
e.preventDefault(); e.preventDefault();
this.props.form.validateFieldsAndScroll((errors, values) => { this.props.form.validateFieldsAndScroll((errors, values) => {
if (!!errors) { if (errors) {
console.log('Errors in form!!!'); console.log('Errors in form!!!');
return; return;
} }

View File

@ -101,7 +101,8 @@ The return value of `getFieldProps` contains `id`、`value`(or any other props `
### Form.Item ### Form.Item
> If Form.Item has multiple children, `help`, `required`, and `validateStatus` can't be generated automatically. > * If Form.Item has multiple children, `help`, `required`, and `validateStatus` can't be generated automatically.
> * Form controls must be child of Form.Item, otherwise, you need to set `help`, `required` and `validateStatus` by yourself.
| Property | Description | Type | Optional | Default Value | | Property | Description | Type | Optional | Default Value |
|-----------|------------------------------------------|-----------|-------|--------| |-----------|------------------------------------------|-----------|-------|--------|

View File

@ -1,40 +1,3 @@
import React, { PropTypes } from 'react';
import createDOMForm from 'rc-form/lib/createDOMForm';
import Form from './Form'; import Form from './Form';
import FormItem from './FormItem';
import ValueMixin from './ValueMixin';
import assign from 'object-assign';
import { FIELD_META_PROP } from './constants';
Form.create = (o = {}) => {
const options = assign({}, o, {
fieldNameProp: 'id',
fieldMetaProp: FIELD_META_PROP,
});
const formWrapper = createDOMForm(options);
/* eslint-disable react/prefer-es6-class */
return (Component) => formWrapper(React.createClass({
propTypes: {
form: PropTypes.object.isRequired,
},
childContextTypes: {
form: PropTypes.object.isRequired,
},
getChildContext() {
return {
form: this.props.form,
};
},
render() {
return <Component {...this.props} />;
},
}));
};
Form.Item = FormItem;
// @Deprecated
Form.ValueMixin = ValueMixin;
export default Form; export default Form;

View File

@ -103,7 +103,8 @@ CustomizedForm = Form.create({})(CustomizedForm);
### Form.Item ### Form.Item
> 一个 Form.Item 建议只放一个 child有多个 child 时,`help` `required` `validateStatus` 无法自动生成。 > * 一个 Form.Item 建议只放一个 child有多个 child 时,`help` `required` `validateStatus` 无法自动生成。
> * 只有当表单域为 Form.Item 的子元素时,才会自动生成 `help` `required` `validateStatus`,其它情况请自行设置。
| 参数 | 说明 | 类型 | 可选值 | 默认值 | | 参数 | 说明 | 类型 | 可选值 | 默认值 |
|-----------|------------------------------------------|-----------|-------|--------| |-----------|------------------------------------------|-----------|-------|--------|

View File

@ -0,0 +1,125 @@
---
category: Components
chinese: 图标
type: Basic
english: Icon
toc: false
---
Meaningful vector graphics.
## Icons naming convention
We provide semantic name for every icon, and naming rules are as follows:
- Scanning line icon has the similar name with its solid onebut it's distinguished by `-o`, for example, `question-circle`(a full circle) and `question-circle-o`(an empty circle);
- Naming sequence`[icon's name]-[shape, optional]-[Scanning line or not]-[direction, optional]`.
## How to use
Use tag <Icon /> to create an icon and set its type in the type prop, for example:
```html
<Icon type="link" />
```
Finally, it will be rendered as follow:
```html
<i class="anticon anticon-${type}"></i>
```
## Local deployment of icons font
By default, icon components uses [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。
### 一. Directional Icons
```__react
import IconSet from 'site/theme/template/IconSet';
const icons1 = ['step-backward', 'step-forward', 'fast-backward', 'fast-forward', 'shrink', 'arrow-salt', 'down', 'up', 'left', 'right', 'caret-down', 'caret-up', 'caret-left', 'caret-right', 'caret-circle-right', 'caret-circle-left', 'caret-circle-o-right', 'caret-circle-o-left', 'circle-right', 'circle-left', 'circle-o-right', 'circle-o-left', 'double-right', 'double-left', 'verticle-right', 'verticle-left', 'forward', 'backward', 'rollback', 'enter', 'retweet', 'swap', 'swap-left', 'swap-right', 'arrow-right', 'arrow-up', 'arrow-down', 'arrow-left', 'play-circle', 'play-circle-o', 'circle-up', 'circle-down', 'circle-o-up', 'circle-o-down', 'caret-circle-o-up', 'caret-circle-o-down', 'caret-circle-up', 'caret-circle-down'];
ReactDOM.render(<IconSet className="icons" icons={icons1} key="icons1" />, mountNode);
```
### 二. Suggested Icons
```__react
const icons2 = ['question', 'question-circle-o', 'question-circle', 'plus', 'plus-circle-o', 'plus-circle', 'pause', 'pause-circle-o', 'pause-circle', 'minus', 'minus-circle-o', 'minus-circle', 'plus-square', 'minus-square', 'info', 'info-circle-o', 'info-circle', 'exclamation', 'exclamation-circle-o', 'exclamation-circle', 'cross', 'cross-circle-o', 'cross-circle', 'check', 'check-circle-o', 'check-circle', 'clock-circle-o', 'clock-circle'];
ReactDOM.render(<IconSet className="icons" icons={icons2} key="icons2" />, mountNode);
```
### 三. Universal Icons
```__react
const icons3 = ['lock', 'unlock', 'android', 'apple', 'area-chart', 'bar-chart', 'bars', 'book', 'calendar', 'cloud', 'cloud-download', 'code', 'copy', 'credit-card', 'delete', 'desktop', 'download', 'edit', 'ellipsis', 'file', 'file-text', 'file-unknown', 'file-pdf','file-excel', 'file-jpg', 'file-ppt', 'folder', 'folder-open', 'github', 'hdd', 'frown', 'meh', 'inbox', 'laptop', 'appstore-o', 'appstore', 'line-chart', 'link', 'logout', 'mail', 'menu-fold', 'menu-unfold', 'mobile', 'notification', 'paper-clip', 'picture', 'pie-chart', 'poweroff', 'reload', 'search', 'setting', 'share-alt', 'shopping-cart', 'smile', 'tablet', 'tag', 'tags', 'to-top', 'upload', 'user', 'video-camera', 'windows', 'ie', 'chrome', 'home', 'loading', 'smile-circle', 'meh-circle', 'frown-circle', 'tags-o', 'tag-o', 'cloud-upload-o', 'cloud-download-o', 'cloud-upload', 'cloud-o', 'star-o', 'star', 'heart-o', 'heart', 'environment', 'environment-o', 'eye', 'eye-o', 'camera', 'camera-o', 'aliwangwang', 'aliwangwang-o', 'save', 'team', 'solution', 'phone', 'filter', 'exception', 'export', 'customerservice', 'qrcode', 'scan', 'like', 'dislike', 'message', 'pay-circle', 'pay-circle-o', 'calculator', 'pushpin', 'pushpin-o'];
ReactDOM.render(<IconSet className="icons" icons={icons3} key="icons3" />, mountNode);
```
<style>
.markdown .icons {
width: 100%;
}
ul.anticons-list {
margin: 20px 0;
list-style: none;
overflow: hidden;
}
ul.anticons-list li {
float: left;
margin: 6px 6px 6px 0;
width: 145px;
text-align: center;
list-style: none;
cursor: pointer;
height: 100px;
color: #5C6B77;
transition: all 0.2s ease;
position: relative;
padding-top: 10px;
}
ul.anticons-list li:hover {
background-color: #4BB8FF;
color: #fff;
border-radius: 4px;
}
ul.anticons-list li.copied:hover {
color: rgba(255,255,255,0.2);
}
ul.anticons-list li:after {
position: absolute;
top: 10px;
left: 0;
height: 100%;
width: 100%;
content: "Copied!";
text-align: center;
line-height: 110px;
color: #fff;
transition: all 0.3s cubic-bezier(0.18, 0.89, 0.32, 1.28);
opacity: 0;
}
ul.anticons-list li.copied:after {
opacity: 1;
top: 0;
}
.anticon {
font-size: 26px;
margin: 12px 0 16px;
}
.anticon-class {
display: block;
text-align: center;
transform: scale(0.83);
font-family: Consolas;
white-space: nowrap;
}
</style>

View File

@ -1,6 +1,13 @@
import * as React from 'react'; import * as React from 'react';
export default props => { export interface IconProps {
type: string;
className?: string;
title?: string;
onClick?: (e) => void;
}
export default (props: IconProps) => {
const { type, className = '' } = props; const { type, className = '' } = props;
return <i {...props} className={`${className} anticon anticon-${type}`.trim()} />; return <i {...props} className={`${className} anticon anticon-${type}`.trim()} />;
}; };

View File

@ -1,10 +1,18 @@
--- ---
order: 0 order: 0
title: 基本 title:
zh-CN: 基本
en-US: Basic
--- ---
## zh-CN
数字输入框。 数字输入框。
## en-US
Numeric-only input box.
````jsx ````jsx
import { InputNumber } from 'antd'; import { InputNumber } from 'antd';

View File

@ -1,10 +1,18 @@
--- ---
order: 3 order: 3
title: 小数 title:
zh-CN: 小数
en-US: Decimals
--- ---
## zh-CN
和原生的数字输入框一样value 的精度由 step 的小数位数决定。 和原生的数字输入框一样value 的精度由 step 的小数位数决定。
## en-US
A numeric-only input box whose values can be increased or decreased using a decimal step. The number of decimals (also known as precision) is determined by the step prop.
````jsx ````jsx
import { InputNumber } from 'antd'; import { InputNumber } from 'antd';

View File

@ -1,10 +1,18 @@
--- ---
order: 2 order: 2
title: 不可用 title:
zh-CN: 不可用
en-US: Disabled
--- ---
## zh-CN
点击按钮切换可用状态。 点击按钮切换可用状态。
## en-US
Click the button to toggle between available and disabled states.
````jsx ````jsx
import { InputNumber, Button } from 'antd'; import { InputNumber, Button } from 'antd';

View File

@ -1,10 +1,18 @@
--- ---
order: 1 order: 1
title: 三种大小 title:
zh-CN: 三种大小
en-US: Sizes
--- ---
## zh-CN
三种大小的数字输入框,当 size 分别为 `large``small` 时,输入框高度为 `32px``22px` ,默认高度为 `28px` 三种大小的数字输入框,当 size 分别为 `large``small` 时,输入框高度为 `32px``22px` ,默认高度为 `28px`
## en-US
There are three sizes available to a numeric input box. By default, the size is `28px`. The two additional sizes are `large` and `small` which means `32px` and `22px`, respectively.
````jsx ````jsx
import { InputNumber } from 'antd'; import { InputNumber } from 'antd';

View File

@ -0,0 +1,25 @@
---
category: Components
chinese: 数字输入框
type: Form Controls
english: InputNumber
---
Enter a number within certain range with the mouse or keyboard.
## When to use
When a numeric value needs to be provided.
## API
| property | description | type | default |
|-------------|----------------|--------------------|--------------|
| min | min value | Number | -Infinity |
| max | max vale | Number | Infinity |
| value | current value | Number | |
| step | The number to which the current value is increased or decreased. It can be an integer or decimal. | Number or String | 1 |
| defaultValue | initial value | Number | |
| onChange | The callback triggered when the value is changed. | Function | |
| disabled | disable the input | Boolean | false |
| size | width of input box | String | none |

View File

@ -3,7 +3,19 @@ import classNames from 'classnames';
import RcInputNumber from 'rc-input-number'; import RcInputNumber from 'rc-input-number';
import splitObject from '../_util/splitObject'; import splitObject from '../_util/splitObject';
export default class InputNumber extends React.Component { export interface InputNumberProps {
prefixCls?: string;
min?: number;
max?: number;
value?: number;
step?: number | string;
defaultValue?: number;
onChange?: (value: number) => void;
disabled?: boolean;
size?: 'large' | 'small' | 'default';
}
export default class InputNumber extends React.Component<InputNumberProps, any> {
static defaultProps = { static defaultProps = {
prefixCls: 'ant-input-number', prefixCls: 'ant-input-number',
step: 1, step: 1,

View File

@ -1,7 +1,14 @@
import * as React from 'react'; import * as React from 'react';
import classNames from 'classnames'; import classNames from 'classnames';
export default function Group(props) { export interface GroupProps {
className?: string;
size?: 'large' | 'small' | 'default';
children?: any;
style?: React.CSSProperties;
}
const Group: React.StatelessComponent<GroupProps> = (props) => {
const className = classNames({ const className = classNames({
'ant-input-group': true, 'ant-input-group': true,
'ant-input-group-lg': props.size === 'large', 'ant-input-group-lg': props.size === 'large',
@ -13,8 +20,10 @@ export default function Group(props) {
{props.children} {props.children}
</span> </span>
); );
} };
Group.propTypes = { Group.propTypes = {
children: React.PropTypes.any, children: React.PropTypes.any,
}; };
export default Group;

View File

@ -27,7 +27,32 @@ function clearNextFrameAction(nextFrameId) {
} }
} }
export default class Input extends Component { interface AutoSizeType {
minRows?: number;
maxRows?: number;
};
export interface InputProps {
prefixCls?: string;
className?: string;
type: string;
id?: number | string;
value?: any;
defaultValue?: any;
placeholder?: string;
size?: 'large' | 'default' | 'small';
disabled?: boolean;
readOnly?: boolean;
addonBefore?: React.ReactNode;
addonAfter?: React.ReactNode;
onPressEnter?: React.FormEventHandler;
onKeyDown?: React.FormEventHandler;
onChange?: React.FormEventHandler;
autosize?: boolean | AutoSizeType;
}
export default class Input extends Component<InputProps, any> {
static Group: any;
static defaultProps = { static defaultProps = {
defaultValue: '', defaultValue: '',
disabled: false, disabled: false,
@ -58,6 +83,12 @@ export default class Input extends Component {
onKeyDown: PropTypes.func, onKeyDown: PropTypes.func,
}; };
nextFrameActionId: number;
refs: {
[key: string]: any;
input: any;
};
constructor(props) { constructor(props) {
super(props); super(props);
this.state = { this.state = {
@ -98,8 +129,8 @@ export default class Input extends Component {
if (type !== 'textarea' || !autosize || !this.refs.input) { if (type !== 'textarea' || !autosize || !this.refs.input) {
return; return;
} }
const minRows = autosize ? autosize.minRows : null; const minRows = autosize ? (autosize as AutoSizeType).minRows : null;
const maxRows = autosize ? autosize.maxRows : null; const maxRows = autosize ? (autosize as AutoSizeType).maxRows : null;
const textareaStyles = calculateNodeHeight(this.refs.input, false, minRows, maxRows); const textareaStyles = calculateNodeHeight(this.refs.input, false, minRows, maxRows);
this.setState({ textareaStyles }); this.setState({ textareaStyles });
} }

View File

@ -1,10 +1,18 @@
--- ---
order: 2 order: 2
title: 前置/后置标签 title:
zh-CN: 前置/后置标签
en-US: Pre / Post tab
--- ---
## zh-CN
用于配置一些固定组合。 用于配置一些固定组合。
## en-US
Using pre & post tabs example.
````jsx ````jsx
import { Input, Select } from 'antd'; import { Input, Select } from 'antd';
const Option = Select.Option; const Option = Select.Option;

View File

@ -1,18 +1,28 @@
--- ---
order: 6 order: 6
title: 适应文本高度的文本域 title:
zh-CN: 适应文本高度的文本域
en-US: Autosizing the height to fit the content
--- ---
## zh-CN
`autosize` 属性适用于 `textarea` 节点,并且只有高度会自动变化。另外 `autosize` 可以设定为一个对象,指定最小行数和最大行数。 `autosize` 属性适用于 `textarea` 节点,并且只有高度会自动变化。另外 `autosize` 可以设定为一个对象,指定最小行数和最大行数。
## en-US
`autosize` prop for a `textarea` type of `Input` makes the height to automatically adjust based on the content.
An options object can be provided to `autosize` to specify the minimum and maximum number of lines the textarea will automatically adjust.
````jsx ````jsx
import { Input } from 'antd'; import { Input } from 'antd';
ReactDOM.render( ReactDOM.render(
<div> <div>
<Input type="textarea" placeholder="自适应内容高度" autosize /> <Input type="textarea" placeholder="Autosize height based on content lines" autosize />
<div style={{ margin: '24px 0' }} /> <div style={{ margin: '24px 0' }} />
<Input type="textarea" placeholder="有最大高度和最小高度" autosize={{ minRows: 2, maxRows: 6 }} /> <Input type="textarea" placeholder="Autosize height with minimum and maximum number of lines" autosize={{ minRows: 2, maxRows: 6 }} />
</div> </div>
, mountNode); , mountNode);
```` ````

View File

@ -1,10 +1,18 @@
--- ---
order: 0 order: 0
title: 基本使用 title:
zh-CN: 基本使用
en-US: Basic usage
--- ---
## zh-CN
基本使用。 基本使用。
## en-US
Basic usage example
````jsx ````jsx
import { Input } from 'antd'; import { Input } from 'antd';

View File

@ -1,10 +1,18 @@
--- ---
order: 3 order: 3
title: 输入框组合 title:
zh-CN: 输入框组合
en-US: Input Group
--- ---
## zh-CN
输入框的组合展现。 输入框的组合展现。
## en-US
Input.Group example
````jsx ````jsx
import { Input, Col } from 'antd'; import { Input, Col } from 'antd';
const InputGroup = Input.Group; const InputGroup = Input.Group;

View File

@ -1,10 +1,18 @@
--- ---
order: 4 order: 4
title: 搜索框 title:
zh-CN: 搜索框
en-US: Search box
--- ---
## zh-CN
带有搜索按钮的输入框。 带有搜索按钮的输入框。
## en-US
Example of creating a search box by grouping a standard input with a search button.
````jsx ````jsx
import { Input, Button } from 'antd'; import { Input, Button } from 'antd';
import classNames from 'classnames'; import classNames from 'classnames';

View File

@ -1,20 +1,30 @@
--- ---
order: 1 order: 1
title: 三种大小 title:
zh-CN: 三种大小
en-US: Three sizes of Input
--- ---
## zh-CN
我们为 `<Input />` 输入框定义了三种尺寸(大、默认、小),高度分别为 `32px`、`28px` 和 `22px` 我们为 `<Input />` 输入框定义了三种尺寸(大、默认、小),高度分别为 `32px`、`28px` 和 `22px`
注意: 在表单里面,我们只使用大尺寸的输入框。 注意: 在表单里面,我们只使用大尺寸的输入框。
## en-US
There are three sizes of an Input box: `large` (32px)、`default` (28px) and `small` (22px).
Note: Inside of forms, only the large size is used.
````jsx ````jsx
import { Input } from 'antd'; import { Input } from 'antd';
ReactDOM.render( ReactDOM.render(
<div className="example-input"> <div className="example-input">
<Input size="large" placeholder="大尺寸" /> <Input size="large" placeholder="large size" />
<Input placeholder="默认尺寸" /> <Input placeholder="default size" />
<Input size="small" placeholder="小尺寸" /> <Input size="small" placeholder="small size" />
</div> </div>
, mountNode); , mountNode);
```` ````

View File

@ -1,10 +1,18 @@
--- ---
order: 5 order: 5
title: 文本域 title:
zh-CN: 文本域
en-US: Textarea
--- ---
## zh-CN
用于多行输入,指定 `type` 为一个特殊的 `textarea` 用于多行输入,指定 `type` 为一个特殊的 `textarea`
## en-US
For multi-line user input cases, an input whose `type` prop has the value of `"textarea"` can be used.
````jsx ````jsx
import { Input } from 'antd'; import { Input } from 'antd';

View File

@ -0,0 +1,47 @@
---
category: Components
chinese: 输入框
type: Form Controls
english: Input
---
A basic widget for getting the user input is a text field.
Keyboard and mouse can be used for providing or changing data.
## When to Use
- A user input in a form field is needed.
- A search input is required.
## API
### Input
| Property | Description | Type | Available Values | Default |
|----------------|-----------------------|----------|------------------|---------------|
| type | The type of input. For a multi-line input, the 'textarea' value can be used. | string | 'text' or 'textarea' | 'text' |
| id | The identifier. | number or string | | |
| value | The content value. | any | | |
| defaultValue | The initial value. | any | | |
| size | The size of the input box. The implicit value is 'default'. Note: in the context of a form, the 'large' size is used. | string | {'large','default','small'} | 'default' |
| disabled | Tell if the input is disabled. | bool | | false |
| addonBefore | The label text displayed before (on the left side of) the input field. | node | | |
| addonAfter | The label text displayed after (on the right side of) the input field. | node | | |
| onPressEnter | The callback function that is triggered when pressing Enter key. | function(e) | | |
| autosize | Height autosize feature, available when type="textarea". | bool or object | `true` or `{ minRows: 2, maxRows: 6 }` | false |
> When `Input` is used in a `Form.Item` context, if the `Form.Item` has the `id` and `options` props defined
then `value`, `defaultValue`, and `id` props are automatically set.
#### Input.Group
| Property | Description | Type | Available Values | Default |
|-----------|----------------------------------|--------|-----------------------------|-----------|
| size | The size of `Input.Group` specifies the size of the included `Input` fields. | string | {'large','default','small'} | 'default' |
```html
<Input.Group className={string}>
<Input />
<Input />
</Input.Group>
```

View File

@ -1,17 +1,39 @@
import { PropTypes } from 'react';
import * as React from 'react'; import * as React from 'react';
import { PropTypes } from 'react';
import classNames from 'classnames'; import classNames from 'classnames';
import assign from 'object-assign'; import assign from 'object-assign';
const stringOrNumber = PropTypes.oneOfType([PropTypes.string, PropTypes.number]);
const objectOrNumber = PropTypes.oneOfType([PropTypes.object, PropTypes.number]);
import splitObject from '../_util/splitObject'; import splitObject from '../_util/splitObject';
export default function Col(props) { const stringOrNumber = PropTypes.oneOfType([PropTypes.string, PropTypes.number]);
const objectOrNumber = PropTypes.oneOfType([PropTypes.object, PropTypes.number]);
interface ColSize {
span?: number;
order?: number;
offset?: number;
push?: number;
pull?: number;
}
export interface ColProps {
className?: string;
span?: number;
order?: number;
offset?: number;
push?: number;
pull?: number;
xs?: ColSize;
sm?: ColSize;
md?: ColSize;
lg?: ColSize;
}
const Col: React.StatelessComponent<ColProps> = (props) => {
const [{ span, order, offset, push, pull, className, children }, others] = splitObject(props, const [{ span, order, offset, push, pull, className, children }, others] = splitObject(props,
['span', 'order', 'offset', 'push', 'pull', 'className', 'children']); ['span', 'order', 'offset', 'push', 'pull', 'className', 'children']);
let sizeClassObj = {}; let sizeClassObj = {};
['xs', 'sm', 'md', 'lg'].forEach(size => { ['xs', 'sm', 'md', 'lg'].forEach(size => {
let sizeProps = {}; let sizeProps: ColSize = {};
if (typeof props[size] === 'number') { if (typeof props[size] === 'number') {
sizeProps.span = props[size]; sizeProps.span = props[size];
} else if (typeof props[size] === 'object') { } else if (typeof props[size] === 'object') {
@ -38,7 +60,7 @@ export default function Col(props) {
}, sizeClassObj)); }, sizeClassObj));
return <div {...others} className={classes}>{children}</div>; return <div {...others} className={classes}>{children}</div>;
} };
Col.propTypes = { Col.propTypes = {
span: stringOrNumber, span: stringOrNumber,
@ -53,3 +75,5 @@ Col.propTypes = {
md: objectOrNumber, md: objectOrNumber,
lg: objectOrNumber, lg: objectOrNumber,
}; };
export default Col;

View File

@ -1,6 +1,6 @@
--- ---
category: Components category: Components
chinese: 布局 chinese: 栅格
type: Basic type: Basic
cols: 1 cols: 1
english: Layout english: Layout

View File

@ -1,8 +1,19 @@
import React, { Children, cloneElement } from 'react'; import * as React from 'react';
import { Children, cloneElement } from 'react';
import classNames from 'classnames'; import classNames from 'classnames';
import assign from 'object-assign'; import assign from 'object-assign';
import splitObject from '../_util/splitObject'; import splitObject from '../_util/splitObject';
export default class Row extends React.Component {
export interface RowProps {
className?: string;
gutter?: number;
type?: 'flex';
align?: 'top' | 'middle' | 'bottom';
justify?: 'start' | 'end' | 'center' | 'space-around' | 'space-between';
style?: React.CSSProperties;
}
export default class Row extends React.Component<RowProps, any> {
static defaultProps = { static defaultProps = {
gutter: 0, gutter: 0,
}; };
@ -28,7 +39,7 @@ export default class Row extends React.Component {
marginLeft: gutter / -2, marginLeft: gutter / -2,
marginRight: gutter / -2, marginRight: gutter / -2,
}, style) : style; }, style) : style;
const cols = Children.map(children, col => { const cols = Children.map(children, (col: React.ReactElement<any>) => {
if (!col) { if (!col) {
return null; return null;
} }

View File

@ -7,7 +7,7 @@ title:
## zh-CN ## zh-CN
此处列出 Ant Design 中需要国际化支持的组件,你可以在演示里切换语言。 此处列出 Ant Design 中需要国际化支持的组件,你可以在演示里切换语言。涉及时间的组件请注意时区设置 [DatePicker](/components/date-picker/#components-date-picker-demo-locale)。
## en-US ## en-US
@ -32,6 +32,12 @@ const columns = [{
dataIndex: 'age', dataIndex: 'age',
}]; }];
const customLocale = {
timezoneOffset: 8 * 60,
firstDayOfWeek: 1,
minimalDaysInFirstWeek: 1,
};
const Page = React.createClass({ const Page = React.createClass({
getInitialState() { getInitialState() {
return { return {
@ -112,6 +118,10 @@ const App = React.createClass({
this.setState({ locale: e.target.value }); this.setState({ locale: e.target.value });
}, },
render() { render() {
const locale = { ...this.state.locale };
if (locale.DatePicker) {
locale.DatePicker = { ...locale.DatePicker, ...customLocale };
}
return ( return (
<div> <div>
<div className="change-locale"> <div className="change-locale">
@ -121,7 +131,7 @@ const App = React.createClass({
<Radio.Button key="cn">中文</Radio.Button> <Radio.Button key="cn">中文</Radio.Button>
</Radio.Group> </Radio.Group>
</div> </div>
<LocaleProvider locale={this.state.locale}><Page /></LocaleProvider> <LocaleProvider locale={locale}><Page /></LocaleProvider>
</div> </div>
); );
}, },

View File

@ -29,7 +29,7 @@ let App = React.createClass({
handleSubmit(e) { handleSubmit(e) {
e.preventDefault(); e.preventDefault();
this.props.form.validateFields((errors, values) => { this.props.form.validateFields((errors, values) => {
if (!!errors) { if (errors) {
console.log('Errors in form!!!'); console.log('Errors in form!!!');
return; return;
} }

View File

@ -45,7 +45,7 @@ const App = React.createClass({
</MenuItemGroup> </MenuItemGroup>
</SubMenu> </SubMenu>
<Menu.Item key="alipay"> <Menu.Item key="alipay">
<a href="http://www.alipay.com/" target="_blank">导航四 - 链接</a> <a href="http://www.alipay.com/" target="_blank" rel="noopener noreferrer">导航四 - 链接</a>
</Menu.Item> </Menu.Item>
</Menu> </Menu>
); );

View File

@ -89,6 +89,12 @@
} }
} }
&-horizontal,
&-inline,
&-vertical {
z-index: auto;
}
&-inline, &-inline,
&-vertical { &-vertical {
border-right: 1px solid @border-color-split; border-right: 1px solid @border-color-split;

View File

@ -7,7 +7,12 @@ import classNames from 'classnames';
import { getConfirmLocale } from './locale'; import { getConfirmLocale } from './locale';
import assign from 'object-assign'; import assign from 'object-assign';
class ActionButton extends React.Component { export interface ActionButtonProps {
type: 'primary' | 'ghost' | 'dashed';
actionFn: Function;
closeModal: Function;
}
class ActionButton extends React.Component<ActionButtonProps, any> {
constructor(props) { constructor(props) {
super(props); super(props);
this.state = { this.state = {

View File

@ -45,9 +45,11 @@ const Test = React.createClass({
<Button type="primary" onClick={this.showModal}> <Button type="primary" onClick={this.showModal}>
Open modal dialog Open modal dialog
</Button> </Button>
<Modal ref="modal" <Modal
visible={this.state.visible} visible={this.state.visible}
title="Title" onOk={this.handleOk} onCancel={this.handleCancel} title="Title"
onOk={this.handleOk}
onCancel={this.handleCancel}
footer={[ footer={[
<Button key="back" type="ghost" size="large" onClick={this.handleCancel}>Return</Button>, <Button key="back" type="ghost" size="large" onClick={this.handleCancel}>Return</Button>,
<Button key="submit" type="primary" size="large" loading={this.state.loading} onClick={this.handleOk}> <Button key="submit" type="primary" size="large" loading={this.state.loading} onClick={this.handleOk}>

View File

@ -57,7 +57,7 @@ export default class Pagination extends React.Component<PaginationProps, any> {
render() { render() {
let className = this.props.className; let className = this.props.className;
let selectComponentClass = Select; let selectComponentClass = Select as React.ReactNode;
let locale; let locale;
if (this.context.antLocale && this.context.antLocale.Pagination) { if (this.context.antLocale && this.context.antLocale.Pagination) {

View File

@ -1 +1,2 @@
module.exports = require('rc-pagination/lib/locale/en_US'); import en_US from 'rc-pagination/lib/locale/en_US';
export default en_US;

View File

@ -1 +1,2 @@
module.exports = require('rc-pagination/lib/locale/zh_CN'); import zh_CN from 'rc-pagination/lib/locale/zh_CN';
export default zh_CN;

View File

@ -1,56 +0,0 @@
---
order: 1
title: 进场和离场
---
同时支持进场和离场动画。
````jsx
import { QueueAnim, Button } from 'antd';
const Test = React.createClass({
getInitialState() {
return {
show: true,
};
},
onClick() {
this.setState({
show: !this.state.show,
});
},
render() {
const list = this.state.show ? [
<div className="demo-kp" key="a">
<ul>
<li></li>
<li></li>
<li></li>
</ul>
</div>,
<div className="demo-listBox" key="b">
<div className="demo-list">
<div className="title"></div>
<ul>
<li></li>
<li></li>
<li></li>
</ul>
</div>
</div>,
] : null;
return (
<div>
<p className="buttons">
<Button type="primary" onClick={this.onClick}>切换</Button>
</p>
<QueueAnim className="demo-content">
{list}
</QueueAnim>
</div>
);
},
});
ReactDOM.render(<Test />, mountNode);
````

View File

@ -1,67 +0,0 @@
---
order: 5
title: 添加与删除
---
场景里有增加或删除条目时也会触发动画。
````jsx
import { QueueAnim, Button } from 'antd';
const Test = React.createClass({
getInitialState() {
return {
show: true,
items: [
<li key="0"></li>,
<li key="1"></li>,
<li key="2"></li>,
],
};
},
onClick() {
this.setState({
show: !this.state.show,
});
},
onAdd() {
const items = this.state.items;
items.push(<li key={Date.now()}></li>);
this.setState({
show: true,
items,
});
},
onRemove() {
const items = this.state.items;
items.splice(items.length - 1, 1);
this.setState({
show: true,
items,
});
},
render() {
return (
<div>
<p className="buttons">
<Button type="primary" onClick={this.onClick}>切换</Button>
<Button onClick={this.onAdd} style={{ marginLeft: 10 }}>添加</Button>
<Button onClick={this.onRemove} style={{ marginLeft: 10 }}>删除</Button>
</p>
<div className="demo-content">
<div className="demo-listBox" key="b">
<div className="demo-list">
<div className="title"></div>
<QueueAnim component="ul" type={['right', 'left']}>
{this.state.show ? this.state.items : null}
</QueueAnim>
</div>
</div>
</div>
</div>
);
},
});
ReactDOM.render(<Test />, mountNode);
````

View File

@ -1,61 +0,0 @@
---
order: 3
title: 自定义动画进出场
---
通过 `animConfig` 来自定义动画进出场。
````jsx
import { QueueAnim, Button } from 'antd';
const Test = React.createClass({
getInitialState() {
return {
show: true,
};
},
onClick() {
this.setState({
show: !this.state.show,
});
},
render() {
const list = this.state.show ? [
<div className="demo-kp" key="a">
<ul>
<li></li>
<li></li>
<li></li>
</ul>
</div>,
<div className="demo-listBox" key="b">
<div className="demo-list">
<div className="title"></div>
<ul>
<li></li>
<li></li>
<li></li>
</ul>
</div>
</div>,
] : null;
return (
<div>
<p className="buttons">
<Button type="primary" onClick={this.onClick}>切换</Button>
</p>
<QueueAnim className="demo-content"
animConfig={[
{ opacity: [1, 0], translateY: [0, 50] },
{ opacity: [1, 0], translateY: [0, -50] },
]}
>
{list}
</QueueAnim>
</div>
);
},
});
ReactDOM.render(<Test />, mountNode);
````

View File

@ -1,60 +0,0 @@
---
order: 2
title: 进场和离场
---
通过把属性设置一个数组来分别表示进出场的效果,`type`、`animConfig`、`delay`、`duration`、`interval`、`ease` 等属性均支持配置为数组。
````jsx
import { QueueAnim, Button } from 'antd';
const Test = React.createClass({
getInitialState() {
return {
show: true,
};
},
onClick() {
this.setState({
show: !this.state.show,
});
},
render() {
const list = this.state.show ? [
<div className="demo-kp" key="a">
<ul>
<li></li>
<li></li>
<li></li>
</ul>
</div>,
<div className="demo-listBox" key="b">
<div className="demo-list">
<div className="title"></div>
<ul>
<li></li>
<li></li>
<li></li>
</ul>
</div>
</div>,
] : null;
return (
<div>
<p className="buttons">
<Button type="primary" onClick={this.onClick}>切换</Button>
</p>
<QueueAnim className="demo-content"
key="demo"
type={['right', 'left']}
ease={['easeOutQuart', 'easeInOutQuart']}
>
{list}
</QueueAnim>
</div>
);
},
});
ReactDOM.render(<Test />, mountNode);
````

View File

@ -1,64 +0,0 @@
---
order: 4
title: 表单动画进出场
---
表单组合的进场与出场动画。
````jsx
import { QueueAnim, Button, Radio, Input, Form, Row, Col } from 'antd';
const FormItem = Form.Item;
const RadioGroup = Radio.Group;
const Test = React.createClass({
getInitialState() {
return {
show: true,
};
},
onClick() {
this.setState({
show: !this.state.show,
});
},
render() {
const formItemLayout = {
labelCol: { span: 6 },
wrapperCol: { span: 14 },
};
return (
<div>
<p className="buttons">
<Button type="primary" onClick={this.onClick}>切换</Button>
</p>
<QueueAnim component={Form} className="ant-form ant-form-horizontal" type="bottom" leaveReverse>
{this.state.show ? [
<FormItem key="item1" {...formItemLayout} label="用户名:">
<p className="ant-form-text">大眼萌 minion</p>
</FormItem>,
<FormItem key="item2" {...formItemLayout} label="密码:">
<Input type="password" placeholder="请输入密码" />
</FormItem>,
<FormItem key="item3" {...formItemLayout} label="您的性别:">
<RadioGroup>
<Radio value="male">男的</Radio>
<Radio value="female">女的</Radio>
</RadioGroup>
</FormItem>,
<FormItem key="item4" {...formItemLayout} label="备注:">
<Input type="textarea" placeholder="随便写" />
</FormItem>,
<Row key="submit">
<Col span="16" offset="6">
<Button type="primary" htmlType="submit">确定</Button>
</Col>
</Row>,
] : null}
</QueueAnim>
</div>
);
},
});
ReactDOM.render(<Test />, mountNode);
````

View File

@ -1,76 +0,0 @@
---
order: 6
title: 一个复杂些的例子
---
模拟一个完整的页面。
````jsx
import { QueueAnim, Button } from 'antd';
const Test = React.createClass({
getInitialState() {
return {
show: true,
};
},
onClick() {
this.setState({
show: !this.state.show,
});
},
render() {
const page = this.state.show ? [
<div className="demo-header" key="header">
<div className="logo">
<img alt="logo" width="30" src="https://t.alipayobjects.com/images/rmsweb/T1B9hfXcdvXXXXXXXX.svg" />
<span>logo</span>
</div>
<QueueAnim component="ul">
<li key="0"></li>
<li key="1"></li>
<li key="2"></li>
<li key="3"></li>
<li key="4"></li>
</QueueAnim>
</div>,
<QueueAnim className="demo-content" key="content" delay={300}>
<div className="demo-title" key="title">我是标题</div>
<div className="demo-kp" key="b">
<QueueAnim component="ul">
<li key="0"></li>
<li key="1"></li>
<li key="2"></li>
</QueueAnim>
</div>
<div className="demo-title" key="title2">我是标题</div>
<div className="demo-listBox">
<QueueAnim className="demo-list" delay={500}>
<div className="title" key="title3"></div>
<QueueAnim component="ul" type="bottom" key="li">
<li key="0"></li>
<li key="1"></li>
<li key="2"></li>
<li key="3"></li>
<li key="4"></li>
</QueueAnim>
</QueueAnim>
</div>
</QueueAnim>,
<QueueAnim delay={1000} type="bottom" key="footerBox">
<div className="demo-footer" key="footer"></div>
</QueueAnim>,
] : null;
return (
<div>
<p className="buttons">
<Button type="primary" onClick={this.onClick}>切换</Button>
</p>
<QueueAnim type={['right', 'left']}>{page}</QueueAnim>
</div>
);
},
});
ReactDOM.render(<Test />, mountNode);
````

View File

@ -1,140 +0,0 @@
---
order: 7
iframe: true
title: Router 默认进出场
---
router 组合的进场与出场动画。
````jsx
const ReactRouter = require('react-router');
let { Router, Route, Link, hashHistory } = ReactRouter;
import { QueueAnim, Menu } from 'antd';
function App(props) {
const key = props.location.pathname;
const keys = key.replace('/', '') ? [key.replace('/', '')] : ['home'];
return (
<div>
<Menu style={{ marginBottom: 10 }} mode="horizontal" selectedKeys={keys}>
<Menu.Item key="home">
<Link to="/">首页</Link>
</Menu.Item>
<Menu.Item key="page1">
<Link to="/page1">Page 1</Link>
</Menu.Item>
<Menu.Item key="page2">
<Link to="/page2">Page 2</Link>
</Menu.Item>
</Menu>
<QueueAnim type={['right', 'left']} className="demo-router-wrap">
{React.cloneElement(props.children || <Home />, { key })}
</QueueAnim>
</div>
);
}
function Home() {
return (
<div className="demo-router-child">
<QueueAnim className="demo-content">
<div className="demo-kp" key="a">
<QueueAnim component="ul">
<li key="0"></li>
<li key="1"></li>
<li key="2"></li>
</QueueAnim>
</div>
<div className="demo-kp" key="b">
<QueueAnim component="ul">
<li key="0"></li>
<li key="1"></li>
<li key="2"></li>
</QueueAnim>
</div>
<div className="demo-kp" key="c">
<QueueAnim component="ul">
<li key="0"></li>
<li key="1"></li>
<li key="2"></li>
</QueueAnim>
</div>
</QueueAnim>
</div>
);
}
function Page1() {
return (
<div className="demo-router-child">
<QueueAnim className="demo-content">
<div className="demo-kp" key="b">
<QueueAnim component="ul">
<li key="0"></li>
<li key="1"></li>
<li key="2"></li>
</QueueAnim>
</div>
<div className="demo-listBox">
<QueueAnim className="demo-list" delay={200}>
<div className="title" key="title3"></div>
<QueueAnim component="ul" animConfig={{ opacity: [1, 0], translateY: [0, 30], scale: [1, 0.9] }} key="ul">
<li key="0"></li>
<li key="1"></li>
<li key="2"></li>
</QueueAnim>
</QueueAnim>
</div>
</QueueAnim>
</div>
);
}
function Page2() {
return (
<div className="demo-router-child">
<div className="demo-content">
<div className="demo-listBox">
<QueueAnim className="demo-list">
<div className="title" key="title3"></div>
<QueueAnim component="ul" animConfig={{ opacity: [1, 0], translateY: [0, 30], scale: [1, 0.9] }} key="li">
<li key="0"></li>
<li key="1"></li>
<li key="2"></li>
<li key="3"></li>
<li key="4"></li>
<li key="5"></li>
</QueueAnim>
</QueueAnim>
</div>
</div>
</div>
);
}
ReactDOM.render((
<Router history={hashHistory}>
<Route path="/" component={App} ignoreScrollBehavior>
<Route path="page1" component={Page1} />
<Route path="page2" component={Page2} />
</Route>
</Router>
), mountNode);
````
````css
#components-queue-anim-demo-router iframe {
height: 260px;
}
#components-queue-anim-demo-router .demo-router-wrap {
position: relative;
width: 100%;
margin: auto;
height:200px;
overflow: hidden;
}
#components-queue-anim-demo-router .queue-anim-leaving {
position: absolute;
width:100%;
}
````

View File

@ -1,33 +0,0 @@
---
order: 0
title: 默认
---
最简单的进场例子。
````jsx
import { QueueAnim } from 'antd';
ReactDOM.render(
<QueueAnim delay={500} style={{ height: 150 }}>
<div key="a">依次进场</div>
<div key="b">依次进场</div>
<div key="c">依次进场</div>
<div key="d">依次进场</div>
<div key="e">依次进场</div>
<div key="f">依次进场</div>
</QueueAnim>
, mountNode);
````
````css
.code-box-demo > div {
overflow: hidden;
}
.code-box-demo .buttons {
text-align: center;
margin: 0 auto;
margin-bottom: 20px;
}
````

View File

@ -1,48 +0,0 @@
---
category: Components
chinese: 进出场动画
type: Other
english: QueueAnim
---
通过简单的配置对一组元素添加串行的进场动画效果。
## 何时使用
- 从内容A到内容B的转变过程时能有效的吸引用户注意力突出视觉中心提高整体视觉效果。
- 小的信息元素排布或块状较多的情况下,根据一定的路径层次依次进场,区分维度层级,来凸显量级,使页面转场更加流畅和舒适,提高整体视觉效果和产品的质感。
- 特别适合首页和需要视觉展示效果的宣传页,以及单页应用的切换页面动效。
## API
> 此组件 `antd@1.0.0+` 后标记为废弃,您可以直接使用 `import QueueAnim from 'rc-queue-anim'` 来代替,相关文档也已移到 [ant-motioin](http://motion.ant.design/components/queue-anim)。
> [ant-motioin](http://motion.ant.design/) 是一个动效设计语言,欢迎关注。
元素依次进场。
```html
<QueueAnim>
<div key='demo1'>依次进场</div>
<div key='demo2'>依次进场</div>
<div key='demo3'>依次进场</div>
<div key='demo4'>依次进场</div>
</QueueAnim>
```
> 每个子标签必须带 key如果未设置 key 将不执行动画。
|参数 |类型 |默认 |详细 |
|------------|----------------|---------|----------------|
| type | string / array | `right` | 动画内置参数 <br/> `left` `right` `top` `bottom` `scale` `scaleBig` `scaleX` `scaleY`|
| animConfig | object / array | null | 配置动画参数 <br/>`{opacity:[1, 0],translateY:[0, -30]}` 具体参考 [velocity](http://julian.com/research/velocity) 的写法|
| delay | number / array | 0 | 整个动画的延时,以毫秒为单位 |
| duration | number / array | 500 | 每个动画的时间,以毫秒为单位 |
| interval | number / array | 100 | 每个动画的间隔时间,以毫秒为单位 |
| leaveReverse | boolean | false | 出场时是否倒放,从最后一个 dom 开始往上播放 |
| ease | string / array | `easeOutQuart` | 动画的缓动函数,[查看详细](http://julian.com/research/velocity/#easing) |
| animatingClassName | array | `['queue-anim-entering', 'queue-anim-leaving']` | 进出场动画进行中的类名 |
| component | string | `div` | QueueAnim 替换的标签名 |
> 当以上数据类型为 Array 时,`['left', 'top']` 第一个为进场动画属性, 第二个为离场属性。

View File

@ -1,14 +0,0 @@
import * as React from 'react';
import RcQueueAnim from 'rc-queue-anim';
import warning from 'warning';
export default class QueueAnim extends React.Component {
componentDidMount() {
warning(false, '`QueueAnim` is deprecated, ' +
'you can import QueueAnim from \'rc-queue-anim\' directly.' +
'The Demo will be moved to http://motion.ant.design/component/queue-anim');
}
render() {
return <RcQueueAnim {...this.props} />;
}
}

View File

@ -4,4 +4,5 @@ import Button from './radioButton';
Radio.Button = Button; Radio.Button = Button;
Radio.Group = Group; Radio.Group = Group;
export { Button, Group };
export default Radio; export default Radio;

View File

@ -31,6 +31,9 @@ export interface SelectProps {
defaultActiveFirstOption?: boolean; defaultActiveFirstOption?: boolean;
labelInValue?: boolean; labelInValue?: boolean;
getPopupContainer?: (triggerNode: React.ReactNode) => React.ReactNode; getPopupContainer?: (triggerNode: React.ReactNode) => React.ReactNode;
style?: React.CSSProperties;
dropdownMenuStyle?: React.CSSProperties;
onChange?: (value) => void;
} }
export interface SelectContext { export interface SelectContext {
@ -39,6 +42,8 @@ export interface SelectContext {
}; };
} }
export { Option, OptGroup }
export default class Select extends React.Component<SelectProps, any> { export default class Select extends React.Component<SelectProps, any> {
static Option = Option; static Option = Option;
static OptGroup = OptGroup; static OptGroup = OptGroup;

View File

@ -152,16 +152,16 @@
} }
&-lg { &-lg {
.ant-select-selection--single { .@{select-prefix-cls}-selection--single {
height: 32px; height: 32px;
.ant-select-selection__rendered { .@{select-prefix-cls}-selection__rendered {
line-height: 30px; line-height: 30px;
} }
} }
.ant-select-selection--multiple { .@{select-prefix-cls}-selection--multiple {
min-height: 32px; min-height: 32px;
.ant-select-selection__rendered { .@{select-prefix-cls}-selection__rendered {
li { li {
height: 24px; height: 24px;
line-height: 24px; line-height: 24px;
@ -171,18 +171,18 @@
} }
&-sm { &-sm {
.ant-select-selection { .@{select-prefix-cls}-selection {
border-radius: @border-radius-sm; border-radius: @border-radius-sm;
} }
.ant-select-selection--single { .@{select-prefix-cls}-selection--single {
height: 22px; height: 22px;
.ant-select-selection__rendered { .@{select-prefix-cls}-selection__rendered {
line-height: 20px; line-height: 20px;
} }
} }
.ant-select-selection--multiple { .@{select-prefix-cls}-selection--multiple {
min-height: 22px; min-height: 22px;
.ant-select-selection__rendered { .@{select-prefix-cls}-selection__rendered {
li { li {
height: 14px; height: 14px;
line-height: 14px; line-height: 14px;
@ -223,14 +223,17 @@
&-search--inline { &-search--inline {
float: left; float: left;
width: 100%; width: 100%;
height: 100%;
.@{select-prefix-cls}-search__field__wrap { .@{select-prefix-cls}-search__field__wrap {
width: 100%; width: 100%;
height: 100%;
} }
.@{select-prefix-cls}-search__field { .@{select-prefix-cls}-search__field {
border: 0; border: 0;
font-size: 100%; font-size: 100%;
height: 100%;
background: transparent; background: transparent;
outline: 0; outline: 0;
border-radius: @border-radius-base; border-radius: @border-radius-base;
@ -361,6 +364,9 @@
position: absolute; position: absolute;
left: 0; left: 0;
right: 0; right: 0;
> ul {
height: 100%;
}
} }
} }
} }

View File

@ -103,7 +103,7 @@ export default class Spin extends React.Component<SpinProps, any> {
const spinElement = ( const spinElement = (
<div {...divProps} className={spinClassName}> <div {...divProps} className={spinClassName}>
<span className={`${prefixCls}-dot`} /> <span className={`${prefixCls}-dot`} />
<div className={`${prefixCls}-text`}>{tip || '加载中...'}</div> {tip ? <div className={`${prefixCls}-text`}>{tip}</div> : null}
</div> </div>
); );

View File

@ -106,11 +106,6 @@
.square(@spin-dot-size-lg); .square(@spin-dot-size-lg);
} }
&-text,
&&-show-text &-dot {
display: none;
}
&&-show-text &-text { &&-show-text &-text {
display: block; display: block;
} }

View File

@ -16,7 +16,7 @@ Let's generate 3~6 steps randomly, and proceed to a random step.
````jsx ````jsx
import { Steps, Button } from 'antd'; import { Steps, Button } from 'antd';
const Step = Steps.Step; const Step = Steps.Step;
const array = Array.apply(null, Array(Math.floor(Math.random() * 3) + 3)); const array = [...Array(Math.floor(Math.random() * 3) + 3)];
const steps = array.map((item, i) => ({ const steps = array.map((item, i) => ({
title: `步骤${i + 1}`, title: `步骤${i + 1}`,
})); }));

View File

@ -4,6 +4,7 @@
@success-color : #87d068; @success-color : #87d068;
@error-color : #f50; @error-color : #f50;
@warning-color : #fa0; @warning-color : #fa0;
@normal-color : #d9d9d9;
// ------ Base & Require ------ // ------ Base & Require ------
@body-background : #fff; @body-background : #fff;

View File

@ -96,6 +96,7 @@ interface TableContext {
export default class Table extends React.Component<TableProps, any> { export default class Table extends React.Component<TableProps, any> {
static propTypes = { static propTypes = {
dataSource: React.PropTypes.array, dataSource: React.PropTypes.array,
columns: React.PropTypes.array.isRequired,
prefixCls: React.PropTypes.string, prefixCls: React.PropTypes.string,
useFixedHeader: React.PropTypes.bool, useFixedHeader: React.PropTypes.bool,
rowSelection: React.PropTypes.object, rowSelection: React.PropTypes.object,
@ -311,11 +312,11 @@ export default class Table extends React.Component<TableProps, any> {
return; return;
} }
return (a, b) => { return (a, b) => {
let result = sortColumn.sorter(a, b); const result = sortColumn.sorter(a, b);
if (result !== 0) { if (result !== 0) {
return (sortOrder === 'descend') ? -result : result; return (sortOrder === 'descend') ? -result : result;
} }
return a.indexForSort - b.indexForSort; return 0;
}; };
} }
@ -774,9 +775,6 @@ export default class Table extends React.Component<TableProps, any> {
let data = this.props.dataSource || []; let data = this.props.dataSource || [];
// 优化本地排序 // 优化本地排序
data = data.slice(0); data = data.slice(0);
for (let i = 0; i < data.length; i++) {
data[i] = assign({}, data[i], { indexForSort: i });
}
const sorterFn = this.getSorterFn(); const sorterFn = this.getSorterFn();
if (sorterFn) { if (sorterFn) {
data = data.sort(sorterFn); data = data.sort(sorterFn);

View File

@ -35,9 +35,9 @@ const columns = [{
render: (text, record) => ( render: (text, record) => (
<span> <span>
<a href="#">操作一{record.name}</a> <a href="#">操作一{record.name}</a>
<span className="ant-divider"></span> <span className="ant-divider" />
<a href="#">操作二</a> <a href="#">操作二</a>
<span className="ant-divider"></span> <span className="ant-divider" />
<a href="#" className="ant-dropdown-link"> <a href="#" className="ant-dropdown-link">
更多 <Icon type="down" /> 更多 <Icon type="down" />
</a> </a>

Some files were not shown because too many files have changed in this diff Show More