Skip to content

Commit

Permalink
feat(SearchTree): 增加单选模式 #547 (#589)
Browse files Browse the repository at this point in the history
  • Loading branch information
nullptr-z committed Mar 2, 2022
1 parent 934abc2 commit ee8ccd2
Show file tree
Hide file tree
Showing 3 changed files with 104 additions and 17 deletions.
67 changes: 56 additions & 11 deletions packages/react-search-tree/README.md
Expand Up @@ -61,23 +61,47 @@ const data = [
const Demo = () => {

const [value,valueSet]=useState([{ label: '东花市街道', key: '2-3-1' }])
const [valueSinge,valueSingeSet]=useState([{ label: '上海市', key: '1-0-0' }])

const onChange=(selectd, selectedAll, isChecked)=>{
console.log('SearchTree-> onChange',selectedAll, selectd, isChecked)
valueSet(selectedAll)
}

const onChangeSinge=(selectd, selectedAll, isChecked)=>{
console.log('SearchTree-> onChange', selectd, selectedAll, isChecked)
valueSingeSet(selectedAll)
}

return (
<>
<SearchTree
allowClear={true}
onSearch={(searchValue)=>console.log('SearchTree-> SearchTreeOption',searchValue)}
onChange={onChange}
value={value}
options={data}
placeholder="请输入选择"
/>
</>
<Row>
<Col >
<label>多选</label>
<SearchTree
style={{width:400}}
allowClear={true}
onSearch={(searchValue)=>console.log('multiple',searchValue)}
onChange={onChange}
value={value}
options={data}
placeholder="请输入选择"
/>
</Col>
<Col >
<label>单选</label>
<SearchTree
style={{width:400}}
multiple={false}
allowClear={true}
onSearch={(searchValue)=>console.log('singe',searchValue)}
onChange={onChangeSinge}
value={valueSinge}
options={data}
placeholder="请输入选择"
/>
</Col>

</Row>
)
}
ReactDOM.render(<Demo />, _mount_);
Expand Down Expand Up @@ -157,7 +181,10 @@ const form=useRef()
];

const setValue=()=>{
form.current.setFields({ searchTree: [{ label: '东城区', key: '2-1-0' }, { label: '外滩街道', key: '1-3-0' }] })
form.current.setFields({
searchTree: [{ label: '东城区', key: '2-1-0' }, { label: '外滩街道', key: '1-3-0' }],
searchTreeSinge:[{ label: '前门街道', key: '2-3-3' }]
})
}

