import { AnyAction , Dispatch } from 'redux' ; import { ThunkDispatch } from 'redux-thunk' ; import { compare , EncodeEntry , extend } from 'vega' ; import { getFieldDef } from 'vega-lite/build/src/channeldef' ; import { CompiledBinding } from '.' ; import MARK_EXTENTS from '../../constants/markExtents' ; import { State } from '../../store' ; import { propSg } from '../../util/prop-signal' ; import { disableMarkVisual , setMarkVisual , updateMarkProperty } from '../markActions' ; import { setSignal } from '../signalActions' ; const getInVis = require ( '../../util/immutable-utils' ) . getInVis ; param { Function } dispatch param { ImmutableMap } state param { Object } parsed returns { void } export default function parseMarks ( dispatch , state , parsed ) { const markType = parsed . markType ; const map = parsed . map ; const markId = parsed . markId ; const channel = parsed . channel ; let pathgroup = null ; let def = parsed . output . marks [ 0 ] ; if ( def . type === 'group' && def . name . indexOf ( 'pathgroup' ) >= 0 ) { pathgroup = def ; def = def . marks [ 0 ] ; } if ( markType === 'rect' && ( channel === 'x' || channel === 'y' ) ) { rectSpatial ( dispatch , state , parsed , def . encode . update ) ; } else if ( markType === 'text' && channel === 'text' ) { textTemplate ( dispatch , parsed ) ; } else { bindProperty ( dispatch , parsed , def . encode . update ) ; } if ( pathgroup ) { dispatch ( updateMarkProperty ( { property : '_facet' , value : { ... pathgroup . from . facet , data : map . data [ pathgroup . from . facet . data ] } } , markId ) ) ; } else if ( def . from && def . from . data ) { dispatch ( updateMarkProperty ( { property : 'from' , value : { data : map . data [ def . from . data ] } } , markId ) ) ; } } param { Function } dispatch param { Object } parsed param { Object } def param { string } property returns { void } function bindProperty ( dispatch , parsed , update , property ? ) { const map = parsed . map , markId = parsed . markId , markType = parsed . markType ; property = property || parsed . property ; if ( property === 'detail' ) { return ; } const def = property === 'stroke' ? update . stroke || update . fill : update [ property ] ; if ( 'scale' in def && typeof def . scale === 'string' ) { def . scale = map . scales [ def . scale ] ; } if ( 'value' in def ) { def [ 'signal' ] = propSg ( markId , markType , property ) ; dispatch ( setSignal ( def . value , def [ 'signal' ] ) ) ; delete def . value ; } dispatch ( setMarkVisual ( { property : property , def : def as any } , markId ) ) ; map . marks [ markId ] = map . marks [ markId ] || { } ; map [ property ] = Date . now ( ) ; } param { Function } dispatch param { ImmutableMap } state param { Object } parsed param { Object } def returns { void } const RECT_SPANS = { x : 'width' , y : 'height' } ; function rectSpatial ( dispatch , state , parsed , def ) { const channel = parsed . channel as 'x' | 'y' , property = parsed . property , markId = parsed . markId , map = parsed . map . marks [ markId ] , max = channel + '2' , cntr = channel + 'c' , span = RECT_SPANS [ channel ] , EXTENTS = Object . values ( MARK_EXTENTS [ channel ] ) , props = getInVis ( state , `marks.${ markId }.encode.update` ) ; let count = 0 ; if ( property !== `${ channel }+` ) { EXTENTS . map ( ext => extend ( { } , { ts : ( map && map [ ext . name ] ) || 0 } , ext ) ) . sort ( compare ( 'ts' , 'descending' ) ) . forEach ( ( ext ) => { const name = ext . name ; if ( name === property ) { return ; } else if ( count >= 1 ) { dispatch ( disableMarkVisual ( name , markId ) ) ; } else if ( ! props [ name ] . _disabled ) { ++ count ; } } ) ; def [ property ] = def [ channel ] || def [ cntr ] || def [ property ] ; return bindProperty ( dispatch , parsed , def ) ; } EXTENTS . forEach ( ext => dispatch ( disableMarkVisual ( ext . name , markId ) ) ) ; if ( def [ max ] ) { bindProperty ( dispatch , parsed , def , channel ) ; bindProperty ( dispatch , parsed , def , max ) ; } else { bindProperty ( dispatch , parsed , def , channel ) ; def [ span ] = { scale : ( def [ channel ] as any ) . scale , band : true , offset : - 1 } ; bindProperty ( dispatch , parsed , def , span ) ; } } param { Function } dispatch param { Object } parsed param { Object } def returns { void } function textTemplate ( dispatch , parsed ) { const text = getFieldDef ( parsed . input . encoding . text ) ; dispatch ( setMarkVisual ( { property : 'text' , def : { signal : `datum.${ text . field }` } } , parsed . markId ) ) ; }