import * as React from 'react' ; type FeatureGroup = { [ featureName ] : boolean | FeatureGroup ; } ; export type FeatureFlags = string [ ] | FeatureGroup ; const FeatureFlagsContext = React . createContext < FeatureGroup > ( { } ) ; function transformFlags ( features ) { if ( ! Array . isArray ( features ) ) return features ; return Object . fromEntries ( features . map ( feature => [ feature , true ] ) ) ; } function mergeFeatures ( a , b ) { return { ... a , ... b } ; } export function FlagsProvider ( { features = { } , children , } ) { const currentFeatures = useFeatures ( ) ; return ( < FeatureFlagsContext . Provider value = { mergeFeatures ( transformFlags ( currentFeatures ) , transformFlags ( features ) ) } > { children } < /FeatureFlagsContext.Provider>); } export function useFeatures ( ) { return React . useContext ( FeatureFlagsContext ) ; } export function useFeature ( name ) { const features = useFeatures ( ) ; if ( Array . isArray ( features ) ) return features . includes ( name ) ; if ( typeof features [ name ] === 'boolean' ) return features [ name ] ; return name . split ( '/' ) . reduce < FeatureGroup | boolean > ( ( featureGroup , featureName ) => { if ( typeof featureGroup === 'boolean' ) return featureGroup ; if ( featureGroup [ featureName ] === undefined ) return false ; return featureGroup [ featureName ] ; } , features ) ; } export function Feature ( { name , children , render = children , } ) { const hasFeature = useFeature ( name ) ; if ( typeof render === 'function' ) return render ( hasFeature ) ; if ( ! hasFeature ) return null ; return render ; } export function withFeature ( featureName ) { return ( Component ) => ( props ) => { return ( < Feature name = { featureName } > < Component { ... props } / > < /Feature>); } ; }