import { FC , useEffect , useMemo } from 'react' ; import { useDispatch } from 'react-redux' ; import { bindActionCreators } from 'redux' ; import { OptionalKeys , RequiredKeys } from 'utility-types' ; import { Spec as Spec } from '../specs' ; import { stripUndefined } from '../utils/common' ; import { upsertSpec as upsertSpecAction , removeSpec as removeSpecAction } from './actions/specs' ; internal export interface DispatchProps { upsertSpec : typeof upsertSpecAction ; removeSpec : typeof removeSpecAction ; } internal export function useSpecFactory < Props extends Spec > ( props ) { const dispatch = useDispatch ( ) ; const { upsertSpec , removeSpec } = useMemo ( ( ) => ( { upsertSpec : bindActionCreators ( upsertSpecAction , dispatch ) , removeSpec : bindActionCreators ( removeSpecAction , dispatch ) , } ) , [ dispatch ] ) ; useEffect ( ( ) => { upsertSpec ( props ) ; } ) ; useEffect ( ( ) => ( ) => { removeSpec ( props . id ) ; } , [ ] ) ; } internal export const specComponentFactory = < S extends Spec > ( ) => < Overrides extends SFOverrideKeys < S > , Defaults extends SFDefaultKeys < S , Overrides > , Optionals extends SFOptionalKeys < S , Overrides , Defaults > , Requires extends SFRequiredKeys < S , Overrides , Defaults , Optionals > > ( overrides , defaults ) : FC < SFProps < S , Overrides , Defaults , Optionals , Requires > > => { return ( props ) => { useSpecFactory < S > ( { ... defaults , ... stripUndefined ( props ) , ... overrides } ) ; return null ; } ; } ; internal export const buildSFProps = < S extends Spec > ( ) => < Overrides extends SFOverrideKeys < S > , Defaults extends SFDefaultKeys < S , Overrides > , Optionals extends SFOptionalKeys < S , Overrides , Defaults > , Requires extends SFRequiredKeys < S , Overrides , Defaults , Optionals > > ( overrides , defaults ) : BuildProps < S , Overrides , Defaults , Optionals , Requires > => ( { overrides , defaults , optionals : { } as Pick < S , Optionals > , requires : { } as Pick < S , Requires > , } ) ; public export type SFProps < S extends Spec , Overrides extends SFOverrideKeys < S > , Defaults extends SFDefaultKeys < S , Overrides > , Optionals extends SFOptionalKeys < S , Overrides , Defaults > , Requires extends SFRequiredKeys < S , Overrides , Defaults , Optionals > > = Pick < S , Optionals | Requires > & Partial < Pick < S , Defaults > > ; public export interface BuildProps < S extends Spec , Overrides extends SFOverrideKeys < S > , Defaults extends SFDefaultKeys < S , Overrides > , Optionals extends SFOptionalKeys < S , Overrides , Defaults > , Requires extends SFRequiredKeys < S , Overrides , Defaults , Optionals > > { overrides : SFOverrides < S , Overrides > ; defaults : SFDefaults < S , Overrides , Defaults > ; deprecated optionals : Pick < S , Optionals > ; deprecated requires : Pick < S , Requires > ; } /** All specs __must__ provide these as overrides */ type RequiredSpecProps = keyof Pick < Spec , 'chartType' | 'specType' > ; type SFOverrideKeys < S extends Spec > = keyof S ; type SFDefaultKeys < S extends Spec , Overrides extends keyof S > = keyof Omit < S , Overrides > ; type SFOptionalKeys < S extends Spec , Overrides extends keyof S , Defaults extends keyof Omit < S , Overrides > > = OptionalKeys < Omit < S , Overrides | Defaults > > ; type SFRequiredKeys < S extends Spec , Overrides extends keyof S , Defaults extends keyof Omit < S , Overrides > , Optionals extends SFOptionalKeys < S , Overrides , Defaults > > = RequiredKeys < Omit < S , Overrides | Defaults | Optionals > > ; type SFOverrides < S extends Spec , Overrides extends keyof S > = Required < Pick < S , Overrides | RequiredSpecProps > > ; type SFDefaults < S extends Spec , Overrides extends SFOverrideKeys < S > , Defaults extends SFDefaultKeys < S , Overrides > > = Required < Pick < S , Defaults > > ;