import { Observable , BehaviorSubject , Subscription } from 'rxjs' ; import { tap , share , filter } from 'rxjs/operators' ; import { Atom as _Atom , ReadOnlyAtom , JsonAtom , CombinedAtomViewImpl } from './base' ; export { ReadOnlyAtom } from './base' ; export type Atom < T > = _Atom < T > ; export namespace Atom { export template T param initialValue returns export function create < T > ( initialValue ) { return new JsonAtom ( initialValue ) ; } export function log < T > ( atom , name ? ) ; export function log < T > ( atom , name ? ) ; export function log < T > ( atom , logger ? ) ; export function log < T > ( atom , logger ? ) ; export function log < T > ( atom , logger ? ) { const logState = ( msg , color , x ) => console . log ( '%c' + msg , `color: ${ color }; font-weight: bold` , x ) ; let prevState = atom . get ( ) ; atom . subscribe ( newState => { if ( typeof logger === 'function' ) { logger ( prevState , newState ) ; } else { console . group ( `UPDATE ${ logger ? `TYPE: ${ logger } ` : '' }@ ${ new Date ( ) . toTimeString ( ) }` ) ; logState ( 'prev state' , '#9E9E9E' , prevState ) ; logState ( 'next state' , '#4CAF50' , newState ) ; console . groupEnd ( ) ; } prevState = newState ; } ) ; return atom ; } export function combine < T1 , T2 , TResult > ( source1 , source2 , combineFn ) ; export function combine < T1 , T2 , T3 , TResult > ( source1 , source2 , source3 , combineFn ) ; export function combine < T1 , T2 , T3 , T4 , TResult > ( source1 , source2 , source3 , source4 , combineFn ) ; export function combine < T1 , T2 , T3 , T4 , T5 , TResult > ( source1 , source2 , source3 , source4 , source5 , combineFn ) ; export function combine < T1 , T2 , T3 , T4 , T5 , T6 , TResult > ( source1 , source2 , source3 , source4 , source5 , source6 , combineFn ) ; export function combine < T1 , T2 , T3 , T4 , T5 , T6 , T7 , TResult > ( source1 , source2 , source3 , source4 , source5 , source6 , source7 , combineFn ) ; export function combine < TResult > ( ... args ) { return new CombinedAtomViewImpl < TResult > ( args . slice ( undefined , - 1 ) as ReadOnlyAtom < any > [ ] , xs => ( args [ args . length - 1 ] as ( ( ... xs : any [ ] ) => TResult ) ) ( ... xs ) ) ; } export template T param src returns export function fromObservable < T > ( src ) { const atomSubj = new BehaviorSubject < Atom < T > | null > ( null ) ; const initAndUpdateAtom = src . pipe ( tap ( x => { const atom = atomSubj . value ; if ( atom === null ) { atomSubj . next ( Atom . create ( x ) ) ; } else atom . set ( x ) ; } ) , share ( ) ) ; return new Observable < ReadOnlyAtom < T > > ( o => { const sub = new Subscription ( ) ; sub . add ( atomSubj . pipe ( filter ( ( x ) : x is Atom < T > => ! ! x ) ) . subscribe ( o ) ) ; sub . add ( initAndUpdateAtom . subscribe ( undefined , e => o . error ( e ) , ( ) => o . complete ( ) ) ) ; return sub ; } ) ; } }