diff --git a/.eslintrc.json b/.eslintrc.json index caf7efe8d6..8f6cb778f5 100644 --- a/.eslintrc.json +++ b/.eslintrc.json @@ -7,9 +7,12 @@ "jest": true, "es6": true }, - "ecmaFeatures": { - "jsx": true, - "experimentalObjectRestSpread": true + "parserOptions": { + "ecmaVersion": 6, + "ecmaFeatures": { + "jsx": true, + "experimentalObjectRestSpread": true + } }, "plugins": [ "markdown", @@ -28,6 +31,8 @@ "react/jsx-closing-bracket-location": 0, "react/jsx-no-bind": 0, "no-param-reassign": 0, - "max-len": 0 + "no-return-assign": 0, + "max-len": 0, + "consistent-return": 0 } } diff --git a/CHANGELOG.md b/CHANGELOG.md index 6071b276e9..2ff13c4f0b 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -4,6 +4,18 @@ --- +## 0.12.4 + +`2016-02-22` + +- Radio 的 value 支持更多类型。[#1043](https://github.com/ant-design/ant-design/pull/1043) +- 修复 Spin 组件的大小、居中等样式问题。 +- FormItem 补充 extra 属性的文档。[#931](https://github.com/ant-design/ant-design/issues/931) +- 修复的 Table 下树形数据和选择框配合时的样式问题。 +- 修复一个水平表单的错误提示的样式错位问题。[#1040](https://github.com/ant-design/ant-design/issues/1040) +- 改进 Input disabled 的样式。 +- 添加了一个轻微的 Button 点击动效。 + ## 0.12.3 `2016-02-19` diff --git a/components/badge/index.jsx b/components/badge/index.jsx index cd51874288..7076faaad3 100644 --- a/components/badge/index.jsx +++ b/components/badge/index.jsx @@ -4,10 +4,6 @@ import ScrollNumber from './ScrollNumber'; import classNames from 'classnames'; class AntBadge extends React.Component { - constructor(props) { - super(props); - } - render() { let { count, prefixCls, overflowCount, className, style, children } = this.props; const dot = this.props.dot; diff --git a/components/button/button.jsx b/components/button/button.jsx index b9e7ec6110..59111b7605 100644 --- a/components/button/button.jsx +++ b/components/button/button.jsx @@ -30,9 +30,17 @@ export default class Button extends React.Component { window.PIE.attach(findDOMNode(this)); } } + handleClick(...args) { + const buttonNode = findDOMNode(this); + buttonNode.className = buttonNode.className.replace(`${prefix}clicked`, ''); + setTimeout(() => { + buttonNode.className += ` ${prefix}clicked`; + }, 10); + this.props.onClick(...args); + } render() { const props = this.props; - const { type, shape, size, onClick, className, htmlType, children, ...others } = props; + const { type, shape, size, className, htmlType, children, ...others } = props; // large => lg // small => sm @@ -53,7 +61,7 @@ export default class Button extends React.Component { const kids = React.Children.map(children, insertSpace); return ( - ); diff --git a/components/calendar/demo/locale.md b/components/calendar/demo/locale.md index 94b22c1ad4..f292bbc540 100644 --- a/components/calendar/demo/locale.md +++ b/components/calendar/demo/locale.md @@ -15,6 +15,6 @@ function onPanelChange(value, mode) { } ReactDOM.render( - + , mountNode); ```` diff --git a/components/calendar/index.jsx b/components/calendar/index.jsx index cd6266b06f..6be2b5e8e0 100644 --- a/components/calendar/index.jsx +++ b/components/calendar/index.jsx @@ -92,7 +92,7 @@ class Calendar extends Component { locale={locale.lang} prefixCls={prefixCls} onTypeChange={this.setType.bind(this)} - onValueChange={this.setValue.bind(this)}/> + onValueChange={this.setValue.bind(this)} /> - +

{text}

- +

{text}

- +

{text}

