Merge remote-tracking branch 'ant/develop-0.10.0' into feature-spin

This commit is contained in:
KgTong 2015-10-30 13:11:39 +08:00
commit b0bad43bf8
19 changed files with 337 additions and 78 deletions

View File

@ -13,7 +13,7 @@
标记了一个(或封装一组)操作命令,响应用户点击行为,触发相应的业务逻辑。 标记了一个(或封装一组)操作命令,响应用户点击行为,触发相应的业务逻辑。
## 如何使用 ## API
- 通过设置 Button 的属性来产生不同的按钮样式,推荐顺序为:`type` -> `shape` -> `size` -> `loading` -> `disabled` - 通过设置 Button 的属性来产生不同的按钮样式,推荐顺序为:`type` -> `shape` -> `size` -> `loading` -> `disabled`

View File

@ -39,6 +39,8 @@ function createPicker(TheCalendar) {
onSelect: null, // onSelect: null, //
onChange() {}, // onChange Validator onChange() {}, // onChange Validator
locale: {}, locale: {},
//
//
placement: { placement: {
points: ['tl', 'tl'], points: ['tl', 'tl'],
overflow: { adjustX: 0, adjustY: 0 }, overflow: { adjustX: 0, adjustY: 0 },
@ -84,13 +86,13 @@ function createPicker(TheCalendar) {
return date; return date;
} }
} }
return null; return undefined;
}, },
// remove input readonly warning // remove input readonly warning
handleInputChange() {}, handleInputChange() {},
handleChange(value) { handleChange(value) {
this.setState({ value }); this.setState({ value });
const timeValue = value ? new Date(value.getTime()) : null; const timeValue = value ? new Date(value.getTime()) : undefined;
// onSelect . // onSelect .
if (this.props.onSelect) { if (this.props.onSelect) {
require('util-deprecate')(this.props.onSelect, 'onSelect property of Datepicker is deprecated, use onChange instead')(timeValue); require('util-deprecate')(this.props.onSelect, 'onSelect property of Datepicker is deprecated, use onChange instead')(timeValue);
@ -134,13 +136,14 @@ function createPicker(TheCalendar) {
onChange={this.handleChange}> onChange={this.handleChange}>
{ {
({value}) => { ({value}) => {
return ([<input return <span>
disabled={this.props.disabled} <input disabled={this.props.disabled}
onChange={this.handleInputChange} onChange={this.handleInputChange}
value={value && this.getFormatter().format(value)} value={value && this.getFormatter().format(value)}
placeholder={this.props.placeholder} placeholder={this.props.placeholder}
className={'ant-calendar-picker-input ant-input' + sizeClass} />, className={'ant-calendar-picker-input ant-input' + sizeClass} />
<span className="ant-calendar-picker-icon" />]); <span className="ant-calendar-picker-icon" />
</span>;
} }
} }
</Datepicker> </Datepicker>

View File

@ -0,0 +1,121 @@
# 表格行/列合并
- order: 13
表头只支持列合并,使用 column 里的 colSpan 进行设置。
表格支持行/列合并,可以指定内容对齐方式,使用 render 里的单元格属性 colSpan 或者 rowSpan 设值为 0 时,设置的表格不会渲染。
---
````jsx
import { Table } from 'antd';
// 事例表中第四行合并了五列,除了第一列设置 colSpan = 5 外
// 其他列的第四行 colSpan = 0 (被合并掉,不会渲染)
const renderContent = function(value, row, index) {
let obj = {
children: value,
props: {}
}
if (index === 4) {
obj.props.colSpan = 0;
}
return obj;
};
const columns = [{
title: '姓名',
dataIndex: 'name',
render: function(text, row, index) {
if (index < 4) {
return <a href="javascript:;">{text}</a>;
} else {
return {
children: <a href="javascript:;">{text}</a>,
props: {
align: 'center',
colSpan: 5
}
}
}
}
}, {
title: '年龄',
dataIndex: 'age',
render: renderContent
}, {
title: '家庭电话',
colSpan: 2,
dataIndex: 'tel',
render: function(value, row, index) {
let obj = {
children: value,
props:{}
}
// 第三列的第三行行合并
if (index === 2) {
obj.props.rowSpan = 2;
}
// 第三列的第四行被合并没了,设置 rowSpan = 0 直接不用渲染
if (index === 3) {
obj.props.rowSpan = 0;
}
if (index === 4) {
obj.props.colSpan = 0;
}
return obj;
}
}, {
title: '手机号',
colSpan: 0,
dataIndex: 'phone',
render: renderContent
}, {
title: '住址',
dataIndex: 'address',
render: renderContent
}];
const data = [{
key: '1',
name: '胡彦斌',
age: 32,
tel: '0571-22098909',
phone: 18889898989,
address: '西湖区湖底公园1号'
}, {
key: '2',
name: '胡彦祖',
tel: '0571-22098333',
phone: 18889898888,
age: 42,
address: '西湖区湖底公园1号'
}, {
key: '3',
name: '李大嘴',
age: 32,
tel: '0575-22098909',
phone: 18900010002,
address: '西湖区湖底公园1号'
}, {
key: '4',
name: '李夫人',
age: 18,
tel: '0575-22098909',
phone: 18900010002,
address: '西湖区湖底公园1号'
}, {
key: '5',
name: '习大大',
age: 18,
tel: '0575-22098909',
phone: 18900010002,
address: '西湖区湖底公园1号'
}];
ReactDOM.render(<Table columns={columns} dataSource={data} bordered={true} />
, document.getElementById('components-table-demo-colspan-rowspan'));
````

View File

@ -78,8 +78,9 @@ var dataSource = new Table.DataSource({
|------------|----------------------------|-----------------|---------------------|---------| |------------|----------------------------|-----------------|---------------------|---------|
| title | 列头显示文字 | String or React.Element | | | | title | 列头显示文字 | String or React.Element | | |
| dataIndex | 列数据在 data 中对应的 key | String | | | | dataIndex | 列数据在 data 中对应的 key | String | | |
| colSpan | 表头列合并,设置为0时,不渲染 | Number | | |
| key | React 需要的 key | String | | | | key | React 需要的 key | String | | |
| render | 生成复杂数据的渲染函数,参数分别为当前列的值,当前列数据,列索引 | Function(text, record, index) {} | | | | render | 生成复杂数据的渲染函数,参数分别为当前列的值,当前列数据,列索引@return里面可以设置表格[行/列合并](#demo-colspan-rowspan) | Function(text, record, index) {} | | |
| filters | 表头的筛选菜单项 | Array | | | | filters | 表头的筛选菜单项 | Array | | |
| onFilter | 本地模式下,确定筛选的运行函数 | Function | | | | onFilter | 本地模式下,确定筛选的运行函数 | Function | | |
| sorter | 排序函数,本地模式下为一个函数,远程模式下为布尔值 | Function or Boolean | | 无 | | sorter | 排序函数,本地模式下为一个函数,远程模式下为布尔值 | Function or Boolean | | 无 |

View File

@ -1,85 +1,105 @@
# 添加 # 动态的页签
- order: 4 - order: 4
演示添加删除功能 演示添加删除和附加操作
--- ---
````jsx ````jsx
import { Tabs, Button, Icon } from 'antd'; import { Tabs, Button, Icon, message } from 'antd';
const TabPane = Tabs.TabPane; const TabPane = Tabs.TabPane;
var index = 0; let index = 0;
const closeStyle = { const closeStyle = {
position: 'absolute', position: 'absolute',
top: 0, top: 8,
right: -10, right: -9,
};
var addStyle = {
pointerEvents: 'auto',
color: 'black',
}; };
var Test = React.createClass({ const addStyle = {
pointerEvents: 'auto',
color: '#2db7f5',
position: 'absolute',
top: 8,
left: 0,
marginLeft: -8,
};
const Test = React.createClass({
getInitialState() { getInitialState() {
return { return {
tabs: [{ tabs: [{
title: 'title ' + index, title: 'title ' + index,
content: 'content ' + index, content: 'content ' + index,
index: index
}], }],
activeKey: 'title ' + index activeKey: index.toString()
}; };
}, },
remove(title, e) { remove(index, e) {
e.stopPropagation(); e.stopPropagation();
if(this.state.tabs.length === 1) { let tabs = this.state.tabs;
antd.message.error('仅剩一个,不能删除'); let activeKey = this.state.activeKey;
let foundIndex = 0;
if(tabs.length === 1) {
message.error('仅剩一个,不能删除');
return; return;
} }
var foundIndex = 0;
var tabs = this.state.tabs.filter(function (t, index) { const newTabs = tabs.filter(tab => {
if (t.title !== title) { if (tab.index !== index) {
return true; return true;
} else { } else {
foundIndex = index; foundIndex = index;
return false; return false;
} }
}); });
var activeKey = this.state.activeKey;
if (activeKey === title) { if (activeKey === index) {
if (foundIndex) { activeKey = tabs[foundIndex - 1].index;
foundIndex--;
}
activeKey = tabs[foundIndex].title;
} }
this.setState({tabs, activeKey})
this.setState({
tabs: newTabs, activeKey
});
}, },
add() { add() {
index++; index += 1;
this.setState({ this.setState({
tabs: this.state.tabs.concat({ tabs: this.state.tabs.concat({
title: 'title '+index, title: 'title ' + index,
content: 'content '+index, content: 'content ' + index,
}) index: index,
}),
activeKey: index.toString(),
}); });
}, },
onChange(activeKey) { onChange(activeKey) {
this.setState({activeKey}); console.log(activeKey);
this.setState({ activeKey });
}, },
render() { render() {
return <Tabs const addBtn = <Icon style={addStyle} type="plus-circle" onClick={this.add} />;
onChange={this.onChange} const operations = <Button>操作</Button>;
activeKey={this.state.activeKey} return (
tabBarExtraContent={<Button type="primary">其它操作</Button>}> <Tabs onChange={this.onChange}
{ activeKey={this.state.activeKey}
this.state.tabs.map((t)=>{ tabBarExtraContent={operations}>
return <TabPane key={t.title} tab={<div>{t.title} <Icon type="cross" style={closeStyle} onClick={this.remove.bind(this,t.title)}></Icon></div>}> {
{t.content} this.state.tabs.map(tab => (
</TabPane>; <TabPane key={tab.index} tab={
}).concat(<TabPane key="__add" disabled tab={<Icon style={addStyle} type="plus-circle" onClick={this.add}></Icon>} />) <div>
} {tab.title}
</Tabs> <Icon type="cross" style={closeStyle} onClick={this.remove.bind(this, tab.index)} />
</div>
}>{tab.content}</TabPane>
))
}
<TabPane key="__add" disabled tab={addBtn} />
</Tabs>
);
} }
}) })

View File

@ -7,8 +7,8 @@
--- ---
````jsx ````jsx
var Tree = antd.Tree; import { Tree } from 'antd';
var TreeNode = Tree.TreeNode; const TreeNode = Tree.TreeNode;
ReactDOM.render( ReactDOM.render(
<Tree defaultExpandAll={false}> <Tree defaultExpandAll={false}>

View File

@ -7,8 +7,8 @@
--- ---
````jsx ````jsx
var Tree = antd.Tree; import { Tree } from 'antd';
var TreeNode = Tree.TreeNode; const TreeNode = Tree.TreeNode;
function handleCheck(info) { function handleCheck(info) {
console.log('check: ', info); console.log('check: ', info);

View File

@ -0,0 +1,80 @@
# 异步数据加载
- order: 3
异步加载数据
---
````jsx
import { Tree } from 'antd';
const TreeNode = Tree.TreeNode;
const asyncTree = [
{name: "pNode 01", key: "0-0"},
];
const generateTreeNodes = () => {
const arr = [
{name: "伯约", key: "0-0-0"},
];
return arr;
}
const TreeDemo = React.createClass({
timeout(duration = 0) {
return new Promise((resolve, reject) => {
setTimeout(resolve.bind(this), duration);
})
},
getInitialState() {
return {
treeData: []
};
},
componentDidMount() {
this.timeout(1000).then(() => {
this.setState({
treeData: asyncTree
});
return asyncTree;
});
},
handleSelect(info) {
console.log('selected', info);
},
handleDataLoaded(treeNode) {
return this.timeout(1000).then(() => {
const child = generateTreeNodes();
const treeData = [...this.state.treeData];
treeData.forEach((item) => {
if (item.key === treeNode.props.eventKey) {
item.children = child;
}
});
this.setState({treeData});
return child;
});
},
render() {
const loop = (data) => {
return data.map((item) => {
if (item.children) {
return <TreeNode title={item.name} key={item.key}>{loop(item.children)}</TreeNode>;
} else {
return <TreeNode title={item.name} key={item.key}></TreeNode>;
}
})
};
const parseTreeNode = data => loop(data);
let treeNodes = parseTreeNode(this.state.treeData);
return (
<Tree onSelect={this.handleSelect} onDataLoaded={this.handleDataLoaded} showLine={false}>
{treeNodes}
</Tree>
)
}
})
ReactDOM.render(<TreeDemo />, document.getElementById('components-tree-demo-dynamic'));
````

View File

@ -7,9 +7,8 @@
--- ---
````jsx ````jsx
var Tree = antd.Tree; import { Tree, Button } from 'antd';
var TreeNode = Tree.TreeNode; const TreeNode = Tree.TreeNode;
var Button = antd.Button;
class TreeDemo extends React.Component { class TreeDemo extends React.Component {
constructor(props) { constructor(props) {

View File

@ -24,6 +24,7 @@
|defaultSelectedKeys | 默认选中的树节点 | String[] | [] | |defaultSelectedKeys | 默认选中的树节点 | String[] | [] |
|onCheck | 点击树节点或复选框触发 | function(e:{checked:bool,node,checkedKeys,event}) | - | |onCheck | 点击树节点或复选框触发 | function(e:{checked:bool,node,checkedKeys,event}) | - |
|onSelect | 点击树节点触发 | function(e:{checked:bool,node,checkedKeys,event}) | - | |onSelect | 点击树节点触发 | function(e:{checked:bool,node,checkedKeys,event}) | - |
|onDataLoaded | 异步加载数据 | function(node)| - |
### TreeNode props ### TreeNode props

View File

@ -4,30 +4,19 @@ import Icon from '../iconfont';
const prefixCls = 'ant-upload'; const prefixCls = 'ant-upload';
export default React.createClass({ export default React.createClass({
getDefaultProps() { getDefaultProps() {
return { return {
items: [] items: []
}; };
}, },
getInitialState() {
return {
items: this.props.items
};
},
componentWillReceiveProps(nextProps) {
if ('items' in nextProps) {
this.setState({
items: nextProps.items
});
}
},
handleClose(file) { handleClose(file) {
this.props.onRemove(file); this.props.onRemove(file);
}, },
render() { render() {
let list = this.state.items.map((file) => { let list = this.props.items.map((file) => {
let statusIcon = file.status === 'done' ? let statusIcon = file.status === 'done' ?
<Icon type="check" className={prefixCls + '-success-icon'} /> : <Icon type="check" className={prefixCls + '-success-icon'} /> :
<Icon type="loading" />; <Icon type="loading" />;

View File

@ -13,7 +13,7 @@ Ant Design React 致力于提供给程序员愉悦的开发体验。
### 1. 安装命令行工具 ### 1. 安装命令行工具
```bash ```bash
$ npm install antd-bin -g $ npm install antd-init -g
``` ```
[更多使用说明](https://github.com/ant-design/antd-bin#使用说明)。 [更多使用说明](https://github.com/ant-design/antd-bin#使用说明)。
@ -24,7 +24,7 @@ $ npm install antd-bin -g
```bash ```bash
$ mkdir antd-demo && cd antd-demo $ mkdir antd-demo && cd antd-demo
$ antd init $ antd-init
$ npm install $ npm install
``` ```

View File

@ -55,10 +55,10 @@
"rc-slider": "~1.5.0", "rc-slider": "~1.5.0",
"rc-steps": "~1.4.0", "rc-steps": "~1.4.0",
"rc-switch": "~1.2.0", "rc-switch": "~1.2.0",
"rc-table": "~3.3.0", "rc-table": "~3.4.0",
"rc-tabs": "~5.4.3", "rc-tabs": "~5.4.3",
"rc-tooltip": "~3.0.1", "rc-tooltip": "~3.0.1",
"rc-tree": "~0.16.2", "rc-tree": "~0.18.1",
"rc-upload": "~1.6.4", "rc-upload": "~1.6.4",
"rc-util": "~2.0.3", "rc-util": "~2.0.3",
"react-slick": "~0.8.0", "react-slick": "~0.8.0",

View File

@ -90,6 +90,7 @@
border: 0; border: 0;
width: 100%; width: 100%;
cursor: auto; cursor: auto;
outline: 0;
} }
&-week-number { &-week-number {
@ -156,6 +157,7 @@
padding: 0; padding: 0;
background: transparent; background: transparent;
text-align: center; text-align: center;
transition: background 0.3s ease;
&:hover { &:hover {
background: tint(@primary-color, 90%); background: tint(@primary-color, 90%);
@ -233,6 +235,35 @@
margin: 0 0 0 8px; margin: 0 0 0 8px;
} }
.@{calendar-prefix-cls}-clear-btn {
position: absolute;
right: 6px;
text-indent: -99px;
overflow: hidden;
width: 20px;
height: 20px;
text-align: center;
line-height: 20px;
top: 6px;
margin: 0;
}
.@{calendar-prefix-cls}-clear-btn:after {
content: "\e620";
font-family: "anticon";
font-size: 12px;
color: #aaa;
display: inline-block;
line-height: 1;
width: 20px;
text-indent: 43px;
transition: color 0.3s ease;
}
.@{calendar-prefix-cls}-clear-btn:hover:after {
color: #666;
}
.@{calendar-prefix-cls}-ok-btn { .@{calendar-prefix-cls}-ok-btn {
.btn; .btn;
.btn-primary; .btn-primary;

View File

@ -39,6 +39,7 @@
line-height: 24px; line-height: 24px;
padding: 0 6px; padding: 0 6px;
border-radius: 4px; border-radius: 4px;
transition: background 0.3s ease;
&:hover { &:hover {
background: tint(@primary-color, 90%); background: tint(@primary-color, 90%);

View File

@ -39,6 +39,7 @@
line-height: 24px; line-height: 24px;
padding: 0 6px; padding: 0 6px;
border-radius: 4px; border-radius: 4px;
transition: background 0.3s ease;
&:hover { &:hover {
background: tint(@primary-color, 90%); background: tint(@primary-color, 90%);

View File

@ -54,6 +54,7 @@
border-radius: 4px; border-radius: 4px;
margin: 0 auto; margin: 0 auto;
color: #666; color: #666;
transition: background 0.3s ease;
&:hover { &:hover {
background: tint(@primary-color, 90%); background: tint(@primary-color, 90%);

View File

@ -39,6 +39,7 @@
line-height: 24px; line-height: 24px;
padding: 0 6px; padding: 0 6px;
border-radius: 4px; border-radius: 4px;
transition: background 0.3s ease;
&:hover { &:hover {
background: tint(@primary-color, 90%); background: tint(@primary-color, 90%);

View File

@ -57,6 +57,16 @@
cursor: pointer; cursor: pointer;
outline: none; outline: none;
} }
&.@{tree-prefix-cls}-icon_loading {
&:after {
content: '\e610';
display: inline-block;
font-family: 'anticon';
font-weight: bold;
.animation(loadingCircle 1s infinite linear);
margin-top:8px;
}
}
&.@{tree-prefix-cls}-switcher { &.@{tree-prefix-cls}-switcher {
&-disabled { &-disabled {
background: #fff; background: #fff;