Merge branch '0.8.0' of github.com:ant-design/ant-design into 0.8.0

This commit is contained in:
jljsj 2015-07-31 13:56:45 +08:00
commit 0c04548a78
35 changed files with 688 additions and 302 deletions

View File

@ -1,3 +1,8 @@
## 0.7.3 (2015-07-30)
* 小幅重构了 Table 分页,修复了分页导致的数据不展示的问题。
* 更新了部分文档。
## 0.7.2 (2015-07-27)
* 修复本地模式下 pagination 为 false 时数据无法显示的 [问题](https://github.com/ant-design/ant-design/commit/1954586665e59031eae5d2c8b2cdb08f83d64fcb)。

View File

@ -1,5 +1,7 @@
# Ant Design [![](https://img.shields.io/travis/ant-design/ant-design.svg?style=flat-square)](https://travis-ci.org/ant-design/ant-design) [![npm package](https://img.shields.io/npm/v/antd.svg?style=flat-square)](https://www.npmjs.org/package/antd) [![Dependency Status](https://david-dm.org/ant-design/ant-design.svg?style=flat-square)](https://david-dm.org/ant-design/ant-design)
[![Join the chat at https://gitter.im/ant-design/ant-design](https://badges.gitter.im/Join%20Chat.svg)](https://gitter.im/ant-design/ant-design?utm_source=badge&utm_medium=badge&utm_campaign=pr-badge&utm_content=badge)
一套企业级的前端设计语言和基于 React 的实现。
设计文档和组件实现均在紧密整理和开发中,部分页面可能不完善,预计 8 月份释出正式版本。

View File

@ -9,6 +9,6 @@
````jsx
var Alert = require('antd/lib/alert');
React.render(<Alert message="警告提示的文案" type="success" />
React.render(<Alert message="成功提示的文案" type="success" />
, document.getElementById('components-alert-demo-basic'));
````

View File

@ -18,8 +18,8 @@ React.render(<div>
type="warn"
closable
onClose={onClose} />
<Alert message="警告提示的标题"
description="警告提示的文案警告提示的文案警告提示的文案警告提示的文案警告提示的文案警告提示的文案警告提示的文案"
<Alert message="错误提示的文案"
description="错误提示的辅助性文字介绍错误提示的辅助性文字介绍错误提示的辅助性文字介绍错误提示的辅助性文字介绍错误提示的辅助性文字介绍错误提示的辅助性文字介绍"
type="error"
closable
onClose={onClose} />

View File

@ -11,6 +11,6 @@ var Alert = require('antd/lib/alert');
var link = <a href="javascript:;">不再提醒</a>
React.render(
<Alert message="警告提示的文案" type="info" closeText={link} />
<Alert message="消息提示的文案" type="info" closeText={link} />
, document.getElementById('components-alert-demo-close-type'));
````

View File

@ -10,19 +10,19 @@
var Alert = require('antd/lib/alert');
React.render(<div>
<Alert message="警告提示的文案"
description="警告提示的辅助性文字介绍警告提示的辅助性文字介绍警告提示的辅助性文字介绍警告提示的辅助性文字介绍"
<Alert message="成功提示的文案"
description="成功提示的辅助性文字介绍成功提示的辅助性文字介绍成功提示的辅助性文字介绍成功提示的辅助性文字介绍"
type="success" />
<Alert message="警告提示的文案"
description="警告提示的辅助性文字介绍警告提示的辅助性文字介绍警告提示的辅助性文字介绍警告提示的辅助性文字介绍警告提示的辅助性文字介绍"
<Alert message="消息提示的文案"
description="消息提示的辅助性文字介绍消息提示的辅助性文字介绍消息提示的辅助性文字介绍"
type="info" />
<Alert
message="警告提示的文案"
description="警告提示的辅助性文字介绍"
description="警告提示的辅助性文字介绍警告提示的辅助性文字介绍"
type="warn" />
<Alert
message="警告提示的文案"
description="警告提示的辅助性文字介绍警告提示的辅助性文字介绍警告提示的辅助性文字介绍警告提示的辅助性文字介绍警告提示的辅助性文字介绍警告提示的辅助性文字介绍警告提示的辅助性文字介绍"
message="错误提示的文案"
description="错误提示的辅助性文字介绍错误提示的辅助性文字介绍错误提示的辅助性文字介绍错误提示的辅助性文字介绍错误提示的辅助性文字介绍错误提示的辅助性文字介绍"
type="error" />
</div>, document.getElementById('components-alert-demo-description'));
````

View File

@ -10,10 +10,10 @@
var Alert = require('antd/lib/alert');
React.render(<div>
<Alert message="警告提示的文案" type="success" />
<Alert message="警告提示的文案警告提示的文案" type="info" />
<Alert message="成功提示的文案" type="success" />
<Alert message="消息提示的文案" type="info" />
<Alert message="警告提示的文案" type="warn" />
<Alert message="警告提示的文案警告提示的文案" type="error" />
<Alert message="错误提示的文案" type="error" />
</div>,
document.getElementById('components-alert-demo-style'));
````

View File

@ -27,11 +27,13 @@ export default React.createClass({
iconClass += 'check-circle';
break;
case 'info':
iconClass += 'question-circle';
iconClass += 'info-circle';
break;
case 'error':
iconClass += 'exclamation-circle';
break;
case 'warn':
iconClass += 'info-circle';
iconClass += 'question-circle';
break;
default:
iconClass += 'default';

View File

@ -17,8 +17,8 @@
| 参数 | 说明 | 类型 | 默认值 |
|----------- |--------------------------------------------------------- | ---------- |-------|
| type | 必选参数,指定警告提示的样式,有四种选择`success`、`info`、`warn`、`error` | String | 无 |
| closable | 可选参数,值为字符串`true`时显示关闭按钮,默认不显示 | String | 无 |
| closeText | 可选参数,自定义关闭 | String | 无 |
| closable | 可选参数,默认不显示关闭按钮 | Boolean | 无 |
| closeText | 可选参数,自定义关闭按钮 | String | 无 |
| message | 必选参数,警告提示内容 | String | 无 |
| description | 可选参数,警告提示的辅助性文字介绍 | String | 无 |
| onClose | 可选参数,关闭时触发的回调函数 | Function | 无 |
| onClose | 可选参数,关闭时触发的回调函数 | Function | 无 |

View File

@ -21,9 +21,6 @@ var App = React.createClass({
render() {
var loadingClass = this.state.loading ? 'ant-btn-loading' : '';
return <div>
<button className="ant-btn ant-btn-primary ant-btn-circle">
<i className="anticon anticon-loading"></i>
</button>
<button className="ant-btn ant-btn-primary ant-btn-lg ant-btn-loading">
加载中
</button>

View File

@ -20,7 +20,7 @@
一级子元素依次进场。
```jsx
```html
<EnterAnimation>
<div>依次进场</div>
<div>依次进场</div>
@ -31,7 +31,7 @@
如子节点有 `enter-data` 值,则只执行有 `enter-data` 的节点的动画,相反所有子节点上都没有 `enter-data`则执行遍历dom下一级节点来执行动画。
```jsx
```html
<EnterAnimation type="left" delay={2}>
<div>
<div enter-data>
@ -40,7 +40,6 @@
</div>
<div enter-data>依次进场</div>
<div enter-data={{type: 'bottom'}}>依次进场,并修改动画效果</div>
<div enter-data={{style: 'margin-top:100px'}}>依次进场,并使用样式修改动画效果</div>
<div>没有动画</div>
</EnterAnimation>
```

View File

@ -3,6 +3,7 @@
- category: Components
- chinese: 布局
- order: 0
- cols: 1
---

View File

@ -8,6 +8,7 @@
````jsx
var message = antd.message;
var success = function() {
message.success('这是一条成功的提示');
};

View File

@ -2,13 +2,19 @@ import React from 'react';
import Notification from 'rc-notification';
let defaultDuration = 1.5;
let top;
var messageInstance;
function getMessageInstance() {
return Notification.newInstance({
messageInstance = messageInstance || Notification.newInstance({
prefixCls: 'ant-message',
transitionName: 'move-up',
style: {} //
style: {
top: top
} //
});
return messageInstance;
}
function notice(content, duration = defaultDuration, type) {
@ -18,7 +24,6 @@ function notice(content, duration = defaultDuration, type) {
'error': 'anticon-exclamation-circle ant-message-error'
})[type];
getMessageInstance().notice({
key: 'simpleMessage',
duration: duration,
style: {},
content: <div className="ant-message-custom-content">
@ -37,5 +42,10 @@ export default {
},
error(content, duration) {
notice(content, duration, 'error');
},
config(options) {
if (options.top) {
top = options.top;
}
}
};

View File

@ -25,3 +25,18 @@
|------------|----------------|----------------------------|--------------|
| content | 提示内容 | React.Element or String | 无 |
| duration | 自动关闭的延时 | number | 1.5 |
还提供了一个全局配置方法:
- `message.config(options)`
```js
message.config({
top: 100
});
```
| 参数 | 说明 | 类型 | 默认值 |
|------------|--------------------|----------------------------|--------------|
| top | 消息距离顶部的位置 | Number | 24px |

View File

@ -10,10 +10,11 @@
var Progress = antd.Progress.Line;
React.render(
<div>
<Progress percent="30" width="170" strokeWidth="3" />
<Progress percent="70" width="170" strokeWidth="3" status="exception" />
<Progress percent="100" width="170" strokeWidth="3" />
<div style={{ width: 170 }}>
<Progress percent="30" strokeWidth="5" />
<Progress percent="50" strokeWidth="5" status="active" />
<Progress percent="70" strokeWidth="5" status="exception" />
<Progress percent="100" strokeWidth="5" />
</div>
, document.getElementById('components-progress-demo-line-mini'));
````

View File

@ -12,8 +12,10 @@ var Progress = antd.Progress.Line;
React.render(
<div>
<Progress percent="30" />
<Progress percent="50" status="active" />
<Progress percent="70" status="exception" />
<Progress percent="100" />
<Progress percent="50" showInfo={false} />
</div>
, document.getElementById('components-progress-demo-line'));
````

View File

@ -1,65 +1,72 @@
import {Line as Progressline, Circle as Progresscircle} from 'rc-progress';
import {Circle as Progresscircle} from 'rc-progress';
import React from 'react';
import assign from 'object-assign';
const prefixCls = 'ant-progress';
const statusColorMap = {
'normal': '#2db7f5',
'exception': '#ff6600',
'success': '#87d068'
};
var Line = React.createClass({
propTypes: {
status: React.PropTypes.oneOf(['normal', 'exception', 'active', 'success']),
showInfo: React.PropTypes.bool,
percent: React.PropTypes.number,
strokeWidth: React.PropTypes.number
},
getDefaultProps() {
return {
width: 300,
percent: 0,
strokeWidth: 3,
status: 'normal' // exception
strokeWidth: 10,
status: 'normal', // exception active
showInfo: true
};
},
render() {
var statusColorMap = {
'normal': '#3FC7FA',
'exception': '#FE8C6A',
'success': '#85D262'
};
var props = assign({}, this.props);
if (parseInt(props.percent) === 100) {
props.status = 'success';
}
var style = {
'width': props.width
};
var fontSize = (props.width / 100 * props.strokeWidth);
var iconStyle = {
'fontSize': (fontSize < 12) ? 12 : fontSize
};
var textStyle = {
'color': statusColorMap[props.status]
};
var progressInfo;
if (props.status === 'exception') {
progressInfo = (
<span style={textStyle} className='ant-progress-line-text'>
<i style={iconStyle} className="anticon anticon-exclamation-circle"></i>
</span>
);
} else if (props.status === 'success') {
progressInfo = (
<span style={textStyle} className='ant-progress-line-text'>
<i style={iconStyle} className="anticon anticon-check-circle"></i>
</span>
);
} else {
progressInfo = (
<span className='ant-progress-line-text'>{props.percent}%</span>
);
var progressInfo, fullCls = '';
if(props.showInfo === true){
if (props.status === 'exception') {
progressInfo = (
<span className={prefixCls + '-line-text'}>
<i className="anticon anticon-exclamation-circle"></i>
</span>
);
} else if (props.status === 'success') {
progressInfo = (
<span className={prefixCls + '-line-text'}>
<i className="anticon anticon-check-circle"></i>
</span>
);
} else {
progressInfo = (
<span className={prefixCls + '-line-text'}>{props.percent}%</span>
);
}
}else {
fullCls = ' ' + prefixCls + '-line-wrap-full';
}
var persentStyle = {
width: props.percent + '%',
height: props.strokeWidth
};
return (
<div className='ant-progress-line-wrap'>
<div className='ant-progress-line-inner' style={style}>
<Progressline percent={props.percent} strokeWidth={props.strokeWidth}
strokeColor={statusColorMap[props.status]} trailColor="#e9e9e9" />
</div>
<div className={prefixCls + '-line-wrap clearfix status-' + props.status + fullCls}>
{progressInfo}
<div className={prefixCls + '-line-outer'}>
<div className={prefixCls + '-line-inner'}>
<div className={prefixCls + '-line-bg'} style={persentStyle}></div>
</div>
</div>
</div>
);
}
@ -75,12 +82,6 @@ var Circle = React.createClass({
};
},
render() {
var statusColorMap = {
'normal': '#3FC7FA',
'exception': '#FE8C6A',
'success': '#85D262'
};
var props = assign({}, this.props);
if (parseInt(props.percent) === 100) {
@ -89,36 +90,31 @@ var Circle = React.createClass({
var style = {
'width': props.width,
'height': props.width
};
var wrapStyle = {
'height': props.width,
'fontSize': props.width * 0.16 + 6
};
var textStyle = {
'color': statusColorMap[props.status]
};
var progressInfo;
if (props.status === 'exception') {
progressInfo = (
<span style={textStyle} className='ant-progress-circle-text'>
<span className={prefixCls + '-circle-text'}>
<i className='anticon anticon-exclamation'></i>
</span>
);
} else if (props.status === 'success') {
progressInfo = (
<span style={textStyle} className='ant-progress-circle-text'>
<span className={prefixCls + '-circle-text'}>
<i className="anticon anticon-check"></i>
</span>
);
} else {
progressInfo = (
<span className="ant-progress-circle-text">{props.percent}%</span>
<span className={prefixCls + '-circle-text'}>{props.percent}%</span>
);
}
return (
<div className="ant-progress-circle-wrap" style={wrapStyle}>
<div className="ant-progress-circle-inner" style={style}>
<div className={prefixCls + '-circle-wrap status-' + props.status} >
<div className={prefixCls + '-circle-inner'} style={style}>
<Progresscircle percent={props.percent} strokeWidth={props.strokeWidth}
strokeColor={statusColorMap[props.status]} trailColor="#e9e9e9" />
{progressInfo}

View File

@ -16,15 +16,25 @@
* 当需要显示一个操作完成的百分比时。
## API
## Progress Circle API
| 参数 | 说明 | 类型 | 默认值 |
|----------|---------------|----------|-------------|
| percent | 百分比 | number | 0 |
| status | 状态有两个值normal、exception | string | normal |
| strokeWidth | 进度条线宽度,单位是进度条画布宽度的百分比 | number | 1 |
| strokeWidth | 进度条线宽度,单位是进度条画布宽度的百分比 | number | 1 |
| width | 必填进度条画布宽度单位px。这里没有提供height属性设置Line型高度就是strokeWidthCircle型高度等于width | number | null |
## Progress Bar API
| 参数 | 说明 | 类型 | 默认值 |
|----------|---------------|----------|-------------|
| percent | 百分比 | number | 0 |
| status | 状态有两个值normal、exception、active三种状态 | string | normal |
| strokeWidth | 进度条线的宽度单位是px | number | 1 |
| showInfo | 是否显示进度数值和状态图标 | bool | true |

View File

@ -1,38 +1,47 @@
import React from 'react';
import Menu from 'rc-menu';
export default React.createClass({
var FilterMenu = React.createClass({
getInitialState() {
return {
selectedFilters: []
selectedFilters: this.props.selectedFilters
};
},
componentWillReceiveProps(nextProps){
this.setState({
selectedFilters: nextProps.selectedFilters
});
},
getDefaultProps() {
return {
handleFilter: function() {},
handleFilter: function () {
},
column: null
};
},
handleSelectFilter: function(selected) {
this.state.selectedFilters.push(selected);
handleSelectFilter: function (selected) {
this.setState({
selectedFilters: this.state.selectedFilters
selectedFilters: this.state.selectedFilters.concat(selected)
});
},
handleDeselectFilter: function(key) {
handleDeselectFilter: function (key) {
var index = this.state.selectedFilters.indexOf(key);
if (index !== -1) {
this.state.selectedFilters.splice(index, 1);
var selectedFilters = this.state.selectedFilters.concat();
selectedFilters.splice(index, 1);
this.setState({
selectedFilters: selectedFilters
});
}
this.setState({
selectedFilters: this.state.selectedFilters
});
},
handleClearFilters() {
this.setState({
selectedFilters: []
});
},
handleConfirm(){
this.props.confirmFilter(this.props.column, this.state.selectedFilters);
},
renderMenus(items) {
let menuItems = items.map((item) => {
return <Menu.Item key={item.value}>{item.text}</Menu.Item>;
@ -41,33 +50,34 @@ export default React.createClass({
},
render() {
let column = this.props.column;
column.selectedFilters = this.state.selectedFilters;
return <Menu multiple={true}
prefixCls="ant-dropdown-menu"
className="ant-table-filter-dropdown"
onSelect={this.handleSelectFilter}
onDeselect={this.handleDeselectFilter}
selectedKeys={column.selectedFilters}>
prefixCls="ant-dropdown-menu"
className="ant-table-filter-dropdown"
onSelect={this.handleSelectFilter}
onDeselect={this.handleDeselectFilter}
selectedKeys={this.state.selectedFilters}>
{this.renderMenus(column.filters)}
<Menu.Divider />
<Menu.Item disabled>
<a className="ant-table-filter-dropdown-link confirm"
style={{
style={{
cursor: 'pointer',
pointerEvents: 'visible'
}}
onClick={this.props.confirmFilter}>
onClick={this.handleConfirm}>
确定
</a>
<a className="ant-table-filter-dropdown-link clear"
style={{
style={{
cursor: 'pointer',
pointerEvents: 'visible'
}}
onClick={this.handleClearFilters}>
onClick={this.handleClearFilters}>
清空
</a>
</Menu.Item>
</Menu>;
}
});
export default FilterMenu;

View File

@ -6,22 +6,33 @@ import Checkbox from '../checkbox';
import FilterMenu from './filterMenu';
import Pagination from '../pagination';
import objectAssign from 'object-assign';
import equals from 'is-equal-shallow';
function noop() {
}
function defaultResolve(data) {
return data || [];
}
export default React.createClass({
getInitialState() {
this.initDataSource(this.props.dataSource);
let noPagination = (this.props.pagination === false);
let pagination = this.initPagination(this.props.pagination);
return {
//
selectedRowKeys: [],
loading: false,
pagination: pagination,
noPagination: noPagination,
data: []
// only for remote
data: [],
filters: {},
loading: !this.isLocalDataSource(),
sortColumn: '',
sortOrder: '',
sorter: null,
pagination: this.hasPagination() ? objectAssign({
pageSize: 10
}, this.props.pagination) : {}
};
},
getDefaultProps() {
return {
prefixCls: 'ant-table',
@ -30,44 +41,47 @@ export default React.createClass({
size: 'normal'
};
},
componentWillReceiveProps(nextProps) {
if ('pagination' in nextProps) {
let noPagination = (nextProps.pagination === false);
if (('pagination' in nextProps) && nextProps.pagination !== false) {
this.setState({
pagination: this.initPagination(nextProps.pagination),
noPagination: noPagination
pagination: objectAssign({}, this.state.pagination, nextProps.pagination)
});
}
if ('dataSource' in nextProps) {
this.initDataSource(nextProps.dataSource);
if (!this.isLocalDataSource()) {
if (!equals(nextProps, this.props)) {
this.setState({
selectedRowKeys: [],
loading: true
}, this.fetch);
}
}
if (nextProps.columns !== this.props.columns) {
this.setState({
data: nextProps.dataSource
filters: {}
});
}
},
initDataSource(dataSource) {
//
if (Array.isArray(dataSource)) {
this.mode = 'local';
//
this.originDataSource = dataSource.slice(0);
} else {
this.mode = 'remote';
this.dataSource = objectAssign({
resolve: function(data) {
return data || [];
},
getParams: function() {},
getPagination: function() {}
}, dataSource);
hasPagination(pagination) {
if (pagination === undefined) {
pagination = this.props.pagination;
}
return pagination !== false;
},
initPagination(pagination) {
isLocalDataSource() {
return Array.isArray(this.props.dataSource);
},
getRemoteDataSource() {
return objectAssign({
pageSize: 10,
total: this.props.dataSource.length
}, pagination);
resolve: defaultResolve,
getParams: noop,
getPagination: noop
}, this.props.dataSource);
},
toggleSortOrder(order, column) {
let sortColumn = this.state.sortColumn;
let sortOrder = this.state.sortOrder;
@ -89,8 +103,8 @@ export default React.createClass({
sortColumn.className = 'ant-table-column-sort';
}
}
if (this.mode === 'local') {
sorter = function() {
if (this.isLocalDataSource()) {
sorter = function () {
let result = column.sorter.apply(this, arguments);
if (sortOrder === 'ascend') {
return result;
@ -99,87 +113,101 @@ export default React.createClass({
}
};
}
this.setState({
this.fetch({
sortOrder: sortOrder,
sortColumn: sortColumn,
sorter: sorter
}, this.fetch);
});
},
handleFilter(column) {
let columnIndex = this.props.columns.indexOf(column);
let filterFns = [];
if (this.mode === 'local') {
filterFns[columnIndex] = function(record) {
if (column.selectedFilters.length === 0) {
return true;
}
return column.selectedFilters.some(function(value) {
return column.onFilter.call(this, value, record);
});
};
}
this.setState({
filterFns: filterFns
}, this.fetch);
handleFilter(column, filters) {
filters = objectAssign({}, this.state.filters, {
[this.getColumnKey(column)]: filters
});
this.fetch({
selectedRowKeys: [],
filters: filters
});
},
handleSelect(rowIndex, e) {
handleSelect(record, rowIndex, e) {
let checked = e.target.checked;
let selectedRowKeys = this.state.selectedRowKeys.concat();
let key = this.getRecordKey(record, rowIndex);
if (checked) {
this.state.selectedRowKeys.push(rowIndex);
selectedRowKeys.push(this.getRecordKey(record, rowIndex));
} else {
this.state.selectedRowKeys = this.state.selectedRowKeys.filter(function(i) {
return rowIndex !== i;
selectedRowKeys = selectedRowKeys.filter((i) => {
return key !== i;
});
}
this.setState({
selectedRowKeys: this.state.selectedRowKeys
selectedRowKeys: selectedRowKeys
});
if (this.props.rowSelection.onSelect) {
let currentRow = this.state.data[rowIndex - 1];
let selectedRows = this.state.data.filter((row, i) => {
return this.state.selectedRowKeys.indexOf(i + 1) >= 0;
let data = this.getCurrentPageData();
let selectedRows = data.filter((row, i) => {
return selectedRowKeys.indexOf(this.getRecordKey(row, i)) >= 0;
});
this.props.rowSelection.onSelect(currentRow, checked, selectedRows);
this.props.rowSelection.onSelect(record, checked, selectedRows);
}
},
handleSelectAllRow(e) {
let checked = e.target.checked;
let selectedRowKeys = checked ? this.state.data.map(function(item, i) {
return i + 1;
}) : [];
let data = this.getCurrentPageData();
let selectedRowKeys = checked ? data.map((item, i) => {
return this.getRecordKey(item, i);
}) : [];
this.setState({
selectedRowKeys: selectedRowKeys
});
if (this.props.rowSelection.onSelectAll) {
let selectedRows = this.state.data.filter((row, i) => {
return selectedRowKeys.indexOf(i + 1) >= 0;
let selectedRows = data.filter((row, i) => {
return selectedRowKeys.indexOf(this.getRecordKey(row, i)) >= 0;
});
this.props.rowSelection.onSelectAll(checked, selectedRows);
}
},
handlePageChange(current) {
let pagination = this.state.pagination || {};
let pagination = objectAssign({}, this.state.pagination);
if (current) {
pagination.current = current;
} else {
pagination.current = pagination.current || 1;
}
this.setState({
this.fetch({
//
selectedRowKeys: [],
pagination: pagination
}, this.fetch);
});
},
renderSelectionCheckBox(value, record, index) {
let rowIndex = index + 1; // 1
let rowIndex = this.getRecordKey(record, index); // 1
let checked = this.state.selectedRowKeys.indexOf(rowIndex) >= 0;
return <Checkbox checked={checked} onChange={this.handleSelect.bind(this, rowIndex)} />;
return <Checkbox checked={checked} onChange={this.handleSelect.bind(this, record, rowIndex)}/>;
},
getRecordKey(record, index) {
return record.key || index;
},
renderRowSelection() {
var columns = this.props.columns;
let columns = this.props.columns.concat();
if (this.props.rowSelection) {
let checked = this.state.data.every(function(item, i) {
return this.state.selectedRowKeys.indexOf(i + 1) >= 0;
}, this);
let checkboxAll = <Checkbox checked={checked} onChange={this.handleSelectAllRow} />;
let data = this.getCurrentPageData();
let checked;
if (!data.length) {
checked = false;
} else {
checked = data.every((item, i) => {
let key = this.getRecordKey(item, i);
return this.state.selectedRowKeys.indexOf(key) >= 0;
});
}
let checkboxAll = <Checkbox checked={checked} onChange={this.handleSelectAllRow}/>;
let selectionColumn = {
key: 'selection-column',
title: checkboxAll,
@ -188,7 +216,7 @@ export default React.createClass({
className: 'ant-table-selection-column'
};
if (columns[0] &&
columns[0].key === 'selection-column') {
columns[0].key === 'selection-column') {
columns[0] = selectionColumn;
} else {
columns.unshift(selectionColumn);
@ -196,22 +224,31 @@ export default React.createClass({
}
return columns;
},
renderColumnsDropdown() {
return this.props.columns.map((column) => {
if (!column.originTitle) {
column.originTitle = column.title;
}
getCurrentPageData() {
return this.isLocalDataSource() ? this.getLocalDataPaging() : this.state.data;
},
getColumnKey(column) {
return column.key || column.dataIndex;
},
renderColumnsDropdown(columns) {
return columns.map((column) => {
let key = this.getColumnKey(column);
let filterDropdown, menus, sortButton;
if (column.filters && column.filters.length > 0) {
column.selectedFilters = column.selectedFilters || [];
menus = <FilterMenu column={column} confirmFilter={this.handleFilter.bind(this, column)} />;
let colFilters = this.state.filters[key] || [];
menus = <FilterMenu column={column}
selectedFilters={colFilters}
confirmFilter={this.handleFilter}/>;
let dropdownSelectedClass = '';
if (column.selectedFilters && column.selectedFilters.length > 0) {
if (colFilters.length > 0) {
dropdownSelectedClass = 'ant-table-filter-selected';
}
filterDropdown = <Dropdown trigger="click"
closeOnSelect={false}
overlay={menus}>
closeOnSelect={false}
overlay={menus}>
<i title="筛选" className={'anticon anticon-bars ' + dropdownSelectedClass}></i>
</Dropdown>;
}
@ -220,151 +257,195 @@ export default React.createClass({
sortButton = <div className="ant-table-column-sorter">
<span className={'ant-table-column-sorter-up ' +
((isSortColumn && this.state.sortOrder === 'ascend') ? 'on' : 'off')}
title="升序排序"
onClick={this.toggleSortOrder.bind(this, 'ascend', column)}>
title="升序排序"
onClick={this.toggleSortOrder.bind(this, 'ascend', column)}>
<i className="anticon anticon-caret-up"></i>
</span>
<span className={'ant-table-column-sorter-down ' +
((isSortColumn && this.state.sortOrder === 'descend') ? 'on' : 'off')}
title="降序排序"
onClick={this.toggleSortOrder.bind(this, 'descend', column)}>
title="降序排序"
onClick={this.toggleSortOrder.bind(this, 'descend', column)}>
<i className="anticon anticon-caret-down"></i>
</span>
</div>;
}
if (!column.originalTitle) {
column.originalTitle = column.title;
}
column.title = [
column.originTitle,
column.originalTitle,
sortButton,
filterDropdown
];
return column;
});
},
renderPagination() {
//
if (this.state.noPagination) {
return '';
if (!this.hasPagination()) {
return null;
}
let classString = 'ant-table-pagination';
if (this.props.size === 'small') {
classString += ' mini';
}
let total;
if (this.isLocalDataSource()) {
total = this.getLocalData().length;
}
return <Pagination className={classString}
onChange={this.handlePageChange}
onChange={this.handlePageChange}
total={total}
pageSize={10}
{...this.state.pagination} />;
},
prepareParamsArguments() {
prepareParamsArguments(state) {
//
let pagination;
let filters = {};
let sorter = {};
pagination = this.state.pagination;
this.props.columns.forEach(function(column) {
if (column.dataIndex && column.selectedFilters &&
column.selectedFilters.length > 0) {
filters[column.dataIndex] = column.selectedFilters;
pagination = state.pagination;
this.props.columns.forEach((column) => {
let colFilters = state.filters[this.getColumnKey(column)] || [];
if (colFilters.length > 0) {
filters[this.getColumnKey(column)] = colFilters;
}
});
if (this.state.sortColumn && this.state.sortOrder &&
this.state.sortColumn.dataIndex) {
sorter.field = this.state.sortColumn.dataIndex;
sorter.order = this.state.sortOrder;
if (state.sortColumn &&
state.sortOrder &&
state.sortColumn.dataIndex) {
sorter.field = state.sortColumn.dataIndex;
sorter.order = state.sortOrder;
}
return [pagination, filters, sorter];
},
fetch() {
if (this.mode === 'remote') {
fetch(newState) {
if (this.isLocalDataSource()) {
if (newState) {
this.setState(newState);
}
} else {
let state = objectAssign({}, this.state, newState);
if (newState || !this.state.loading) {
this.setState(objectAssign({
loading: true
}, newState));
}
// remote 使 this.dataSource
let dataSource = this.dataSource;
this.setState({
loading: true
});
let dataSource = this.getRemoteDataSource();
jQuery.ajax({
url: dataSource.url,
data: dataSource.getParams.apply(this, this.prepareParamsArguments()) || {},
data: dataSource.getParams.apply(this, this.prepareParamsArguments(state)) || {},
headers: dataSource.headers,
dataType: 'json',
success: (result) => {
if (this.isMounted()) {
let pagination = objectAssign(
this.state.pagination,
state.pagination,
dataSource.getPagination.call(this, result)
);
this.setState({
loading: false,
data: dataSource.resolve.call(this, result),
pagination: pagination,
loading: false
pagination: pagination
});
}
},
error: () => {
this.setState({
loading: false
loading: false,
data: []
});
}
});
} else {
let data = this.props.dataSource;
let current, pageSize;
//
if (this.state.noPagination) {
pageSize = Number.MAX_VALUE;
current = 1;
} else {
pageSize = this.state.pagination.pageSize;
current = this.state.pagination.current;
}
//
if (this.state.sortOrder && this.state.sorter) {
data = data.sort(this.state.sorter);
} else {
data = this.originDataSource.slice();
}
//
if (this.state.filterFns) {
this.state.filterFns.forEach(function(filterFn) {
if (typeof filterFn === 'function') {
data = data.filter(filterFn);
}
});
}
//
// ---
//
//
if (data.length > pageSize || pageSize === Number.MAX_VALUE) {
data = data.filter(function(item, i) {
if (i >= (current - 1) * pageSize &&
i < current * pageSize) {
return item;
}
});
}
//
this.setState({
data: data
});
}
},
componentDidMount() {
this.handlePageChange();
},
render() {
this.props.columns = this.renderRowSelection();
var classString = '';
if (this.state.loading) {
findColumn(myKey) {
return this.props.columns.filter((c) => {
return this.getColumnKey(c) === myKey;
})[0];
},
getLocalDataPaging() {
let data = this.getLocalData();
let current, pageSize;
let state = this.state;
//
if (!this.hasPagination()) {
pageSize = Number.MAX_VALUE;
current = 1;
} else {
pageSize = state.pagination.pageSize;
current = state.pagination.current;
}
//
// ---
//
//
if (data.length > pageSize || pageSize === Number.MAX_VALUE) {
data = data.filter((item, i) => {
if (i >= (current - 1) * pageSize &&
i < current * pageSize) {
return item;
}
});
}
return data;
},
getLocalData() {
let state = this.state;
let data = this.props.dataSource;
//
if (state.sortOrder && state.sorter) {
data = data.sort(state.sorter);
}
//
if (state.filters) {
Object.keys(state.filters).forEach((columnKey) => {
let col = this.findColumn(columnKey);
let values = state.filters[columnKey] || [];
if (values.length === 0) {
return;
}
data = data.filter((record) => {
return values.some((v)=> {
return col.onFilter(v, record);
});
});
});
}
return data;
},
componentDidMount() {
if (!this.isLocalDataSource()) {
this.fetch();
}
},
render() {
let data = this.getCurrentPageData();
let columns = this.renderRowSelection();
let classString = '';
if (this.state.loading && this.isLocalDataSource()) {
classString += ' ant-table-loading';
}
if (this.props.size === 'small') {
classString += ' ant-table-small';
}
columns = this.renderColumnsDropdown(columns);
return <div className="clearfix">
<Table data={this.state.data}
columns={this.renderColumnsDropdown()}
className={classString}
{...this.props} />
<Table
{...this.props}
data={data || []}
columns={columns}
className={classString}
/>
{this.renderPagination()}
</div>;
}

View File

@ -0,0 +1,22 @@
# 基本
- order: 0
简单的标签展示,添加 closable 表示可关闭。
---
````jsx
var Tag = antd.Tag;
function onClose(e) {
console.log(this.props.children);
}
React.render(<div>
<Tag>标签一</Tag>
<Tag>标签二</Tag>
<Tag closable onClose={onClose}>标签三</Tag>
<Tag href="http://www.baidu.com">标签四(链接)</Tag>
</div>, document.getElementById('components-tag-demo-basic'));
````

View File

@ -0,0 +1,19 @@
# 各种类型
四种颜色的标签。
- order: 1
---
````jsx
var Tag = antd.Tag;
React.render(<div>
<Tag closable color="blue">蓝色</Tag>
<Tag closable color="green">绿色</Tag>
<Tag closable color="yellow">黄色</Tag>
<Tag closable color="red">红色</Tag>
</div>, document.getElementById('components-tag-demo-colorful'));
````

36
components/tag/index.jsx Normal file
View File

@ -0,0 +1,36 @@
import React from 'react';
const prefixCls = 'ant-tag';
class AntTag extends React.Component {
constructor(props) {
super(props);
this.state = {
closed: false
};
}
close(e) {
this.setState({
closed: true
});
this.props.onClose.call(this, e);
}
render() {
let close = this.props.closable ?
<i className="anticon anticon-cross" onClick={this.close.bind(this)}></i> : '';
let colorClass = this.props.prefixCls + '-' + this.props.color;
return this.state.closed ? null : <div className={this.props.prefixCls + ' ' + colorClass}>
<a className={this.props.prefixCls + '-text'} {...this.props} />
{close}
</div>;
}
}
AntTag.defaultProps = {
prefixCls: prefixCls,
closable: false,
onClose: function() {}
};
export default AntTag;

View File

@ -4,3 +4,19 @@
- chinese: 标签
---
进行标记和分类的小标签。
## 何时使用
- 用于标记事物的属性和维度。
- 进行分类。
## API
| 参数 | 说明 | 类型 | 可选值 | 默认值 |
|----------------|--------------------------------|------------|---------|--------|
| href | 链接的地址,会传给 a 标签 | string | | false |
| closable | 标签是否可以关闭 | boolean | | false |
| onClose | 组合时根据此项判定checked | function | | 无 |
| color | 标签的色彩 | string | blue green yellow red | 无 |

View File

@ -19,6 +19,7 @@ var antd = {
Switch: require('./components/switch'),
Checkbox: require('./components/checkbox'),
Table: require('./components/table'),
Tag: require('./components/tag'),
Collapse: require('./components/collapse'),
message: require('./components/message'),
Slider: require('./components/slider'),

View File

@ -1,7 +1,7 @@
{
"name": "antd",
"version": "0.7.3-beta6",
"stableVersion": "0.7.2",
"version": "0.8.0-beta1",
"stableVersion": "0.7.3",
"title": "Ant Design",
"description": "一个设计语言&前端框架",
"homepage": "http://ant.design/",

View File

@ -18,7 +18,7 @@ $(function () {
return <Option sData={s} key={s.title} text={'跳转到 ' + s.title}>
<strong>{s.title}</strong>
&nbsp;
<span>{s.desc}</span>
<span className="ant-component-decs">{s.desc}</span>
</Option>;
});
},
@ -34,12 +34,11 @@ $(function () {
},
render() {
return <Select combobox style={{width: 200}}
return <Select combobox style={{width: 260}}
onSelect={this.handleSelect}
optionLabelProp="text"
dropdownMenuStyle={{maxHeight: 200, overflow: 'auto'}}
searchPlaceholder="搜索组件..."
renderDropdownToBody={true}
filterOption={this.filterOption}>{this.getOptions()}</Select>;
}
});

View File

@ -78,7 +78,7 @@
{% block scripts %}{% endblock %}
</head>
<body {% block bodyAttribute %}{% endblock %}>
<header id="header">
<header id="header" class="clearfix">
<a class="logo" href="/">
<img width="60" src="https://t.alipayobjects.com/images/rmsweb/T1B9hfXcdvXXXXXXXX.svg">
{{ config.site.name }}

View File

@ -117,7 +117,6 @@ a:hover {
header {
width: 100%;
background: #fff;
overflow: hidden;
border-bottom: 1px solid #eee;
font-size: 16px;
}
@ -167,6 +166,10 @@ a.logo {
margin-top: -2px;
}
#autoComplete .ant-select {
font-size: 14px;
}
#autoComplete .ant-select-selection--single {
border: transparent;
outline: none;
@ -179,6 +182,20 @@ a.logo {
box-shadow: none;
}
#autoComplete .ant-select-dropdown {
border: 0;
border-radius: 0;
box-shadow: 0 0 8px rgba(0,0,0,0.25);
}
#autoComplete .ant-component-decs {
font-size: 12px;
position: absolute;
top: 9px;
color: #aaa;
right: 16px;
}
#autoComplete input::-webkit-input-placeholder,
#autoComplete input::-moz-placeholder,
#autoComplete input:-ms-input-placeholder {

View File

@ -44,6 +44,8 @@
&-loading {
padding-right: 31px;
pointer-events: none;
opacity: 0.75;
&:after {
font-family: anticon;
.animation(loadingCircle 1s infinite linear);

View File

@ -23,4 +23,5 @@
@import "divider";
@import "slider";
@import "radio";
@import "tag";
@import "alert";

View File

@ -5,29 +5,73 @@
&-circle-wrap {
display: inline-block;
}
&-line-wrap {
width: 100%;
font-size: 12px;
position: relative;
}
&-line-outer {
margin-right: 45px;
}
&-line-wrap-full {
.@{prefixProgressClass}-line-outer {
margin-right: 0;
}
}
&-line-inner {
display: inline-block;
svg {
vertical-align: middle;
}
width: 100%;
background-color: #E9E9E9;
border-radius: 100px;
}
&-line-bg {
border-radius: 100px;
background-color: @primary-color;
transition: all 0.6s linear 0s;
}
&-line-text {
display: inline-block;
position: absolute;
bottom: 0;
right: 0;
width: 35px;
text-align: left;
font-size: 1em;
margin-left: 10px;
line-height: 1;
.anticon {
font-size: 12px;
}
}
&-line-wrap.status-active {
.@{prefixProgressClass}-line-bg:before {
content: "";
opacity: 0;
position: absolute;
top: 0px;
left: 0px;
right: 0px;
bottom: 0px;
background: #fff;
border-radius: 10px;
animation: progress-active 2s ease infinite;
}
}
&-line-wrap.status-exception {
.@{prefixProgressClass}-line-bg {
background-color: @error-color;
}
.@{prefixProgressClass}-line-text {
color: @error-color;
}
}
&-line-wrap.status-success {
.@{prefixProgressClass}-line-bg {
background-color: @success-color;
}
.@{prefixProgressClass}-line-text {
color: @success-color;
}
}
&-circle-inner {
position: relative;
@ -47,4 +91,25 @@
font-size: 14/12em;
}
}
&-circle-wrap.status-exception {
.@{prefixProgressClass}-circle-text {
color: @error-color;
}
}
&-circle-wrap.status-success {
.@{prefixProgressClass}-circle-text {
color: @success-color;
}
}
}
@keyframes progress-active {
0% {
opacity: .3;
width: 0;
}
100% {
opacity: 0;
width: 100%;
}
}

View File

@ -197,6 +197,7 @@
}
&-slide-horizontal-backward-enter {
display: block !important;
transform: translateX(-100%);
}
@ -206,6 +207,7 @@
}
&-slide-horizontal-backward-leave {
display: block !important;
position: absolute;
top: 0;
left: 0;
@ -220,6 +222,7 @@
}
&-slide-horizontal-forward-enter {
display: block !important;
transform: translateX(100%);
}
@ -229,6 +232,7 @@
}
&-slide-horizontal-forward-leave {
display: block !important;
position: absolute;
transform: translateX(0);
top: 0;

72
style/components/tag.less Normal file
View File

@ -0,0 +1,72 @@
@import "../mixins/index";
@tagPrefixClass: ~"@{css-prefix}tag";
.@{tagPrefixClass} {
display: inline-block;
line-height: 22px;
height: 22px;
padding: 0 8px;
border-radius: 20px;
background: #f3f3f3;
font-size: @font-size-base;
margin-right: 4px;
margin-bottom: 8px;
transition: all 0.3s ease;
vertical-align: middle;
opacity: 0.85;
&:hover {
opacity: 1;
}
&,
a,
a:hover {
color: @text-color;
}
.anticon-cross {
.iconfont-size-under-12px(7px);
cursor: pointer;
font-weight: bold;
margin-left: 3px;
position: relative;
top: -1px;
color: #6666;
transition: all 0.3s ease;
opacity: 0.66;
&:hover {
opacity: 1;
}
}
&-blue,
&-green,
&-yellow,
&-red {
&,
a,
a:hover,
.anticon-cross,
.anticon-cross:hover {
color: #fff;
}
}
&-blue {
background: @primary-color;
}
&-green {
background: @success-color;
}
&-yellow {
background: @warning-color;
}
&-red {
background: @error-color;
}
}