import * as React from 'react' ; import classNames from 'classnames/dedupe' ; import { CommonProps } from './common-prop-types' ; type ControlProps = React . SelectHTMLAttributes < HTMLSelectElement > ; type ControlPropsCleaned = Omit < ControlProps , 'id' | 'name' > ; interface SelectOption { value : string ; label : string ; group ? : string ; } interface Props extends CommonProps , ControlPropsCleaned { options : SelectOption [ ] ; multiple : boolean ; elementRef : React . RefObject < HTMLSelectElement > ; } type State = Record < string , unknown > ; class SelectControl extends React . Component < Props , State > { public static defaultProps = { multiple : false , elementRef : React . createRef < HTMLSelectElement > ( ) , } ; public constructor ( props ) { super ( props ) ; } private renderOption = ( item , key ) : JSX . Element => { const { label , value , ... rest } = item ; const option = ( < option key = { key } value = { value } { ... rest } > { label } < /option>); return option ; } ; public render ( ) { const { options } = this . props ; let groups = options . filter ( ( item ) : string => ( item . group ? item . group : '' ) ) . map ( ( item ) : string => ( item . group ? item . group : '' ) ) ; const onlyUnique = ( value , index , self ) : boolean => { return self . indexOf ( value ) === index ; } ; groups = groups . filter ( onlyUnique ) ; let optionNodes ; if ( groups . length === 0 ) { optionNodes = options . map ( ( item , index ) => { return this . renderOption ( item , `${ index }` ) ; } ) ; } else { const itemsWithoutGroup = options . filter ( ( item ) : boolean => ! item . group ) ; optionNodes = itemsWithoutGroup . map ( ( item , index ) => { return this . renderOption ( item , `no-group-${ index }` ) ; } ) ; groups . forEach ( ( group , groupIndex ) : void => { const groupItems = options . filter ( ( item ) : boolean => item . group === group ) ; const groupOptionNodes = groupItems . map ( ( item , index ) => this . renderOption ( item , `${ groupIndex }-${ index }` ) ) ; optionNodes . push ( < optgroup label = { group } key = { groupIndex } > { groupOptionNodes } < /optgroup>); } ) ; } const { className , elementRef , ... selectProps } = this . props ; return ( < select { ... selectProps } className = { classNames ( [ 'custom-select' , className ] ) } ref = { elementRef } > { optionNodes } < /select>); } } export { Props } ; export default SelectControl ;