import { isValidElement , ReactElement } from 'react' ; import { cloneElement } from 'react' ; import invariant from 'tiny-invariant' ; import { ChainableConnectors , ConnectorsRecord } from './interfaces' ; function setRef ( ref , node ) { if ( node ) { if ( typeof ref === 'function' ) { ref ( node ) ; } else { ref . current = node ; } } } export function cloneWithRef ( element , newRef ) { const previousRef = element . ref ; invariant ( typeof previousRef !== 'string' , 'Cannot connect to an element with an existing string ref. ' + 'Please convert it to use a callback ref instead, or wrap it into a <span> or <div>. ' + 'Read more: https://facebook.github.io/react/docs/more-about-refs.html#the-ref-callback-attribute' ) ; if ( ! previousRef ) { return cloneElement ( element , { ref : newRef , } ) ; } else { return cloneElement ( element , { ref : ( node ) => { setRef ( previousRef , node ) ; setRef ( newRef , node ) ; } , } ) ; } } function throwIfCompositeComponentElement ( element ) { if ( typeof element . type === 'string' ) { return ; } throw new Error ( ) ; } export function wrapHookToRecognizeElement ( hook ) { return ( elementOrNode = null , ... args ) => { if ( ! isValidElement ( elementOrNode ) ) { if ( ! elementOrNode ) { return ; } const node = elementOrNode ; node && hook ( node , ... args ) ; return node ; } const element = elementOrNode ; throwIfCompositeComponentElement ( element as any ) ; return cloneWithRef ( element , hook ) ; } ; } export function wrapConnectorHooks < H extends ConnectorsRecord > ( connectors ) { return Object . keys ( connectors ) . reduce ( ( accum , key ) => { accum [ key ] = wrapHookToRecognizeElement ( ( ... args ) => { return connectors [ key ] ( ... args ) ; } ) ; return accum ; } , { } ) as any ; }