diff --git a/components/affix/index.md b/components/affix/index.md index f9c572c7b2..89c2af0c05 100644 --- a/components/affix/index.md +++ b/components/affix/index.md @@ -1,14 +1,21 @@ # Affix - category: Components -- chinese: 固定 +- chinese: 固钉 --- +将页面元素钉在可视范围。 + +## 何时使用 + +当内容区域比较长,需要滚动页面时,这部分内容对应的操作或者导航需要在滚动范围内始终展现。常用于侧边菜单和按钮组合。 + +页面可视范围过小时,慎用此功能以免遮挡页面内容。 + ## API -属性如下 | 成员 | 说明 | 类型 | 默认值 | |-------------|----------------|--------------------|--------------| -| offset | 达到指定偏移量后触发 | Number | 0 | +| offset | 达到指定偏移量后触发 | Number | 0 | diff --git a/components/alert/index.md b/components/alert/index.md index e2b5ec4a69..2662d9efcf 100644 --- a/components/alert/index.md +++ b/components/alert/index.md @@ -9,8 +9,8 @@ ## 何时使用 -- 当系统需要向用户显示警告的信息时。 -- 始终展现,不会自动消失,用户可以点击关闭。 +- 当某个页面需要向用户显示警告的信息时。 +- 非浮层的静态展现形式,始终展现,不会自动消失,用户可以点击关闭。 ## API diff --git a/components/carousel/index.md b/components/carousel/index.md index a0944e0a40..03c6bb4cc2 100644 --- a/components/carousel/index.md +++ b/components/carousel/index.md @@ -5,10 +5,13 @@ --- -旋转木马,轮播组件。 +旋转木马,一组轮播的区域。 ## 何时使用 +- 当有一组平级的内容。 +- 当内容空间不足时,可以用走马灯的形式进行收纳,进行轮播展现。 +- 常用于一组图片或卡片轮播。 ## API diff --git a/components/datepicker/demo/basic.md b/components/datepicker/demo/basic.md index d1f1ba75be..068b24431d 100644 --- a/components/datepicker/demo/basic.md +++ b/components/datepicker/demo/basic.md @@ -11,6 +11,6 @@ var Datepicker = antd.Datepicker; React.render( - + , document.getElementById('components-datepicker-demo-basic')); ```` diff --git a/components/datepicker/demo/size.md b/components/datepicker/demo/size.md index 9dcf44390e..d42f89e549 100644 --- a/components/datepicker/demo/size.md +++ b/components/datepicker/demo/size.md @@ -7,7 +7,6 @@ --- ````jsx -// or require('antd/lib/datepicker'); var Datepicker = antd.Datepicker; React.render( diff --git a/components/datepicker/index.jsx b/components/datepicker/index.jsx index 228a38e4f1..7ffb397704 100644 --- a/components/datepicker/index.jsx +++ b/components/datepicker/index.jsx @@ -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={} 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}> Checkbox 多选框:
diff --git a/components/menu/demo/nav.md b/components/menu/demo/nav.md new file mode 100644 index 0000000000..28371fdc3f --- /dev/null +++ b/components/menu/demo/nav.md @@ -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( + 导航一}> + 选项1 + 选项2 + 选项3 + 选项4 + + 导航二}> + 选项5 + 选项6 + 三级导航}> + 选项7 + 选项8 + + + 导航三}> + 选项9 + 选项10 + 选项11 + 选项12 + + +, document.getElementById('components-menu-demo-nav')); +```` diff --git a/components/menu/demo/side.md b/components/menu/demo/side.md new file mode 100644 index 0000000000..6a67248783 --- /dev/null +++ b/components/menu/demo/side.md @@ -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( + 导航一}> + 选项1 + 选项2 + 选项3 + 选项4 + + 导航二}> + 选项5 + 选项6 + 三级导航}> + 选项7 + 选项8 + + + 导航三}> + 选项9 + 选项10 + 选项11 + 选项12 + + +, document.getElementById('components-menu-demo-side')); +```` diff --git a/components/menu/index.jsx b/components/menu/index.jsx new file mode 100644 index 0000000000..9b160bec41 --- /dev/null +++ b/components/menu/index.jsx @@ -0,0 +1,20 @@ +import Menu from 'rc-menu'; +import React from 'react'; + +const AntMenu = React.createClass({ + getDefaultProps(){ + return { + prefixCls: 'ant-menu' + }; + }, + + render(){ + return ; + } +}); + +AntMenu.Divider = Menu.Divider; +AntMenu.Item = Menu.Item; +AntMenu.SubMenu = Menu.SubMenu; + +export default AntMenu; diff --git a/components/menu/index.md b/components/menu/index.md index 1203b0074a..341c52e7a3 100644 --- a/components/menu/index.md +++ b/components/menu/index.md @@ -5,3 +5,45 @@ --- +## 何时使用 + +需要多级菜单时 + +```html + + 菜单项 + + 子菜单项 + + +``` + +## 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)[] | 子菜单的菜单项 | | | diff --git a/components/notification/demo/basic.md b/components/notification/demo/basic.md index 16be5fdfb4..37fdbf1e98 100644 --- a/components/notification/demo/basic.md +++ b/components/notification/demo/basic.md @@ -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( , document.getElementById('components-notification-demo-basic')); -```` \ No newline at end of file +```` diff --git a/components/notification/demo/onclose.md b/components/notification/demo/onclose.md index e4bb9e805a..c994656f00 100644 --- a/components/notification/demo/onclose.md +++ b/components/notification/demo/onclose.md @@ -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( , document.getElementById('components-notification-demo-onclose')); -```` \ No newline at end of file +```` diff --git a/components/notification/demo/with-btn-onclose.md b/components/notification/demo/with-btn-onclose.md index 93bfa83a10..38549b1ed2 100644 --- a/components/notification/demo/with-btn-onclose.md +++ b/components/notification/demo/with-btn-onclose.md @@ -21,19 +21,18 @@ var close = function() { var onClose = function() { // 默认按钮关闭时的业务处理 console.log("我被默认的关闭按钮关闭了!"); -} +}; var btn = ; var openNotification = function() { - var args = { + notification.open({ message: "这是标题", description: "这是提示框的文案这是提示框示框的文案这是提示是提示框的文案这是提示框的文案", btn: btn, key: key, onClose: onClose - }; - notification.open(args); + }); }; React.render( diff --git a/components/notification/demo/with-btn.md b/components/notification/demo/with-btn.md index 8beec8288b..1e70d9f1bb 100644 --- a/components/notification/demo/with-btn.md +++ b/components/notification/demo/with-btn.md @@ -18,13 +18,12 @@ var close = function() { var btn = ; var openNotification = function() { - var args = { + notification.open({ message: "这是标题", description: "这是提示框的文案这是提示框示框的文案这是提示是提示框的文案这是提示框的文案", btn: btn, key: key - }; - notification.open(args); + }); }; React.render( @@ -32,4 +31,4 @@ React.render( , document.getElementById('components-notification-demo-with-btn')); -```` \ No newline at end of file +```` diff --git a/components/notification/demo/with-icon.md b/components/notification/demo/with-icon.md index fae11d88d1..155a7fc894 100644 --- a/components/notification/demo/with-icon.md +++ b/components/notification/demo/with-icon.md @@ -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); + }); }; }; diff --git a/components/notification/index.jsx b/components/notification/index.jsx index 771b667a4d..55e5ada85f 100644 --- a/components/notification/index.jsx +++ b/components/notification/index.jsx @@ -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:
-

