1
1
import clsx from 'clsx' ;
2
- import React , { useContext , useState } from 'react' ;
2
+ import React , { useContext , useMemo , useCallback } from 'react' ;
3
3
import { AccordionContext } from '../AccordionContext' ;
4
4
import type { AccordionItemProps } from './types' ;
5
5
import MDBCollapse from '../../Collapse/Collapse' ;
@@ -21,26 +21,42 @@ const MDBAccordionItem: React.FC<AccordionItemProps> = React.forwardRef<HTMLAllC
21
21
} ,
22
22
ref
23
23
) => {
24
- const { activeItem, setActiveItem, alwaysOpen, initialActive } = useContext ( AccordionContext ) ;
24
+ const { activeItem, setActiveItem, alwaysOpen, onChange } = useContext ( AccordionContext ) ;
25
25
26
- const [ openState , setOpenState ] = useState ( initialActive ) ;
26
+ const isCollapsed : boolean = useMemo ( ( ) => {
27
+ const isArray = Array . isArray ( activeItem ) ;
28
+ if ( isArray ) {
29
+ return activeItem . includes ( collapseId ) ;
30
+ }
31
+ return activeItem === collapseId ;
32
+ } , [ activeItem , collapseId ] ) ;
27
33
28
34
const classes = clsx ( 'accordion-item' , className ) ;
29
35
const headerClasses = clsx ( 'accordion-header' , headerClassName ) ;
30
36
const bodyClasses = clsx ( 'accordion-body' , bodyClassName ) ;
31
- const buttonClasses = clsx (
32
- 'accordion-button' ,
33
- alwaysOpen ? collapseId !== openState && 'collapsed' : collapseId !== activeItem && 'collapsed' ,
34
- btnClassName
35
- ) ;
37
+ const buttonClasses = clsx ( 'accordion-button' , ! isCollapsed && 'collapsed' , btnClassName ) ;
36
38
37
- const toggleAccordion = ( value : number ) => {
38
- if ( alwaysOpen ) {
39
- value !== openState ? setOpenState ( value ) : setOpenState ( 0 ) ;
40
- } else {
41
- value !== activeItem ? setActiveItem ( value ) : setActiveItem ( 0 ) ;
42
- }
43
- } ;
39
+ const toggleAccordion = useCallback (
40
+ ( itemId : number ) => {
41
+ let newValue : number | number [ ] = itemId ;
42
+ const isArray = Array . isArray ( activeItem ) ;
43
+
44
+ if ( isArray ) {
45
+ activeItem . includes ( itemId )
46
+ ? ( newValue = activeItem . filter ( ( item ) => item !== itemId ) )
47
+ : ( newValue = alwaysOpen ? [ ...activeItem , itemId ] : [ itemId ] ) ;
48
+ } else {
49
+ newValue = activeItem === itemId ? 0 : itemId ;
50
+
51
+ // if alwaysOpen is true, we must convert newValue to array
52
+ alwaysOpen && ( newValue = [ newValue ] ) ;
53
+ }
54
+
55
+ onChange ?.( newValue ) ;
56
+ setActiveItem ( newValue ) ;
57
+ } ,
58
+ [ onChange , activeItem , setActiveItem , alwaysOpen ]
59
+ ) ;
44
60
45
61
return (
46
62
< Tag className = { classes } ref = { ref } { ...props } >
@@ -49,10 +65,7 @@ const MDBAccordionItem: React.FC<AccordionItemProps> = React.forwardRef<HTMLAllC
49
65
{ headerTitle }
50
66
</ button >
51
67
</ h2 >
52
- < MDBCollapse
53
- id = { collapseId . toString ( ) }
54
- show = { alwaysOpen ? openState === collapseId : activeItem === collapseId }
55
- >
68
+ < MDBCollapse id = { collapseId . toString ( ) } show = { isCollapsed } >
56
69
< div className = { bodyClasses } style = { bodyStyle } >
57
70
{ children }
58
71
</ div >
0 commit comments