Skip to content

Commit

Permalink
✨[TreeSelect]支持设置弹出位置
Browse files Browse the repository at this point in the history
  • Loading branch information
liyuan-meng committed Nov 30, 2023
1 parent a104032 commit cf6460f
Show file tree
Hide file tree
Showing 3 changed files with 240 additions and 31 deletions.
199 changes: 199 additions & 0 deletions src/components/tree-select/demos/position.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,199 @@
---
order: 2
title: 多层单选与多选
desc: 与Tree结合的树下拉
---

```jsx
import React from 'react';
import { TreeSelect } from 'cloud-react';

class TreeSelectDemo extends React.Component {
treeData = [
{
id: 11,
name: '禁止删除节点',
pId: 1,
disableRemove: true,
children: [
{
id: 113,
name: '删除三个',
pId: 11,
children: [
{
id: 1131,
name: '禁止删除节点31',
pId: 113,
children: []
},
{
id: 1132,
name: '禁止删除节点32',
pId: 113,
children: [
{
id: 11321,
name: '禁止删除节点321',
pId: 1132,
children: []
}
]
}
]
},
{
id: 114,
name: '禁止删除节点4',
pId: 11,
children: []
}
]
},
{
id: 14,
name: '未分类',
pId: 1,
disableRemove: true,
disableAdd: true,
disableRename: true,
children: []
}
];

constructor(props) {
super(props);

this.state = {
selectedNodes: [
{
id: 11321,
name: '禁止删除节点321',
pId: 1132,
children: []
}
],
confirmNodes: [],
singleNodes: [
{
id: 11321,
name: '禁止删除节点321',
pId: 1132,
children: []
}
]
};
setTimeout(() => {
this.setState({
confirmNodes: [this.treeData[0]]
});
}, 1000);

}

handleChange = (node, selectedNodes) => {
console.log(node, selectedNodes);

this.setState({
selectedNodes
});
};

handleConfirmChange = (node, selectedNodes) => {
console.log(node, selectedNodes);

this.setState({
confirmNodes: selectedNodes
});
};

onOk = (node, selectedNodes) => {
console.log(node, selectedNodes);

this.setState({
confirmNodes: selectedNodes
});
};

onChangeSingle = (node, selectedNodes) => {
console.log(node, selectedNodes);

this.setState({
singleNodes: selectedNodes
});
};

render() {
return (
<div style={{ display: 'flex', flexDirection: 'column', gap: 20 }}>
<div>
<h5>左上</h5>
<TreeSelect
allowClear
position="top"
type="single"
isUnfold
containParentNode
placeholder="选择一个选项"
style={{ width: 260 }}
dropdownStyle={{ width: 328 }}
dataSource={this.treeData}
value={this.state.singleNodes}
onChange={this.onChangeSingle}
/>
</div>
<div>
<h5>左下</h5>
<TreeSelect
allowClear
position="bottom"
type="single"
isUnfold
containParentNode
placeholder="选择一个选项"
style={{ width: 260 }}
dropdownStyle={{ width: 328 }}
dataSource={this.treeData}
value={this.state.singleNodes}
onChange={this.onChangeSingle}
/>
</div>
<div>
<h5>右上</h5>
<TreeSelect
allowClear
position="top"
type="single"
isUnfold
containParentNode
placeholder="选择一个选项"
style={{ width: 260 }}
dropdownStyle={{ width: 328, right: 0 }}
dataSource={this.treeData}
value={this.state.singleNodes}
onChange={this.onChangeSingle}
/>
</div>
<div>
<h5>右下</h5>
<TreeSelect
allowClear
position="bottom"
type="single"
isUnfold
containParentNode
placeholder="选择一个选项"
style={{ width: 260 }}
dropdownStyle={{ width: 328, right: 0 }}
dataSource={this.treeData}
value={this.state.singleNodes}
onChange={this.onChangeSingle}
/>
</div>
</div>
);
}
}

export default TreeSelectDemo;
```
63 changes: 34 additions & 29 deletions src/components/tree-select/index.js
Original file line number Diff line number Diff line change
Expand Up @@ -149,33 +149,30 @@ class TreeSelect extends Component {
}

