import { OperatorFunction , merge , combineLatest , of } from 'rxjs' ; import { share , startWith , map , filter , mapTo , delay , endWith , scan , takeUntil , last } from 'rxjs/operators' ; import { isEqual } from 'lodash' ; export const LOADING = 'loading' as const ; template T export interface MaybeLoadingResult < T > { /**
     * Whether the result provider is currently getting a new result.
     */ isLoading : boolean ; /**
     * The latest result.
     */ result : T ; } param loaderDelay param emptyResultValue template TResult template TEmpty export const emitLoading = < TResult , TEmpty > ( loaderDelay , emptyResultValue ) : OperatorFunction < MaybeLoadingResult < TResult | TEmpty > , TResult | TEmpty | typeof LOADING | undefined > => source => { const sharedSource = source . pipe ( endWith < Partial < MaybeLoadingResult < TResult | TEmpty > > > ( { isLoading : false } ) , scan < Partial < MaybeLoadingResult < TResult | TEmpty > > , MaybeLoadingResult < TResult | TEmpty > > ( ( previous , current ) => ( { ... previous , ... current } ) , { isLoading : true , result : emptyResultValue } ) , share ( ) ) ; return merge ( [ undefined ] , combineLatest ( [ sharedSource . pipe ( startWith ( { isLoading : true , result : emptyResultValue } ) ) , of ( null ) . pipe ( delay ( loaderDelay ) , takeUntil ( sharedSource . pipe ( last ( null , null ) ) ) ) , ] ) . pipe ( filter ( ( [ { isLoading , result } ] ) => isLoading && isEqual ( result , emptyResultValue ) ) , mapTo ( LOADING ) ) , sharedSource . pipe ( filter ( ( { isLoading , result } ) => ! isLoading || ! isEqual ( result , emptyResultValue ) ) , map ( ( { result } ) => result ) ) ) ; } ;