1
1
/* eslint-disable no-labels */
2
2
import React , { useState , useEffect , useRef } from 'react'
3
+ import Chip from './Chip.jsx'
3
4
import CloseIcon from './CloseIcon.jsx'
4
5
import DownIcon from './DownIcon.jsx'
5
6
import Options from './Options'
@@ -9,7 +10,6 @@ import useComponentVisible from './useComponentVisible.jsx'
9
10
MultiSelect . defaultProps = {
10
11
clearable : true ,
11
12
downArrow : true ,
12
- width : 300 ,
13
13
singleSelect : false ,
14
14
jsonValue : false ,
15
15
defaultValue : '' ,
@@ -20,7 +20,7 @@ MultiSelect.defaultProps = {
20
20
limit : null ,
21
21
emptyDataLabel : 'No Data Found' ,
22
22
placeholder : 'Select...' ,
23
- onChange : ( ) => { } ,
23
+ onChange : ( ) => { } ,
24
24
options : [
25
25
{
26
26
label : 'Empty' ,
@@ -29,12 +29,12 @@ MultiSelect.defaultProps = {
29
29
style : { textAlign : 'center' }
30
30
}
31
31
] ,
32
- customValue : false
32
+ customValue : false ,
33
+ chipAlternateText : 'Item Selected'
33
34
}
34
35
35
36
function MultiSelect ( {
36
37
options : userOptions ,
37
- width,
38
38
downArrowIcon,
39
39
closeIcon,
40
40
clearable,
@@ -53,17 +53,27 @@ function MultiSelect({
53
53
disabled,
54
54
limit,
55
55
emptyDataLabel,
56
- customValue
56
+ customValue,
57
+ onMenuOpen,
58
+ onMenuClose,
59
+ chipAlternateText
57
60
} ) {
58
61
const [ value , setValue ] = useState ( [ ] )
59
62
const [ options , setOptions ] = useState ( userOptions || [ ] )
60
63
const [ search , setSearch ] = useState ( null )
61
64
const inputFld = useRef ( null )
62
65
const {
63
- ref,
66
+ ref : componentRef ,
64
67
isComponentVisible : menuOpen ,
65
68
setIsComponentVisible : setMenuOpen
66
- } = useComponentVisible ( false )
69
+ } = useComponentVisible ( {
70
+ initialIsVisible : false ,
71
+ onClickOutside : onMenuClose
72
+ } )
73
+
74
+ const calculatedWidth = `calc(100% - ${
75
+ clearable && downArrow ? 60 : downArrow || clearable ? 40 : 5
76
+ } px)`
67
77
68
78
const getValueObjFromOptios = ( defaultValue , options ) => {
69
79
if ( ! defaultValue ) return [ ]
@@ -124,6 +134,7 @@ function MultiSelect({
124
134
setOptions ( [ ...options , ...customValuesGroup ] )
125
135
return [ ...searchedOptions , ...extraValues ]
126
136
}
137
+
127
138
useEffect ( ( ) => {
128
139
setOptions ( userOptions )
129
140
} , [ userOptions ] )
@@ -316,6 +327,18 @@ function MultiSelect({
316
327
}
317
328
}
318
329
330
+ const notClickableItem = ( target ) => {
331
+ if (
332
+ target . hasAttribute ( 'clickable' ) ||
333
+ target . parentNode . hasAttribute ( 'clickable' ) ||
334
+ target . parentNode . parentNode . hasAttribute ( 'clickable' ) ||
335
+ target . parentNode . parentNode . parentNode . hasAttribute ( 'clickable' )
336
+ ) {
337
+ return false
338
+ }
339
+ return true
340
+ }
341
+
319
342
const checkIsDropdownHandle = ( target ) => {
320
343
if (
321
344
target . hasAttribute ( 'dropdown-handle' ) ||
@@ -326,116 +349,95 @@ function MultiSelect({
326
349
}
327
350
}
328
351
352
+ const focusSearchInput = ( ) => {
353
+ if ( inputFld . current ) {
354
+ inputFld . current . focus ( )
355
+ }
356
+ }
357
+
329
358
const openMenu = ( { target } ) => {
330
- if ( checkIsDropdownHandle ( target ) ) {
331
- setMenuOpen ( ! menuOpen )
332
- } else {
333
- setMenuOpen ( true )
359
+ if ( notClickableItem ( target ) ) {
360
+ if ( checkIsDropdownHandle ( target ) ) {
361
+ if ( ! menuOpen ) {
362
+ setMenuOpen ( true )
363
+ onMenuOpen ( )
364
+ focusSearchInput ( )
365
+ } else {
366
+ setMenuOpen ( false )
367
+ onMenuClose ( )
368
+ }
369
+ } else {
370
+ setMenuOpen ( true )
371
+ onMenuOpen ( )
372
+ focusSearchInput ( )
373
+ }
334
374
}
335
375
}
336
376
337
- const showChipText = ( opt ) => {
338
- if ( typeof opt . label === 'object' ) {
339
- return opt ?. title || opt . value
377
+ const showLabel = ( optionObj ) => {
378
+ console . log ( optionObj )
379
+ if ( typeof optionObj . label === 'object' ) {
380
+ return optionObj ?. title || optionObj . value
340
381
} else {
341
- return opt . label
382
+ return optionObj . label
383
+ }
384
+ }
385
+
386
+ const getActiveClass = ( ) => {
387
+ const el = componentRef . current
388
+ var rect = el . getBoundingClientRect ( )
389
+ if ( window . innerHeight - ( rect . top + el . clientHeight ) < 200 ) {
390
+ return 'msl-active-up'
342
391
}
392
+ return 'msl-active'
343
393
}
344
394
345
395
return (
346
396
< div
347
- ref = { ref }
397
+ ref = { componentRef }
348
398
{ ...attr }
349
399
onClick = { openMenu }
350
400
tabIndex = '0'
351
401
onKeyPress = { openMenu }
352
- style = { { ...style , width } }
353
- className = { `msl-wrp msl-vars ${ className } ${ disabled ? 'msl-disabled' : ''
354
- } `}
402
+ style = { { ...style } }
403
+ className = { `msl-wrp msl-vars ${ className } ${
404
+ disabled ? 'msl-disabled' : ''
405
+ } `}
355
406
>
356
407
< input name = { name } type = 'hidden' value = { value ?. map ( ( itm ) => itm . value ) } />
357
- < div data-msl className = { `msl ${ menuOpen ? 'msl-active' : '' } ` } >
408
+ < div data-msl className = { `msl ${ menuOpen && getActiveClass ( ) } ` } >
358
409
< div
359
410
data-msl
360
411
className = 'msl-input-wrp'
361
- style = { {
362
- width : `calc(100% - ${ clearable && downArrow
363
- ? '60px'
364
- : downArrow || clearable
365
- ? '40px'
366
- : '5px'
367
- } `
368
- } }
412
+ style = { { width : calculatedWidth } }
369
413
>
370
414
{ ! singleSelect &&
371
415
! disableChip &&
372
416
value . map ( ( val , i ) => (
373
- < div key = { `msl-chip-${ i + 11 } ` } className = 'msl-chip' >
374
- { showChipText ( val ) }
375
- < div
376
- role = 'button'
377
- aria-label = 'delete-value'
378
- onClick = { ( ) => deleteValue ( i ) }
379
- onKeyPress = { ( ) => deleteValue ( i ) }
380
- tabIndex = '0'
381
- className = 'msl-btn msl-chip-delete msl-flx'
382
- >
383
- < CloseIcon />
384
- </ div >
385
- < span />
386
- </ div >
417
+ < Chip
418
+ key = { `msl-chip-${ i + 11 } ` }
419
+ value = { val }
420
+ deleteAction = { ( ) => deleteValue ( i ) }
421
+ />
387
422
) ) }
388
- { ! singleSelect && disableChip && value . length === 1 ? (
423
+ { ! singleSelect && disableChip && value . length > 0 && (
389
424
< span
390
425
className = 'msl-single-value'
391
426
data-msl
392
- style = { {
393
- width :
394
- width -
395
- ( clearable && downArrow
396
- ? 60
397
- : downArrow || clearable
398
- ? 40
399
- : 5 )
400
- } }
427
+ style = { { width : calculatedWidth } }
401
428
>
402
- { value [ 0 ] . label } d
429
+ { value . length === 1
430
+ ? showLabel ( value [ 0 ] )
431
+ : `${ value . length } ${ chipAlternateText } ` }
403
432
</ span >
404
- ) : (
405
- disableChip &&
406
- value . length > 1 && (
407
- < span
408
- className = 'msl-single-value'
409
- data-msl
410
- style = { {
411
- width :
412
- width -
413
- ( clearable && downArrow
414
- ? 60
415
- : downArrow || clearable
416
- ? 40
417
- : 5 )
418
- } }
419
- >
420
- { value . length } Selected
421
- </ span >
422
- )
423
- ) }
433
+ ) }
424
434
{ singleSelect && value . length === 1 && (
425
435
< span
426
436
className = 'msl-single-value'
427
437
data-msl
428
- style = { {
429
- width :
430
- width -
431
- ( clearable && downArrow
432
- ? 60
433
- : downArrow || clearable
434
- ? 40
435
- : 5 )
436
- } }
438
+ style = { { width : calculatedWidth } }
437
439
>
438
- { value [ 0 ] . label }
440
+ { showLabel ( value [ 0 ] ) }
439
441
</ span >
440
442
) }
441
443
{ showSearchOption ( ) && (
@@ -454,6 +456,7 @@ function MultiSelect({
454
456
{ clearable && value . length > 0 && (
455
457
< div
456
458
role = 'button'
459
+ clickable = 'true'
457
460
aria-label = 'close-menu'
458
461
onClick = { clearValue }
459
462
onKeyPress = { clearValue }
@@ -503,12 +506,12 @@ function MultiSelect({
503
506
} }
504
507
/>
505
508
) : (
506
- ( ( search && ! search . length ) || ( options && ! options . length ) ) && (
507
- < option className = 'msl-option msl-option-disable' >
508
- { emptyDataLabel }
509
- </ option >
510
- )
511
- ) }
509
+ ( ( search && ! search . length ) || ( options && ! options . length ) ) && (
510
+ < option className = 'msl-option msl-option-disable' >
511
+ { emptyDataLabel }
512
+ </ option >
513
+ )
514
+ ) }
512
515
</ div >
513
516
</ div >
514
517
)
0 commit comments