@@ -3,11 +3,7 @@ import * as PropTypes from 'prop-types'
3
3
import * as _ from 'lodash'
4
4
5
5
import { Extendable , ShorthandValue , ComponentEventHandler } from '../../../types/utils'
6
- import {
7
- ComponentSlotStylesInput ,
8
- ComponentVariablesInput ,
9
- ComponentSlotClasses ,
10
- } from '../../themes/types'
6
+ import { ComponentSlotStylesInput , ComponentVariablesInput } from '../../themes/types'
11
7
import Downshift , {
12
8
DownshiftState ,
13
9
StateChangeOptions ,
@@ -24,13 +20,15 @@ import {
24
20
customPropTypes ,
25
21
commonPropTypes ,
26
22
handleRef ,
23
+ UIComponentProps ,
27
24
} from '../../lib'
28
25
import keyboardKey from 'keyboard-key'
29
26
import List from '../List/List'
30
- import Text from '../Text/Text'
31
27
import Ref from '../Ref/Ref'
32
- import { UIComponentProps } from '../../lib/commonPropInterfaces '
28
+ import DropdownIndicator from './DropdownIndicator '
33
29
import DropdownItem from './DropdownItem'
30
+ import DropdownMessageLoading from './DropdownMessageLoading'
31
+ import DropdownMessageNoResults from './DropdownMessageNoResults'
34
32
import DropdownSelectedItem , { DropdownSelectedItemProps } from './DropdownSelectedItem'
35
33
import DropdownSearchInput , { DropdownSearchInputProps } from './DropdownSearchInput'
36
34
import Button from '../Button/Button'
@@ -70,6 +68,8 @@ export interface DropdownProps extends UIComponentProps<DropdownProps, DropdownS
70
68
*/
71
69
getA11yStatusMessage ?: ( options : A11yStatusMessageOptions < ShorthandValue > ) => string
72
70
71
+ indicator ?: ShorthandValue
72
+
73
73
/** Array of props for generating list options (Dropdown.Item[]) and selected item labels(Dropdown.SelectedItem[]), if it's a multiple selection. */
74
74
items ?: ShorthandValue [ ]
75
75
@@ -78,11 +78,16 @@ export interface DropdownProps extends UIComponentProps<DropdownProps, DropdownS
78
78
*/
79
79
itemToString ?: ( item : ShorthandValue ) => string
80
80
81
+ loading ?: boolean
82
+
81
83
/** A dropdown can perform a multiple selection. */
82
84
multiple ?: boolean
83
85
84
- /** A string to be displayed in the list when dropdown has no available items to show. */
85
- noResultsMessage ?: string
86
+ /** A message to be displayed in the list when dropdown is loading. */
87
+ messageLoading ?: ShorthandValue
88
+
89
+ /** A message to be displayed in the list when dropdown has no available items to show. */
90
+ messageNoResults ?: ShorthandValue
86
91
87
92
/**
88
93
* Callback for change in dropdown search query value.
@@ -110,9 +115,6 @@ export interface DropdownProps extends UIComponentProps<DropdownProps, DropdownS
110
115
/** Sets search query value (controlled mode). */
111
116
searchQuery ?: string
112
117
113
- /** Whether toggle button (that shows/hides items list) should be rendered. */
114
- toggleButton ?: boolean
115
-
116
118
/** Sets currently selected value(s) (controlled mode). */
117
119
value ?: ShorthandValue | ShorthandValue [ ]
118
120
}
@@ -155,17 +157,19 @@ export default class Dropdown extends AutoControlledComponent<
155
157
fluid : PropTypes . bool ,
156
158
getA11ySelectionMessage : PropTypes . object ,
157
159
getA11yStatusMessage : PropTypes . func ,
160
+ indicator : customPropTypes . itemShorthand ,
158
161
items : customPropTypes . collectionShorthand ,
159
162
itemToString : PropTypes . func ,
163
+ loading : PropTypes . bool ,
160
164
multiple : PropTypes . bool ,
161
- noResultsMessage : PropTypes . string ,
165
+ messageLoading : PropTypes . string ,
166
+ messageNoResults : PropTypes . string ,
162
167
onSearchQueryChange : PropTypes . func ,
163
168
onSelectedChange : PropTypes . func ,
164
169
placeholder : PropTypes . string ,
165
170
search : PropTypes . oneOfType ( [ PropTypes . bool , PropTypes . func ] ) ,
166
171
searchQuery : PropTypes . string ,
167
172
searchInput : customPropTypes . itemShorthand ,
168
- toggleButton : PropTypes . bool ,
169
173
value : PropTypes . oneOfType ( [
170
174
customPropTypes . itemShorthand ,
171
175
customPropTypes . collectionShorthand ,
@@ -174,6 +178,7 @@ export default class Dropdown extends AutoControlledComponent<
174
178
175
179
static defaultProps = {
176
180
as : 'div' ,
181
+ indicator : '' ,
177
182
itemToString : item => {
178
183
if ( ! item || React . isValidElement ( item ) ) {
179
184
return ''
@@ -186,6 +191,8 @@ export default class Dropdown extends AutoControlledComponent<
186
191
187
192
return `${ item } `
188
193
} ,
194
+ messageLoading : 'Loading...' ,
195
+ messageNoResults : "We couldn't find any matches." ,
189
196
}
190
197
191
198
static autoControlledProps = [ 'searchQuery' , 'value' ]
@@ -211,7 +218,15 @@ export default class Dropdown extends AutoControlledComponent<
211
218
variables,
212
219
unhandledProps,
213
220
} : RenderResultConfig < DropdownProps > ) {
214
- const { search, multiple, toggleButton, getA11yStatusMessage, itemToString } = this . props
221
+ const {
222
+ fluid,
223
+ indicator,
224
+ loading,
225
+ search,
226
+ multiple,
227
+ getA11yStatusMessage,
228
+ itemToString,
229
+ } = this . props
215
230
const { searchQuery } = this . state
216
231
217
232
return (
@@ -262,7 +277,15 @@ export default class Dropdown extends AutoControlledComponent<
262
277
variables ,
263
278
)
264
279
: this . renderTriggerButton ( styles , getToggleButtonProps ) }
265
- { toggleButton && this . renderToggleButton ( getToggleButtonProps , classes , isOpen ) }
280
+ { DropdownIndicator . create ( indicator , {
281
+ defaultProps : {
282
+ ...getToggleButtonProps ( ) ,
283
+ fluid,
284
+ loading,
285
+ open : isOpen ,
286
+ variables,
287
+ } ,
288
+ } ) }
266
289
{ this . renderItemsList (
267
290
styles ,
268
291
variables ,
@@ -322,7 +345,7 @@ export default class Dropdown extends AutoControlledComponent<
322
345
) => void ,
323
346
variables ,
324
347
) : JSX . Element {
325
- const { searchInput, multiple, placeholder, toggleButton } = this . props
348
+ const { indicator , searchInput, multiple, placeholder } = this . props
326
349
const { searchQuery, value } = this . state
327
350
328
351
const noPlaceholder =
@@ -331,7 +354,7 @@ export default class Dropdown extends AutoControlledComponent<
331
354
return DropdownSearchInput . create ( searchInput || { } , {
332
355
defaultProps : {
333
356
placeholder : noPlaceholder ? '' : placeholder ,
334
- hasToggleButton : ! ! toggleButton ,
357
+ hasToggleButton : ! ! indicator ,
335
358
variables,
336
359
inputRef : this . inputRef ,
337
360
} ,
@@ -346,19 +369,6 @@ export default class Dropdown extends AutoControlledComponent<
346
369
} )
347
370
}
348
371
349
- private renderToggleButton (
350
- getToggleButtonProps : ( options ?: GetToggleButtonPropsOptions ) => any ,
351
- classes : ComponentSlotClasses ,
352
- isOpen : boolean ,
353
- ) {
354
- const { onClick } = getToggleButtonProps ( )
355
- return (
356
- < span className = { classes . toggleButton } onClick = { onClick } >
357
- { isOpen ? String . fromCharCode ( 9650 ) : String . fromCharCode ( 9660 ) }
358
- </ span >
359
- )
360
- }
361
-
362
372
private renderItemsList (
363
373
styles : ComponentSlotStylesInput ,
364
374
variables : ComponentVariablesInput ,
@@ -370,7 +380,10 @@ export default class Dropdown extends AutoControlledComponent<
370
380
getItemProps : ( options : GetItemPropsOptions < ShorthandValue > ) => any ,
371
381
getInputProps : ( options ?: GetInputPropsOptions ) => any ,
372
382
) {
373
- const accessibilityMenuProps = getMenuProps ( { refKey : 'innerRef' } , { suppressRefError : true } )
383
+ const { innerRef, ...accessibilityMenuProps } = getMenuProps (
384
+ { refKey : 'innerRef' } ,
385
+ { suppressRefError : true } ,
386
+ )
374
387
const { search } = this . props
375
388
// If it's just a selection, some attributes and listeners from Downshift input need to go on the menu list.
376
389
if ( ! search ) {
@@ -387,7 +400,7 @@ export default class Dropdown extends AutoControlledComponent<
387
400
)
388
401
}
389
402
}
390
- const { innerRef , ... accessibilityMenuPropsRest } = accessibilityMenuProps
403
+
391
404
return (
392
405
< Ref
393
406
innerRef = { ( listElement : HTMLElement ) => {
@@ -396,49 +409,42 @@ export default class Dropdown extends AutoControlledComponent<
396
409
} }
397
410
>
398
411
< List
399
- { ...accessibilityMenuPropsRest }
412
+ { ...accessibilityMenuProps }
400
413
styles = { styles . list }
401
414
tabIndex = { search ? undefined : - 1 } // needs to be focused when trigger button is activated.
402
415
aria-hidden = { ! isOpen }
403
- items = { isOpen ? this . renderItems ( styles , variables , getItemProps , highlightedIndex ) : [ ] }
416
+ items = { isOpen ? this . renderItems ( variables , getItemProps , highlightedIndex ) : [ ] }
404
417
/>
405
418
</ Ref >
406
419
)
407
420
}
408
421
409
422
private renderItems (
410
- styles : ComponentSlotStylesInput ,
411
423
variables : ComponentVariablesInput ,
412
424
getItemProps : ( options : GetItemPropsOptions < ShorthandValue > ) => any ,
413
425
highlightedIndex : number ,
414
426
) {
415
- const { noResultsMessage } = this . props
427
+ const { loading, messageLoading, messageNoResults } = this . props
428
+
416
429
const filteredItems = this . getItemsFilteredBySearchQuery ( )
430
+ const items = filteredItems . map ( ( item , index ) =>
431
+ DropdownItem . create ( item , {
432
+ defaultProps : {
433
+ active : highlightedIndex === index ,
434
+ variables,
435
+ ...( typeof item === 'object' &&
436
+ ! item . hasOwnProperty ( 'key' ) && {
437
+ key : ( item as any ) . header ,
438
+ } ) ,
439
+ } ,
440
+ overrideProps : ( ) => this . handleItemOverrides ( item , index , getItemProps ) ,
441
+ } ) ,
442
+ )
417
443
418
- if ( filteredItems . length > 0 ) {
419
- return filteredItems . map ( ( item , index ) => {
420
- return DropdownItem . create ( item , {
421
- defaultProps : {
422
- active : highlightedIndex === index ,
423
- variables,
424
- ...( typeof item === 'object' &&
425
- ! item . hasOwnProperty ( 'key' ) && {
426
- key : ( item as any ) . header ,
427
- } ) ,
428
- } ,
429
- overrideProps : ( ) => this . handleItemOverrides ( item , index , getItemProps ) ,
430
- } )
431
- } )
432
- }
433
- // render no match message.
434
444
return [
435
- noResultsMessage
436
- ? {
437
- key : 'dropdown-no-results' ,
438
- content : < Text weight = "bold" content = { noResultsMessage } /> ,
439
- styles : styles . emptyListItem ,
440
- }
441
- : null ,
445
+ ...items ,
446
+ loading && DropdownMessageLoading . create ( messageLoading ) ,
447
+ ! loading && items . length === 0 && DropdownMessageNoResults . create ( messageNoResults ) ,
442
448
]
443
449
}
444
450
0 commit comments