1- import React , { ReactElement } from 'react' ;
1+ import React , { useEffect , useState , ReactElement , ReactNode } from 'react' ;
22import { TransitionGroup } from 'react-transition-group' ;
33import { ValueContainerProps } from '../components/containers' ;
44import { GroupBase } from '../types' ;
@@ -11,12 +11,92 @@ export type ValueContainerComponent = <
1111 props : ValueContainerProps < Option , IsMulti , Group >
1212) => ReactElement ;
1313
14+ interface IsMultiValueContainerProps extends ValueContainerProps {
15+ component : ValueContainerComponent ;
16+ }
17+
1418// make ValueContainer a transition group
1519const AnimatedValueContainer =
1620 ( WrappedComponent : ValueContainerComponent ) =>
1721 < Option , IsMulti extends boolean , Group extends GroupBase < Option > > (
1822 props : ValueContainerProps < Option , IsMulti , Group >
1923 ) =>
20- < TransitionGroup component = { WrappedComponent } { ...( props as any ) } /> ;
24+ props . isMulti ? (
25+ < IsMultiValueContainer component = { WrappedComponent } { ...( props as any ) } />
26+ ) : (
27+ < TransitionGroup component = { WrappedComponent } { ...( props as any ) } />
28+ ) ;
29+
30+ const IsMultiValueContainer = ( {
31+ component,
32+ ...restProps
33+ } : IsMultiValueContainerProps ) => {
34+ const multiProps = useIsMultiValueContainer ( restProps ) ;
35+
36+ return < TransitionGroup component = { component } { ...( multiProps as any ) } /> ;
37+ } ;
38+
39+ const useIsMultiValueContainer = ( {
40+ children,
41+ ...props
42+ } : ValueContainerProps ) => {
43+ const {
44+ isMulti,
45+ hasValue,
46+ innerProps,
47+ selectProps : { components, controlShouldRenderValue } ,
48+ } = props ;
49+
50+ const [ cssDisplayFlex , setCssDisplayFlex ] = useState (
51+ isMulti && controlShouldRenderValue && hasValue
52+ ) ;
53+ const [ removingValue , setRemovingValue ] = useState ( false ) ;
54+
55+ useEffect ( ( ) => {
56+ if ( hasValue && ! cssDisplayFlex ) {
57+ setCssDisplayFlex ( true ) ;
58+ }
59+ } , [ hasValue , cssDisplayFlex ] ) ;
60+
61+ useEffect ( ( ) => {
62+ if ( removingValue && ! hasValue && cssDisplayFlex ) {
63+ setCssDisplayFlex ( false ) ;
64+ }
65+ setRemovingValue ( false ) ;
66+ } , [ removingValue , hasValue , cssDisplayFlex ] ) ;
67+
68+ const onExited = ( ) => setRemovingValue ( true ) ;
69+
70+ const childMapper = ( child : ReactNode ) => {
71+ if ( isMulti && React . isValidElement ( child ) ) {
72+ // Add onExited callback to MultiValues
73+ if ( child . type === components . MultiValue ) {
74+ return React . cloneElement ( child , { onExited } ) ;
75+ }
76+ // While container flexed, Input cursor is shown after Placeholder text,
77+ // so remove Placeholder until display is set back to grid
78+ if ( child . type === components . Placeholder && cssDisplayFlex ) {
79+ return null ;
80+ }
81+ }
82+ return child ;
83+ } ;
84+
85+ const newInnerProps = {
86+ ...innerProps ,
87+ style : {
88+ ...innerProps ?. style ,
89+ display : cssDisplayFlex ? 'flex' : 'grid' ,
90+ } ,
91+ } ;
92+
93+ const newProps = {
94+ ...props ,
95+ innerProps : newInnerProps ,
96+ children : React . Children . toArray ( children ) . map ( childMapper ) ,
97+ } ;
98+
99+ return newProps ;
100+ } ;
21101
22102export default AnimatedValueContainer ;
0 commit comments