1
- import React , { useRef } from 'react' ;
1
+ import React , { useRef , useState } from 'react' ;
2
2
import PropTypes from 'prop-types' ;
3
3
4
4
import DataDrivenSelect from '@data-driven-forms/common/src/select' ;
5
5
import parseInternalValue from '@data-driven-forms/common/src/select/parse-internal-value' ;
6
6
import Downshift from 'downshift' ;
7
- import { CaretDownIcon } from '@patternfly/react-icons' ;
7
+ import { CaretDownIcon , CloseIcon } from '@patternfly/react-icons' ;
8
8
import '@patternfly/react-styles/css/components/Select/select.css' ;
9
+ import '@patternfly/react-styles/css/components/Chip/chip.css' ;
10
+ import '@patternfly/react-styles/css/components/ChipGroup/chip-group.css' ;
9
11
10
12
import './select-styles.scss' ;
11
13
import Menu from './menu' ;
12
14
import ClearIndicator from './clear-indicator' ;
13
15
import ValueContainer from './value-container' ;
14
16
15
- const itemToString = ( value ) => {
17
+ const itemToString = ( value , isMulti , showMore , handleShowMore , handleChange ) => {
16
18
if ( ! value ) {
17
19
return '' ;
18
20
}
19
21
20
22
if ( Array . isArray ( value ) ) {
23
+ if ( ! value || value . length === 0 ) {
24
+ return ;
25
+ }
26
+
27
+ if ( isMulti ) {
28
+ const visibleOptions = showMore ? value : value . slice ( 0 , 3 ) ;
29
+ return (
30
+ < div className = "pf-c-chip-group" onClick = { ( event ) => event . stopPropagation ( ) } >
31
+ < ul className = "pf-c-chip-group__list" aria-label = "Chip group category" >
32
+ { visibleOptions . map ( ( item , index ) => {
33
+ const label = typeof item === 'object' ? item . label : item ;
34
+ return (
35
+ < li className = "pf-c-chip-group__list-item" onClick = { ( event ) => event . stopPropagation ( ) } key = { label } >
36
+ < div className = "pf-c-chip" >
37
+ < span className = "pf-c-chip__text" id = { `pf-random-id-${ index } -${ label } ` } >
38
+ { label }
39
+ </ span >
40
+ < button onClick = { ( ) => handleChange ( item ) } className = "pf-c-button pf-m-plain" type = "button" >
41
+ < CloseIcon />
42
+ </ button >
43
+ </ div >
44
+ </ li >
45
+ ) ;
46
+ } ) }
47
+ { value . length > 3 && (
48
+ < li className = "pf-c-chip-group__list-item" >
49
+ < button type = "button" onClick = { handleShowMore } className = "pf-c-chip pf-m-overflow" >
50
+ < span className = "pf-c-chip__text" > { showMore ? 'Show less' : `${ value . length - 3 } more` } </ span >
51
+ </ button >
52
+ </ li >
53
+ ) }
54
+ </ ul >
55
+ </ div >
56
+ ) ;
57
+ }
58
+
21
59
return value . map ( ( item ) => ( typeof item === 'object' ? item . label : item ) ) . join ( ',' ) ;
22
60
}
23
61
@@ -30,6 +68,29 @@ const itemToString = (value) => {
30
68
31
69
const filterOptions = ( options , filterValue = '' ) => options . filter ( ( { label } ) => label . toLowerCase ( ) . includes ( filterValue . toLowerCase ( ) ) ) ;
32
70
71
+ const getValue = ( isMulti , option , value ) => {
72
+ if ( ! isMulti ) {
73
+ return option ;
74
+ }
75
+
76
+ const isSelected = value . find ( ( { value } ) => value === option . value ) ;
77
+ return isSelected ? value . filter ( ( { value } ) => value !== option . value ) : [ ...value , option ] ;
78
+ } ;
79
+
80
+ const stateReducer = ( state , changes , keepMenuOpen ) => {
81
+ switch ( changes . type ) {
82
+ case Downshift . stateChangeTypes . keyDownEnter :
83
+ case Downshift . stateChangeTypes . clickItem :
84
+ return {
85
+ ...changes ,
86
+ isOpen : keepMenuOpen ? state . isOpen : ! state . isOpen ,
87
+ highlightedIndex : state . highlightedIndex
88
+ } ;
89
+ default :
90
+ return changes ;
91
+ }
92
+ } ;
93
+
33
94
const InternalSelect = ( {
34
95
noResultsMessage,
35
96
noOptionsMessage,
@@ -41,33 +102,35 @@ const InternalSelect = ({
41
102
isSearchable,
42
103
isDisabled,
43
104
isClearable,
105
+ isMulti,
44
106
...props
45
107
} ) => {
46
- // console.log(props );
108
+ const [ showMore , setShowMore ] = useState ( false ) ;
47
109
const inputRef = useRef ( ) ;
48
110
const parsedValue = parseInternalValue ( value ) ;
111
+ const handleShowMore = ( ) => setShowMore ( ( prev ) => ! prev ) ;
112
+ const handleChange = ( option ) => onChange ( getValue ( isMulti , option , value ) ) ;
49
113
return (
50
114
< Downshift
51
115
id = { props . id || props . name }
52
- onChange = { ( value ) => {
53
- return onChange ( value ) ;
54
- } }
55
- itemToString = { itemToString }
116
+ onChange = { handleChange }
117
+ itemToString = { ( value ) => itemToString ( value , isMulti , showMore , handleShowMore , handleChange ) }
56
118
selectedItem = { value }
119
+ stateReducer = { ( state , changes ) => stateReducer ( state , changes , isMulti ) }
57
120
>
58
121
{ ( { isOpen, inputValue, itemToString, selectedItem, clearSelection, getInputProps, getToggleButtonProps, getItemProps, highlightedIndex } ) => {
59
122
const toggleButtonProps = getToggleButtonProps ( ) ;
60
123
return (
61
124
< div className = "pf-c-select" >
62
- < button disabled = { isDisabled } className = { `pf-c-select__toggle${ isDisabled ? ' pf-m-disabled' : '' } ` } { ...toggleButtonProps } >
125
+ < div disabled = { isDisabled } className = { `pf-c-select__toggle${ isDisabled ? ' pf-m-disabled' : '' } ` } { ...toggleButtonProps } >
63
126
< div className = "pf-c-select_toggle-wrapper ddorg__pf4-component-mapper__select-toggle-wrapper" >
64
- < ValueContainer placeholder = { placeholder } value = { itemToString ( selectedItem ) } />
127
+ < ValueContainer placeholder = { placeholder } value = { itemToString ( selectedItem , isMulti , showMore , handleShowMore , handleChange ) } />
65
128
</ div >
66
129
< span className = "pf-c-select__toggle-arrow" >
67
130
{ isClearable && parsedValue && < ClearIndicator clearSelection = { clearSelection } /> }
68
131
< CaretDownIcon />
69
132
</ span >
70
- </ button >
133
+ </ div >
71
134
{ isOpen && (
72
135
< Menu
73
136
noResultsMessage = { noResultsMessage }
@@ -82,7 +145,8 @@ const InternalSelect = ({
82
145
options = { options }
83
146
getItemProps = { getItemProps }
84
147
highlightedIndex = { highlightedIndex }
85
- selectedItem = { parsedValue }
148
+ selectedItem = { isMulti ? value : parsedValue }
149
+ isMulti = { isMulti }
86
150
/>
87
151
) }
88
152
</ div >
@@ -109,7 +173,8 @@ InternalSelect.propTypes = {
109
173
isDisabled : PropTypes . bool ,
110
174
isClearable : PropTypes . bool ,
111
175
noResultsMessage : PropTypes . node ,
112
- noOptionsMessage : PropTypes . func
176
+ noOptionsMessage : PropTypes . func ,
177
+ isMulti : PropTypes . bool
113
178
} ;
114
179
115
180
const Select = ( { selectVariant, menuIsPortal, ...props } ) => {
0 commit comments