1- import React , { useRef } from 'react' ;
1+ import React , { useRef , useState } from 'react' ;
22import PropTypes from 'prop-types' ;
33
44import DataDrivenSelect from '@data-driven-forms/common/src/select' ;
55import parseInternalValue from '@data-driven-forms/common/src/select/parse-internal-value' ;
66import Downshift from 'downshift' ;
7- import { CaretDownIcon } from '@patternfly/react-icons' ;
7+ import { CaretDownIcon , CloseIcon } from '@patternfly/react-icons' ;
88import '@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' ;
911
1012import './select-styles.scss' ;
1113import Menu from './menu' ;
1214import ClearIndicator from './clear-indicator' ;
1315import ValueContainer from './value-container' ;
1416
15- const itemToString = ( value ) => {
17+ const itemToString = ( value , isMulti , showMore , handleShowMore , handleChange ) => {
1618 if ( ! value ) {
1719 return '' ;
1820 }
1921
2022 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+
2159 return value . map ( ( item ) => ( typeof item === 'object' ? item . label : item ) ) . join ( ',' ) ;
2260 }
2361
@@ -30,6 +68,29 @@ const itemToString = (value) => {
3068
3169const filterOptions = ( options , filterValue = '' ) => options . filter ( ( { label } ) => label . toLowerCase ( ) . includes ( filterValue . toLowerCase ( ) ) ) ;
3270
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+
3394const InternalSelect = ( {
3495 noResultsMessage,
3596 noOptionsMessage,
@@ -41,33 +102,35 @@ const InternalSelect = ({
41102 isSearchable,
42103 isDisabled,
43104 isClearable,
105+ isMulti,
44106 ...props
45107} ) => {
46- // console.log(props );
108+ const [ showMore , setShowMore ] = useState ( false ) ;
47109 const inputRef = useRef ( ) ;
48110 const parsedValue = parseInternalValue ( value ) ;
111+ const handleShowMore = ( ) => setShowMore ( ( prev ) => ! prev ) ;
112+ const handleChange = ( option ) => onChange ( getValue ( isMulti , option , value ) ) ;
49113 return (
50114 < Downshift
51115 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 ) }
56118 selectedItem = { value }
119+ stateReducer = { ( state , changes ) => stateReducer ( state , changes , isMulti ) }
57120 >
58121 { ( { isOpen, inputValue, itemToString, selectedItem, clearSelection, getInputProps, getToggleButtonProps, getItemProps, highlightedIndex } ) => {
59122 const toggleButtonProps = getToggleButtonProps ( ) ;
60123 return (
61124 < 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 } >
63126 < 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 ) } />
65128 </ div >
66129 < span className = "pf-c-select__toggle-arrow" >
67130 { isClearable && parsedValue && < ClearIndicator clearSelection = { clearSelection } /> }
68131 < CaretDownIcon />
69132 </ span >
70- </ button >
133+ </ div >
71134 { isOpen && (
72135 < Menu
73136 noResultsMessage = { noResultsMessage }
@@ -82,7 +145,8 @@ const InternalSelect = ({
82145 options = { options }
83146 getItemProps = { getItemProps }
84147 highlightedIndex = { highlightedIndex }
85- selectedItem = { parsedValue }
148+ selectedItem = { isMulti ? value : parsedValue }
149+ isMulti = { isMulti }
86150 />
87151 ) }
88152 </ div >
@@ -109,7 +173,8 @@ InternalSelect.propTypes = {
109173 isDisabled : PropTypes . bool ,
110174 isClearable : PropTypes . bool ,
111175 noResultsMessage : PropTypes . node ,
112- noOptionsMessage : PropTypes . func
176+ noOptionsMessage : PropTypes . func ,
177+ isMulti : PropTypes . bool
113178} ;
114179
115180const Select = ( { selectVariant, menuIsPortal, ...props } ) => {
0 commit comments