From 35ef2b0b2d4d9b3ea0b179aff801d528c73e6c6a Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E7=84=B6=E5=88=99?= Date: Mon, 28 Dec 2015 19:16:02 +0800 Subject: [PATCH 01/19] add tree-select --- components/tree-select/demo/basic.md | 55 ++++++++++++++ components/tree-select/demo/enhance.md | 99 ++++++++++++++++++++++++++ components/tree-select/index.jsx | 57 +++++++++++++++ components/tree-select/index.md | 28 ++++++++ index.js | 1 + package.json | 3 +- 6 files changed, 242 insertions(+), 1 deletion(-) create mode 100644 components/tree-select/demo/basic.md create mode 100644 components/tree-select/demo/enhance.md create mode 100644 components/tree-select/index.jsx create mode 100644 components/tree-select/index.md diff --git a/components/tree-select/demo/basic.md b/components/tree-select/demo/basic.md new file mode 100644 index 0000000000..211f7b4cf8 --- /dev/null +++ b/components/tree-select/demo/basic.md @@ -0,0 +1,55 @@ +# 基本 + +- order: 0 + +最简单的用法。 + +--- + +````jsx +import { TreeSelect } from 'antd'; +const TreeNode = TreeSelect.TreeNode; + +const Demo = React.createClass({ + getInitialState() { + return { + value: '1', + }; + }, + onChange(e) { + let value; + if (e.target) { + value = e.target.value; + } else { + value = e; + } + this.setState({value}); + }, + render() { + return ( +
+

Single Select

+ + + + + + + + sss} /> + + + +
+ ); + }, +}); + +ReactDOM.render( + +, document.getElementById('components-tree-select-demo-basic')); +```` diff --git a/components/tree-select/demo/enhance.md b/components/tree-select/demo/enhance.md new file mode 100644 index 0000000000..f6a3096996 --- /dev/null +++ b/components/tree-select/demo/enhance.md @@ -0,0 +1,99 @@ +# 更多功能 + +- order: 1 + +更多功能。 + +--- + +````jsx +import { TreeSelect } from 'antd'; +const TreeNode = TreeSelect.TreeNode; + +const x = 5; +const y = 3; +const z = 2; +const gData = []; +const generateData = (_level, _preKey, _tns) => { + const preKey = _preKey || '0'; + const tns = _tns || gData; + + const children = []; + for (let i = 0; i < x; i++) { + const key = `${preKey}-${i}`; + tns.push({title: key, key: key}); + if (i < y) { + children.push(key); + } + } + if (_level < 0) { + return tns; + } + const __level = _level - 1; + children.forEach((key, index) => { + tns[index].children = []; + return generateData(__level, key, tns[index].children); + }); +}; +generateData(z); + +const Demo = React.createClass({ + getInitialState() { + return { + value: [], + }; + }, + onDeselect(selectedValue) { + console.log('onDeselect', selectedValue); + const newVal = [...this.state.value]; + newVal.splice(newVal.indexOf(selectedValue), 1); + this.setState({ + value: newVal, + }); + }, + onSelect(selectedKey, node, selectedKeys) { + console.log('selected: ', selectedKey, selectedKeys); + this.setState({ + value: selectedKeys, + }); + }, + onCheck(checkedKey, node, checkedKeys) { + console.log('onCheck:', checkedKey); + this.setState({ + value: checkedKeys, + }); + }, + render() { + const loop = data => { + return data.map((item) => { + if (item.children) { + return {loop(item.children)}; + } + return ; + }); + }; + const treeProps = { + showIcon: false, + showLine: true, + checkable: true, + defaultCheckedKeys: this.state.value, + defaultSelectedKeys: this.state.value, + // selectedKeys: this.state.value, + // checkedKeys: this.state.value, + // onCheck: this.onCheck, + }; + return (
+

more

+ + {loop(gData)} + +
); + }, +}); + +ReactDOM.render(
+ +
+, document.getElementById('components-tree-select-demo-enhance')); +```` diff --git a/components/tree-select/index.jsx b/components/tree-select/index.jsx new file mode 100644 index 0000000000..aea1760da6 --- /dev/null +++ b/components/tree-select/index.jsx @@ -0,0 +1,57 @@ +import React from 'react'; +import TreeSelect, { TreeNode } from 'rc-tree-select'; +import classNames from 'classnames'; +import assign from 'object-assign'; +import animation from '../common/openAnimation'; + +const AntTreeSelect = React.createClass({ + getDefaultProps() { + return { + prefixCls: 'ant-select', + transitionName: 'slide-up', + optionLabelProp: 'value', + choiceTransitionName: 'zoom', + showSearch: false, + size: 'default' + }; + }, + render() { + const props = this.props; + let { + size, className, combobox, notFoundContent + } = this.props; + + const cls = classNames({ + 'ant-select-lg': size === 'large', + 'ant-select-sm': size === 'small', + [className]: !!className, + }); + + if (combobox) { + notFoundContent = null; + } + + const treeProps = { + prefixCls: 'ant-tree', + checkable: false, + showIcon: false, + openAnimation: animation + }; + assign(treeProps, props.treeProps); + + let checkable = treeProps.checkable; + if (checkable) { + treeProps.checkable = ; + } + + return ( + + ); + } +}); + +AntTreeSelect.TreeNode = TreeNode; +export default AntTreeSelect; diff --git a/components/tree-select/index.md b/components/tree-select/index.md new file mode 100644 index 0000000000..3e4cf4e5e1 --- /dev/null +++ b/components/tree-select/index.md @@ -0,0 +1,28 @@ +# TreeSelect + +- category: Components +- chinese: 树选择控件 +- type: 表单 + +--- + +## 何时使用 + +当需要从树控件中灵活地筛选数据时 + +## API + +### Tree props + +| 参数 | 说明 | 类型 | 默认值 | +|-----------|------------------------------------------|------------|--------| +|multiple | 是否支持多选 | bool | false | +|[select-props](http://ant.design/components/select/#select-props) | the same as select props | || +|treeProps | 和tree props相同(除了onSelect、onCheck) | | [tree-props](http://ant.design/components/tree/#tree-props) | + +### TreeNode props + +| 参数 | 说明 | 类型 | 默认值 | +|-----------|------------------------------------------|------------|--------| +|value | default as optionFilterProp | String | 'value' | +|[treenode-props](http://ant.design/components/tree/#treenode-props) |和 treeNode props 相同||| diff --git a/index.js b/index.js index 0b5a8bbbbc..0b37921669 100644 --- a/index.js +++ b/index.js @@ -29,6 +29,7 @@ const antd = { Alert: require('./components/alert'), Validation: require('./components/validation'), Tree: require('./components/tree'), + TreeSelect: require('./components/tree-select'), Upload: require('./components/upload'), Badge: require('./components/badge'), Menu: require('./components/menu'), diff --git a/package.json b/package.json index e136f00b41..d81846da3c 100644 --- a/package.json +++ b/package.json @@ -60,7 +60,8 @@ "rc-tabs": "~5.5.0", "rc-time-picker": "~1.0.0", "rc-tooltip": "~3.3.0", - "rc-tree": "~0.19.0", + "rc-tree": "^0.21.2", + "rc-tree-select": "~0.2.1", "rc-trigger": "~1.0.6", "rc-upload": "~1.7.0", "rc-util": "~3.0.1", From fb111e585a504b29464a37d8ef342b95e2b64e85 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E7=84=B6=E5=88=99?= Date: Mon, 28 Dec 2015 19:19:02 +0800 Subject: [PATCH 02/19] fix demo --- components/tree-select/demo/basic.md | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/components/tree-select/demo/basic.md b/components/tree-select/demo/basic.md index 211f7b4cf8..01b94d91e2 100644 --- a/components/tree-select/demo/basic.md +++ b/components/tree-select/demo/basic.md @@ -37,10 +37,10 @@ const Demo = React.createClass({ - + - - sss} /> + + sss} key="random3" /> From edad25b8f656099dd178fcff5f68470668113ae3 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E7=84=B6=E5=88=99?= Date: Tue, 29 Dec 2015 15:33:09 +0800 Subject: [PATCH 03/19] up demo --- components/tree-select/demo/basic.md | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/components/tree-select/demo/basic.md b/components/tree-select/demo/basic.md index 01b94d91e2..e395225ae8 100644 --- a/components/tree-select/demo/basic.md +++ b/components/tree-select/demo/basic.md @@ -13,7 +13,7 @@ const TreeNode = TreeSelect.TreeNode; const Demo = React.createClass({ getInitialState() { return { - value: '1', + value: 'leaf1', }; }, onChange(e) { @@ -30,14 +30,14 @@ const Demo = React.createClass({

