11import clsx from 'clsx' ;
2- import React , { useContext , useState } from 'react' ;
2+ import React , { useContext , useMemo , useCallback } from 'react' ;
33import { AccordionContext } from '../AccordionContext' ;
44import type { AccordionItemProps } from './types' ;
55import MDBCollapse from '../../Collapse/Collapse' ;
@@ -21,26 +21,42 @@ const MDBAccordionItem: React.FC<AccordionItemProps> = React.forwardRef<HTMLAllC
2121 } ,
2222 ref
2323 ) => {
24- const { activeItem, setActiveItem, alwaysOpen, initialActive } = useContext ( AccordionContext ) ;
24+ const { activeItem, setActiveItem, alwaysOpen, onChange } = useContext ( AccordionContext ) ;
2525
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 ] ) ;
2733
2834 const classes = clsx ( 'accordion-item' , className ) ;
2935 const headerClasses = clsx ( 'accordion-header' , headerClassName ) ;
3036 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 ) ;
3638
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+ ) ;
4460
4561 return (
4662 < Tag className = { classes } ref = { ref } { ...props } >
@@ -49,10 +65,7 @@ const MDBAccordionItem: React.FC<AccordionItemProps> = React.forwardRef<HTMLAllC
4965 { headerTitle }
5066 </ button >
5167 </ h2 >
52- < MDBCollapse
53- id = { collapseId . toString ( ) }
54- show = { alwaysOpen ? openState === collapseId : activeItem === collapseId }
55- >
68+ < MDBCollapse id = { collapseId . toString ( ) } show = { isCollapsed } >
5669 < div className = { bodyClasses } style = { bodyStyle } >
5770 { children }
5871 </ div >
0 commit comments