import React from 'react' ; import { isWeb , useIsomorphicLayoutEffect } from '../constants/platform' ; import { addMediaQueryListener , mediaState , removeMediaQueryListener } from './useMedia' ; type FeatureDefinition = { isEnabled : ( props : any ) => boolean ; Component : any ; } ; const createDefinition = ( { Component , propNames , } ) : FeatureDefinition => ( { isEnabled : ( props ) => propNames . some ( ( name ) => ! ! props [ name ] ) , Component , } ) ; let featureDefinitions = null ; export const useFeatures = ( props , utils ? ) => { if ( ! featureDefinitions ) { featureDefinitions = loadFeatures ( ) ; } const features = [ ] ; for ( const name in featureDefinitions ) { const { isEnabled , Component } = featureDefinitions [ name ] ; if ( isEnabled ( props ) && Component ) { features . push ( < Component key = { name } { ... props } _utils = { utils } / > ) ; } } return features ; } ; function loadFeatures ( ) { return { ... ( ! isWeb && { mediaQuery : loadMediaQueryFeature ( ) , } ) , } ; } function loadMediaQueryFeature ( ) { const mediaPropNames = Object . keys ( mediaState ) ; return createDefinition ( { Component : ( props ) => { const keys = mediaPropNames . flatMap ( ( x ) => ( x in props ? x . slice ( 1 ) : [ ] ) ) ; useIsomorphicLayoutEffect ( ( ) => { for ( const key of keys ) { addMediaQueryListener ( key , props . _utils . forceUpdate ) ; } return ( ) => { for ( const key of keys ) { removeMediaQueryListener ( key , props . _utils . forceUpdate ) ; } } ; } , [ keys . join ( ',' ) ] ) ; return null ; } , propNames : mediaPropNames , } ) ; }