forked from vega/vega-lite
/
defined.ts
56 lines (49 loc) · 1.84 KB
/
defined.ts
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
import {POSITION_SCALE_CHANNELS} from '../../../channel';
import {ScaleChannel} from '../../../channel';
import {Value} from '../../../channeldef';
import {hasContinuousDomain} from '../../../scale';
import {Dict, keys} from '../../../util';
import {VgEncodeEntry} from '../../../vega.schema';
import {getMarkPropOrConfig, signalOrValueRef} from '../../common';
import {UnitModel} from '../../unit';
import {fieldInvalidPredicate} from './valueref';
export function defined(model: UnitModel): VgEncodeEntry {
const {config, markDef} = model;
const invalid = getMarkPropOrConfig('invalid', markDef, config);
if (invalid) {
const signal = allFieldsInvalidPredicate(model, {channels: POSITION_SCALE_CHANNELS});
if (signal) {
return {defined: {signal}};
}
}
return {};
}
function allFieldsInvalidPredicate(
model: UnitModel,
{invalid = false, channels}: {invalid?: boolean; channels: ScaleChannel[]}
) {
const filterIndex = channels.reduce((aggregator: Dict<true>, channel) => {
const scaleComponent = model.getScaleComponent(channel);
if (scaleComponent) {
const scaleType = scaleComponent.get('type');
const field = model.vgField(channel, {expr: 'datum', binSuffix: model.stack?.impute ? 'mid' : undefined});
// While discrete domain scales can handle invalid values, continuous scales can't.
if (field && hasContinuousDomain(scaleType)) {
aggregator[field] = true;
}
}
return aggregator;
}, {});
const fields = keys(filterIndex);
if (fields.length > 0) {
const op = invalid ? '||' : '&&';
return fields.map(field => fieldInvalidPredicate(field, invalid)).join(` ${op} `);
}
return undefined;
}
export function valueIfDefined(prop: string, value: Value): VgEncodeEntry {
if (value !== undefined) {
return {[prop]: signalOrValueRef(value)};
}
return undefined;
}