merge 0.8.0

This commit is contained in:
zhujun24 2015-08-06 18:28:48 +08:00
commit ec462fde00
50 changed files with 600 additions and 166 deletions

View File

@ -1,14 +1,21 @@
# Affix
- category: Components
- chinese: 固
- chinese: 固
---
将页面元素钉在可视范围。
## 何时使用
当内容区域比较长,需要滚动页面时,这部分内容对应的操作或者导航需要在滚动范围内始终展现。常用于侧边菜单和按钮组合。
页面可视范围过小时,慎用此功能以免遮挡页面内容。
## API
属性如下
| 成员 | 说明 | 类型 | 默认值 |
|-------------|----------------|--------------------|--------------|
| offset | 达到指定偏移量后触发 | Number | 0 |
| offset | 达到指定偏移量后触发 | Number | 0 |

View File

@ -9,8 +9,8 @@
## 何时使用
- 当系统需要向用户显示警告的信息时。
- 始终展现,不会自动消失,用户可以点击关闭。
- 当某个页面需要向用户显示警告的信息时。
- 非浮层的静态展现形式,始终展现,不会自动消失,用户可以点击关闭。
## API

View File

@ -5,10 +5,13 @@
---
旋转木马,轮播组件
旋转木马,一组轮播的区域
## 何时使用
- 当有一组平级的内容。
- 当内容空间不足时,可以用走马灯的形式进行收纳,进行轮播展现。
- 常用于一组图片或卡片轮播。
## API

View File

@ -11,6 +11,6 @@
var Datepicker = antd.Datepicker;
React.render(
<Datepicker value="" />
<Datepicker />
, document.getElementById('components-datepicker-demo-basic'));
````

View File

