@@ -4,45 +4,85 @@ import { IProps } from '@uiw/utils';
4
4
import Dropdown , { DropdownProps } from '@uiw/react-dropdown' ;
5
5
import Menu from '@uiw/react-menu' ;
6
6
import Icon from '@uiw/react-icon' ;
7
+ import './style/index.less' ;
7
8
8
9
type ValueType = Array < string | number > ;
9
- type optionType = { value : string | number ; label : React . ReactNode ; children ?: Array < optionType > } ;
10
+ type OptionType = { value : string | number ; label : React . ReactNode ; children ?: Array < OptionType > } ;
10
11
11
12
export interface CascaderProps extends IProps , DropdownProps {
12
- option ?: Array < optionType > ;
13
+ option ?: Array < OptionType > ;
13
14
value ?: ValueType ;
14
- onChange ?: ( value : ValueType , selectedOptions : Array < optionType > ) => void ;
15
+ onChange ?: ( isSeleted : boolean , value : ValueType , selectedOptions : Array < OptionType > ) => void ;
15
16
allowClear ?: boolean ;
16
17
placeholder ?: string ;
17
18
isOpen ?: boolean ;
18
19
}
19
20
20
21
function Cascader ( props : CascaderProps ) {
21
- const { placeholder, prefixCls = 'w-search-select' , className, style = { width : 200 } , option = [ ] , others } = props ;
22
+ const {
23
+ value,
24
+ onChange,
25
+
26
+ allowClear,
27
+ placeholder,
28
+ prefixCls = 'w-cascader' ,
29
+ className,
30
+ style = { width : 200 } ,
31
+ option = [ ] ,
32
+ others,
33
+ } = props ;
22
34
23
35
const cls = [ prefixCls , className ] . filter ( Boolean ) . join ( ' ' ) . trim ( ) ;
24
36
const [ innerIsOpen , setInnerIsOpen ] = useState ( false ) ;
25
- const [ selectedValue , setSelectedValue ] = useState < Array < optionType > > ( [ ] ) ;
37
+ const [ selectedValue , setSelectedValue ] = useState < Array < OptionType > > ( [ ] ) ;
38
+ const [ selectIconType , setSelectIconType ] = useState ( '' ) ;
39
+
40
+ useEffect ( ( ) => {
41
+ const valueTemp : Array < OptionType > = [ ] ;
42
+ let optChildren = option ;
43
+ value ?. map ( ( item ) => {
44
+ const findOpt = optChildren . find ( ( opt ) => opt . value === item ) ;
45
+ optChildren = findOpt ?. children || [ ] ;
46
+ valueTemp . push ( { label : item , value : item , ...findOpt } ) ;
47
+ } ) ;
48
+ setSelectedValue ( valueTemp ) ;
49
+ } , [ value ] ) ;
26
50
27
51
function onVisibleChange ( isOpen : boolean ) {
28
52
setInnerIsOpen ( isOpen ) ;
29
53
}
30
54
31
- const handleItemClick = ( optionsItem : optionType , level : number ) => {
55
+ function renderSelectIcon ( type : string ) {
56
+ let selectIconType ;
57
+ if ( type === 'enter' && allowClear && selectedValue . length > 0 ) {
58
+ selectIconType = 'close' ;
59
+ } else {
60
+ selectIconType = '' ;
61
+ }
62
+ setSelectIconType ( selectIconType ) ;
63
+ }
64
+
65
+ const handleItemClick = ( optionsItem : OptionType , level : number ) => {
32
66
selectedValue . splice ( level , selectedValue . length - level , optionsItem ) ;
33
- setSelectedValue ( [ ...selectedValue ] ) ;
34
67
35
- handelChange ( ) ;
68
+ handelChange ( true , selectedValue ) ;
36
69
} ;
37
70
38
- const handelChange = ( ) => {
71
+ const handelChange = ( isSeleted : boolean , selectedValue : Array < OptionType > ) => {
72
+ setSelectedValue ( [ ...selectedValue ] ) ;
39
73
const value = selectedValue . map ( ( item ) => item . value ) ;
40
- props . onChange ?.( value , selectedValue ) ;
74
+ onChange ?.( isSeleted , value , selectedValue ) ;
75
+ } ;
76
+
77
+ const onClear = ( e : React . MouseEvent < any , MouseEvent > ) => {
78
+ e . stopPropagation ( ) ;
79
+ console . log ( 123 ) ;
80
+ handelChange ( false , [ ] ) ;
41
81
} ;
42
82
43
- const widths = ( style ?. width as number ) * 0.6 || undefined ;
83
+ const widths = ( style ?. width as number ) * 0.5 || undefined ;
44
84
45
- const OptionIter = ( option : Array < optionType > , level : number = 0 ) => {
85
+ const OptionIter = ( option : Array < OptionType > , level : number = 0 ) => {
46
86
if ( ! option ) return ;
47
87
48
88
return (
@@ -59,15 +99,15 @@ function Cascader(props: CascaderProps) {
59
99
{ ! option || option . length === 0 ? (
60
100
< div style = { { color : '#c7c7c7' , fontSize : 12 } } > { '没有数据' } </ div >
61
101
) : (
62
- option . map ( ( item , index ) => {
63
- const active = selectedValue [ level ] ?. value === item . value ;
102
+ option . map ( ( opt , index ) => {
103
+ const active = selectedValue [ level ] ?. value === opt . value ;
64
104
return (
65
105
< Menu . Item
66
106
active = { active }
67
107
key = { index }
68
- text = { item . label }
69
- addonAfter = { item . children ? < Icon type = "right" /> : undefined }
70
- onClick = { ( ) => handleItemClick ( item , level ) }
108
+ text = { opt . label }
109
+ addonAfter = { opt . children ? < Icon type = "right" /> : undefined }
110
+ onClick = { ( ) => handleItemClick ( opt , level ) }
71
111
/>
72
112
) ;
73
113
} )
@@ -77,7 +117,7 @@ function Cascader(props: CascaderProps) {
77
117
} ;
78
118
79
119
const inputValue = useMemo ( ( ) => {
80
- return selectedValue . map ( ( item ) => item . label ) . join ( ' / ' ) ;
120
+ return selectedValue . map ( ( opt ) => opt . label ) . join ( ' / ' ) ;
81
121
} , [ selectedValue . length ] ) ;
82
122
83
123
return (
@@ -101,7 +141,20 @@ function Cascader(props: CascaderProps) {
101
141
</ div >
102
142
}
103
143
>
104
- < Input value = { inputValue } onChange = { ( ) => { } } placeholder = { placeholder } style = { { width : style ?. width } } />
144
+ < span onMouseLeave = { ( ) => renderSelectIcon ( 'leave' ) } onMouseOver = { ( ) => renderSelectIcon ( 'enter' ) } >
145
+ < Input
146
+ value = { inputValue }
147
+ onChange = { ( ) => { } }
148
+ placeholder = { placeholder }
149
+ style = { { width : style ?. width } }
150
+ readOnly
151
+ addonAfter = {
152
+ selectIconType === 'close' && (
153
+ < Icon type = { `${ selectIconType } ` } onClick = { onClear } className = { `${ prefixCls } -close` } />
154
+ )
155
+ }
156
+ />
157
+ </ span >
105
158
</ Dropdown >
106
159
) ;
107
160
}
0 commit comments