mirror of
https://github.com/ant-design/ant-design.git
synced 2024-11-29 05:29:37 +08:00
Merge branch '0.8.0' of github.com:ant-design/ant-design into 0.8.0
This commit is contained in:
commit
0c04548a78
@ -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)。
|
||||
|
@ -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 月份释出正式版本。
|
||||
|
@ -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'));
|
||||
````
|
||||
|
@ -18,8 +18,8 @@ React.render(<div>
|
||||
type="warn"
|
||||
closable
|
||||
onClose={onClose} />
|
||||
<Alert message="警告提示的标题"
|
||||
description="警告提示的文案警告提示的文案警告提示的文案警告提示的文案警告提示的文案警告提示的文案警告提示的文案"
|
||||
<Alert message="错误提示的文案"
|
||||
description="错误提示的辅助性文字介绍错误提示的辅助性文字介绍错误提示的辅助性文字介绍错误提示的辅助性文字介绍错误提示的辅助性文字介绍错误提示的辅助性文字介绍"
|
||||
type="error"
|
||||
closable
|
||||
onClose={onClose} />
|
||||
|
@ -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'));
|
||||
````
|
||||
|
@ -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'));
|
||||
````
|
||||
|
@ -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'));
|
||||
````
|
||||
|
@ -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';
|
||||
|
@ -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 | 无 |
|
||||
|
@ -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>
|
||||
|
@ -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>
|
||||
```
|
||||
|
@ -3,6 +3,7 @@
|
||||
- category: Components
|
||||
- chinese: 布局
|
||||
- order: 0
|
||||
- cols: 1
|
||||
|
||||
---
|
||||
|
||||
|
@ -8,6 +8,7 @@
|
||||
|
||||
````jsx
|
||||
var message = antd.message;
|
||||
|
||||
var success = function() {
|
||||
message.success('这是一条成功的提示');
|
||||
};
|
||||
|
@ -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;
|
||||
}
|
||||
}
|
||||
};
|
||||
|
@ -25,3 +25,18 @@
|
||||
|------------|----------------|----------------------------|--------------|
|
||||
| content | 提示内容 | React.Element or String | 无 |
|
||||
| duration | 自动关闭的延时 | number | 1.5 |
|
||||
|
||||
|
||||
还提供了一个全局配置方法:
|
||||
|
||||
- `message.config(options)`
|
||||
|
||||
```js
|
||||
message.config({
|
||||
top: 100
|
||||
});
|
||||
```
|
||||
|
||||
| 参数 | 说明 | 类型 | 默认值 |
|
||||
|------------|--------------------|----------------------------|--------------|
|
||||
| top | 消息距离顶部的位置 | Number | 24px |
|
||||
|
@ -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'));
|
||||
````
|
||||
|
@ -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'));
|
||||
````
|
||||
|
@ -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}
|
||||
|
@ -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型高度就是strokeWidth,Circle型高度等于width | number | null |
|
||||
|
||||
|
||||
## Progress Bar API
|
||||
|
||||
| 参数 | 说明 | 类型 | 默认值 |
|
||||
|----------|---------------|----------|-------------|
|
||||
| percent | 百分比 | number | 0 |
|
||||
| status | 状态,有两个值normal、exception、active三种状态 | string | normal |
|
||||
| strokeWidth | 进度条线的宽度,单位是px | number | 1 |
|
||||
| showInfo | 是否显示进度数值和状态图标 | bool | true |
|
||||
|
||||
|
||||
|
||||
|
||||
|
@ -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;
|
||||
|
@ -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>;
|
||||
}
|
||||
|
22
components/tag/demo/basic.md
Normal file
22
components/tag/demo/basic.md
Normal 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'));
|
||||
````
|
19
components/tag/demo/colorful.md
Normal file
19
components/tag/demo/colorful.md
Normal 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
36
components/tag/index.jsx
Normal 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;
|
@ -4,3 +4,19 @@
|
||||
- chinese: 标签
|
||||
|
||||
---
|
||||
|
||||
进行标记和分类的小标签。
|
||||
|
||||
## 何时使用
|
||||
|
||||
- 用于标记事物的属性和维度。
|
||||
- 进行分类。
|
||||
|
||||
## API
|
||||
|
||||
| 参数 | 说明 | 类型 | 可选值 | 默认值 |
|
||||
|----------------|--------------------------------|------------|---------|--------|
|
||||
| href | 链接的地址,会传给 a 标签 | string | | false |
|
||||
| closable | 标签是否可以关闭 | boolean | | false |
|
||||
| onClose | 组合时根据此项判定checked | function | | 无 |
|
||||
| color | 标签的色彩 | string | blue green yellow red | 无 |
|
||||
|
1
index.js
1
index.js
@ -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'),
|
||||
|
@ -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/",
|
||||
|
@ -18,7 +18,7 @@ $(function () {
|
||||
return <Option sData={s} key={s.title} text={'跳转到 ' + s.title}>
|
||||
<strong>{s.title}</strong>
|
||||
|
||||
<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>;
|
||||
}
|
||||
});
|
||||
|
@ -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 }}
|
||||
|
@ -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 {
|
||||
|
@ -44,6 +44,8 @@
|
||||
|
||||
&-loading {
|
||||
padding-right: 31px;
|
||||
pointer-events: none;
|
||||
opacity: 0.75;
|
||||
&:after {
|
||||
font-family: anticon;
|
||||
.animation(loadingCircle 1s infinite linear);
|
||||
|
@ -23,4 +23,5 @@
|
||||
@import "divider";
|
||||
@import "slider";
|
||||
@import "radio";
|
||||
@import "tag";
|
||||
@import "alert";
|
||||
|
@ -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%;
|
||||
}
|
||||
}
|
||||
|
@ -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
72
style/components/tag.less
Normal 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;
|
||||
}
|
||||
}
|
Loading…
Reference in New Issue
Block a user