positionPop = () => {
const {
props: { isAppendToBody, position },
selectedContainerStyle: { left, top, bottom, height },
optionsNodeStyle: { height: optionsHeight },
} = this;
const isBottomDistanceEnough =
bottom + optionsHeight < this.document.documentElement.clientHeight;
const isLocationTop =
optionsHeight < top && !isBottomDistanceEnough && position === 'auto';
const borderTop = isLocationTop ? '1px solid #d9d9d9' : null;
if (isAppendToBody) {
this.setState({
style: {
position: 'fixed',
left: `${left}px`,
top: isLocationTop ? `${top - optionsHeight}px` : `${bottom}px`,
borderTop,
},
});
} else {
this.setState({
style: {
top: isLocationTop ? `${-optionsHeight - 4}px` : `${height + 4}px`,
borderTop,
},
});
}
setTimeout(() => {
const {
props: { isAppendToBody, position },
selectedContainerStyle: { left, top, bottom, height },
optionsNodeStyle: { height: optionsHeight },
} = this;
const isBottomDistanceEnough = bottom + optionsHeight < this.document.documentElement.clientHeight;
const isLocationTop = position === 'top' || optionsHeight < top && !isBottomDistanceEnough && position === 'auto';
if (isAppendToBody) {
this.setState({
style: {
position: 'fixed',
left: `${left}px`,
top: isLocationTop ? `${top - optionsHeight}px` : `${bottom + 4}px`,
},
});
} else {
this.setState({
style: {
top: isLocationTop ? `${-optionsHeight - 4}px` : `${height + 4}px`,
},
});
}
});
};

handleClick = (e) => {
Expand Down Expand Up @@ -345,6 +342,8 @@ class TreeSelect extends Component {
allowClear,
style,
className,
dropdownStyle,
dropdownClassName,
isAppendToBody,
searchable,
} = this.props;
Expand All @@ -358,9 +357,9 @@ class TreeSelect extends Component {
);
const treeOptionsContainer = open ? (
<div
className={`${selector}-container`}
className={`${selector}-container ${dropdownClassName}`}
ref={this.optionsNode}
style={{ ...popupStyle, minWidth: width }}
style={{ ...popupStyle, minWidth: width, ...dropdownStyle }}
>
{this.renderTreeNode()}
</div>
Expand Down Expand Up @@ -423,6 +422,9 @@ TreeSelect.propTypes = {
onReset: PropTypes.func,
searchInBox: PropTypes.bool,
maxTagCount: PropTypes.number,
dropdownStyle: PropTypes.object,
dropdownClassName: PropTypes.string,
position: PropTypes.oneOf(['top', 'bottom', 'auto']),
};

TreeSelect.defaultProps = {
Expand Down Expand Up @@ -450,6 +452,9 @@ TreeSelect.defaultProps = {
onReset: noop,
searchInBox: false,
maxTagCount: undefined,
dropdownStyle: {},
dropdownClassName: '',
position: 'bottom',
};

export default TreeSelect;
9 changes: 7 additions & 2 deletions src/components/tree-select/index.md
Original file line number Diff line number Diff line change
Expand Up @@ -39,6 +39,9 @@ group:
| onSelectClose | 下拉选择框关闭的时候回调此函数 | function | - |
| searchInBox | 搜索框在外侧 | boolean | false |
| maxTagCount | 多选下拉最多显示多少个tag | number | - |
| position | 下拉框定位:`top` `bottom` `auto`(是否启用自动定位,如需使用可设置为`auto`| string | `bottom` |
| dropdownClassName | 下拉框类名 | string | - |
| dropdownStyle | 下拉框样式 | object | {} |

#### `single = true`,单选下拉树时候支持的配置
| 属性 | 说明 | 类型 | 默认值 |
Expand All @@ -61,7 +64,6 @@ group:
| onReset | 重置回调 | function | - |
| containParentNode | 结果是否包含各个父节点 | boolean | false |


树的更多属性配置可参考 **Tree** 组件

### 代码演示
Expand All @@ -73,5 +75,8 @@ group:
<embed src="@components/tree-select/demos/searchable.md" />

### 不与Tree结合的树下拉
<embed src="@components/tree-select/demos/basic-tree-select.md" />
<embed src="@components/tree-select/demos/basic-tree-select.md" />

### 弹出位置
<embed src="@components/tree-select/demos/position.md" />

0 comments on commit cf6460f

Please sign in to comment.