{args.message}

-

{args.description}

, - 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:

{args.message}

-

{args.description}

, - 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:

{args.message}

-

{args.description}

{args.btn}
, - 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 diff --git a/components/notification/index.md b/components/notification/index.md index 990fb0646a..82472b170c 100644 --- a/components/notification/index.md +++ b/components/notification/index.md @@ -9,7 +9,11 @@ ## 何时使用 -- 当系统需要在窗口右上角显示通知提醒信息时。 +在系统右上角显示通知提醒信息。经常用于以下情况: + +- 较为复杂的通知内容。 +- 带有交互的通知,给出用户下一步的行动点。 +- 系统主动推送。 ## API @@ -30,8 +34,9 @@ config 参数如下: | btn | 自定义关闭按钮 | React.Element | 无 | | key | 当前通知唯一标志 | String | 无 | | onClose | 点击默认关闭按钮时触发的回调函数 | Function | 无 | +| duration | 默认五秒后自动关闭,配置为 null 则不自动关闭 | Number | 5 | -还提供了一个全局配置方法: +还提供了一个全局配置方法,需要在调用前提前配置,一次有效。 - `notification.config(options)` diff --git a/components/select/demo/coordinate.md b/components/select/demo/coordinate.md new file mode 100644 index 0000000000..a83588fb12 --- /dev/null +++ b/components/select/demo/coordinate.md @@ -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 ; + }); + var cityOptions = this.state.cities.map(function(city) { + return ; + }); + return
+ +   + +
; + } +}); +React.render(, document.getElementById('components-select-demo-coordinate')); +```` + diff --git a/components/select/index.md b/components/select/index.md index 5456602134..d651f6305d 100644 --- a/components/select/index.md +++ b/components/select/index.md @@ -24,7 +24,8 @@ | 参数 | 说明 | 类型 | 默认值 | |----------|----------------|----------|--------------| -| value | 指定默认选中的条目 | string/Array | 无 | +| value | 指定选中的条目 | string/Array | 无 | +| defaultValue | 指定默认选中的条目 | string/Array | 无 | | multiple | 支持多选 | | false | | filterOption | 是否根据输入项进行筛选 | | true | | tags | 可以把随意输入的条目作为tag,输入项不需要与下拉选项匹配 | |false | diff --git a/components/table/demo/ajax.md b/components/table/demo/ajax.md index 613ea5cda6..445e60bb44 100644 --- a/components/table/demo/ajax.md +++ b/components/table/demo/ajax.md @@ -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( -, document.getElementById('components-table-demo-ajax')); +function fetch() { + dataSource.fetch().then(function() { + console.log('fetch done'); + }); +} + +React.render(
+
+ +, document.getElementById('components-table-demo-ajax')); ```` diff --git a/components/table/demo/nopagination.md b/components/table/demo/nopagination.md index 1d11a40bbe..1feabbf1e3 100644 --- a/components/table/demo/nopagination.md +++ b/components/table/demo/nopagination.md @@ -1,6 +1,6 @@ # 不显示分页 -- order: 8 +- order: 9 传入 pagination 为 false 即可。 diff --git a/components/table/index.jsx b/components/table/index.jsx index e271d88d35..6b9e526046 100644 --- a/components/table/index.jsx +++ b/components/table/index.jsx @@ -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({ ; } }); + +AntTable.DataSource = DataSource; + +export default AntTable; diff --git a/components/table/index.md b/components/table/index.md index 8d9e6d2c6c..a2b8b7e823 100644 --- a/components/table/index.md +++ b/components/table/index.md @@ -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) {} -}; +}); +
``` diff --git a/components/tabs/demo/basic.md b/components/tabs/demo/basic.md index d979c79549..d6c1d4014f 100644 --- a/components/tabs/demo/basic.md +++ b/components/tabs/demo/basic.md @@ -2,7 +2,7 @@ - order: 0 -默认选中第二项。 +默认选中第一项。 --- @@ -15,10 +15,10 @@ function callback(key) { } React.render( - - 选项卡一 - 选项卡二 - 选项卡三 + + 选项卡一内容 + 选项卡二内容 + 选项卡三内容 , document.getElementById('components-tabs-demo-basic')); ```` diff --git a/components/tabs/demo/disabled.md b/components/tabs/demo/disabled.md index 13c1a96219..7b8ad27555 100644 --- a/components/tabs/demo/disabled.md +++ b/components/tabs/demo/disabled.md @@ -14,9 +14,9 @@ function callback(key) {} React.render( - 选项卡一 - 选项卡二 - 选项卡三 + 选项卡一 + 选项卡二 + 选项卡三 , document.getElementById('components-tabs-demo-disabled')); ```` diff --git a/components/tabs/demo/icon.md b/components/tabs/demo/icon.md index 3084cc6337..782c7dc1fb 100644 --- a/components/tabs/demo/icon.md +++ b/components/tabs/demo/icon.md @@ -10,19 +10,17 @@ var Tabs = antd.Tabs; var TabPane = Tabs.TabPane; -function callback(key) {} - var tabContent = [ - tab 1, - tab 2, - tab 3, + 选项卡一, + 选项卡二, + 选项卡三, ]; React.render( - + 选项卡一 - 选项卡一 - 选项卡一 + 选项卡二 + 选项卡三 , document.getElementById('components-tabs-demo-icon')); ```` diff --git a/components/tabs/demo/size.md b/components/tabs/demo/size.md index b1094419c7..e339251161 100644 --- a/components/tabs/demo/size.md +++ b/components/tabs/demo/size.md @@ -12,9 +12,9 @@ var TabPane = Tabs.TabPane; React.render( - 选项卡一 - 选项卡二 - 选项卡三 + 选项卡一内容 + 选项卡二内容 + 选项卡三内容 , document.getElementById('components-tabs-demo-size')); ```` diff --git a/components/tabs/demo/slide.md b/components/tabs/demo/slide.md index 892572a9b2..ce1cc98657 100644 --- a/components/tabs/demo/slide.md +++ b/components/tabs/demo/slide.md @@ -14,15 +14,15 @@ function callback(key) {} React.render( - 选项卡一 - 选项卡二 - 选项卡三 - 选项卡四 - 选项卡五 - 选项卡六 - 选项卡七 - 选项卡八 - 选项卡九 + 选项卡一 + 选项卡二 + 选项卡三 + 选项卡四 + 选项卡五 + 选项卡六 + 选项卡七 + 选项卡八 + 选项卡九 , document.getElementById('components-tabs-demo-slide')); ```` diff --git a/components/tree/index.md b/components/tree/index.md index 5853657c38..c02e552414 100644 --- a/components/tree/index.md +++ b/components/tree/index.md @@ -1,8 +1,12 @@ # Tree - category: Components -- chinese: 树形控件 +- chinese: 树 --- +树形控件。 +## 何时使用 + +文件夹、组织架构、生物分类、国家地区等等,世间万物的大多数结构都是树形结构。使用`树控件`可以完整展现其中的层级关系,并具有展开收起选择等交互功能。 diff --git a/components/upload/index.md b/components/upload/index.md index df9009aeeb..f46a33a5c8 100644 --- a/components/upload/index.md +++ b/components/upload/index.md @@ -5,4 +5,10 @@ --- +文件选择上传和拖拽上传控件。 +## 何时使用 + +- 当需要上传一个或一些文件时。 +- 当需要展现上传的进度时。 +- 当需要使用拖拽交互时。 diff --git a/components/validation/demo/basic.md b/components/validation/demo/basic.md index 271534b8d2..839ea8b59e 100644 --- a/components/validation/demo/basic.md +++ b/components/validation/demo/basic.md @@ -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 (
- +
- +
-
+
- + {status.name.isValidating ?
正在校验中...
: null} {status.name.errors ?
{status.name.errors.join(',')}
: null} @@ -138,11 +154,11 @@ var Form = React.createClass({
- +
-
- - +
+ + {status.email.errors ?
{status.email.errors.join(',')}
: null}
@@ -150,11 +166,11 @@ var Form = React.createClass({
- +
-
+
- @@ -168,9 +184,9 @@ var Form = React.createClass({
- +
-
+
@@ -183,11 +199,11 @@ var Form = React.createClass({
- +
-
- - +
+ + {status.passwd.errors ?
{status.passwd.errors.join(',')}
: null}
@@ -195,28 +211,28 @@ var Form = React.createClass({
- +
-
- + - + {status.rePasswd.errors ?
{status.rePasswd.errors.join(', ')}
: null}
-
- +
-
+
- + {status.textarea.errors ?
{status.textarea.errors.join(',')}
: null}
@@ -224,10 +240,10 @@ var Form = React.createClass({
-
+
    - 重 置 + 重 置
diff --git a/components/validation/demo/customize.md b/components/validation/demo/customize.md index be71cf5ce7..d2e31184d3 100644 --- a/components/validation/demo/customize.md +++ b/components/validation/demo/customize.md @@ -4,6 +4,8 @@ 密码校验实例。 +这里使用了 validation 的 `forceValidate(fields, callback)` 方法,在对第一次输入的密码进行校验时会触发二次密码的校验。 + --- ````jsx @@ -145,14 +147,14 @@ var Form = React.createClass({ return ( - +
-
+
- + {status.pass.errors ?
{status.pass.errors.join(',')}
: null}
@@ -165,13 +167,13 @@ var Form = React.createClass({
-
+
- + {status.rePass.errors ?
{status.rePass.errors.join(', ')}
: null}
@@ -185,7 +187,7 @@ var Form = React.createClass({
    - 重 置 + 重 置
diff --git a/components/validation/index.md b/components/validation/index.md index 9fe0001496..e266f7b22d 100644 --- a/components/validation/index.md +++ b/components/validation/index.md @@ -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` 为允许; diff --git a/index.js b/index.js index 09a12847f1..ea73f8e8d6 100644 --- a/index.js +++ b/index.js @@ -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; diff --git a/package.json b/package.json index 19e31d9b6d..56bf0f40e1 100644 --- a/package.json +++ b/package.json @@ -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" diff --git a/site/templates/code.html b/site/templates/code.html index 54b2848ed2..9dfe12ea72 100644 --- a/site/templates/code.html +++ b/site/templates/code.html @@ -1,13 +1,13 @@ -
+
{{ post.html }}
{{ post.meta.description }} - +
diff --git a/site/theme.js b/site/theme.js index 24c6b01a53..ac8a9872e0 100644 --- a/site/theme.js +++ b/site/theme.js @@ -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('-'); } }; diff --git a/static/style.css b/static/style.css index 6834f9b2e8..85c963b7f4 100644 --- a/static/style.css +++ b/static/style.css @@ -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; } diff --git a/style/components/datepicker/Calendar.less b/style/components/datepicker/Calendar.less index 69d3b38bbf..1be6170e4f 100644 --- a/style/components/datepicker/Calendar.less +++ b/style/components/datepicker/Calendar.less @@ -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 { diff --git a/style/components/datepicker/Picker.less b/style/components/datepicker/Picker.less index 4d64aaa56e..21f971a8da 100644 --- a/style/components/datepicker/Picker.less +++ b/style/components/datepicker/Picker.less @@ -11,6 +11,10 @@ position: relative; display: inline-block; + &-input { + outline: none; + } + &-icon { position: absolute; -webkit-user-select: none; diff --git a/style/components/form.less b/style/components/form.less index 6a6558206c..1de1117601 100644 --- a/style/components/form.less +++ b/style/components/form.less @@ -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} { diff --git a/style/components/index.less b/style/components/index.less index 89dfcf42c7..b570a8feb1 100644 --- a/style/components/index.less +++ b/style/components/index.less @@ -29,3 +29,4 @@ @import "tree"; @import "carousel/slick"; @import "carousel/slick-theme"; +@import "menu"; diff --git a/style/components/menu.less b/style/components/menu.less new file mode 100644 index 0000000000..c01902937b --- /dev/null +++ b/style/components/menu.less @@ -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; + } + } +} diff --git a/style/components/tabs.less b/style/components/tabs.less index 7fa2ca390d..097642767d 100644 --- a/style/components/tabs.less +++ b/style/components/tabs.less @@ -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 { diff --git a/style/core/base.less b/style/core/base.less index 419852ec77..eac808bfa2 100644 --- a/style/core/base.less +++ b/style/core/base.less @@ -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 { diff --git a/style/themes/default/custom.less b/style/themes/default/custom.less index 503279bbe0..c17ec024b3 100644 --- a/style/themes/default/custom.less +++ b/style/themes/default/custom.less @@ -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;