import { Axis , AXIS_PROPERTIES } from 'vega-lite/build/src/axis' ; import { BinParams } from 'vega-lite/build/src/bin' ; import { Legend , LEGEND_PROPERTIES } from 'vega-lite/build/src/legend' ; import { Scale , SCALE_PROPERTIES } from 'vega-lite/build/src/scale' ; import { EncodingSortField } from 'vega-lite/build/src/sort' ; import { Flag } from 'vega-lite/build/src/util' ; import { AutoCountQuery , FieldQuery , ValueQuery } from './query/encoding' ; import { TransformQuery } from './query/transform' ; import { Diff , flagKeys } from './util' ; /**
 * There are two types of `Property`'s.
 * One is just flat property names.
 * (Try to hover `FlatProp` to see all of them.)
 * Another is an object that describes a parent property (e.g., `scale`) and the child property (e.g., `type`)
 */ export type Property = FlatProp | EncodingNestedProp ; export type FlatProp = MarkProp | TransformProp | ViewProp | EncodingTopLevelProp ; export type MarkProp = 'mark' | 'stack' ; export type TransformProp = keyof TransformQuery ; export type ViewProp = 'width' | 'height' | 'background' | 'padding' | 'title' ; export type EncodingTopLevelProp = Diff < keyof ( FieldQuery & ValueQuery & AutoCountQuery ) , 'description' > ; export type EncodingNestedProp = BinProp | SortProp | ScaleProp | AxisProp | LegendProp ; export type EncodingNestedChildProp = keyof BinParams | keyof EncodingSortField < string > | keyof Scale | keyof Axis | keyof Legend < any > ; /**
 * An object that describes a parent property (e.g., `scale`) and the child property (e.g., `type`)
 */ export type BaseEncodingNestedProp < P , T > = { parent : P ; child : keyof T ; } ; export type BinProp = BaseEncodingNestedProp < 'bin' , BinParams > ; export type SortProp = BaseEncodingNestedProp < 'sort' , EncodingSortField < string > > ; export type ScaleProp = BaseEncodingNestedProp < 'scale' , Scale > ; export type AxisProp = BaseEncodingNestedProp < 'axis' , Axis > ; export type LegendProp = BaseEncodingNestedProp < 'legend' , Legend < any > > ; export function isEncodingNestedProp ( p ) { return ! ! p [ 'parent' ] ; } const ENCODING_TOPLEVEL_PROP_INDEX = { channel : 1 , aggregate : 1 , autoCount : 1 , bin : 1 , timeUnit : 1 , hasFn : 1 , sort : 1 , stack : 1 , field : 1 , type : 1 , format : 1 , scale : 1 , axis : 1 , legend : 1 , value : 1 , } ; export const ENCODING_TOPLEVEL_PROPS = flagKeys ( ENCODING_TOPLEVEL_PROP_INDEX ) ; export function isEncodingTopLevelProperty ( p ) { return p . toString ( ) in ENCODING_TOPLEVEL_PROP_INDEX ; } export type EncodingNestedPropParent = 'bin' | 'scale' | 'sort' | 'axis' | 'legend' ; const ENCODING_NESTED_PROP_PARENT_INDEX = { bin : 1 , scale : 1 , sort : 1 , axis : 1 , legend : 1 , } ; export function isEncodingNestedParent ( prop ) { return ENCODING_NESTED_PROP_PARENT_INDEX [ prop as string ] ; } export const BIN_CHILD_PROPS = [ 'maxbins' , 'divide' , 'extent' , 'base' , 'step' , 'steps' , 'minstep' ] ; export const SORT_CHILD_PROPS = [ 'field' , 'op' , 'order' ] ; const BIN_PROPS = BIN_CHILD_PROPS . map ( ( c ) : BinProp => { return { parent : 'bin' , child : c } ; } ) ; export const SORT_PROPS = SORT_CHILD_PROPS . map ( ( c ) : SortProp => { return { parent : 'sort' , child : c } ; } ) ; export const SCALE_PROPS = SCALE_PROPERTIES . map ( ( c ) : ScaleProp => { return { parent : 'scale' , child : c } ; } ) ; const AXIS_PROPS = AXIS_PROPERTIES . map ( ( c ) : AxisProp => { return { parent : 'axis' , child : c } ; } ) ; const LEGEND_PROPS = LEGEND_PROPERTIES . map ( ( c ) : LegendProp => { return { parent : 'legend' , child : c } ; } ) ; export const ENCODING_NESTED_PROPS = ( [ ] as EncodingNestedProp [ ] ) . concat ( BIN_PROPS , SORT_PROPS , SCALE_PROPS , AXIS_PROPS , LEGEND_PROPS ) ; export const VIEW_PROPS = [ 'width' , 'height' , 'background' , 'padding' , 'title' ] as Property [ ] ; const PROP_KEY_DELIMITER = '.' ; export function toKey ( p ) { if ( isEncodingNestedProp ( p ) ) { return p . parent + PROP_KEY_DELIMITER + p . child ; } return p ; } export function fromKey ( k ) { const split = k . split ( PROP_KEY_DELIMITER ) ; if ( split . length === 1 ) { return k as Property ; } else if ( split . length === 2 ) { return { parent : split [ 0 ] , child : split [ 1 ] , } as EncodingNestedProp ; } else { throw `Invalid property key with ${ split . length } dots: ${ k }` ; } } const ENCODING_NESTED_PROP_INDEX = ENCODING_NESTED_PROPS . reduce ( ( i , prop ) => { i [ prop . parent ] = i [ prop . parent ] || [ ] ; i [ prop . parent ] [ prop . child ] = prop ; return i ; } , { } ) ; export function getEncodingNestedProp ( parent , child ) { return ( ENCODING_NESTED_PROP_INDEX [ parent ] || { } ) [ child ] ; } export function isEncodingProperty ( p ) { return isEncodingTopLevelProperty ( p ) || isEncodingNestedProp ( p ) ; } export const ALL_ENCODING_PROPS = ( [ ] as Property [ ] ) . concat ( ENCODING_TOPLEVEL_PROPS , ENCODING_NESTED_PROPS ) ; export const DEFAULT_PROP_PRECEDENCE = ( [ 'type' , 'field' , 'bin' , 'timeUnit' , 'aggregate' , 'autoCount' , 'channel' , 'mark' , 'stack' , 'scale' , 'sort' , 'axis' , 'legend' , ] as Property [ ] ) . concat ( BIN_PROPS , SCALE_PROPS , AXIS_PROPS , LEGEND_PROPS , SORT_PROPS ) ; export namespace Property { export const MARK = 'mark' ; export const TRANSFORM = 'transform' ; export const STACK = 'stack' ; export const FORMAT = 'format' ; export const CHANNEL = 'channel' ; export const AGGREGATE = 'aggregate' ; export const AUTOCOUNT = 'autoCount' ; export const BIN = 'bin' ; export const HAS_FN = 'hasFn' ; export const TIMEUNIT = 'timeUnit' ; export const FIELD = 'field' ; export const TYPE = 'type' ; export const SORT = 'sort' ; export const SCALE = 'scale' ; export const AXIS = 'axis' ; export const LEGEND = 'legend' ; export const WIDTH = 'width' ; export const HEIGHT = 'height' ; export const BACKGROUND = 'background' ; export const PADDING = 'padding' ; export const TITLE = 'title' ; }