Single Select

- - + + sss} key="random3" /> From 0ee47a3538245ccf211fe533e22eb01c3e82c5ae Mon Sep 17 00:00:00 2001 From: Benjy Cui Date: Tue, 29 Dec 2015 17:34:42 +0800 Subject: [PATCH 04/19] bump 0.11.1 --- CHANGELOG.md | 6 +++--- package.json | 2 +- 2 files changed, 4 insertions(+), 4 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index f613f3d4fa..f5906507ed 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -4,12 +4,12 @@ --- -## 0.11.1 `developing` +## 0.11.1 `2015-12-29` - 修复一个 Table 无法修改 pageSize 的问题。 - 修复一个 Table 子表格展开的对齐问题。 -- 修复一个 chrome 下部分图标左侧切边的问题。 -- 修复搜索输入框在表单下使用的样式问题。 +- 修复一个 Chrome 下部分图标左侧切边的问题。 +- 修复搜索输入框在表单下使用的样式问题。[#762](https://github.com/ant-design/ant-design/issues/762) ## 0.11.0 `2015-12-28` diff --git a/package.json b/package.json index ebfc43593a..d77e834239 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "antd", - "version": "0.11.0", + "version": "0.11.1", "title": "Ant Design", "description": "一个 UI 设计语言", "homepage": "http://ant.design/", From 98b899d0cc12f402edf3ff6c34de6569ee4c6ebb Mon Sep 17 00:00:00 2001 From: afc163 Date: Tue, 29 Dec 2015 22:40:09 +0800 Subject: [PATCH 05/19] timePicker en-US, ref #771 --- components/date-picker/locale/en_US.js | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/components/date-picker/locale/en_US.js b/components/date-picker/locale/en_US.js index cb67d925d1..aff512e58b 100644 --- a/components/date-picker/locale/en_US.js +++ b/components/date-picker/locale/en_US.js @@ -5,7 +5,8 @@ import CalendarLocale from 'rc-calendar/lib/locale/en_US'; // 统一合并为完整的 Locale let locale = objectAssign({}, GregorianCalendarLocale); locale.lang = objectAssign({ - placeholder: 'Select a date' + placeholder: 'Select date', + timePlaceholder: 'Select time', }, CalendarLocale); // All settings at: From 6d4c4e12d133242964687495d963bbd25bc50689 Mon Sep 17 00:00:00 2001 From: afc163 Date: Tue, 29 Dec 2015 23:39:21 +0800 Subject: [PATCH 06/19] Add advanced search form demo --- components/form/demo/advanced-search-form.md | 121 +++++++++++++++++++ components/form/index.md | 6 + site/static/tomorrow.css | 2 + 3 files changed, 129 insertions(+) create mode 100644 components/form/demo/advanced-search-form.md diff --git a/components/form/demo/advanced-search-form.md b/components/form/demo/advanced-search-form.md new file mode 100644 index 0000000000..6836cd43ab --- /dev/null +++ b/components/form/demo/advanced-search-form.md @@ -0,0 +1,121 @@ +# 高级搜索 + +- order: 10 + +三列栅格式的表单排列方式,常用于数据表格的高级搜索。 + +有部分定制的样式代码,由于输入标签长度不确定,需要根据具体情况自行调整。 + +--- + +````jsx +import { Form, Input, Row, Col, Button } from 'antd'; +const FormItem = Form.Item; + +ReactDOM.render( +
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+, mountNode); +```` + +````css +/* 定制样式 */ + +.advanced-search-form { + padding: 16px 8px; + background: #FBFBFB; + border: 1px solid #d9d9d9; + border-radius: 6px; +} + +/* 由于输入标签长度不确定,所以需要微调使之看上去居中 */ +.advanced-search-form > .row { + margin-left: -10px; +} + +.advanced-search-form > .row > .col-8 { + padding: 0 8px; +} + +.advanced-search-form .ant-form-item { + margin-bottom: 16px; +} + +.advanced-search-form .ant-btn + .ant-btn { + margin-left: 8px; +} +```` + + diff --git a/components/form/index.md b/components/form/index.md index 8cbdab87d9..234713a52d 100644 --- a/components/form/index.md +++ b/components/form/index.md @@ -3,6 +3,7 @@ - category: Components - chinese: 表单 - type: 表单 +- cols: 1 --- @@ -86,3 +87,8 @@ Mixin:当表单控件的输入值改变时,更新 formData。 ``` + diff --git a/site/static/tomorrow.css b/site/static/tomorrow.css index 9026804c27..1c6cbceb88 100644 --- a/site/static/tomorrow.css +++ b/site/static/tomorrow.css @@ -41,6 +41,7 @@ code { color: #888; font-size: 90%; border: 1px solid #e9e9e9; + white-space: nowrap; } pre code { @@ -53,4 +54,5 @@ pre code { padding: 10px 15px; border-radius: 6px; font-size: 14px; + white-space: pre; } From e44faf9d4812f4a7c804c757739f2dd8a14c946b Mon Sep 17 00:00:00 2001 From: afc163 Date: Tue, 29 Dec 2015 23:43:10 +0800 Subject: [PATCH 07/19] fix demo style --- components/form/demo/advanced-search-form.md | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/components/form/demo/advanced-search-form.md b/components/form/demo/advanced-search-form.md index 6836cd43ab..2c2b58c686 100644 --- a/components/form/demo/advanced-search-form.md +++ b/components/form/demo/advanced-search-form.md @@ -91,7 +91,7 @@ ReactDOM.render( .advanced-search-form { padding: 16px 8px; - background: #FBFBFB; + background: #f8f8f8; border: 1px solid #d9d9d9; border-radius: 6px; } @@ -115,7 +115,7 @@ ReactDOM.render( ```` From 88a22815b8ac5f89c08adbf0c39d39e788abcf9c Mon Sep 17 00:00:00 2001 From: afc163 Date: Wed, 30 Dec 2015 01:12:15 +0800 Subject: [PATCH 08/19] update site code style --- site/static/style.css | 12 ++---------- site/static/tomorrow.css | 7 +++---- 2 files changed, 5 insertions(+), 14 deletions(-) diff --git a/site/static/style.css b/site/static/style.css index 9652398b59..1f7c4dfcc3 100644 --- a/site/static/style.css +++ b/site/static/style.css @@ -556,13 +556,6 @@ footer ul li > a { margin: 20px 0; } -.markdown code, -.markdown kbd, -.markdown pre, -.markdown samp { - font-family: Consolas, monospace; -} - .markdown p, .markdown pre { margin: 1.2em 0; @@ -590,14 +583,13 @@ footer ul li > a { } .markdown pre { - background: #F7F7F7; border-radius: 6px; } .markdown pre code { - background: #F7F7F7; border: none; - padding: 12px 20px; + padding: 1em 2em; + background: #f9f9f9; margin: 0; } diff --git a/site/static/tomorrow.css b/site/static/tomorrow.css index 1c6cbceb88..585bc4608a 100644 --- a/site/static/tomorrow.css +++ b/site/static/tomorrow.css @@ -35,11 +35,11 @@ } code { - background: #f6f6f6; + background: #f7f7f7; padding: 1px 6px; border-radius: 3px; color: #888; - font-size: 90%; + font-size: 0.8rem; border: 1px solid #e9e9e9; white-space: nowrap; } @@ -48,11 +48,10 @@ pre code { display: block; background: white; color: #666; - font-family: Consolas, monospace; line-height: 1.5; border: 1px solid #e9e9e9; padding: 10px 15px; border-radius: 6px; - font-size: 14px; + font-size: 0.9rem; white-space: pre; } From cf38545e2c0c1453e88943158a6d652f187f69ba Mon Sep 17 00:00:00 2001 From: afc163 Date: Wed, 30 Dec 2015 13:59:51 +0800 Subject: [PATCH 09/19] update react family version --- package.json | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/package.json b/package.json index d77e834239..fb87c352fe 100644 --- a/package.json +++ b/package.json @@ -99,10 +99,10 @@ "lodash": "^3.10.0", "nico-jsx": "~0.7.0", "pre-commit": "1.x", - "react": "~0.14.2", - "react-addons-test-utils": "~0.14.2", + "react": "~0.14.5", + "react-addons-test-utils": "~0.14.5", "react-copy-to-clipboard": "^3.0.4", - "react-dom": "~0.14.2", + "react-dom": "~0.14.5", "react-router": "~1.0.3", "react-stateless-wrapper": "~1.0.2", "reqwest": "~2.0.5", From 97993b3bed5ed706bab0cc162bf5a4af79504f07 Mon Sep 17 00:00:00 2001 From: afc163 Date: Wed, 30 Dec 2015 15:19:31 +0800 Subject: [PATCH 10/19] update jsfiddle examples --- docs/getting-started.md | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/docs/getting-started.md b/docs/getting-started.md index 44a2c7d95e..f1bf6ccde5 100644 --- a/docs/getting-started.md +++ b/docs/getting-started.md @@ -9,9 +9,9 @@ Ant Design React 致力于提供给程序员**愉悦**的开发体验。 ## 第一个例子 -最简单的试用方式参照以下 JSFiddle 演示, 也推荐 Fork 本例来进行 Bug Report, 注意不要在实际项目中这样使用。 +最简单的试用方式参照以下 JSFiddle 演示, 也推荐 Fork 本例来进行 `Bug Report`, 注意不要在实际项目中这样使用。 -- [antd JSFiddle](http://jsfiddle.net/yiminghe/9zrstuto/1/) +- [antd JSFiddle](http://jsfiddle.net/9zrstuto/70/) ## 标准开发 From 564c425ad70212032c1e9d665e612886baafea01 Mon Sep 17 00:00:00 2001 From: yiminghe Date: Tue, 29 Dec 2015 20:38:31 +0800 Subject: [PATCH 11/19] up deps --- package.json | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/package.json b/package.json index fb87c352fe..21840cef69 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "antd", - "version": "0.11.1", + "version": "0.12.0-alpha1", "title": "Ant Design", "description": "一个 UI 设计语言", "homepage": "http://ant.design/", @@ -56,7 +56,7 @@ "rc-steps": "~1.4.1", "rc-switch": "~1.3.1", "rc-table": "~3.7.1", - "rc-tabs": "~5.5.0", + "rc-tabs": "~5.6.0", "rc-time-picker": "~1.0.0", "rc-tooltip": "~3.3.0", "rc-tree": "~0.19.0", From 20ce55933ebf29ac57c7f31f4f808b942f2d3b0c Mon Sep 17 00:00:00 2001 From: afc163 Date: Tue, 29 Dec 2015 11:46:13 +0800 Subject: [PATCH 12/19] Add cascade --- components/cascader/demo/basic.md | 43 ++++++++++++ components/cascader/demo/custom-trigger.md | 53 ++++++++++++++ components/cascader/demo/hover.md | 49 +++++++++++++ components/cascader/index.jsx | 53 ++++++++++++++ components/cascader/index.md | 15 ++++ index.js | 1 + package.json | 2 + style/components/cascader.less | 80 ++++++++++++++++++++++ style/components/index.less | 1 + 9 files changed, 297 insertions(+) create mode 100644 components/cascader/demo/basic.md create mode 100644 components/cascader/demo/custom-trigger.md create mode 100644 components/cascader/demo/hover.md create mode 100644 components/cascader/index.jsx create mode 100644 components/cascader/index.md create mode 100644 style/components/cascader.less diff --git a/components/cascader/demo/basic.md b/components/cascader/demo/basic.md new file mode 100644 index 0000000000..fd2f89066c --- /dev/null +++ b/components/cascader/demo/basic.md @@ -0,0 +1,43 @@ +# 基本 + +- order: 0 + +省市级联。 + +--- + +````jsx +import { Cascader } from 'antd'; + +const options = [{ + value: 'zhejiang', + label: '浙江', + children: [{ + value: 'hangzhou', + label: '杭州', + children: [{ + value: 'xihu', + label: '西湖', + }], + }], +}, { + value: 'jiangsu', + label: '江苏', + children: [{ + value: 'nanjing', + label: '南京', + children: [{ + value: 'zhonghuamen', + label: '中华门', + }], + }], +}]; + +function onChange(value) { + console.log(value); +} + +ReactDOM.render( + +, mountNode); +```` diff --git a/components/cascader/demo/custom-trigger.md b/components/cascader/demo/custom-trigger.md new file mode 100644 index 0000000000..ddc07c01a1 --- /dev/null +++ b/components/cascader/demo/custom-trigger.md @@ -0,0 +1,53 @@ +# 可以自定义显示 + +- order: 1 + +切换按钮和结果分开。 + +--- + +````jsx +import { Cascader } from 'antd'; + +const options = [{ + value: 'zhejiang', + label: '浙江', + children: [{ + value: 'hangzhou', + label: '杭州', + }], +}, { + value: 'jiangsu', + label: '江苏', + children: [{ + value: 'nanjing', + label: '南京', + }], +}]; + +const CitySwitcher = React.createClass({ + getInitialState() { + return { + text: '未选择', + }; + }, + onChange(value, selectedOptions) { + this.setState({ + text: selectedOptions.map(o => o.label).join(', '), + }); + }, + render() { + return ( + + {this.state.text} +   + + 切换城市 + + + ); + }, +}); + +ReactDOM.render(, mountNode); +```` diff --git a/components/cascader/demo/hover.md b/components/cascader/demo/hover.md new file mode 100644 index 0000000000..f9e51caa30 --- /dev/null +++ b/components/cascader/demo/hover.md @@ -0,0 +1,49 @@ +# 移入展开 + +- order: 2 + +通过移入展开下级菜单,点击完成选择。 + +--- + +````jsx +import { Cascader } from 'antd'; + +const options = [{ + value: 'zhejiang', + label: '浙江', + children: [{ + value: 'hangzhou', + label: '杭州', + children: [{ + value: 'xihu', + label: '西湖', + }], + }], +}, { + value: 'jiangsu', + label: '江苏', + children: [{ + value: 'nanjing', + label: '南京', + children: [{ + value: 'zhonghuamen', + label: '中华门', + }], + }], +}]; + +function onChange(value) { + console.log(value); +} + +// 只展示最后一项 +function displayRender(label) { + return label[label.length - 1]; +} + +ReactDOM.render( + +, mountNode); +```` diff --git a/components/cascader/index.jsx b/components/cascader/index.jsx new file mode 100644 index 0000000000..369fc104cd --- /dev/null +++ b/components/cascader/index.jsx @@ -0,0 +1,53 @@ +import React from 'react'; +import Cascader from 'rc-cascader'; +import Input from '../input'; +import arrayTreeFilter from 'array-tree-filter'; + +class AntCascader extends React.Component { + constructor(props) { + super(props); + this.state = { + value: [], + }; + [ + 'handleChange', + 'getLabel', + ].forEach((method) => this[method] = this[method].bind(this)); + } + handleChange(value, selectedOptions) { + this.setState({ value }); + this.props.onChange(value, selectedOptions); + } + getLabel() { + const { options, displayRender } = this.props; + const label = arrayTreeFilter(options, (o, level) => o.value === this.state.value[level]) + .map(o => o.label); + return displayRender(label); + } + render() { + const { prefixCls, children, placeholder, style } = this.props; + return ( + + {children || + } + + ); + } +} + +AntCascader.defaultProps = { + prefixCls: 'ant-cascader', + placeholder: '请选择', + transitionName: 'slide-up', + onChange() {}, + options: [], + displayRender(label) { + return label.join(' / '); + }, +}; + +export default AntCascader; diff --git a/components/cascader/index.md b/components/cascader/index.md new file mode 100644 index 0000000000..bab13eff65 --- /dev/null +++ b/components/cascader/index.md @@ -0,0 +1,15 @@ +# Cascader + +- category: Components +- chinese: 级联选择 +- type: 表单 + +--- + +级联选择框。 + +## 何时使用 + + +## API + diff --git a/index.js b/index.js index 0b5a8bbbbc..0e61e43f2c 100644 --- a/index.js +++ b/index.js @@ -43,6 +43,7 @@ const antd = { Calendar: require('./components/calendar'), TimePicker: require('./components/time-picker'), Transfer: require('./components/transfer'), + Cascader: require('./components/cascader'), }; antd.version = require('./package.json').version; diff --git a/package.json b/package.json index 21840cef69..a7e5f16409 100644 --- a/package.json +++ b/package.json @@ -32,6 +32,7 @@ ], "license": "MIT", "dependencies": { + "array-tree-filter": "~1.0.0", "classnames": "~2.2.0", "css-animation": "1.1.x", "gregorian-calendar": "~4.1.0", @@ -39,6 +40,7 @@ "object-assign": "~4.0.1", "rc-animate": "~2.0.2", "rc-calendar": "~5.2.0", + "rc-cascader": "~0.3.0", "rc-checkbox": "~1.1.1", "rc-collapse": "~1.4.4", "rc-dialog": "~5.2.2", diff --git a/style/components/cascader.less b/style/components/cascader.less new file mode 100644 index 0000000000..e79f6089f7 --- /dev/null +++ b/style/components/cascader.less @@ -0,0 +1,80 @@ +.ant-cascader { + font-size: @font-size-base; + &-input { + width: 172px; + display: block; + } + &-menus { + font-size: 12px; + overflow: hidden; + background: #fff; + position: absolute; + border: 1px solid @border-color-base; + border-radius: @border-radius-base; + box-shadow: @box-shadow-base; + &-hidden { + display: none; + } + &.slide-up-enter.slide-up-enter-active&-placement-bottomLeft, + &.slide-up-appear.slide-up-appear-active&-placement-bottomLeft { + animation-name: antSlideUpIn; + } + + &.slide-up-enter.slide-up-enter-active&-placement-topLeft, + &.slide-up-appear.slide-up-appear-active&-placement-topLeft { + animation-name: antSlideDownIn; + } + + &.slide-up-leave.slide-up-leave-active&-placement-bottomLeft { + animation-name: antSlideUpOut; + } + + &.slide-up-leave.slide-up-leave-active&-placement-topLeft { + animation-name: antSlideDownOut; + } + } + &-menu { + float: left; + width: 111px; + height: 180px; + list-style: none; + margin: 0; + padding: 0; + border-right: 1px solid @border-color-split; + &:last-child { + border-right-color: transparent; + margin-right: -1px; + } + } + &-menu-item { + height: 32px; + line-height: 32px; + padding: 0 16px; + cursor: pointer; + white-space: nowrap; + overflow: hidden; + text-overflow: ellipsis; + transition: all 0.3s ease; + &:hover { + background: tint(@primary-color, 90%); + } + &-active { + background: tint(@primary-color, 80%); + &:hover { + background: tint(@primary-color, 80%); + } + } + &-expand { + position: relative; + &:after { + content: '\e600'; + font-family: 'anticon'; + .iconfont-size-under-12px(8px); + color: #999; + position: absolute; + right: 15px; + line-height: 32px; + } + } + } +} diff --git a/style/components/index.less b/style/components/index.less index 0048394171..ed1ad82834 100644 --- a/style/components/index.less +++ b/style/components/index.less @@ -38,3 +38,4 @@ @import "calendar"; @import "timepicker"; @import "transfer"; +@import "cascader"; From a1743d7e58015264023fe7fe4c1ee0adce4d0504 Mon Sep 17 00:00:00 2001 From: afc163 Date: Tue, 29 Dec 2015 18:24:21 +0800 Subject: [PATCH 13/19] update cascader document --- components/cascader/demo/basic.md | 2 +- components/cascader/index.md | 17 +++++++++++++++++ components/select/demo/coordinate.md | 2 ++ 3 files changed, 20 insertions(+), 1 deletion(-) diff --git a/components/cascader/demo/basic.md b/components/cascader/demo/basic.md index fd2f89066c..445f039f4f 100644 --- a/components/cascader/demo/basic.md +++ b/components/cascader/demo/basic.md @@ -2,7 +2,7 @@ - order: 0 -省市级联。 +省市区级联。 --- diff --git a/components/cascader/index.md b/components/cascader/index.md index bab13eff65..91648eb24a 100644 --- a/components/cascader/index.md +++ b/components/cascader/index.md @@ -8,8 +8,25 @@ 级联选择框。 + ## 何时使用 +- 需要从一组相关联的数据集合进行选择,例如省市区,公司层级,事物分类等。 +- 从一个较大的数据集合中进行选择时,用多级分类进行分隔,方便选择。 +- 比起 Select 组件,可以在同一个浮层中完成选择,有较好的体验。 ## API +```html + +``` + +| 参数 | 说明 | 类型 | 默认值 | +|------|------|------|--------| +| options | 可选项数据源 | object | - | +| defaultValue | 默认的选中项 | array |[] | +| value | 指定选中项 | array | - | +| onChange | 选择完成后的回调 | `function(value, selectedOptions)` | - | +| displayRender | 选择后展示的渲染函数 | `function(label)`` | `function(label) { return label.join(' / ') }` | +| style | 自定义样式 | string | - | +| popupClassName | 自定义浮层类名 | string | - | diff --git a/components/select/demo/coordinate.md b/components/select/demo/coordinate.md index 07b9e5224f..cfe89f6525 100644 --- a/components/select/demo/coordinate.md +++ b/components/select/demo/coordinate.md @@ -4,6 +4,8 @@ 省市联动是典型的例子。 +推荐使用 [cascader](/components/cascader/) 组件。 + --- ````jsx From fcba79f070233b7ec01fbc242f0c7af689855318 Mon Sep 17 00:00:00 2001 From: afc163 Date: Tue, 29 Dec 2015 18:27:46 +0800 Subject: [PATCH 14/19] update cascader api --- components/cascader/index.md | 1 + 1 file changed, 1 insertion(+) diff --git a/components/cascader/index.md b/components/cascader/index.md index 91648eb24a..92c76c37cc 100644 --- a/components/cascader/index.md +++ b/components/cascader/index.md @@ -30,3 +30,4 @@ | displayRender | 选择后展示的渲染函数 | `function(label)`` | `function(label) { return label.join(' / ') }` | | style | 自定义样式 | string | - | | popupClassName | 自定义浮层类名 | string | - | +| placeholder | 输入框占位文本 | string | '请选择' | From 5f0aecfd5e1b86194aa3d744ad4ae61ab30c9a78 Mon Sep 17 00:00:00 2001 From: afc163 Date: Tue, 29 Dec 2015 18:31:48 +0800 Subject: [PATCH 15/19] Add prop size for cascader --- components/cascader/index.jsx | 10 ++++++++-- components/cascader/index.md | 1 + 2 files changed, 9 insertions(+), 2 deletions(-) diff --git a/components/cascader/index.jsx b/components/cascader/index.jsx index 369fc104cd..775631031a 100644 --- a/components/cascader/index.jsx +++ b/components/cascader/index.jsx @@ -2,6 +2,7 @@ import React from 'react'; import Cascader from 'rc-cascader'; import Input from '../input'; import arrayTreeFilter from 'array-tree-filter'; +import classNames from 'classnames'; class AntCascader extends React.Component { constructor(props) { @@ -25,12 +26,16 @@ class AntCascader extends React.Component { return displayRender(label); } render() { - const { prefixCls, children, placeholder, style } = this.props; + const { prefixCls, children, placeholder, style, size } = this.props; + const sizeCls = classNames({ + 'ant-input-lg': size === 'large', + 'ant-input-sm': size === 'small', + }); return ( {children || } @@ -48,6 +53,7 @@ AntCascader.defaultProps = { displayRender(label) { return label.join(' / '); }, + size: 'default', }; export default AntCascader; diff --git a/components/cascader/index.md b/components/cascader/index.md index 92c76c37cc..4d9ce58c3f 100644 --- a/components/cascader/index.md +++ b/components/cascader/index.md @@ -31,3 +31,4 @@ | style | 自定义样式 | string | - | | popupClassName | 自定义浮层类名 | string | - | | placeholder | 输入框占位文本 | string | '请选择' | +| size | 输入框大小,可选 `large` `default` `small` | string | `default` | From aa27737d24eb169e3a2bcbe78f574e20cc2cc26f Mon Sep 17 00:00:00 2001 From: afc163 Date: Tue, 29 Dec 2015 21:18:27 +0800 Subject: [PATCH 16/19] Add clear icon --- components/cascader/demo/default-value.md | 43 ++++++++++++++++++ components/cascader/index.jsx | 53 +++++++++++++++++++---- package.json | 2 +- style/components/cascader.less | 26 +++++++++++ 4 files changed, 115 insertions(+), 9 deletions(-) create mode 100644 components/cascader/demo/default-value.md diff --git a/components/cascader/demo/default-value.md b/components/cascader/demo/default-value.md new file mode 100644 index 0000000000..db4ea4eee0 --- /dev/null +++ b/components/cascader/demo/default-value.md @@ -0,0 +1,43 @@ +# 默认值 + +- order: 0 + +默认值通过数组的方式指定。 + +--- + +````jsx +import { Cascader } from 'antd'; + +const options = [{ + value: 'zhejiang', + label: '浙江', + children: [{ + value: 'hangzhou', + label: '杭州', + children: [{ + value: 'xihu', + label: '西湖', + }], + }], +}, { + value: 'jiangsu', + label: '江苏', + children: [{ + value: 'nanjing', + label: '南京', + children: [{ + value: 'zhonghuamen', + label: '中华门', + }], + }], +}]; + +function onChange(value) { + console.log(value); +} + +ReactDOM.render( + +, mountNode); +```` diff --git a/components/cascader/index.jsx b/components/cascader/index.jsx index 775631031a..d68271a104 100644 --- a/components/cascader/index.jsx +++ b/components/cascader/index.jsx @@ -1,6 +1,7 @@ import React from 'react'; import Cascader from 'rc-cascader'; import Input from '../input'; +import Icon from '../icon'; import arrayTreeFilter from 'array-tree-filter'; import classNames from 'classnames'; @@ -8,15 +9,33 @@ class AntCascader extends React.Component { constructor(props) { super(props); this.state = { - value: [], + value: props.value || props.defaultValue || [], + popupVisible: false, }; [ 'handleChange', + 'handlePopupVisibleChange', + 'setValue', 'getLabel', + 'clearSelection', ].forEach((method) => this[method] = this[method].bind(this)); } + componentWillReceiveProps(nextProps) { + if ('value' in nextProps) { + this.setState({ value: nextProps.value }); + } + } handleChange(value, selectedOptions) { - this.setState({ value }); + this.setValue(value, selectedOptions); + } + handlePopupVisibleChange(popupVisible) { + this.setState({ popupVisible }); + this.props.onPopupVisibleChange(popupVisible); + } + setValue(value, selectedOptions = []) { + if (!('value' in this.props)) { + this.setState({ value }); + } this.props.onChange(value, selectedOptions); } getLabel() { @@ -25,20 +44,37 @@ class AntCascader extends React.Component { .map(o => o.label); return displayRender(label); } + clearSelection(e) { + e.preventDefault(); + this.setValue([]); + this.setState({ popupVisible: false }); + } render() { const { prefixCls, children, placeholder, style, size } = this.props; const sizeCls = classNames({ 'ant-input-lg': size === 'large', 'ant-input-sm': size === 'small', }); + const clearIcon = this.state.value.length > 0 ? + : null; return ( - + {children || - } + + + {clearIcon} + + } ); } @@ -54,6 +90,7 @@ AntCascader.defaultProps = { return label.join(' / '); }, size: 'default', + onPopupVisibleChange() {}, }; export default AntCascader; diff --git a/package.json b/package.json index a7e5f16409..3188130e81 100644 --- a/package.json +++ b/package.json @@ -40,7 +40,7 @@ "object-assign": "~4.0.1", "rc-animate": "~2.0.2", "rc-calendar": "~5.2.0", - "rc-cascader": "~0.3.0", + "rc-cascader": "~0.4.0", "rc-checkbox": "~1.1.1", "rc-collapse": "~1.4.4", "rc-dialog": "~5.2.2", diff --git a/style/components/cascader.less b/style/components/cascader.less index e79f6089f7..e2063faba6 100644 --- a/style/components/cascader.less +++ b/style/components/cascader.less @@ -4,6 +4,32 @@ width: 172px; display: block; } + &-picker { + position: relative; + display: inline-block; + &-clear { + opacity: 0; + visibility: hidden; + position: absolute; + right: 8px; + top: 50%; + font-size: 12px; + color: #ccc; + width: 12px; + height: 12px; + margin-top: -6px; + line-height: 12px; + cursor: pointer; + transition: color 0.3s ease, opacity 0.15s ease; + &:hover { + color: #999; + } + } + &:hover &-clear { + opacity: 1; + visibility: visible; + } + } &-menus { font-size: 12px; overflow: hidden; From 7051b2c78681bc3fec5ed542e2d1199e0553875c Mon Sep 17 00:00:00 2001 From: afc163 Date: Tue, 29 Dec 2015 22:34:23 +0800 Subject: [PATCH 17/19] Add arrow style --- components/cascader/index.jsx | 6 ++++++ style/components/cascader.less | 33 ++++++++++++++++++++++++++++++--- 2 files changed, 36 insertions(+), 3 deletions(-) diff --git a/components/cascader/index.jsx b/components/cascader/index.jsx index d68271a104..448766707a 100644 --- a/components/cascader/index.jsx +++ b/components/cascader/index.jsx @@ -46,6 +46,7 @@ class AntCascader extends React.Component { } clearSelection(e) { e.preventDefault(); + e.stopPropagation(); this.setValue([]); this.setState({ popupVisible: false }); } @@ -59,6 +60,10 @@ class AntCascader extends React.Component { : null; + const arrowCls = classNames({ + [`${prefixCls}-picker-arrow`]: true, + [`${prefixCls}-picker-arrow-expand`]: this.state.popupVisible, + }); return ( {clearIcon} + } diff --git a/style/components/cascader.less b/style/components/cascader.less index e2063faba6..dfc2b9d7b9 100644 --- a/style/components/cascader.less +++ b/style/components/cascader.less @@ -1,17 +1,23 @@ -.ant-cascader { +@cascader-prefix-cls: ant-cascader; + +.@{cascader-prefix-cls} { font-size: @font-size-base; &-input { width: 172px; display: block; + cursor: pointer; } &-picker { position: relative; display: inline-block; + cursor: pointer; + &-clear { opacity: 0; - visibility: hidden; position: absolute; right: 8px; + z-index: 1; + background: #fff; top: 50%; font-size: 12px; color: #ccc; @@ -25,9 +31,30 @@ color: #999; } } + &:hover &-clear { opacity: 1; - visibility: visible; + } + + // arrow + &-arrow { + position: absolute; + top: 50%; + right: 8px; + width: 12px; + height: 12px; + margin-top: -6px; + line-height: 12px; + .iconfont-size-under-12px(8px); + &:before { + transition: transform 0.2s ease; + } + &&-expand { + .ie-rotate(2); + &:before { + .rotate(180deg); + } + } } } &-menus { From 122f969462b26323d51765f520e166c91629a252 Mon Sep 17 00:00:00 2001 From: afc163 Date: Wed, 30 Dec 2015 14:21:15 +0800 Subject: [PATCH 18/19] upgrade rc-cascader version --- package.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/package.json b/package.json index 3188130e81..4daf8a7a7d 100644 --- a/package.json +++ b/package.json @@ -40,7 +40,7 @@ "object-assign": "~4.0.1", "rc-animate": "~2.0.2", "rc-calendar": "~5.2.0", - "rc-cascader": "~0.4.0", + "rc-cascader": "~0.5.0", "rc-checkbox": "~1.1.1", "rc-collapse": "~1.4.4", "rc-dialog": "~5.2.2", From f40d5ff36b53493d9422645b90c76d9a7d007b2e Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E7=84=B6=E5=88=99?= Date: Thu, 31 Dec 2015 14:38:35 +0800 Subject: [PATCH 19/19] big change --- components/tree-select/demo/basic.md | 2 +- components/tree-select/demo/enhance.md | 42 +- components/tree-select/index.jsx | 20 +- components/tree-select/index.md | 31 +- package.json | 4 +- style/components/index.less | 1 + style/components/treeSelect.less | 580 +++++++++++++++++++++++++ 7 files changed, 632 insertions(+), 48 deletions(-) create mode 100644 style/components/treeSelect.less diff --git a/components/tree-select/demo/basic.md b/components/tree-select/demo/basic.md index e395225ae8..4562aade6f 100644 --- a/components/tree-select/demo/basic.md +++ b/components/tree-select/demo/basic.md @@ -32,7 +32,7 @@ const Demo = React.createClass({ diff --git a/components/tree-select/demo/enhance.md b/components/tree-select/demo/enhance.md index f6a3096996..cd6e59543a 100644 --- a/components/tree-select/demo/enhance.md +++ b/components/tree-select/demo/enhance.md @@ -10,9 +10,9 @@ import { TreeSelect } from 'antd'; const TreeNode = TreeSelect.TreeNode; -const x = 5; -const y = 3; -const z = 2; +const x = 3; +const y = 2; +const z = 1; const gData = []; const generateData = (_level, _preKey, _tns) => { const preKey = _preKey || '0'; @@ -40,27 +40,19 @@ generateData(z); const Demo = React.createClass({ getInitialState() { return { - value: [], + value: ['0-0'], }; }, - onDeselect(selectedValue) { - console.log('onDeselect', selectedValue); - const newVal = [...this.state.value]; - newVal.splice(newVal.indexOf(selectedValue), 1); - this.setState({ - value: newVal, - }); - }, onSelect(selectedKey, node, selectedKeys) { console.log('selected: ', selectedKey, selectedKeys); this.setState({ value: selectedKeys, }); }, - onCheck(checkedKey, node, checkedKeys) { - console.log('onCheck:', checkedKey); + onChange(value) { + console.log('selected ' + value); this.setState({ - value: checkedKeys, + value: value, }); }, render() { @@ -72,20 +64,18 @@ const Demo = React.createClass({ return ; }); }; - const treeProps = { - showIcon: false, - showLine: true, - checkable: true, - defaultCheckedKeys: this.state.value, - defaultSelectedKeys: this.state.value, - // selectedKeys: this.state.value, - // checkedKeys: this.state.value, - // onCheck: this.onCheck, + const tProps = { + // defaultValue: this.state.value, + value: this.state.value, + onChange: this.onChange, + onSelect: this.onSelect, + multiple: true, + // treeCheckable: true, + treeDefaultExpandAll: true, }; return (

more

- + {loop(gData)}
); diff --git a/components/tree-select/index.jsx b/components/tree-select/index.jsx index aea1760da6..56e1d5ccc0 100644 --- a/components/tree-select/index.jsx +++ b/components/tree-select/index.jsx @@ -1,13 +1,13 @@ import React from 'react'; import TreeSelect, { TreeNode } from 'rc-tree-select'; import classNames from 'classnames'; -import assign from 'object-assign'; -import animation from '../common/openAnimation'; +// import assign from 'object-assign'; +// import animation from '../common/openAnimation'; const AntTreeSelect = React.createClass({ getDefaultProps() { return { - prefixCls: 'ant-select', + prefixCls: 'ant-tree-select', transitionName: 'slide-up', optionLabelProp: 'value', choiceTransitionName: 'zoom', @@ -31,22 +31,14 @@ const AntTreeSelect = React.createClass({ notFoundContent = null; } - const treeProps = { - prefixCls: 'ant-tree', - checkable: false, - showIcon: false, - openAnimation: animation - }; - assign(treeProps, props.treeProps); - - let checkable = treeProps.checkable; + let checkable = props.treeCheckable; if (checkable) { - treeProps.checkable = ; + checkable = ; } return ( ); diff --git a/components/tree-select/index.md b/components/tree-select/index.md index 3e4cf4e5e1..8f389fc216 100644 --- a/components/tree-select/index.md +++ b/components/tree-select/index.md @@ -16,13 +16,34 @@ | 参数 | 说明 | 类型 | 默认值 | |-----------|------------------------------------------|------------|--------| -|multiple | 是否支持多选 | bool | false | -|[select-props](http://ant.design/components/select/#select-props) | the same as select props | || -|treeProps | 和tree props相同(除了onSelect、onCheck) | | [tree-props](http://ant.design/components/tree/#tree-props) | +| value | 指定当前选中的条目 | string/Array | 无 | +| defaultValue | 指定默认选中的条目 | string/Array | 无 | +| multiple | 支持多选 | boolean | false | +| tags | 可以把随意输入的条目作为 tag,输入项不需要与下拉选项匹配 | boolean |false | +| onSelect | 被选中时调用,参数为选中项的 value 值 | function(value, option) | 无 | +| onChange | 选中option,或input的value变化(combobox 模式下)时,调用此函数 | function(value, label) | 无 | +| allowClear | 显示清除按钮 | boolean | false | +| onSearch | 文本框值变化时回调 | function(value: String) | | +| placeholder | 选择框默认文字 | string | 无 | +| searchPlaceholder | 搜索框默认文字 | string | 无 | +| dropdownMatchSelectWidth | 下拉菜单和选择器同宽 | boolean | true | +| combobox | 输入框自动提示模式 | boolean | false | +| size | 选择框大小,可选 `large` `small` | String | default | +| showSearch | 在下拉中显示搜索框 | boolean | false | +| disabled | 是否禁用 | boolean | false | +| treeDefaultExpandAll | 默认展开所有树节点 | bool | false | +| treeCheckable | 显示checkbox | bool | false | +| filterTreeNode | 是否根据输入项进行筛选,返回值true | function(treeNode) | - | +| treeNodeFilterProp | 输入项过滤对应的 treeNode 属性 | String | 'value' | +| treeNodeLabelProp | 作为显示的prop设置 | String | 'value' | +| loadData | 异步加载数据 | function(node) | - | ### TreeNode props | 参数 | 说明 | 类型 | 默认值 | |-----------|------------------------------------------|------------|--------| -|value | default as optionFilterProp | String | 'value' | -|[treenode-props](http://ant.design/components/tree/#treenode-props) |和 treeNode props 相同||| +| disabled | 是否禁用 | Boolean | false | +| key | 此项必须设置 | String | | +| value | 默认根据此属性值进行筛选 | String | - | +| title | 树节点显示的内容 | String | '---' | +| isLeaf | 是否是叶子节点 | bool | false | diff --git a/package.json b/package.json index d81846da3c..51d55791fa 100644 --- a/package.json +++ b/package.json @@ -60,8 +60,8 @@ "rc-tabs": "~5.5.0", "rc-time-picker": "~1.0.0", "rc-tooltip": "~3.3.0", - "rc-tree": "^0.21.2", - "rc-tree-select": "~0.2.1", + "rc-tree": "^0.23.1", + "rc-tree-select": "^0.3.3", "rc-trigger": "~1.0.6", "rc-upload": "~1.7.0", "rc-util": "~3.0.1", diff --git a/style/components/index.less b/style/components/index.less index 0048394171..fb3d57d20b 100644 --- a/style/components/index.less +++ b/style/components/index.less @@ -27,6 +27,7 @@ @import "tag"; @import "alert"; @import "tree"; +@import "treeSelect"; @import "carousel/slick"; @import "carousel/slick-theme"; @import "upload"; diff --git a/style/components/treeSelect.less b/style/components/treeSelect.less new file mode 100644 index 0000000000..6bf36e14f3 --- /dev/null +++ b/style/components/treeSelect.less @@ -0,0 +1,580 @@ +@tree-select-tree-prefix-cls: ant-tree-select-tree; +.antCheckboxFn(@checkbox-prefix-cls: ant-tree-select-tree-checkbox); +@import "../mixins/iconfont"; +.antTreeSwitcherIcon() { + position: relative; + &:after { + .iconfont-size-under-12px(6px); + content: '\e611'; + display: inline-block; + font-family: 'anticon'; + font-weight: bold; + position: absolute; + top: 10px; + right: 4px; + color: #666; + transition: transform .3s ease; + } +} +.@{tree-select-tree-prefix-cls} { + margin: 0; + padding: 5px; + font-size: 12px; + li { + padding: 0; + margin: 0; + list-style: none; + white-space: nowrap; + outline: 0; + ul { + margin: 0; + padding: 0 0 0 18px; + } + a { + display: inline-block; + padding: 1px 4px; + border-radius: 2px; + margin: 0; + cursor: pointer; + height: 20px; + text-decoration: none; + vertical-align: top; + color: #666; + } + span { + &.@{tree-select-tree-prefix-cls}-checkbox { + margin: 3px 4px 0 0; + } + &.@{tree-select-tree-prefix-cls}-switcher-noop, + &.@{tree-select-tree-prefix-cls}-switcher, + &.@{tree-select-tree-prefix-cls}-iconEle { + line-height: 0; + margin: 0; + width: 16px; + height: 18px; + display: inline-block; + vertical-align: middle; + border: 0 none; + cursor: pointer; + outline: none; + } + &.@{tree-select-tree-prefix-cls}-icon_loading { + &:after { + content: '\e6a1'; + display: inline-block; + font-family: 'anticon'; + font-weight: bold; + .animation(loadingCircle 1s infinite linear); + margin-top: 8px; + } + } + &.@{tree-select-tree-prefix-cls}-switcher { + &-disabled { + background: #fff; + position: relative; + &:after { + content: '-'; + position: absolute; + top: 8px; + left: 6px; + color: gray; + } + } + &.@{tree-select-tree-prefix-cls}-roots_open, + &.@{tree-select-tree-prefix-cls}-center_open, + &.@{tree-select-tree-prefix-cls}-bottom_open, + &.@{tree-select-tree-prefix-cls}-noline_open { + .antTreeSwitcherIcon(); + } + &.@{tree-select-tree-prefix-cls}-roots_close, + &.@{tree-select-tree-prefix-cls}-center_close, + &.@{tree-select-tree-prefix-cls}-bottom_close, + &.@{tree-select-tree-prefix-cls}-noline_close { + .antTreeSwitcherIcon(); + .ie-rotate(3); + &:after { + transform: rotate(270deg) scale(0.5); + } + } + } + } + } + &-child-tree { + display: none; + &-open { + display: block; + } + } + &-treenode-disabled { + >span, + >a { + color: gray; + } + } + &-node-selected { + background-color: tint(@primary-color, 90%); + } + &-icon__open { + margin-right: 2px; + vertical-align: top; + } + &-icon__close { + margin-right: 2px; + vertical-align: top; + } +} + + +@tree-select-prefix-cls: ant-tree-select; + +@duration: .3s; + +@import "../mixins/iconfont"; +//mixin +.selection__clear() { + cursor: pointer; + float: right; + font-weight: bold; +} + +.@{tree-select-prefix-cls} { + box-sizing: border-box; + display: inline-block; + margin: 0; + position: relative; + vertical-align: middle; + color: #666; + font-size: @font-size-base; + + > ul > li > a { + padding: 0; + background-color: #fff; + } + + // arrow + &-arrow { + .iconfont-mixin(); + position: absolute; + top: 50%; + right: 8px; + line-height: 1; + margin-top: -5px; + .iconfont-size-under-12px(8px); + + * { + display: none; + } + + &:before { + content: '\e603'; + transition: transform 0.2s ease; + } + } + + &-selection { + outline: none; + user-select: none; + + box-sizing: border-box; + display: block; + + background-color: #fff; + border-radius: @border-radius-base; + border: 1px solid #d9d9d9; + .transition(all .3s @ease-in-out); + + &:hover { + .hover; + } + &:active { + .active; + } + } + + &-disabled { + color: #ccc; + } + + &-disabled &-selection { + &:hover, + &:active { + border-color: #d9d9d9; + } + } + + &-disabled &-selection--single { + cursor: not-allowed; + } + + &-selection--single { + height: 28px; + cursor: pointer; + + .@{tree-select-prefix-cls}-selection__rendered { + display: block; + overflow: hidden; + text-overflow: ellipsis; + white-space: nowrap; + padding-left: 8px; + padding-right: 24px; + line-height: 26px; + } + + .@{tree-select-prefix-cls}-selection__clear { + .selection__clear(); + } + + .@{tree-select-prefix-cls}-selection__placeholder { + color: #ccc; + } + } + + &-lg { + .ant-select-selection--single { + height: 32px; + .ant-select-selection__rendered { + line-height: 30px; + } + } + + .ant-select-selection--multiple { + min-height: 32px; + .ant-select-selection__rendered { + li { + height: 24px; + .ant-select-selection__choice__content { + font-size: 14px; + line-height: 24px; + } + } + } + } + } + + &-sm { + .ant-select-selection--single { + height: 22px; + .ant-select-selection__rendered { + line-height: 20px; + } + } + .ant-select-selection--multiple { + min-height: 22px; + .ant-select-selection__rendered { + li { + height: 14px; + .ant-select-selection__choice__content { + line-height: 14px; + position: relative; + top: -3px; + } + .ant-select-selection__choice__remove { + position: relative; + top: -4px; + } + } + } + } + } + + &-disabled &-selection__choice__remove { + color: #ccc; + cursor: default; + &:hover { + color: #ccc; + } + } + + &-search__field__wrap { + display: inline-block; + position: relative; + } + + &-search__field__placeholder { + position: absolute; + top: 0; + left: 3px; + color: #aaa; + } + + &-search--inline { + float: left; + + .@{tree-select-prefix-cls}-search__field__wrap { + width: 100%; + } + + .@{tree-select-prefix-cls}-search__field { + border: 0; + font-size: 100%; + background: transparent; + outline: 0; + } + > i { + float: right; + } + } + + &-selection--multiple { + min-height: 28px; + cursor: text; + + .@{tree-select-prefix-cls}-search__field__placeholder { + top: 6px; + left: 10px; + } + + .@{tree-select-prefix-cls}-search--inline { + width: auto; + .@{tree-select-prefix-cls}-search__field { + width: 0.75em; + } + } + + .@{tree-select-prefix-cls}-selection__rendered { + overflow: hidden; + text-overflow: ellipsis; + padding-left: 6px; + padding-bottom: 4px; + } + + .@{tree-select-prefix-cls}-selection__clear { + .selection__clear(); + margin-top: 5px; + margin-right: 10px; + } + + > ul > li { + margin-top: 4px; + height: 20px; + line-height: 20px; + } + + .@{tree-select-prefix-cls}-selection__choice { + background-color: #f3f3f3; + border-radius: 4px; + cursor: default; + float: left; + padding: 0 15px; + margin-right: 4px; + max-width: 99%; + position: relative; + overflow: hidden; + transition: padding @duration @ease-in-out; + padding: 0 20px 0 10px; + } + + .@{tree-select-prefix-cls}-selection__choice__content { + display: inline-block; + white-space: nowrap; + overflow: hidden; + text-overflow: ellipsis; + max-width: 100%; + transition: margin @duration @ease-in-out; + } + + .@{tree-select-prefix-cls}-selection__choice__remove { + .iconfont-mixin(); + color: #999; + line-height: 20px; + cursor: pointer; + display: inline-block; + font-weight: bold; + transition: all 0.3s @ease-in-out; + .iconfont-size-under-12px(8px); + position: absolute; + right: 4px; + padding: 0 0 0 8px; + &:hover { + color: #404040; + } + &:before { + content: "\e62d"; + } + } + } + + &-open { + .@{tree-select-prefix-cls}-arrow { + .ie-rotate(2); + -ms-transform: rotate(180deg); + &:before { + .rotate(180deg); + } + } + .@{tree-select-prefix-cls}-selection { + .active(); + } + } + + &-combobox { + .@{tree-select-prefix-cls}-arrow { + display: none; + } + .@{tree-select-prefix-cls}-search--inline { + height: 100%; + float: none; + } + .@{tree-select-prefix-cls}-search__field__placeholder { + left: 10px; + cursor: text; + } + .@{tree-select-prefix-cls}-search__field__wrap { + width: 100%; + height: 100%; + } + .@{tree-select-prefix-cls}-search__field { + padding: 0 10px; + width: 100%; + height: 100%; + position: relative; + z-index: 1; + } + .@{tree-select-prefix-cls}-selection__rendered { + padding: 0; + height: 100%; + } + } +} + +.@{tree-select-prefix-cls}-dropdown { + &.slide-up-enter.slide-up-enter-active&-placement-bottomLeft, + &.slide-up-appear.slide-up-appear-active&-placement-bottomLeft { + animation-name: antSlideUpIn; + } + + &.slide-up-enter.slide-up-enter-active&-placement-topLeft, + &.slide-up-appear.slide-up-appear-active&-placement-topLeft { + animation-name: antSlideDownIn; + } + + &.slide-up-leave.slide-up-leave-active&-placement-bottomLeft { + animation-name: antSlideUpOut; + } + + &.slide-up-leave.slide-up-leave-active&-placement-topLeft { + animation-name: antSlideDownOut; + } + + &-hidden { + display: none; + } + + background-color: white; + border: 1px solid #d9d9d9; + box-shadow: @box-shadow-base; + border-radius: @border-radius-base; + box-sizing: border-box; + z-index: 1070; + left: -9999px; + top: -9999px; + position: absolute; + outline: none; + overflow: hidden; + font-size: @font-size-base; + + &-menu { + outline: none; + margin-bottom: 0; + padding-left: 0; // Override default ul/ol + list-style: none; + max-height: 250px; + overflow: auto; + + &-item-group-list { + margin: 0; + padding: 0; + + > .@{tree-select-prefix-cls}-dropdown-menu-item { + padding-left: 24px; + } + } + + &-item-group-title { + color: #999; + line-height: 1.5; + padding: 8px 15px; + } + + &-item { + position: relative; + display: block; + padding: 7px 15px; + font-weight: normal; + color: #666; + white-space: nowrap; + cursor: pointer; + overflow: hidden; + transition: background 0.3s ease; + + &:first-child { + border-top-left-radius: 4px; + border-top-right-radius: 4px; + } + &:last-child { + border-bottom-left-radius: 4px; + border-bottom-right-radius: 4px; + } + &:hover, + &-active { + background-color: tint(@primary-color, 90%); + } + + &-selected { + background-color: tint(@primary-color, 80%); + &:hover { + background-color: tint(@primary-color, 80%); + } + } + + &-disabled { + color: #ccc; + cursor: not-allowed; + + &:hover { + color: #ccc; + background-color: #fff; + cursor: not-allowed; + } + } + + &-divider { + height: 1px; + margin: 1px 0; + overflow: hidden; + background-color: #e5e5e5; + line-height: 0; + } + } + } + + &-container-open, + &-open { + .@{tree-select-prefix-cls}-dropdown { + display: block; + } + } + + .@{tree-select-prefix-cls}-dropdown-search { + display: block; + padding: 4px; + .@{tree-select-prefix-cls}-search__field__placeholder { + left: 7px; + top: 5px; + } + .@{tree-select-prefix-cls}-search__field__wrap { + width: 100%; + } + .@{tree-select-prefix-cls}-search__field { + padding: 4px 7px; + width: 100%; + box-sizing: border-box; + border: 1px solid #d9d9d9; + border-radius: 4px; + outline: none; + } + &.@{tree-select-prefix-cls}-search--hide { + display: none; + } + } +}