import React , { Component , ComponentType } from 'react' ; import { Dictionary } from '@brandingbrand/fsfoundation' ; export interface ProjectWrapperComponent { } /**
 * wrapp the component with high order component to support
 * component default props, it can be used to specify project
 * specific styling
 */ export default function applyDefaults < T > ( defaultProps , ComponentHolder ) { if ( isStateless ( ComponentHolder ) ) { return function ProjectWrapperComponent ( props ) : React . ReactElement { const mergedProps = mergeProps ( defaultProps , props ) ; return < ComponentHolder { ... mergedProps } / > ; } ; } else { return class ProjectWrapperComponent extends Component { comp : any ; setValue = ( v ) => { if ( this . comp . setValue ) { this . comp . setValue ( v ) ; } } ; extratRef = ( comp ) => ( this . comp = comp ) ; render ( ) { const mergedProps = mergeProps ( defaultProps , this . props ) ; return < ComponentHolder ref = { this . extratRef } { ... mergedProps } />; } } ; } } /**
 * merge new props to default props,
 * if the default prop is array or object, merge them
 * or override default
 */ export function mergeProps ( defaultProps , newProps ) { if ( ! defaultProps ) { return newProps ; } const props = { ... defaultProps } ; Object . keys ( newProps ) . forEach ( key => { const val = newProps [ key ] ; if ( props [ key ] ) { if ( Array . isArray ( props [ key ] ) ) { if ( Array . isArray ( val ) ) { props [ key ] = [ ... props [ key ] , ... val ] ; } else { props [ key ] = [ ... props [ key ] , val ] ; } } else if ( typeof props [ key ] === 'object' && ! React . isValidElement ( props [ key ] ) ) { if ( typeof val === 'object' ) { props [ key ] = { ... props [ key ] , ... val } ; } else if ( typeof val === 'number' ) { props [ key ] = [ props [ key ] , val ] ; } } else { props [ key ] = val ; } } else { props [ key ] = val ; } } ) ; return props ; } export function isStateless < T > ( Component ) { return ! Component . prototype . render ; }