import { group , line , rect , svg , text } from "@thi.ng/hiccup-svg" ; import { fit , fit01 } from "@thi.ng/math" ; import { map , mapcat , mapIndexed , range } from "@thi.ng/transducers" ; const mappedRange = ( from , to , step , start , end ) => map ( ( n ) => [ fit ( n , from , to , start , end ) , n ] , range ( from , to , step ) ) ; const mappedTicks = ( start , end , ticks ) => mapIndexed ( ( i , x ) => [ fit01 ( i / ticks . length , start , end ) , x ] , 0 , ticks ) ; export const tick = ( x1 , y1 , x2 , y2 , tx , ty , label ) => [ line ( [ x1 , y1 ] , [ x2 , y2 ] ) , text ( [ tx , ty ] , label , { stroke : "none" } ) ] ; const tickX = ( y ) => ( [ x , n ] ) => tick ( x , y , x , y + 10 , x , y + 20 , n ) ; const tickY = ( x ) => ( [ y , n ] ) => tick ( x - 10 , y , x , y , x - 15 , y , n ) ; export const labeledTickX = ( y ) => ( [ x , n ] ) => [ line ( [ x , y ] , [ x , y + 5 ] ) , text ( [ x , y + 15 ] , n , { stroke : "none" , "text-anchor" : "end" , transform : `rotate(-45 ${ x } ${ y + 15 })` , } ) , ] ; export const labeledTickY = ( width , fmt = ( x ) => String ( x ) ) => ( x ) => ( [ y , n ] ) => [ ... tick ( x - 5 , y , x , y , x - 10 , y + 4 , n > 0 ? fmt ( n ) : 0 ) , n > 0 ? line ( [ x + 20 , y ] , [ width , y ] , { "stroke-dasharray" : "1 3" } ) : null , ] ; export const axisX = ( { axis : a , domain : d , range : r , label , ticks } ) => [ "g" , { "text-anchor" : "middle" } , line ( [ a [ 0 ] , a [ 2 ] ] , [ a [ 1 ] , a [ 2 ] ] ) , mapcat ( ( label || tickX ) ( a [ 2 ] ) , ticks ? mappedTicks ( r [ 0 ] , r [ 1 ] , ticks ) : mappedRange ( d [ 0 ] , d [ 1 ] , d [ 2 ] , r [ 0 ] , r [ 1 ] ) ) , ] ; export const axisY = ( { axis : a , domain : d , range : r , label , ticks } ) => [ "g" , { "text-anchor" : "end" } , line ( [ a [ 2 ] , a [ 0 ] ] , [ a [ 2 ] , a [ 1 ] ] ) , mapcat ( ( label || tickY ) ( a [ 2 ] ) , ticks ? mappedTicks ( r [ 0 ] , r [ 1 ] , ticks ) : mappedRange ( d [ 0 ] , d [ 1 ] , d [ 2 ] , r [ 0 ] , r [ 1 ] ) ) , ] ; const bar = ( { domain : xd , range : xr } , { domain : yd , range : yr } ) => ( [ xx , yy ] ) => { const y = fit ( yy , yd [ 0 ] , yd [ 1 ] , yr [ 0 ] , yr [ 1 ] ) ; return rect ( [ fit ( xx , xd [ 0 ] , xd [ 1 ] , xr [ 0 ] , xr [ 1 ] ) - 5 , y ] , 10 , yr [ 0 ] - y ) ; } ; export const barChart = ( _ , opts , values , ... xs ) => svg ( opts . attribs , group ( { stroke : opts . axis , fill : opts . axis } , axisX ( opts . x ) , axisY ( opts . y ) ) , group ( { fill : opts . fill } , map ( bar ( opts . x , opts . y ) , values ) ) , ... xs ) ;