import { DEFAULT_IMPL } from "@thi.ng/hdom/default" ; import { replaceChild } from "@thi.ng/hdom/dom" ; import { normalizeTree } from "@thi.ng/hdom/normalize" ; import { memoize1 } from "@thi.ng/memoize/memoize1" ; import { fromInterval } from "@thi.ng/rstream/interval" ; import { updateDOM } from "@thi.ng/transducers-hdom" ; import { cycle } from "@thi.ng/transducers/cycle" ; import { map } from "@thi.ng/transducers/map" ; const COLORS = cycle ( [ "red" , "blue" , "green" , "orange" , "light-blue" ] ) ; /**
 * Abstract base class for components with local state which can
 * re-render themselves on demand, without requiring a full DOM update.
 */ abstract class LocalReRenderable { el ? : HTMLElement ; param el init ( el ) { this . el = el ; } abstract render ( _ , ... args ) ; param args localRender ( ... args ) { const el = this . el ! ; const children = el . parentElement ! . children ; for ( let i = children . length ; i -- > 0 ; ) { if ( children [ i ] === el ) { replaceChild ( { } , DEFAULT_IMPL , this . el ! . parentElement ! , i , normalizeTree ( { } , [ this , ... args ] ) , true ) ; return ; } } } } class Foo extends LocalReRenderable { time ! : number ; col ! : string ; constructor ( public id ) { super ( ) ; this . col = < string > COLORS . next ( ) . value ; } render ( _ , time ) { this . time = time ; return [ `div.dib.w4.br2.pa2.mr2.tc.nosel.bg-${ this . col }` , { __diff : false , onclick : ( ) => { this . col = < string > COLORS . next ( ) . value ; this . localRender ( this . time ) ; } , } , `${ this . id }: ${ time }` , ] ; } } const foo = memoize1 ( ( id ) => new Foo ( id ) ) ; fromInterval ( 2000 ) . transform ( map ( ( time ) => [ "div" , { } , [ foo ( "a" ) , time ] , [ foo ( "b" ) , time ] , [ foo ( "c" ) , time ] , ] ) , updateDOM ( ) ) ;