import { MutableRefObject , Ref } from 'react' ; type OptionalRef < T > = Ref < T > | undefined ; export default function composeRefs < T > ( ... refs ) { if ( refs . length === 2 ) { return composeTwoRefs ( refs [ 0 ] , refs [ 1 ] ) || null ; } const composedRef = refs . slice ( 1 ) . reduce ( ( semiCombinedRef , refToInclude ) => composeTwoRefs ( semiCombinedRef , refToInclude ) , refs [ 0 ] ) ; return composedRef || null ; } type NonNullRef < T > = NonNullable < Ref < T > > ; const composedRefCache = new WeakMap < NonNullRef < unknown > , WeakMap < NonNullRef < unknown > , NonNullRef < unknown > > > ( ) ; function composeTwoRefs < T > ( ref1 , ref2 ) { if ( ref1 && ref2 ) { const ref1Cache = composedRefCache . get ( ref1 ) || new WeakMap < NonNullRef < unknown > , NonNullRef < unknown > > ( ) ; composedRefCache . set ( ref1 , ref1Cache ) ; const composedRef = ref1Cache . get ( ref2 ) || ( ( instance ) : void => { updateRef ( ref1 , instance ) ; updateRef ( ref2 , instance ) ; } ) ; ref1Cache . set ( ref2 , composedRef ) ; return composedRef as NonNullRef < T > ; } if ( ! ref1 ) { return ref2 ; } else { return ref1 ; } } function updateRef < T > ( ref , instance ) { if ( typeof ref === 'function' ) { ref ( instance ) ; } else { ( ref as MutableRefObject < T | null > ) . current = instance ; } }