1
1
'use client' ;
2
- import React , { useMemo } from 'react' ;
2
+ import React , { useEffect , useMemo } from 'react' ;
3
3
import Collapse from './collapse' ;
4
4
import useCurrentState from '../utils/use-current-state' ;
5
5
import { setChildrenIndex } from '../utils/collections' ;
@@ -8,39 +8,53 @@ import useScale, { withScale } from '../use-scale';
8
8
import useClasses from '../use-classes' ;
9
9
10
10
interface Props {
11
- accordion ?: boolean ;
11
+ multiple ?: boolean ;
12
12
className ?: string ;
13
+ value ?: number [ ] ;
14
+ onChange ?: ( openIndices : number [ ] ) => void ;
13
15
}
14
16
15
17
type NativeAttrs = Omit < React . HTMLAttributes < HTMLDivElement > , keyof Props > ;
16
18
export type CollapseGroupProps = Props & NativeAttrs ;
17
19
18
20
const CollapseGroupComponent : React . FC < React . PropsWithChildren < CollapseGroupProps > > = ( {
19
21
children,
20
- accordion = true ,
21
- className = '' ,
22
+ multiple = true ,
23
+ className,
24
+ value = [ ] ,
25
+ onChange,
22
26
...props
23
27
} : React . PropsWithChildren < CollapseGroupProps > ) => {
24
28
const { SCALE , UNIT , CLASS_NAMES } = useScale ( ) ;
25
29
26
- const [ state , setState , stateRef ] = useCurrentState < Array < number > > ( [ ] ) ;
30
+ const [ state , setState , stateRef ] = useCurrentState < Array < number > > ( value ) ;
27
31
const classes = useClasses ( 'collapse-group' , className , CLASS_NAMES ) ;
28
32
29
- const updateValues = ( currentIndex : number , nextState : boolean ) => {
30
- const hasChild = stateRef . current . find ( val => val === currentIndex ) ;
31
- if ( accordion ) {
32
- if ( nextState ) return setState ( [ currentIndex ] ) ;
33
- return setState ( [ ] ) ;
33
+ useEffect ( ( ) => {
34
+ setState ( value ) ;
35
+ } , [ value . join ( ',' ) ] ) ;
36
+
37
+ useEffect ( ( ) => {
38
+ if ( onChange ) {
39
+ onChange ( state ) ;
34
40
}
41
+ } , [ state ] ) ;
35
42
36
- if ( nextState ) {
37
- // In a few cases, the user will set Collapse Component state manually.
38
- // If the user incorrectly set the state, Group component should ignore it.
39
- /* istanbul ignore if */
40
- if ( hasChild ) return ;
41
- return setState ( [ ...stateRef . current , currentIndex ] ) ;
43
+ const updateValues = ( currentIndex : number , nextState : boolean ) => {
44
+ if ( ! multiple ) {
45
+ if ( nextState ) {
46
+ setState ( [ currentIndex ] ) ;
47
+ } else {
48
+ setState ( [ ] ) ;
49
+ }
50
+ } else {
51
+ const currentIndexExists = state . includes ( currentIndex ) ;
52
+ if ( nextState && ! currentIndexExists ) {
53
+ setState ( [ ...state , currentIndex ] ) ;
54
+ } else if ( ! nextState && currentIndexExists ) {
55
+ setState ( state . filter ( item => item !== currentIndex ) ) ;
56
+ }
42
57
}
43
- setState ( stateRef . current . filter ( item => item !== currentIndex ) ) ;
44
58
} ;
45
59
46
60
const initialValue = useMemo < CollapseConfig > (
0 commit comments