@ -7,7 +7,6 @@
---
````jsx
// or require('antd/lib/datepicker');
var Datepicker = antd.Datepicker;
React.render(

View File

@ -10,7 +10,7 @@ import DateTimeFormat from 'gregorian-calendar-format';
//
import Locale from 'gregorian-calendar-format/lib/locale/zh-cn';
Locale.shortMonths = ['1月', '2月', '3月', '4月', '5月', '6月',
'7月', '8月', '9月', '10月', '11月', '12月'];
'7月', '8月', '9月', '10月', '11月', '12月'];
//
//
@ -42,7 +42,8 @@ export default React.createClass({
format: 'yyyy-MM-dd',
placeholder: '请选择日期',
transitionName: 'slide-up',
onSelect: function () {}
onSelect() {
}
};
},
handleChange(v) {
@ -69,9 +70,13 @@ export default React.createClass({
disabled={this.props.disabled}
trigger={<span className="ant-calendar-picker-icon" />}
calendar={calendar}
adjustOrientOnCalendarOverflow={true}
adjustOrientOnCalendarOverflow={{
x: true,
y: false
}}
formatter={new DateTimeFormat(this.props.format)}
value={this.state.value}
defaultValue={this.props.defaultValue}
prefixCls="ant-calendar-picker"
onChange={this.handleChange}>
<input

View File

@ -21,6 +21,7 @@
| 参数 | 说明 | 类型 | 默认值 |
|--------------|----------------|----------|--------------|
| value | 日期 | string | 无 |
| defaultValue | 默认日期 | string | 无 |
| format | 展示的日期格式 | string | "yyyy-MM-dd" |
| disabledDate | 不可选择的日期 | function | 无 |
| onSelect | 选择日期的回调 | function | 无 |

View File

@ -4,6 +4,8 @@
默认子节点进场动画。为避免与本站页面的进场冲突,所以 `EnterAnimation` 里延时 1 秒,递增 `interval` 为 0.3。
刷新页面看效果。
---
````jsx

View File

@ -4,6 +4,8 @@
通过加上 `enter-data` 属性来指定需要动画进场的元素,并且可以定义每个元素的动画效果,用到的参数有 `type` `queueId` `delay`
刷新页面看效果。
---
````jsx

View File

@ -48,13 +48,13 @@ React.render(
<label className="col-6">Checkbox 多选框:</label>
<div className="col-18">
<label className="ant-checkbox-vertical">
<Checkbox /> 选项一
<Checkbox />选项一
</label>
<label className="ant-checkbox-vertical">
<Checkbox /> 选项二
<Checkbox />选项二
</label>
<label className="ant-checkbox-vertical">
<Checkbox disabled={true} /> 选项三(不可选)
<Checkbox disabled={true} />选项三(不可选)
</label>
</div>
</div>

View File

@ -0,0 +1,45 @@
# 导航菜单
- order: 0
基本使用。
---
````jsx
var Menu = antd.Menu;
var MenuItem = Menu.Item;
var SubMenu = Menu.SubMenu;
function handleClick(key) {
console.log('selected ' + key);
}
var align={
points:['lt','lb']
};
React.render(<Menu onClick={handleClick} horizontal>
<SubMenu align={align} title={<span><i className="anticon anticon-apple"></i><span>导航一</span></span>}>
<MenuItem key="1">选项1</MenuItem>
<MenuItem key="2">选项2</MenuItem>
<MenuItem key="3">选项3</MenuItem>
<MenuItem key="4">选项4</MenuItem>
</SubMenu>
<SubMenu align={align} title={<span><i className="anticon anticon-apple"></i><span>导航二</span></span>}>
<MenuItem key="5">选项5</MenuItem>
<MenuItem key="6">选项6</MenuItem>
<SubMenu title={<span><i className="anticon anticon-apple"></i><span>三级导航</span></span>}>
<MenuItem key="7">选项7</MenuItem>
<MenuItem key="8">选项8</MenuItem>
</SubMenu>
</SubMenu>
<SubMenu align={align} title={<span><i className="anticon anticon-apple"></i><span>导航三</span></span>}>
<MenuItem key="9">选项9</MenuItem>
<MenuItem key="10">选项10</MenuItem>
<MenuItem key="11">选项11</MenuItem>
<MenuItem key="12">选项12</MenuItem>
</SubMenu>
</Menu>
, document.getElementById('components-menu-demo-nav'));
````

View File

@ -0,0 +1,41 @@
# 侧边菜单
- order: 1
基本使用。
---
````jsx
var Menu = antd.Menu;
var MenuItem = Menu.Item;
var SubMenu = Menu.SubMenu;
function handleClick(key) {
console.log('selected ' + key);
}
React.render(<Menu onClick={handleClick} style={{width:200}} vertical>
<SubMenu title={<span><i className="anticon anticon-apple"></i><span>导航一</span></span>}>
<MenuItem key="1">选项1</MenuItem>
<MenuItem key="2">选项2</MenuItem>
<MenuItem key="3">选项3</MenuItem>
<MenuItem key="4">选项4</MenuItem>
</SubMenu>
<SubMenu title={<span><i className="anticon anticon-apple"></i><span>导航二</span></span>}>
<MenuItem key="5">选项5</MenuItem>
<MenuItem key="6">选项6</MenuItem>
<SubMenu title={<span><i className="anticon anticon-apple"></i><span>三级导航</span></span>}>
<MenuItem key="7">选项7</MenuItem>
<MenuItem key="8">选项8</MenuItem>
</SubMenu>
</SubMenu>
<SubMenu title={<span><i className="anticon anticon-apple"></i><span>导航三</span></span>}>
<MenuItem key="9">选项9</MenuItem>
<MenuItem key="10">选项10</MenuItem>
<MenuItem key="11">选项11</MenuItem>
<MenuItem key="12">选项12</MenuItem>
</SubMenu>
</Menu>
, document.getElementById('components-menu-demo-side'));
````

20
components/menu/index.jsx Normal file
View File

@ -0,0 +1,20 @@
import Menu from 'rc-menu';
import React from 'react';
const AntMenu = React.createClass({
getDefaultProps(){
return {
prefixCls: 'ant-menu'
};
},
render(){
return <Menu {...this.props}/>;
}
});
AntMenu.Divider = Menu.Divider;
AntMenu.Item = Menu.Item;
AntMenu.SubMenu = Menu.SubMenu;
export default AntMenu;

View File

@ -5,3 +5,45 @@
---
## 何时使用
需要多级菜单时
```html
<Menu>
<MenuItem>菜单项</MenuItem>
<SubMenu title="子菜单">
<MenuItem>子菜单项</MenuItem>
</SubMenu>
</Menu>
```
## API
### Menu props
| 参数 | 说明 | 类型 | 默认值 |
|----------|----------------|----------|--------------|
| horizontal | 是否横向菜单 | boolean | false |
| vertical | 是否侧向菜单 | boolean | false |
| multiple | 支持多选 | | false |
| selectedKeys | 选中的菜单项 key 数组 | | |
| onSelect | 被选中时调用,参数为选中的 menuitem key 值 | function | 无 |
| onDeselect | 取消选中时调用,参数为选中的 menuitem key 值仅在multiple生效 | function | 无 |
| onClick | 点击 menuitem 调用此函数,参数为点击的 menuitem key 值 | function | 无 |
| style | 根节点样式 | object | | |
### Menu.Item props
| 参数 | 说明 | 类型 | 默认值 |
|----------|----------------|----------|--------------|
| disabled | 是否禁用 | Boolean | false |
| key | item 的唯一标志 | String | | |
### Menu.SubMenu props
| 参数 | 说明 | 类型 | 默认值 |
|----------|----------------|----------|--------------|
| title | 子菜单项值 | String or React.Element | |
| align | 子菜单的对齐配置 | object | {points:['lt','rt']} 弹出子菜单的 left top 和子菜单项的 right top 对齐 |
| children | (MenuItem or SubMenu)[] | 子菜单的菜单项 | | |

View File

@ -2,7 +2,7 @@
- order: 0
最简单的用法。
最简单的用法,五秒后自动关闭
---
@ -10,11 +10,10 @@
var notification = require('antd/lib/notification');
var openNotification = function() {
var args = {
notification.open({
message: "这是标题",
description: "这是提示框的文案这是提示框的文案这是提示框的文案这是提示框的文案这是提示框的文案这是提示框的文案这是提示框的文案"
};
notification.open(args);
});
};
React.render(
@ -22,4 +21,4 @@ React.render(
<button className='ant-btn ant-btn-primary' onClick={openNotification}>打开通知提醒框</button>
</div>,
document.getElementById('components-notification-demo-basic'));
````
````

View File

@ -11,14 +11,14 @@ var notification = require('antd/lib/notification');
var close = function() {
console.log("我被默认的关闭按钮关闭了!");
}
};
var openNotification = function() {
var args = {
message: "这是标题",
description: "这是提示框的文案这是提示框示框的文案这是提示是提示框的文案这是提示框的文案",
onClose: close
};
};
notification.open(args);
};
@ -27,4 +27,4 @@ React.render(
<button className='ant-btn ant-btn-primary' onClick={openNotification}>打开通知提醒框</button>
</div>,
document.getElementById('components-notification-demo-onclose'));
````
````

View File

@ -21,19 +21,18 @@ var close = function() {
var onClose = function() {
// 默认按钮关闭时的业务处理
console.log("我被默认的关闭按钮关闭了!");
}
};
var btn = <button onClick={close} className="ant-btn ant-btn-primary ant-btn-sm">自定义关闭按钮并触发回调函数</button>;
var openNotification = function() {
var args = {
notification.open({
message: "这是标题",
description: "这是提示框的文案这是提示框示框的文案这是提示是提示框的文案这是提示框的文案",
btn: btn,
key: key,
onClose: onClose
};
notification.open(args);
});
};
React.render(

View File

@ -18,13 +18,12 @@ var close = function() {
var btn = <button onClick={close} className="ant-btn ant-btn-primary ant-btn-sm">自定义关闭按钮</button>;
var openNotification = function() {
var args = {
notification.open({
message: "这是标题",
description: "这是提示框的文案这是提示框示框的文案这是提示是提示框的文案这是提示框的文案",
btn: btn,
key: key
};
notification.open(args);
});
};
React.render(
@ -32,4 +31,4 @@ React.render(
<button className="ant-btn ant-btn-primary" onClick={openNotification}>打开通知提醒框</button>
</div>,
document.getElementById('components-notification-demo-with-btn'));
````
````

View File

@ -2,7 +2,7 @@
- order: 2
通知提醒框左侧有Icon图标。
通知提醒框左侧有图标。
---
@ -11,11 +11,10 @@ var notification = require('antd/lib/notification');
var openNotificationWithIcon = function(type) {
return function(){
var args = {
notification[type]({
message: "这是标题",
description: "这是提示框的文案这是提示框示框的文案这是提示是提示框的文案这是提示框的文案"
};
notification[type](args);
});
};
};

View File

@ -3,22 +3,27 @@ import assign from 'object-assign';
import React from 'react';
let top = 24;
let duration = 3;
var notificationInstance;
let notificationInstance;
function getNotificationInstance() {
notificationInstance = notificationInstance || Notification.newInstance({
prefixCls: 'ant-notification',
style: {
top: top,
right: 0
}
});
prefixCls: 'ant-notification',
style: {
top: top,
right: 0
}
});
return notificationInstance;
}
function notice(args) {
let duration;
if (args.duration === undefined) {
duration = 500;
} else {
duration = args.duration;
}
if (args.icon) {
let prefixCls = ' ant-notification-notice-content-icon-';
let iconClass = 'anticon anticon-';
@ -42,12 +47,10 @@ function notice(args) {
getNotificationInstance().notice({
content: <div>
<i className={iconClass + prefixCls + 'icon-' + args.icon + prefixCls + 'icon'}></i>
<p className={prefixCls + 'message'}>{args.message}</p>
<p className={prefixCls + 'description'}>{args.description}</p>
</div>,
duration: isNaN(args.duration) ? duration : args.duration,
duration: duration,
closable: true,
onClose: args.onClose,
style: {}
@ -58,10 +61,9 @@ function notice(args) {
getNotificationInstance().notice({
content: <div>
<p className={prefixCls + 'message'}>{args.message}</p>
<p className={prefixCls + 'description'}>{args.description}</p>
</div>,
duration: isNaN(args.duration) ? duration : args.duration,
duration: duration,
closable: true,
onClose: args.onClose,
style: {}
@ -70,13 +72,12 @@ function notice(args) {
getNotificationInstance().notice({
content: <div>
<p className={prefixCls + 'message'}>{args.message}</p>
<p className={prefixCls + 'description'}>{args.description}</p>
<span className={prefixCls + 'btn'}>
{args.btn}
</span>
</div>,
duration: isNaN(args.duration) ? duration : args.duration,
duration: duration,
closable: true,
onClose: args.onClose,
key: args.key,
@ -100,7 +101,7 @@ var api = {
}
};
['success', 'info', 'warn', 'error'].forEach((type)=> {
['success', 'info', 'warn', 'error'].forEach((type) => {
api[type] = (args) => {
var newArgs = assign({}, args, {
icon: type

View File

@ -9,7 +9,11 @@
## 何时使用
- 当系统需要在窗口右上角显示通知提醒信息时。
在系统右上角显示通知提醒信息。经常用于以下情况:
- 较为复杂的通知内容。
- 带有交互的通知,给出用户下一步的行动点。
- 系统主动推送。
## API
@ -30,8 +34,9 @@ config 参数如下:
| btn | 自定义关闭按钮 | React.Element | 无 |
| key | 当前通知唯一标志 | String | 无 |
| onClose | 点击默认关闭按钮时触发的回调函数 | Function | 无 |
| duration | 默认五秒后自动关闭,配置为 null 则不自动关闭 | Number | 5 |
还提供了一个全局配置方法
还提供了一个全局配置方法,需要在调用前提前配置,一次有效。
- `notification.config(options)`

View File

@ -0,0 +1,51 @@
# 联动
- order: 6
省市联动是典型的例子。
---
````jsx
var Select = antd.Select;
var Option = Select.Option;
var provinceData = ['浙江', '江苏'];
var cityData = {
'浙江': ['杭州', '宁波', '温州'],
'江苏': ['南京', '苏州', '镇江']
};
var App = React.createClass({
getInitialState() {
return {
cities: cityData[provinceData[0]]
};
},
handleProvinceChange(value) {
this.setState({
cities: cityData[value]
});
},
render() {
var provinceOptions = provinceData.map(function(province) {
return <Option value={province}>{province}</Option>;
});
var cityOptions = this.state.cities.map(function(city) {
return <Option value={city}>{city}</Option>;
});
return <div>
<Select defaultValue={provinceData[0]} style={{width:150}} onChange={this.handleProvinceChange}>
{provinceOptions}
</Select>
&nbsp;
<Select value={this.state.cities[0]} style={{width:150}} onChange={this.handleCityChange}>
{cityOptions}
</Select>
</div>;
}
});
React.render(<App />, document.getElementById('components-select-demo-coordinate'));
````

View File

@ -24,7 +24,8 @@
| 参数 | 说明 | 类型 | 默认值 |
|----------|----------------|----------|--------------|
| value | 指定默认选中的条目 | string/Array<String> | 无 |
| value | 指定选中的条目 | string/Array<String> | 无 |
| defaultValue | 指定默认选中的条目 | string/Array<String> | 无 |
| multiple | 支持多选 | | false |
| filterOption | 是否根据输入项进行筛选 | | true |
| tags | 可以把随意输入的条目作为tag输入项不需要与下拉选项匹配 | |false |

View File

@ -10,6 +10,7 @@
````jsx
var Table = antd.Table;
var columns = [{
title: '姓名',
dataIndex: 'name',
@ -33,7 +34,7 @@ function resolve(result) {
return result.data;
}
var dataSource = {
var dataSource = new Table.DataSource({
url: "/components/table/demo/data.json",
resolve: function(result) {
return result.data;
@ -61,8 +62,16 @@ var dataSource = {
console.log('请求参数:', params);
return params;
}
};
});
React.render(<Table columns={columns} dataSource={dataSource} />
, document.getElementById('components-table-demo-ajax'));
function fetch() {
dataSource.fetch().then(function() {
console.log('fetch done');
});
}
React.render(<div>
<Table columns={columns} dataSource={dataSource} />
<button className="ant-btn ant-btn-primary" onClick={fetch}>外部重新加载数据</button>
</div>, document.getElementById('components-table-demo-ajax'));
````

View File

@ -1,6 +1,6 @@
# 不显示分页
- order: 8
- order: 9
传入 pagination 为 false 即可。

View File

@ -15,7 +15,18 @@ function defaultResolve(data) {
return data || [];
}
export default React.createClass({
class DataSource {
constructor(config) {
this.url = config.url || '';
this.resolve = config.resolve || defaultResolve;
this.getParams = config.getParams || noop;
this.getPagination = config.getPagination || noop;
this.headers = config.headers || {};
this.fetch = noop;
}
}
var AntTable = React.createClass({
getInitialState() {
return {
//
@ -42,6 +53,10 @@ export default React.createClass({
};
},
propTypes: {
dataSource: React.PropTypes.instanceOf(DataSource)
},
componentWillReceiveProps(nextProps) {
if (('pagination' in nextProps) && nextProps.pagination !== false) {
this.setState({
@ -75,11 +90,9 @@ export default React.createClass({
},
getRemoteDataSource() {
return objectAssign({
resolve: defaultResolve,
getParams: noop,
getPagination: noop
}, this.props.dataSource);
let dataSource = this.props.dataSource;
dataSource.fetch = this.fetch;
return dataSource;
},
toggleSortOrder(order, column) {
@ -336,7 +349,7 @@ export default React.createClass({
}
// remote 使 this.dataSource
let dataSource = this.getRemoteDataSource();
jQuery.ajax({
return jQuery.ajax({
url: dataSource.url,
data: dataSource.getParams.apply(this, this.prepareParamsArguments(state)) || {},
headers: dataSource.headers,
@ -450,3 +463,7 @@ export default React.createClass({
</div>;
}
});
AntTable.DataSource = DataSource;
export default AntTable;

View File

@ -38,17 +38,18 @@ var dataSource = [{
**远程数据模式**是更常见的业务场景,是一次只从服务端读取一页的数据放在前端,执行筛选、排序、切换页码等操作时均向后台发送请求,后台返回当页的数据和相关分页信息。
通过指定表格的数据源 `dataSource` 为一个对象如下。
通过指定表格的数据源 `dataSource` 为一个 DataSource 的实例如下。
```jsx
var dataSource = {
var dataSource = new Table.DataSource({
url: '/api/users',
resolve: function(result) {
return result.data;
},
getPagination: function(result) {}
getParams: function(pagination, filters, sorter) {}
};
});
<Table dataSource={dataSource} />
```

View File

@ -2,7 +2,7 @@
- order: 0
默认选中第项。
默认选中第项。
---
@ -15,10 +15,10 @@ function callback(key) {
}
React.render(
<Tabs defaultActiveKey="2" onChange={callback}>
<TabPane tab="tab 1" key="1">选项卡一</TabPane>
<TabPane tab="tab 2" key="2">选项卡二</TabPane>
<TabPane tab="tab 3" key="3">选项卡三</TabPane>
<Tabs defaultActiveKey="1" onChange={callback}>
<TabPane tab="选项卡一" key="1">选项卡一内容</TabPane>
<TabPane tab="选项卡二" key="2">选项卡二内容</TabPane>
<TabPane tab="选项卡三" key="3">选项卡三内容</TabPane>
</Tabs>
, document.getElementById('components-tabs-demo-basic'));
````

View File

@ -14,9 +14,9 @@ function callback(key) {}
React.render(
<Tabs defaultActiveKey="1" onChange={callback}>
<TabPane tab="tab 1" key="1">选项卡一</TabPane>
<TabPane tab="tab 2" disabled={true} key="2">选项卡二</TabPane>
<TabPane tab="tab 3" key="3">选项卡三</TabPane>
<TabPane tab="选项卡一" key="1">选项卡一</TabPane>
<TabPane tab="选项卡二" disabled={true} key="2">选项卡二</TabPane>
<TabPane tab="选项卡三" key="3">选项卡三</TabPane>
</Tabs>
, document.getElementById('components-tabs-demo-disabled'));
````

View File

@ -10,19 +10,17 @@
var Tabs = antd.Tabs;
var TabPane = Tabs.TabPane;
function callback(key) {}
var tabContent = [
<span><i className="anticon anticon-apple"></i>tab 1</span>,
<span><i className="anticon anticon-android"></i>tab 2</span>,
<span><i className="anticon anticon-lock"></i>tab 3</span>,
<span><i className="anticon anticon-apple"></i>选项卡一</span>,
<span><i className="anticon anticon-android"></i>选项卡二</span>,
<span><i className="anticon anticon-lock"></i>选项卡三</span>,
];
React.render(
<Tabs defaultActiveKey="2" onChange={callback}>
<Tabs defaultActiveKey="2">
<TabPane tab={tabContent[0]} key="1">选项卡一</TabPane>
<TabPane tab={tabContent[1]} key="2">选项卡</TabPane>
<TabPane tab={tabContent[2]} key="3">选项卡</TabPane>
<TabPane tab={tabContent[1]} key="2">选项卡</TabPane>
<TabPane tab={tabContent[2]} key="3">选项卡</TabPane>
</Tabs>
, document.getElementById('components-tabs-demo-icon'));
````

View File

@ -12,9 +12,9 @@ var TabPane = Tabs.TabPane;
React.render(
<Tabs defaultActiveKey="2" size="mini">
<TabPane tab="tab 1" key="1">选项卡一</TabPane>
<TabPane tab="tab 2" key="2">选项卡二</TabPane>
<TabPane tab="tab 3" key="3">选项卡三</TabPane>
<TabPane tab="选项卡一" key="1">选项卡一内容</TabPane>
<TabPane tab="选项卡二" key="2">选项卡二内容</TabPane>
<TabPane tab="选项卡三" key="3">选项卡三内容</TabPane>
</Tabs>
, document.getElementById('components-tabs-demo-size'));
````

View File

@ -14,15 +14,15 @@ function callback(key) {}
React.render(
<Tabs defaultActiveKey="1" onChange={callback}>
<TabPane tab="tab 1" key="1">选项卡一</TabPane>
<TabPane tab="tab 2" key="2">选项卡二</TabPane>
<TabPane tab="tab 3" key="3">选项卡三</TabPane>
<TabPane tab="tab 4" key="4">选项卡四</TabPane>
<TabPane tab="tab 5" key="5">选项卡五</TabPane>
<TabPane tab="tab 6" key="6">选项卡六</TabPane>
<TabPane tab="tab 7" key="7">选项卡七</TabPane>
<TabPane tab="tab 8" key="8">选项卡八</TabPane>
<TabPane tab="tab 9" key="9">选项卡九</TabPane>
<TabPane tab="选项一" key="1">选项卡一</TabPane>
<TabPane tab="选项二" key="2">选项卡二</TabPane>
<TabPane tab="选项三" key="3">选项卡三</TabPane>
<TabPane tab="选项四" key="4">选项卡四</TabPane>
<TabPane tab="选项五" key="5">选项卡五</TabPane>
<TabPane tab="选项六" key="6">选项卡六</TabPane>
<TabPane tab="选项七" key="7">选项卡七</TabPane>
<TabPane tab="选项八" key="8">选项卡八</TabPane>
<TabPane tab="选项九" key="9">选项卡九</TabPane>
</Tabs>
, document.getElementById('components-tabs-demo-slide'));
````

View File

@ -1,8 +1,12 @@
# Tree
- category: Components
- chinese: 树形控件
- chinese: 树
---
树形控件。
## 何时使用
文件夹、组织架构、生物分类、国家地区等等,世间万物的大多数结构都是树形结构。使用`树控件`可以完整展现其中的层级关系,并具有展开收起选择等交互功能。

View File

@ -5,4 +5,10 @@
---
文件选择上传和拖拽上传控件。
## 何时使用
- 当需要上传一个或一些文件时。
- 当需要展现上传的进度时。
- 当需要使用拖拽交互时。

View File

@ -2,9 +2,9 @@
- order: 0
基本的表单校验子。
基本的表单校验子。
每个表单域要声明 `name` 属性作为校验的标识,可通过其 `isValidating` `errors` 属性判断是否处于校验中、是否校验不通过状态,具体可参见 **用户名** 校验。
每个表单域要声明 `name` 属性作为校验的标识,可通过其 `isValidating`、`errors` 属性判断是否处于校验中、是否校验不通过状态,具体可参见 **用户名** 校验。
表单提交的时候,通过 Validation 的 validate 方法判断是否所有表单域校验通过isValid 会作为回调函数的参数传入)。
@ -50,11 +50,13 @@ var Form = React.createClass({
passwd: undefined,
rePasswd: undefined,
textarea: undefined
}
},
isEmailOver: false, // email 是否输入完毕
emailValidateMethod: 'onBlur' // 用于改变 email 的验证方法
};
},
validateStyle(item, hasFeedback=true) {
renderValidateStyle(item, hasFeedback=true) {
var formData = this.state.formData;
var status = this.state.status;
@ -68,6 +70,20 @@ var Form = React.createClass({
return classes;
},
handleEmailInputBlur() {
this.setState({
isEmailOver: true
});
},
handleEmailInputFocus() {
if (this.state.isEmailOver) {
this.setState({
emailValidateMethod: 'onChange'
});
}
},
handleReset(e) {
this.refs.validation.reset();
this.setState(this.getInitialState());
@ -76,6 +92,9 @@ var Form = React.createClass({
handleSubmit(e) {
e.preventDefault();
this.setState({
isEmailOver: true
});
var validation = this.refs.validation;
validation.validate((valid) => {
if (!valid) {
@ -93,24 +112,21 @@ var Form = React.createClass({
callback();
} else {
setTimeout(function () {
if (value === 'yiminghe') {
if (value === 'Jasonwood') {
callback([new Error('抱歉,该用户名已被占用。')]);
} else {
callback();
}
}, 1000);
}, 800);
}
},
checkPass(rule, value, callback) {
if (this.state.formData.passwd) {
this.refs.validation.forceValidate(['rePasswd']);
}
callback();
},
checkPass2(rule, value, callback) {
if (value !== this.state.formData.passwd) {
if (value && value !== this.state.formData.passwd) {
callback('两次输入密码不一致!');
} else {
callback();
@ -123,13 +139,13 @@ var Form = React.createClass({
return (
<form onSubmit={this.handleSubmit} className="ant-form-horizontal">
<Validation ref='validation' onValidate={this.handleValidate}>
<Validation ref="validation" onValidate={this.handleValidate}>
<div className="ant-form-item">
<label className="col-6" for="name" required>用户名:</label>
<label className="col-7" for="name" required>用户名:</label>
<div className="col-12">
<div className= {this.validateStyle("name")}>
<div className={this.renderValidateStyle('name')}>
<Validator rules={[{required: true, min: 5, message: '用户名至少为 5 个字符'}, {validator: this.userExists}]}>
<input name='name' className="ant-input" value={formData.name} />
<input name="name" className="ant-input" value={formData.name} placeholder="实时校验,输入 JasonWood 看看" />
</Validator>
{status.name.isValidating ? <div className="ant-form-explain">正在校验中...</div> : null}
{status.name.errors ? <div className="ant-form-explain">{status.name.errors.join(',')}</div> : null}
@ -138,11 +154,11 @@ var Form = React.createClass({
</div>
<div className="ant-form-item">
<label className="col-6" for="email" required>邮箱:</label>
<label className="col-7" for="email" required>邮箱:</label>
<div className="col-12">
<div className= {this.validateStyle("email")}>
<Validator rules={{type: 'email', message: '填写正确的邮箱地址'}} trigger="onBlur">
<input name='email' className="ant-input" value={formData.email} onChange={this.setField.bind(this, 'email')}/>
<div className={this.renderValidateStyle('email', this.state.isEmailOver)}>
<Validator rules={[{required: true, type:'email', message: '输入正确的邮箱地址'}]} trigger={this.state.emailValidateMethod}>
<input name="email" className="ant-input" value={formData.email} placeholder="onBlur 与 onChange 相结合" onChange={this.setField.bind('email')} onBlur={this.handleEmailInputBlur} onFocus={this.handleEmailInputFocus} />
</Validator>
{status.email.errors ? <div className="ant-form-explain">{status.email.errors.join(',')}</div> : null}
</div>
@ -150,11 +166,11 @@ var Form = React.createClass({
</div>
<div className="ant-form-item">
<label className="col-6" required>国籍:</label>
<label className="col-7" required>国籍:</label>
<div className="col-12">
<div className= {this.validateStyle("select", false)}>
<div className={this.renderValidateStyle('select', false)}>
<Validator rules={[{required: true, message: '请选择您的国籍'}]}>
<Select style={{width:200}} name="select" value={formData.select}>
<Select style={{width:100 + "%"}} name="select" value={formData.select}>
<Option value="china">中国</Option>
<Option value="use">美国</Option>
<Option value="japan">日本</Option>
@ -168,9 +184,9 @@ var Form = React.createClass({
</div>
<div className="ant-form-item ant-form-item-compact">
<label className="col-6" required>性别:</label>
<label className="col-7" required>性别:</label>
<div className="col-12">
<div className= {this.validateStyle("radio", false)}>
<div className={this.renderValidateStyle('radio', false)}>
<Validator rules={[{required: true, message: '请选择您的性别'}]}>
<RadioGroup name="radio" value={formData.radio}>
<Radio value="male"></Radio>
@ -183,11 +199,11 @@ var Form = React.createClass({
</div>
<div className="ant-form-item">
<label className="col-6" required>密码:</label>
<label className="col-7" required>密码:</label>
<div className="col-12">
<div className= {this.validateStyle("passwd", false)}>
<Validator trigger="onBlur" rules={[{required: true, whitespace: true, message: '请填写密码'}, {validator: this.checkPass}]}>
<input name='passwd' className="ant-input" type="password" value={formData.passwd}/>
<div className={this.renderValidateStyle('passwd')}>
<Validator rules={[{required: true, whitespace: true, message: '请填写密码'}, {validator: this.checkPass}]}>
<input name="passwd" className="ant-input" type="password" value={formData.passwd}/>
</Validator>
{status.passwd.errors ? <div className="ant-form-explain">{status.passwd.errors.join(',')}</div> : null}
</div>
@ -195,28 +211,28 @@ var Form = React.createClass({
</div>
<div className="ant-form-item">
<label className="col-6" required>确认密码:</label>
<label className="col-7" required>确认密码:</label>
<div className="col-12">
<div className= {this.validateStyle("rePasswd", false)}>
<Validator trigger="onBlur" rules={[{
<div className={this.renderValidateStyle('rePasswd')}>
<Validator rules={[{
required: true,
whitespace: true,
message: '请再次输入密码'
}, {validator: this.checkPass2}]}>
<input name='rePasswd' className="ant-input" type="password" value={formData.rePasswd}/>
<input name="rePasswd" className="ant-input" type="password" value={formData.rePasswd} placeholder="两次输入密码保持一致"/>
</Validator>
{status.rePasswd.errors ? <div className="ant-form-explain"> {status.rePasswd.errors.join(', ')}</div> : null}
</div>
</div>
</div>
<div className="ant-form-item">
<label className="col-6" required>备注:</label>
<label className="col-7" required>备注:</label>
<div className="col-12">
<div className= {this.validateStyle("textarea", false)}>
<div className={this.renderValidateStyle('textarea', false)}>
<Validator rules={[{required: true, message: '真的不打算写点什么吗'}]}>
<textarea className="ant-input" name="textarea" placeholder="写点什么吧"></textarea>
<textarea className="ant-input" name="textarea" value={formData.textarea} placeholder="写点什么吧">
</textarea>
</Validator>
{status.textarea.errors ? <div className="ant-form-explain">{status.textarea.errors.join(',')}</div> : null}
</div>
@ -224,10 +240,10 @@ var Form = React.createClass({
</div>
<div className="ant-form-item">
<div className="col-offset-6 col-12">
<div className="col-offset-7 col-12">
<button type="submit" className="ant-btn ant-btn-primary">确 定</button>
&nbsp;&nbsp;&nbsp;
<a href='#' className="ant-btn" onClick={this.handleReset}>重 置</a>
<a href="#" className="ant-btn" onClick={this.handleReset}>重 置</a>
</div>
</div>
</Validation>

View File

@ -4,6 +4,8 @@
密码校验实例。
这里使用了 validation 的 `forceValidate(fields, callback)` 方法,在对第一次输入的密码进行校验时会触发二次密码的校验。
---
````jsx
@ -145,14 +147,14 @@ var Form = React.createClass({
return (
<form onSubmit={this.handleSubmit} className="ant-form-horizontal">
<Validation ref='validation' onValidate={this.handleValidate}>
<Validation ref="validation" onValidate={this.handleValidate}>
<div className="ant-form-item">
<label className="col-6" required>密码:</label>
<div className="col-10">
<div className= {this.renderValidateStyle("pass", false)}>
<div className={this.renderValidateStyle('pass', false)}>
<Validator rules={[{required: true, whitespace: true, message: '请填写密码'}, {validator: this.checkPass}]} trigger="onChange">
<input name='pass' className="ant-input" type="password" value={formData.pass}/>
<input name="pass" className="ant-input" type="password" value={formData.pass}/>
</Validator>
{status.pass.errors ? <div className="ant-form-explain">{status.pass.errors.join(',')}</div> : null}
</div>
@ -165,13 +167,13 @@ var Form = React.createClass({
<div className="ant-form-item">
<label className="col-6" required>确认密码:</label>
<div className="col-10">
<div className= {this.renderValidateStyle("rePass", false)}>
<div className={this.renderValidateStyle('rePass', false)}>
<Validator rules={[{
required: true,
whitespace: true,
message: '请再次输入密码'
}, {validator: this.checkPass2}]}>
<input name='rePass' className="ant-input" type="password" value={formData.rePass}/>
<input name="rePass" className="ant-input" type="password" value={formData.rePass}/>
</Validator>
{status.rePass.errors ? <div className="ant-form-explain"> {status.rePass.errors.join(', ')}</div> : null}
</div>
@ -185,7 +187,7 @@ var Form = React.createClass({
<div className="col-offset-6 col-12">
<button type="submit" className="ant-btn ant-btn-primary">确 定</button>
&nbsp;&nbsp;&nbsp;
<a href='#' className="ant-btn" onClick={this.handleReset}>重 置</a>
<a href="#" className="ant-btn" onClick={this.handleReset}>重 置</a>
</div>
</div>
</Validation>

View File

@ -10,7 +10,7 @@
## 何时使用
同表单结合使用,对表单域进行校验。
同表单结合使用,对表单域进行校验,提供前台校验和后台实时反馈校验,并对表单错误提供有效信息提示
## API
@ -53,7 +53,7 @@
- `type` : 声明校验的值类型(如 string email这样就会使用默认提供的规则进行校验更多详见 [type](https://github.com/yiminghe/async-validator#user-content-type)
- `required`: 是否必填;
- `pattern`: 声明校验正则表达式;
- `min` / `max`: 最小值、最大值声明;
- `min` / `max`: 最小值、最大值声明(对于 string 和 array 来说,针对的是其长度 length。
- `len`: 字符长度;
- `enum`: 枚举值,对应 type 值为 `enum`,例如 `role: {type: "enum", enum: ['A', 'B', 'C']}`
- `whitespace`: 是否允许空格, `true` 为允许;

View File

@ -7,7 +7,6 @@ var antd = {
Carousel: require('./components/carousel'),
Tabs: require('./components/tabs'),
Modal: require('./components/modal'),
Menu: require('rc-menu'),
Dropdown: require('./components/dropdown'),
Progress: require('./components/progress'),
Popover: require('./components/popover'),
@ -31,7 +30,8 @@ var antd = {
Notification: require('./components/notification'),
Alert: require('./components/alert'),
Validation: require('./components/validation'),
Tree: require('./components/Tree')
Tree: require('./components/Tree'),
Menu: require('./components/Menu')
};
module.exports = antd;

View File

@ -36,26 +36,26 @@
"gregorian-calendar": "~3.0.0",
"gregorian-calendar-format": "~3.0.1",
"is-equal-shallow": "~0.1.3",
"object-assign": "~3.0.0",
"rc-calendar": "~3.11.0",
"object-assign": "3.x",
"rc-calendar": "~3.12.3",
"rc-checkbox": "~1.0.6",
"rc-collapse": "~1.2.3",
"rc-dialog": "~4.4.0",
"rc-dialog": "~4.5.0",
"rc-dropdown": "~1.1.1",
"rc-form-validation": "~2.4.7",
"rc-input-number": "~2.0.1",
"rc-menu": "~3.4.2",
"rc-menu": "~3.5.0",
"rc-notification": "~1.1.0",
"rc-pagination": "~1.1.0",
"rc-progress": "~1.0.0",
"rc-radio": "~2.0.0",
"rc-select": "~4.4.0",
"rc-select": "~4.5.1",
"rc-slider": "~1.3.1",
"rc-steps": "~1.1.4",
"rc-switch": "~1.2.0",
"rc-table": "~3.1.0",
"rc-tabs": "~5.2.0",
"rc-tooltip": "~2.4.0",
"rc-tabs": "~5.3.2",
"rc-tooltip": "~2.5.0",
"rc-tree": "~0.10.0",
"rc-util": "~2.0.3",
"react-slick": "~0.6.4"

View File

@ -1,13 +1,13 @@
<div class="code-box" id="code-box-{{post.meta.id}}">
<div class="code-box" id="{{post.meta.id|removeCodeBoxIdPrefix}}">
<div class="code-box-demo">
<div id="{{post.meta.id}}"></div>
{{ post.html }}
</div>
<div class="code-box-meta markdown">
<div class="code-box-title">
<a href="#code-box-{{post.meta.id}}">{{ post.title }}</a>
<a href="#{{post.meta.id|removeCodeBoxIdPrefix}}">{{ post.title }}</a>
</div>
{{ post.meta.description }}
<span class="collapse anticon anticon-circle-o-right"></span>
<span class="collapse anticon anticon-circle-o-right" unselectable="none" style="-webkit-user-select: none;-moz-user-select: none;-ms-user-select: none;user-select: none;"></span>
</div>
</div>

View File

@ -105,6 +105,9 @@ module.exports = function(nico) {
},
rootDirectoryIs: function(directory, rootDirectory) {
return directory.split('/')[0] === rootDirectory;
},
removeCodeBoxIdPrefix: function(id) {
return id.split('-').slice(2).join('-');
}
};

View File

@ -558,6 +558,12 @@ footer ul li > a {
padding-left: 8px;
}
.markdown > ol li {
list-style: decimal;
margin-left: 20px;
padding-left: 8px;
}
.markdown code {
margin: 0 3px;
}

View File

@ -4,7 +4,6 @@
line-height: 34px;
text-align: center;
user-select: none;
-webkit-user-select: none;
border-bottom: 1px solid #e9e9e9;
a:hover {
@ -209,6 +208,7 @@
&-footer-btn {
text-align: center;
display: block;
line-height: 42px;
}
&-footer > div {

View File

@ -11,6 +11,10 @@
position: relative;
display: inline-block;
&-input {
outline: none;
}
&-icon {
position: absolute;
-webkit-user-select: none;

View File

@ -6,14 +6,12 @@
label {
position: relative;
&[required]:before {
position: absolute;
display: inline-block;
left: ~"-5px \9"; // ie8-9
margin-right: 4px;
content: "*";
color: @label-required-color;
font-family: SimSun;
font-size: @font-size-base;
.translate3d(-10px; 0; 0);
color: @label-required-color;
}
> .@{iconfont-css-prefix} {

View File

@ -29,3 +29,4 @@
@import "tree";
@import "carousel/slick";
@import "carousel/slick-theme";
@import "menu";

135
style/components/menu.less Normal file
View File

@ -0,0 +1,135 @@
@import "../mixins/index";
@menuPrefixCls: ~"@{css-prefix}menu";
.@{menuPrefixCls} {
outline: none;
margin-bottom: 0;
padding-left: 0; // Override default ul/ol
list-style: none;
z-index: 99999;
border: 1px solid #d9d9d9;
box-shadow: 0 0 4px #d9d9d9;
border-radius: 3px;
color: #666;
&-item-group-list {
margin: 0;
padding: 0;
}
&-item-group-title {
color: #999;
line-height: 1.5;
padding: 8px 10px;
border-bottom: 1px solid #dedede;
}
&-item-active, &-submenu-active {
background-color: #eaf8fe;
}
&-item-selected {
background-color: #eaf8fe;
}
& > li&-submenu {
padding: 0;
}
&-submenu-lt-lb > .@{menuPrefixCls} {
top: 100%;
left: 0;
margin-top: 4px;
}
&-submenu-lt-rt > .@{menuPrefixCls} {
top: 0;
left: 100%;
margin-left: 4px;
}
&-item,&-submenu-title {
margin: 0;
position: relative;
display: block;
padding: 7px 7px 7px 16px;
white-space: nowrap;
// Disabled state sets text to gray and nukes hover/tab effects
&.@{menuPrefixCls}-item-disabled, &.@{menuPrefixCls}-submenu-disabled {
color: #777 !important;
}
}
& > &-item-divider {
height: 1px;
margin: 1px 0;
overflow: hidden;
padding: 0;
line-height: 0;
background-color: #e5e5e5;
}
&-submenu {
position: relative;
> .@{menuPrefixCls} {
display: none;
position: absolute;
min-width: 160px;
background-color: #fff;
}
&-open {
> .@{menuPrefixCls} {
display: block;
}
}
}
.@{menuPrefixCls}-submenu-title, .@{menuPrefixCls}-item {
.anticon {
width: 14px;
height: 14px;
margin-right: 8px;
top: -1px;
}
}
&-horizontal {
background-color: #F3F5F7;
border: none;
border-bottom: 1px solid transparent;
border-bottom: 1px solid #d9d9d9;
box-shadow: none;
& > .@{menuPrefixCls}-item , & > .@{menuPrefixCls}-submenu > .@{menuPrefixCls}-submenu-title {
padding: 15px 20px;
}
& > .@{menuPrefixCls}-submenu, & > .@{menuPrefixCls}-item {
float: left;
border-bottom: 2px solid transparent;
&-active {
border-bottom: 2px solid #2db7f5;
background-color: #F3F5F7;
color: #2baee9;
}
}
&:after {
content: "\20";
display: block;
height: 0;
clear: both;
}
}
&-vertical {
padding: 12px 0;
& > .@{menuPrefixCls}-item , & > .@{menuPrefixCls}-submenu > .@{menuPrefixCls}-submenu-title {
padding: 12px 8px 12px 24px;
}
}
}

View File

@ -34,15 +34,18 @@
width: 100%;
position: relative;
white-space: nowrap;
padding-right: 32px;
border-bottom: 1px solid #f3f3f3;
border-bottom: 1px solid #e9e9e9;
margin-bottom: 15px;
.clearfix;
}
&-nav-container-scrolling {
padding-left: 32px;
padding-right: 32px;
}
&-tab-prev, &-tab-next {
user-select: none;
-webkit-user-select: none;
z-index: 2;
margin-right: -2px;
margin-top: 1px;
@ -79,6 +82,12 @@
}
}
&-tab-btn-disabled {
cursor: default;
color: #ccc;
pointer-events: none;
}
&-tab-next {
right: 2px;
@ -89,7 +98,6 @@
&-tab-prev {
left: 0;
background: #fff;
transform: rotate(180deg);
filter: progid:DXImageTransform.Microsoft.BasicImage(rotation=2);
&-icon:before {

View File

@ -41,6 +41,11 @@ ol {
list-style: none;
}
// Remove the clear button of a text input control in IE10+
input::-ms-clear, input::-ms-reveal {
display: none;
}
// Links
// -- TODO --
a {

View File

@ -10,8 +10,8 @@
// ------ Base & Require ------
@body-background : #fff;
@font-family : "Helvetica Neue",Helvetica,"Hiragino Sans GB","Microsoft YaHei","微软雅黑",SimSun,sans-serif;
@code-family : "PT Mono", Menlo, "Courier New", monospace;
@font-family : "Helvetica Neue",Helvetica,"Hiragino Sans GB","STHeitiSC-Light","Microsoft YaHei","微软雅黑",Arial,sans-serif;
@code-family : "PT Mono",Menlo,Consolas,"Courier New",monospace;
@text-color : #666;
@font-size-base : 12px;
@line-height-base : 1.5;