const resetValue=()=>{
Expand All @@ -175,6 +202,7 @@ const form=useRef()
return null;
}}
onSubmit={({initial, current}) => {
console.log('current',current)
const errorObj = {};
if (!current.searchTree) {
errorObj.searchTree = '默认需要选择内容,选择入内容';
Expand Down Expand Up @@ -203,6 +231,19 @@ const form=useRef()
/>
)
},
searchTreeSinge: {
initialValue:[{ label: '东花市街道', key: '2-3-1' }],
children: (
<SearchTree
multiple={false}
allowClear={true}
onSearch={(searchValue)=>console.log('SearchTree-> SearchTreeOption',searchValue)}
onChange={(selectd, selectedAll, isChecked)=>console.log('SearchTree-> onChange', selectd, selectedAll, isChecked)}
options={data}
placeholder="请输入选择"
/>
)
},
}}
>
{({ fields, state, canSubmit }) => {
Expand All @@ -211,6 +252,9 @@ const form=useRef()
<Row>
<Col fixed>{fields.searchTree}</Col>
</Row>
<Row>
<Col fixed>{fields.searchTreeSinge}</Col>
</Row>
<Row>
<Col fixed>
<Button disabled={!canSubmit()} type="primary" htmlType="submit">提交</Button>
Expand Down Expand Up @@ -241,6 +285,7 @@ ReactDOM.render(<Demo />, _mount_);
|--------- |-------- |--------- |-------- |
| allowClear | 支持清除 | Boolean | `false` |
| disabled | 禁用选择器 | Boolean | `false` |
| multiple | 是否可以多选 | Boolean | `true` |
| value | 指定当前选中的条目 | [{label:string, key:string}] | - |
| options | 下拉数据源,可参考Tree下拉数据源 | [{label:string, key:string, children: [{label:string, key:string}] }] | - |
| placeholder | 选择框默认文字 | String | - |
Expand Down
9 changes: 7 additions & 2 deletions packages/react-search-tree/src/SearchTagInput.tsx
Expand Up @@ -120,7 +120,13 @@ function SearchTagInput<V extends SearchTagInputOption>(props: SearchTagInputPro
}, [selectedOption, options, emptyOption]);

return (
<Dropdown className={cls} trigger="focus" {...others} isOpen={innerIsOpen} menu={<Card>{newContent}</Card>}>
<Dropdown
className={cls}
trigger="focus"
{...others}
isOpen={innerIsOpen}
menu={<Card bodyStyle={{ padding: 0 }}>{newContent}</Card>}
>
<div
onMouseOver={() => renderSelectIcon('enter')}
onMouseLeave={() => renderSelectIcon('leave')}
Expand Down Expand Up @@ -156,7 +162,6 @@ function SearchTagInput<V extends SearchTagInputOption>(props: SearchTagInputPro
onChange={(e: React.ChangeEvent<HTMLInputElement>) => handleInputChange(e.target.value)}
value={searchValue}
placeholder={selectedOption.length ? '' : placeholder}
// readOnly={false}
/>
</div>
<span style={{ height: 25 }} className={`${prefixCls}-close-tag-contents`}>
Expand Down
45 changes: 41 additions & 4 deletions packages/react-search-tree/src/index.tsx
@@ -1,6 +1,6 @@
import React, { useState, useEffect } from 'react';
import SearchTagInput, { DropContent, SearchTagInputOption } from './SearchTagInput';
import { TreeData } from '@uiw/react-tree';
import Tree, { TreeData, TreeProps } from '@uiw/react-tree';
import TreeChecked, { TreeCheckedProps } from '@uiw/react-tree-checked';

type SelectOtpion = Record<string, string>;
Expand Down Expand Up @@ -59,18 +59,55 @@ function TreeCheckeds<V extends SearchTagInputOption>(
<TreeChecked defaultExpandAll={true} {...props} data={props.options} selectedKeys={keys} onSelected={onSelected} />
);
}

function SingeTree<V extends SearchTagInputOption>(props: Omit<TreeProps, 'onSelected'> & Partial<DropContent<V>>) {
const [keys, keysSet] = useState<Array<string | number>>([]);

useEffect(() => {
const key = props.values?.[0].key;
keysSet(key ? [key] : []);
}, [props.values]);

const onSelected = (_1: any, _2: any, isChecked: boolean, evn: TreeData) => {
const { key, label } = evn;
const cur = { key, label } as V;
props.onSelected?.([cur], cur, isChecked);
};

return (
<Tree
defaultExpandAll={true}
{...props}
multiple={false}
data={props.options}
selectedKeys={keys}
onSelected={onSelected}
/>
);
}

export interface SearchTreeProps<V> {
onChange?: (selectd: V, selectedAll: Array<V>, isChecked: boolean) => void;
onSearch?: (seachValue: string) => void;
value?: Array<V>;
options?: TreeData[];
treeProps?: Omit<TreeCheckedProps, 'onSelected'> & Partial<DropContent<V>>;
emptyOption?: React.ReactNode;
multiple?: boolean;
}

function SearchTree<V extends SearchTagInputOption>(props: SearchTreeProps<V>) {
const { onChange, onSearch, options = [], value = [], emptyOption = !options.length, treeProps, ...other } = props;
const [selectedValues, selectedValuesSet] = useState<Array<V>>(value);
const {
onChange,
onSearch,
multiple = true,
options = [],
value = [],
emptyOption = !options.length,
treeProps,
...other
} = props;
const [selectedValues, selectedValuesSet] = useState<Array<V>>(Array.isArray(value) ? value : [value]);
const [selectedOptions, selectedOptionSet] = useState<Array<TreeData>>(options);
const [isEmpty, isEmptySet] = useState(emptyOption);

Expand Down Expand Up @@ -125,7 +162,7 @@ function SearchTree<V extends SearchTagInputOption>(props: SearchTreeProps<V>) {
onChange={selectedChange}
values={selectedValues}
options={selectedOptions}
content={<TreeCheckeds {...treeProps} />}
content={multiple ? <TreeCheckeds {...treeProps} /> : <SingeTree {...treeProps} />}
/>
);
}
Expand Down

0 comments on commit ee8ccd2

Please sign in to comment.