Merge pull request #775 from ant-design/feature/tree-select

Feature/tree select
This commit is contained in:
warmhug 2015-12-31 14:50:29 +08:00
commit f0b4a173a5
8 changed files with 826 additions and 1 deletions

View File

@ -0,0 +1,55 @@
# 基本
- order: 0
最简单的用法。
---
````jsx
import { TreeSelect } from 'antd';
const TreeNode = TreeSelect.TreeNode;
const Demo = React.createClass({
getInitialState() {
return {
value: 'leaf1',
};
},
onChange(e) {
let value;
if (e.target) {
value = e.target.value;
} else {
value = e;
}
this.setState({value});
},
render() {
return (
<div style={{margin: 20}}>
<h2>Single Select</h2>
<TreeSelect style={{width: 300}} showSearch
value={this.state.value} optionLabelProp="title"
dropdownMenuStyle={{maxHeight: 200, overflow: 'auto'}}
treeDefaultExpandAll
onChange={this.onChange}>
<TreeNode value="parent 1" title="parent 1" key="0-1">
<TreeNode value="parent 1-0" title="parent 1-0" key="0-1-1">
<TreeNode value="leaf1" title="my leaf" key="random" />
<TreeNode value="leaf2" title="your leaf" key="random1" />
</TreeNode>
<TreeNode value="parent 1-1" title="parent 1-1" key="random2">
<TreeNode value="sss" title={<span style={{color: 'red'}}>sss</span>} key="random3" />
</TreeNode>
</TreeNode>
</TreeSelect>
</div>
);
},
});
ReactDOM.render(
<Demo />
, document.getElementById('components-tree-select-demo-basic'));
````

View File

@ -0,0 +1,89 @@
# 更多功能
- order: 1
更多功能。
---
````jsx
import { TreeSelect } from 'antd';
const TreeNode = TreeSelect.TreeNode;
const x = 3;
const y = 2;
const z = 1;
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: ['0-0'],
};
},
onSelect(selectedKey, node, selectedKeys) {
console.log('selected: ', selectedKey, selectedKeys);
this.setState({
value: selectedKeys,
});
},
onChange(value) {
console.log('selected ' + value);
this.setState({
value: value,
});
},
render() {
const loop = data => {
return data.map((item) => {
if (item.children) {
return <TreeNode key={item.key} value={item.key} title={item.key}>{loop(item.children)}</TreeNode>;
}
return <TreeNode key={item.key} value={item.key} title={item.key} />;
});
};
const tProps = {
// defaultValue: this.state.value,
value: this.state.value,
onChange: this.onChange,
onSelect: this.onSelect,
multiple: true,
// treeCheckable: true,
treeDefaultExpandAll: true,
};
return (<div style={{padding: '10px 30px'}}>
<h3>more</h3>
<TreeSelect style={{width: 300}} {...tProps}>
{loop(gData)}
</TreeSelect>
</div>);
},
});
ReactDOM.render(<div>
<Demo />
</div>
, document.getElementById('components-tree-select-demo-enhance'));
````

View File

@ -0,0 +1,49 @@
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-tree-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;
}
let checkable = props.treeCheckable;
if (checkable) {
checkable = <span className={`${props.prefixCls}-tree-checkbox-inner`}></span>;
}
return (
<TreeSelect {...this.props}
treeCheckable={checkable}
className={cls}
notFoundContent={notFoundContent} />
);
}
});
AntTreeSelect.TreeNode = TreeNode;
export default AntTreeSelect;

View File

@ -0,0 +1,49 @@
# TreeSelect
- category: Components
- chinese: 树选择控件
- type: 表单
---
## 何时使用
当需要从树控件中灵活地筛选数据时
## API
### Tree props
| 参数 | 说明 | 类型 | 默认值 |
|-----------|------------------------------------------|------------|--------|
| value | 指定当前选中的条目 | string/Array<String> | 无 |
| defaultValue | 指定默认选中的条目 | string/Array<String> | 无 |
| 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
| 参数 | 说明 | 类型 | 默认值 |
|-----------|------------------------------------------|------------|--------|
| disabled | 是否禁用 | Boolean | false |
| key | 此项必须设置 | String | |
| value | 默认根据此属性值进行筛选 | String | - |
| title | 树节点显示的内容 | String | '---' |
| isLeaf | 是否是叶子节点 | bool | false |

View File

@ -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'),

View File

@ -61,7 +61,8 @@
"rc-tabs": "~5.6.0",
"rc-time-picker": "~1.0.0",
"rc-tooltip": "~3.3.0",
"rc-tree": "~0.19.0",
"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",

View File

@ -27,6 +27,7 @@
@import "tag";
@import "alert";
@import "tree";
@import "treeSelect";
@import "carousel/slick";
@import "carousel/slick-theme";
@import "upload";

View File

@ -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;
}
}
}