diff --git a/components/collapse/demo/mix.md b/components/collapse/demo/mix.md index d28d3f57b8..ba376017f0 100644 --- a/components/collapse/demo/mix.md +++ b/components/collapse/demo/mix.md @@ -22,17 +22,17 @@ const text = ` ReactDOM.render( - + - +

{text}

- +

{text}

- +

{text}

diff --git a/components/date-picker/RangePicker.jsx b/components/date-picker/RangePicker.jsx index 0b24c77c3d..57d1525a6d 100644 --- a/components/date-picker/RangePicker.jsx +++ b/components/date-picker/RangePicker.jsx @@ -74,7 +74,7 @@ export default React.createClass({ timePicker = (); + transitionName="slide-up" />); } const calendarClassName = classNames({ @@ -151,15 +151,15 @@ export default React.createClass({ onChange={this.handleInputChange} value={start && this.getFormatter().format(start)} placeholder={startPlaceholder} - className="ant-calendar-range-picker-input"/> + className="ant-calendar-range-picker-input" /> ~ - + className="ant-calendar-range-picker-input" /> + ); } diff --git a/components/date-picker/index.jsx b/components/date-picker/index.jsx index 97bd1a2da1..85670591ec 100644 --- a/components/date-picker/index.jsx +++ b/components/date-picker/index.jsx @@ -61,7 +61,7 @@ function createPicker(TheCalendar, defaultFormat) { const timePicker = this.props.showTime ? () + transitionName="slide-up" />) : null; const disabledTime = this.props.showTime ? this.props.disabledTime : null; @@ -139,8 +139,8 @@ function createPicker(TheCalendar, defaultFormat) { value={value && this.getFormatter().format(value)} placeholder={placeholder} style={this.props.style} - className={`ant-calendar-picker-input ant-input${sizeClass}`}/> - + className={`ant-calendar-picker-input ant-input${sizeClass}`} /> + ); } diff --git a/components/dropdown/demo/item.md b/components/dropdown/demo/item.md index 4f58b2397c..5e6d379239 100644 --- a/components/dropdown/demo/item.md +++ b/components/dropdown/demo/item.md @@ -17,7 +17,7 @@ const menu = ( 第二个菜单项 - + 第三个菜单项(不可用) ); diff --git a/components/dropdown/demo/trigger.md b/components/dropdown/demo/trigger.md index a701fcda9a..2a7e8cf04f 100644 --- a/components/dropdown/demo/trigger.md +++ b/components/dropdown/demo/trigger.md @@ -17,7 +17,7 @@ const menu = ( 第二个菜单项 - + 第三个菜单项 ); diff --git a/components/form/FormItem.jsx b/components/form/FormItem.jsx index d96de2627f..b48b029f8b 100644 --- a/components/form/FormItem.jsx +++ b/components/form/FormItem.jsx @@ -58,6 +58,8 @@ class FormItem extends React.Component { } else if (getFieldValue(field) !== undefined) { return 'success'; } + + return ''; } renderValidateWrapper(c1, c2, c3) { diff --git a/components/form/ValueMixin.jsx b/components/form/ValueMixin.jsx index 57637057ce..7450ddd687 100644 --- a/components/form/ValueMixin.jsx +++ b/components/form/ValueMixin.jsx @@ -1,14 +1,3 @@ -function merge() { - const ret = {}; - const args = [].slice.call(arguments, 0); - args.forEach((a) => { - Object.keys(a).forEach((k) => { - ret[k] = a[k]; - }); - }); - return ret; -} - const ValueMixin = { setValue(field, e) { let v = e; @@ -24,7 +13,10 @@ const ValueMixin = { const newFormData = {}; newFormData[field] = v; this.setState({ - formData: merge(this.state.formData, newFormData), + formData: { + ...this.state.formData, + ...newFormData, + }, }); }, }; diff --git a/components/form/demo/disabled.md b/components/form/demo/disabled.md deleted file mode 100644 index c6347d264c..0000000000 --- a/components/form/demo/disabled.md +++ /dev/null @@ -1,50 +0,0 @@ -# 禁用状态 - -- order: 7 - -1) 单独为输入控件设置 `disabled` 属性; - -2) 为 `
` 设置 `disabled` 属性,可以禁用 `
` 中包含的所有控件。 - ---- - -````jsx -import { Row, Col, Button, Input, Form } from 'antd'; -const FormItem = Form.Item; - -ReactDOM.render( -
- - - - -
- 禁用的 fieldset - -

大眼萌 minion

-
- - - - - - - - -
-
-, mountNode); -```` diff --git a/components/form/demo/input-group.md b/components/form/demo/input-group.md index c3fa8a28db..c2c1c22344 100644 --- a/components/form/demo/input-group.md +++ b/components/form/demo/input-group.md @@ -18,14 +18,14 @@ ReactDOM.render( label="标签输入框:" labelCol={{ span: 6 }} wrapperCol={{ span: 16 }}> - + - + - + - +

-

@@ -100,7 +100,7 @@ let Demo = React.createClass({ labelCol={{ span: 8 }} wrapperCol={{ span: 16 }} required> - +
+ })} /> + onContextMenu={noop} onPaste={noop} onCopy={noop} onCut={noop} /> + })} /> + })} /> diff --git a/components/form/index.md b/components/form/index.md index 2ff7a65c9d..31aa52bebe 100644 --- a/components/form/index.md +++ b/components/form/index.md @@ -101,6 +101,7 @@ CustomizedForm = Form.create({})(CustomizedForm); | labelCol | label 标签布局,通 `` 组件,设置 `span` `offset` 值,如 `{span: 3, offset: 12}` | object | | | | wrapperCol | 需要为输入控件设置布局样式时,使用该属性,用法同 labelCol | object | | | | help | 提示信息,如不设置,则会根据校验规则自动生成 | string | | | +| extra | 额外的提示信息,和 help 类似,当需要错误信息和提示文案同时出现时,可以使用这个。 | string | | | | required | 是否必填,如不设置,则会根据校验规则自动生成 | bool | | false | | validateStatus | 校验状态,如不设置,则会根据校验规则自动生成 | string | 'success' 'warning' 'error' 'validating' | | | hasFeedback | 配合 validateStatus 属性使用,是否展示校验状态图标 | bool | | false | diff --git a/components/input/index.jsx b/components/input/index.jsx index e502a70804..1665ca680d 100644 --- a/components/input/index.jsx +++ b/components/input/index.jsx @@ -99,7 +99,7 @@ class Input extends React.Component { ); default: inputClassName = props.className ? props.className : inputClassName; - return ; + return ; } } diff --git a/components/modal/demo/async.md b/components/modal/demo/async.md index eebd848421..ed81f81806 100644 --- a/components/modal/demo/async.md +++ b/components/modal/demo/async.md @@ -55,5 +55,5 @@ const Test = React.createClass({ } }); -ReactDOM.render(, mountNode); +ReactDOM.render(, mountNode); ```` diff --git a/components/modal/demo/footer.md b/components/modal/demo/footer.md index b650d3b1ca..24bf9f45aa 100644 --- a/components/modal/demo/footer.md +++ b/components/modal/demo/footer.md @@ -56,5 +56,5 @@ const Test = React.createClass({ } }); -ReactDOM.render(, mountNode); +ReactDOM.render(, mountNode); ```` diff --git a/components/queue-anim/demo/form.md b/components/queue-anim/demo/form.md index 319386170a..2b82e8210a 100644 --- a/components/queue-anim/demo/form.md +++ b/components/queue-anim/demo/form.md @@ -38,7 +38,7 @@ const Test = React.createClass({
- +
,
diff --git a/components/queue-anim/demo/router.md b/components/queue-anim/demo/router.md index b8908be062..292f736f75 100644 --- a/components/queue-anim/demo/router.md +++ b/components/queue-anim/demo/router.md @@ -29,7 +29,7 @@ const App = React.createClass({ - {React.cloneElement(this.props.children || , { key })} + {React.cloneElement(this.props.children || , { key })}
); diff --git a/components/radio/demo/radiogroup.md b/components/radio/demo/radiogroup.md index 820bab872c..eadfb117f8 100644 --- a/components/radio/demo/radiogroup.md +++ b/components/radio/demo/radiogroup.md @@ -13,11 +13,11 @@ const RadioGroup = Radio.Group; const App = React.createClass({ getInitialState() { return { - value: 'a' + value: 1 }; }, onChange(e) { - console.log(`radio checked:${e.target.value}`); + console.log('radio checked', e.target.value); this.setState({ value: e.target.value }); @@ -26,12 +26,11 @@ const App = React.createClass({ return (
- A - B - C - D + A + B + C + D -
你选中的: {this.state.value}
); } diff --git a/components/radio/group.jsx b/components/radio/group.jsx index 293288e687..113b470690 100644 --- a/components/radio/group.jsx +++ b/components/radio/group.jsx @@ -1,13 +1,15 @@ import React from 'react'; function getCheckedValue(children) { - let checkedValue = null; + let value = null; + let matched = false; React.Children.forEach(children, (radio) => { if (radio.props && radio.props.checked) { - checkedValue = radio.props.value; + value = radio.props.value; + matched = true; } }); - return checkedValue; + return matched ? { value } : undefined; } export default React.createClass({ @@ -16,34 +18,56 @@ export default React.createClass({ prefixCls: 'ant-radio-group', disabled: false, onChange() { - } + }, }; }, getInitialState() { let props = this.props; + let value; + if ('value' in props) { + value = props.value; + } else if ('defaultValue' in props) { + value = props.defaultValue; + } else { + const checkedValue = getCheckedValue(props.children); + value = checkedValue && checkedValue.value; + } return { - value: props.value || props.defaultValue || getCheckedValue(props.children) + value, }; }, componentWillReceiveProps(nextProps) { - if ('value' in nextProps || getCheckedValue(nextProps.children)) { + if ('value' in nextProps) { this.setState({ - value: nextProps.value || getCheckedValue(nextProps.children) + value: nextProps.value, }); + } else { + const checkedValue = getCheckedValue(nextProps.children); + if (checkedValue) { + this.setState({ + value: checkedValue.value, + }); + } } }, onRadioChange(ev) { - this.setState({ - value: ev.target.value - }); + if (!('value' in this.props)) { + this.setState({ + value: ev.target.value, + }); + } this.props.onChange(ev); }, render() { const props = this.props; const children = React.Children.map(props.children, (radio) => { if (radio.props) { + const keyProps = {}; + if (!('key' in radio) && typeof radio.props.value === 'string') { + keyProps.key = radio.props.value; + } return React.cloneElement(radio, { - key: radio.props.value, + ...keyProps, ...radio.props, onChange: this.onRadioChange, checked: this.state.value === radio.props.value, diff --git a/components/table/demo/indent-size.md b/components/table/demo/expand-children.md similarity index 95% rename from components/table/demo/indent-size.md rename to components/table/demo/expand-children.md index 86988a8463..7577deb3ab 100644 --- a/components/table/demo/indent-size.md +++ b/components/table/demo/expand-children.md @@ -78,7 +78,7 @@ const data = [{ }]; ReactDOM.render( - , +
, mountNode ); ```` diff --git a/components/table/filterDropdown.jsx b/components/table/filterDropdown.jsx index 1526d6ae46..97e2921dd7 100644 --- a/components/table/filterDropdown.jsx +++ b/components/table/filterDropdown.jsx @@ -59,9 +59,7 @@ let FilterMenu = React.createClass({ const keyPathOfSelectedItem = this.state.keyPathOfSelectedItem; const containSelected = Object.keys(keyPathOfSelectedItem).some(key => { const keyPath = keyPathOfSelectedItem[key]; - if (keyPath.indexOf(item.value) >= 0) { - return true; - } + return keyPath.indexOf(item.value) >= 0; }); const subMenuCls = containSelected ? 'ant-dropdown-submenu-contain-selected' : ''; return ( diff --git a/components/table/index.jsx b/components/table/index.jsx index e97d8d4d14..7b99c71a29 100644 --- a/components/table/index.jsx +++ b/components/table/index.jsx @@ -134,8 +134,8 @@ let AntTable = React.createClass({ } } if (typeof column.sorter === 'function') { - sorter = function () { - let result = column.sorter.apply(this, arguments); + sorter = function (...args) { + let result = column.sorter.apply(this, args); if (sortOrder === 'ascend') { return result; } else if (sortOrder === 'descend') { @@ -296,7 +296,7 @@ let AntTable = React.createClass({ return ( + value={rowIndex} checked={checked} /> ); }, @@ -315,7 +315,7 @@ let AntTable = React.createClass({ } return ( + onChange={this.handleSelect.bind(this, record, rowIndex)} /> ); }, @@ -408,7 +408,7 @@ let AntTable = React.createClass({ filterDropdown = ( + confirmFilter={this.handleFilter} /> ); } if (column.sorter) { @@ -427,12 +427,12 @@ let AntTable = React.createClass({ - + - + ); @@ -517,10 +517,7 @@ let AntTable = React.createClass({ // 否则进行读取分页数据 if (data.length > pageSize || pageSize === Number.MAX_VALUE) { data = data.filter((item, i) => { - if (i >= (current - 1) * pageSize && - i < current * pageSize) { - return item; - } + return i >= (current - 1) * pageSize && i < current * pageSize; }); } return data; @@ -575,7 +572,7 @@ let AntTable = React.createClass({ if (!data || data.length === 0) { emptyText = (
- {locale.emptyText} + {locale.emptyText}
); emptyClass = ' ant-table-empty'; @@ -587,6 +584,7 @@ let AntTable = React.createClass({ data={data} columns={columns} className={classString} + expandIconColumnIndex={columns[0].key === 'selection-column' ? 1 : 0} expandIconAsCell={expandIconAsCell} /> {emptyText} diff --git a/components/tabs/index.jsx b/components/tabs/index.jsx index 611c7159e0..e84e8c5fa8 100644 --- a/components/tabs/index.jsx +++ b/components/tabs/index.jsx @@ -29,7 +29,7 @@ class AntTabs extends React.Component { let { prefixCls, size, tabPosition, animation, type, children, tabBarExtraContent } = this.props; let className = classNames({ - [this.props.className]: !!this. props.className, + [this.props.className]: !!this.props.className, [`${prefixCls}-mini`]: size === 'small' || size === 'mini', [`${prefixCls}-vertical`]: tabPosition === 'left' || tabPosition === 'right', [`${prefixCls}-card`]: type.indexOf('card') >= 0, diff --git a/components/transfer/demo/advanced.md b/components/transfer/demo/advanced.md index 961d3c0f9e..219ba4df26 100644 --- a/components/transfer/demo/advanced.md +++ b/components/transfer/demo/advanced.md @@ -8,7 +8,6 @@ ````jsx import { Transfer, Button } from 'antd'; -const container = mountNode; const App = React.createClass({ getInitialState() { @@ -66,5 +65,5 @@ const App = React.createClass({ } }); -ReactDOM.render(, container); +ReactDOM.render(, mountNode); ```` diff --git a/components/transfer/index.jsx b/components/transfer/index.jsx index 6bb6fd2679..a2f8517ac8 100644 --- a/components/transfer/index.jsx +++ b/components/transfer/index.jsx @@ -33,6 +33,7 @@ class Transfer extends Component { leftDataSource.splice(index, 1); return true; } + return false; })[0]); }); } @@ -181,14 +182,14 @@ class Transfer extends Component { searchPlaceholder={searchPlaceholder} body={body} footer={footer} - prefixCls={`${prefixCls}-list`}/> + prefixCls={`${prefixCls}-list`} /> + className={`${prefixCls}-operation`} /> + prefixCls={`${prefixCls}-list`} /> ); } diff --git a/components/transfer/list.jsx b/components/transfer/list.jsx index bd8e9fde77..e7e9625162 100644 --- a/components/transfer/list.jsx +++ b/components/transfer/list.jsx @@ -81,21 +81,19 @@ class TransferList extends Component { [`${prefixCls}-with-footer`]: !!footerDom, }); - const showItems = dataSource.map((item) => { - // apply filter + const showItems = dataSource.filter((item) => { const itemText = this.props.render(item); const filterResult = this.matchFilter(itemText, filter); + return !!filterResult; + }).map((item) => { const renderedText = this.props.render(item); - - if (filterResult) { - return ( -
  • - key === item.key)} /> - {renderedText} -
  • - ); - } - }).filter(item => !!item); + return ( +
  • + key === item.key)} /> + {renderedText} +
  • + ); + }); return (
    @@ -104,7 +102,7 @@ class TransferList extends Component { prefixCls: 'ant-transfer', checked: checkStatus === 'all', checkPart: checkStatus === 'part', - checkable: + checkable: })}{(checkedKeys.length > 0 ? `${checkedKeys.length}/` : '') + dataSource.length} 条 {titleText}
    diff --git a/components/transfer/search.jsx b/components/transfer/search.jsx index 203e36ab88..b951f1613a 100644 --- a/components/transfer/search.jsx +++ b/components/transfer/search.jsx @@ -4,10 +4,6 @@ function noop() { } class Search extends Component { - constructor(props) { - super(props); - } - handleChange(e) { this.props.onChange(e); } @@ -22,7 +18,7 @@ class Search extends Component { return ( - + 示例 diff --git a/components/upload/index.jsx b/components/upload/index.jsx index 7104d8c274..e3079bf154 100644 --- a/components/upload/index.jsx +++ b/components/upload/index.jsx @@ -235,7 +235,7 @@ const AntUpload = React.createClass({ uploadList = ( + onRemove={this.handleManualRemove} /> ); } if (type === 'drag') { @@ -292,7 +292,7 @@ const AntUpload = React.createClass({ AntUpload.Dragger = React.createClass({ render() { - return ; + return ; } }); diff --git a/docs/react/getting-started.md b/docs/react/getting-started.md index ea7bd213f1..c386264d0e 100644 --- a/docs/react/getting-started.md +++ b/docs/react/getting-started.md @@ -102,7 +102,7 @@ Ant Design React 支持所有的现代浏览器和 IE8+。