mirror of
https://github.com/ant-design/ant-design.git
synced 2024-11-25 11:40:04 +08:00
Merge remote-tracking branch 'ant/develop-0.10.0' into feature-spin
This commit is contained in:
commit
b0bad43bf8
@ -13,7 +13,7 @@
|
||||
标记了一个(或封装一组)操作命令,响应用户点击行为,触发相应的业务逻辑。
|
||||
|
||||
|
||||
## 如何使用
|
||||
## API
|
||||
|
||||
- 通过设置 Button 的属性来产生不同的按钮样式,推荐顺序为:`type` -> `shape` -> `size` -> `loading` -> `disabled`
|
||||
|
||||
|
@ -39,6 +39,8 @@ function createPicker(TheCalendar) {
|
||||
onSelect: null, // 向前兼容
|
||||
onChange() {}, // onChange 可用于 Validator
|
||||
locale: {},
|
||||
// 自动换方向有很多视觉和交互问题
|
||||
// 需求不是很大,和设计师协商后不做
|
||||
placement: {
|
||||
points: ['tl', 'tl'],
|
||||
overflow: { adjustX: 0, adjustY: 0 },
|
||||
@ -84,13 +86,13 @@ function createPicker(TheCalendar) {
|
||||
return date;
|
||||
}
|
||||
}
|
||||
return null;
|
||||
return undefined;
|
||||
},
|
||||
// remove input readonly warning
|
||||
handleInputChange() {},
|
||||
handleChange(value) {
|
||||
this.setState({ value });
|
||||
const timeValue = value ? new Date(value.getTime()) : null;
|
||||
const timeValue = value ? new Date(value.getTime()) : undefined;
|
||||
// onSelect 为向前兼容.
|
||||
if (this.props.onSelect) {
|
||||
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}>
|
||||
{
|
||||
({value}) => {
|
||||
return ([<input
|
||||
disabled={this.props.disabled}
|
||||
onChange={this.handleInputChange}
|
||||
value={value && this.getFormatter().format(value)}
|
||||
placeholder={this.props.placeholder}
|
||||
className={'ant-calendar-picker-input ant-input' + sizeClass} />,
|
||||
<span className="ant-calendar-picker-icon" />]);
|
||||
return <span>
|
||||
<input disabled={this.props.disabled}
|
||||
onChange={this.handleInputChange}
|
||||
value={value && this.getFormatter().format(value)}
|
||||
placeholder={this.props.placeholder}
|
||||
className={'ant-calendar-picker-input ant-input' + sizeClass} />
|
||||
<span className="ant-calendar-picker-icon" />
|
||||
</span>;
|
||||
}
|
||||
}
|
||||
</Datepicker>
|
||||
|
121
components/table/demo/colspan-rowspan.md
Normal file
121
components/table/demo/colspan-rowspan.md
Normal 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'));
|
||||
````
|
@ -78,8 +78,9 @@ var dataSource = new Table.DataSource({
|
||||
|------------|----------------------------|-----------------|---------------------|---------|
|
||||
| title | 列头显示文字 | String or React.Element | | |
|
||||
| dataIndex | 列数据在 data 中对应的 key | String | | |
|
||||
| colSpan | 表头列合并,设置为0时,不渲染 | Number | | |
|
||||
| key | React 需要的 key | String | | |
|
||||
| render | 生成复杂数据的渲染函数,参数分别为当前列的值,当前列数据,列索引 | Function(text, record, index) {} | | |
|
||||
| render | 生成复杂数据的渲染函数,参数分别为当前列的值,当前列数据,列索引,@return里面可以设置表格[行/列合并](#demo-colspan-rowspan) | Function(text, record, index) {} | | |
|
||||
| filters | 表头的筛选菜单项 | Array | | |
|
||||
| onFilter | 本地模式下,确定筛选的运行函数 | Function | | |
|
||||
| sorter | 排序函数,本地模式下为一个函数,远程模式下为布尔值 | Function or Boolean | | 无 |
|
||||
|
@ -1,85 +1,105 @@
|
||||
# 添加
|
||||
# 动态的页签
|
||||
|
||||
- order: 4
|
||||
|
||||
演示添加删除功能。
|
||||
演示添加删除和附加操作。
|
||||
|
||||
---
|
||||
|
||||
````jsx
|
||||
import { Tabs, Button, Icon } from 'antd';
|
||||
import { Tabs, Button, Icon, message } from 'antd';
|
||||
const TabPane = Tabs.TabPane;
|
||||
|
||||
var index = 0;
|
||||
let index = 0;
|
||||
const closeStyle = {
|
||||
position: 'absolute',
|
||||
top: 0,
|
||||
right: -10,
|
||||
};
|
||||
var addStyle = {
|
||||
pointerEvents: 'auto',
|
||||
color: 'black',
|
||||
top: 8,
|
||||
right: -9,
|
||||
};
|
||||
|
||||
var Test = React.createClass({
|
||||
const addStyle = {
|
||||
pointerEvents: 'auto',
|
||||
color: '#2db7f5',
|
||||
position: 'absolute',
|
||||
top: 8,
|
||||
left: 0,
|
||||
marginLeft: -8,
|
||||
};
|
||||
|
||||
const Test = React.createClass({
|
||||
getInitialState() {
|
||||
return {
|
||||
tabs: [{
|
||||
title: 'title ' + index,
|
||||
content: 'content ' + index,
|
||||
index: index
|
||||
}],
|
||||
activeKey: 'title ' + index
|
||||
activeKey: index.toString()
|
||||
};
|
||||
},
|
||||
remove(title, e) {
|
||||
remove(index, e) {
|
||||
e.stopPropagation();
|
||||
if(this.state.tabs.length === 1) {
|
||||
antd.message.error('仅剩一个,不能删除');
|
||||
let tabs = this.state.tabs;
|
||||
let activeKey = this.state.activeKey;
|
||||
let foundIndex = 0;
|
||||
|
||||
if(tabs.length === 1) {
|
||||
message.error('仅剩一个,不能删除');
|
||||
return;
|
||||
}
|
||||
var foundIndex = 0;
|
||||
var tabs = this.state.tabs.filter(function (t, index) {
|
||||
if (t.title !== title) {
|
||||
|
||||
const newTabs = tabs.filter(tab => {
|
||||
if (tab.index !== index) {
|
||||
return true;
|
||||
} else {
|
||||
foundIndex = index;
|
||||
return false;
|
||||
}
|
||||
});
|
||||
var activeKey = this.state.activeKey;
|
||||
if (activeKey === title) {
|
||||
if (foundIndex) {
|
||||
foundIndex--;
|
||||
}
|
||||
activeKey = tabs[foundIndex].title;
|
||||
|
||||
if (activeKey === index) {
|
||||
activeKey = tabs[foundIndex - 1].index;
|
||||
}
|
||||
this.setState({tabs, activeKey})
|
||||
|
||||
this.setState({
|
||||
tabs: newTabs, activeKey
|
||||
});
|
||||
},
|
||||
add() {
|
||||
index++;
|
||||
index += 1;
|
||||
this.setState({
|
||||
tabs: this.state.tabs.concat({
|
||||
title: 'title '+index,
|
||||
content: 'content '+index,
|
||||
})
|
||||
title: 'title ' + index,
|
||||
content: 'content ' + index,
|
||||
index: index,
|
||||
}),
|
||||
activeKey: index.toString(),
|
||||
});
|
||||
},
|
||||
onChange(activeKey) {
|
||||
this.setState({activeKey});
|
||||
console.log(activeKey);
|
||||
this.setState({ activeKey });
|
||||
},
|
||||
render() {
|
||||
return <Tabs
|
||||
onChange={this.onChange}
|
||||
activeKey={this.state.activeKey}
|
||||
tabBarExtraContent={<Button type="primary">其它操作</Button>}>
|
||||
{
|
||||
this.state.tabs.map((t)=>{
|
||||
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}
|
||||
</TabPane>;
|
||||
}).concat(<TabPane key="__add" disabled tab={<Icon style={addStyle} type="plus-circle" onClick={this.add}></Icon>} />)
|
||||
}
|
||||
</Tabs>
|
||||
const addBtn = <Icon style={addStyle} type="plus-circle" onClick={this.add} />;
|
||||
const operations = <Button>操作</Button>;
|
||||
return (
|
||||
<Tabs onChange={this.onChange}
|
||||
activeKey={this.state.activeKey}
|
||||
tabBarExtraContent={operations}>
|
||||
{
|
||||
this.state.tabs.map(tab => (
|
||||
<TabPane key={tab.index} tab={
|
||||
<div>
|
||||
{tab.title}
|
||||
<Icon type="cross" style={closeStyle} onClick={this.remove.bind(this, tab.index)} />
|
||||
</div>
|
||||
}>{tab.content}</TabPane>
|
||||
))
|
||||
}
|
||||
<TabPane key="__add" disabled tab={addBtn} />
|
||||
</Tabs>
|
||||
);
|
||||
}
|
||||
})
|
||||
|
||||
|
@ -7,8 +7,8 @@
|
||||
---
|
||||
|
||||
````jsx
|
||||
var Tree = antd.Tree;
|
||||
var TreeNode = Tree.TreeNode;
|
||||
import { Tree } from 'antd';
|
||||
const TreeNode = Tree.TreeNode;
|
||||
|
||||
ReactDOM.render(
|
||||
<Tree defaultExpandAll={false}>
|
||||
|
@ -7,8 +7,8 @@
|
||||
---
|
||||
|
||||
````jsx
|
||||
var Tree = antd.Tree;
|
||||
var TreeNode = Tree.TreeNode;
|
||||
import { Tree } from 'antd';
|
||||
const TreeNode = Tree.TreeNode;
|
||||
|
||||
function handleCheck(info) {
|
||||
console.log('check: ', info);
|
||||
|
80
components/tree/demo/dynamic.md
Normal file
80
components/tree/demo/dynamic.md
Normal 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'));
|
||||
````
|
@ -7,9 +7,8 @@
|
||||
---
|
||||
|
||||
````jsx
|
||||
var Tree = antd.Tree;
|
||||
var TreeNode = Tree.TreeNode;
|
||||
var Button = antd.Button;
|
||||
import { Tree, Button } from 'antd';
|
||||
const TreeNode = Tree.TreeNode;
|
||||
|
||||
class TreeDemo extends React.Component {
|
||||
constructor(props) {
|
||||
|
@ -24,6 +24,7 @@
|
||||
|defaultSelectedKeys | 默认选中的树节点 | String[] | [] |
|
||||
|onCheck | 点击树节点或复选框触发 | function(e:{checked:bool,node,checkedKeys,event}) | - |
|
||||
|onSelect | 点击树节点触发 | function(e:{checked:bool,node,checkedKeys,event}) | - |
|
||||
|onDataLoaded | 异步加载数据 | function(node)| - |
|
||||
|
||||
### TreeNode props
|
||||
|
||||
|
@ -4,30 +4,19 @@ import Icon from '../iconfont';
|
||||
|
||||
const prefixCls = 'ant-upload';
|
||||
|
||||
|
||||
export default React.createClass({
|
||||
getDefaultProps() {
|
||||
return {
|
||||
items: []
|
||||
};
|
||||
},
|
||||
getInitialState() {
|
||||
return {
|
||||
items: this.props.items
|
||||
};
|
||||
},
|
||||
componentWillReceiveProps(nextProps) {
|
||||
if ('items' in nextProps) {
|
||||
this.setState({
|
||||
items: nextProps.items
|
||||
});
|
||||
}
|
||||
},
|
||||
|
||||
handleClose(file) {
|
||||
this.props.onRemove(file);
|
||||
},
|
||||
|
||||
render() {
|
||||
let list = this.state.items.map((file) => {
|
||||
let list = this.props.items.map((file) => {
|
||||
let statusIcon = file.status === 'done' ?
|
||||
<Icon type="check" className={prefixCls + '-success-icon'} /> :
|
||||
<Icon type="loading" />;
|
||||
|
@ -13,7 +13,7 @@ Ant Design React 致力于提供给程序员愉悦的开发体验。
|
||||
### 1. 安装命令行工具
|
||||
|
||||
```bash
|
||||
$ npm install antd-bin -g
|
||||
$ npm install antd-init -g
|
||||
```
|
||||
|
||||
[更多使用说明](https://github.com/ant-design/antd-bin#使用说明)。
|
||||
@ -24,7 +24,7 @@ $ npm install antd-bin -g
|
||||
|
||||
```bash
|
||||
$ mkdir antd-demo && cd antd-demo
|
||||
$ antd init
|
||||
$ antd-init
|
||||
$ npm install
|
||||
```
|
||||
|
||||
|
@ -55,10 +55,10 @@
|
||||
"rc-slider": "~1.5.0",
|
||||
"rc-steps": "~1.4.0",
|
||||
"rc-switch": "~1.2.0",
|
||||
"rc-table": "~3.3.0",
|
||||
"rc-table": "~3.4.0",
|
||||
"rc-tabs": "~5.4.3",
|
||||
"rc-tooltip": "~3.0.1",
|
||||
"rc-tree": "~0.16.2",
|
||||
"rc-tree": "~0.18.1",
|
||||
"rc-upload": "~1.6.4",
|
||||
"rc-util": "~2.0.3",
|
||||
"react-slick": "~0.8.0",
|
||||
|
@ -90,6 +90,7 @@
|
||||
border: 0;
|
||||
width: 100%;
|
||||
cursor: auto;
|
||||
outline: 0;
|
||||
}
|
||||
|
||||
&-week-number {
|
||||
@ -156,6 +157,7 @@
|
||||
padding: 0;
|
||||
background: transparent;
|
||||
text-align: center;
|
||||
transition: background 0.3s ease;
|
||||
|
||||
&:hover {
|
||||
background: tint(@primary-color, 90%);
|
||||
@ -233,6 +235,35 @@
|
||||
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 {
|
||||
.btn;
|
||||
.btn-primary;
|
||||
|
@ -39,6 +39,7 @@
|
||||
line-height: 24px;
|
||||
padding: 0 6px;
|
||||
border-radius: 4px;
|
||||
transition: background 0.3s ease;
|
||||
|
||||
&:hover {
|
||||
background: tint(@primary-color, 90%);
|
||||
|
@ -39,6 +39,7 @@
|
||||
line-height: 24px;
|
||||
padding: 0 6px;
|
||||
border-radius: 4px;
|
||||
transition: background 0.3s ease;
|
||||
|
||||
&:hover {
|
||||
background: tint(@primary-color, 90%);
|
||||
|
@ -54,6 +54,7 @@
|
||||
border-radius: 4px;
|
||||
margin: 0 auto;
|
||||
color: #666;
|
||||
transition: background 0.3s ease;
|
||||
|
||||
&:hover {
|
||||
background: tint(@primary-color, 90%);
|
||||
|
@ -39,6 +39,7 @@
|
||||
line-height: 24px;
|
||||
padding: 0 6px;
|
||||
border-radius: 4px;
|
||||
transition: background 0.3s ease;
|
||||
|
||||
&:hover {
|
||||
background: tint(@primary-color, 90%);
|
||||
|
@ -57,6 +57,16 @@
|
||||
cursor: pointer;
|
||||
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 {
|
||||
&-disabled {
|
||||
background: #fff;
|
||||
|
Loading…
Reference in New Issue
Block a user