-
Notifications
You must be signed in to change notification settings - Fork 592
/
ScaleInvalidDataMode.ts
68 lines (61 loc) · 2.38 KB
/
ScaleInvalidDataMode.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
57
58
59
60
61
62
63
64
65
66
67
68
import {SignalRef} from 'vega';
import {ScaleChannel, isPolarPositionChannel, isXorY} from '../../channel';
import {Config} from '../../config';
import {ScaleInvalidDataIncludeAs} from '../../invalid';
import {MarkDef, isPathMark} from '../../mark';
import {ScaleType, hasContinuousDomain} from '../../scale';
import {getMarkPropOrConfig} from '../common';
import {normalizeInvalidDataMode} from './normalizeInvalidDataMode';
export type ScaleInvalidDataMode<C extends ScaleChannel> =
| 'always-valid'
| 'filter'
| 'break-paths'
| 'break-paths-keep-domains'
| ScaleInvalidDataInclude<C>;
export interface ScaleInvalidDataInclude<C extends ScaleChannel> {
includeAs: ScaleInvalidDataIncludeAs<C>;
}
export function isScaleInvalidDataInclude<C extends ScaleChannel>(
invalidDataMode: ScaleInvalidDataMode<C>
): invalidDataMode is ScaleInvalidDataInclude<C> {
return (invalidDataMode as ScaleInvalidDataInclude<C>).includeAs !== undefined;
}
export function getScaleInvalidDataMode<C extends ScaleChannel>({
markDef,
config,
scaleChannel,
scaleType,
isCountAggregate
}: {
markDef: MarkDef;
config: Config<SignalRef>;
scaleChannel: C;
scaleType: ScaleType;
isCountAggregate: boolean;
}): ScaleInvalidDataMode<C> {
if (!scaleType || !hasContinuousDomain(scaleType) || isCountAggregate) {
// - Discrete scales can always display null as another category
// - Count cannot output null values
return 'always-valid';
}
const invalidMode = normalizeInvalidDataMode(getMarkPropOrConfig('invalid', markDef, config), {
isPath: isPathMark(markDef.type)
});
const scaleOutputForInvalid = config.scale?.invalid?.[scaleChannel];
if (scaleOutputForInvalid !== undefined) {
// Regardless of the current invalid mode, if the channel has a default value, we consider the field valid.
return {includeAs: scaleOutputForInvalid};
}
if (invalidMode === 'include') {
// TODO: it's arguable if we should make the behavior inconsistent between position and non-position.
// But this initial PR, we keep the behavior consistent (no breaking changes).
if (isXorY(scaleChannel) || isPolarPositionChannel(scaleChannel)) {
return {includeAs: 'min'};
}
return {includeAs: 'zero-or-min'};
}
return invalidMode;
}
export function shouldBreakPath(mode: ScaleInvalidDataMode<any>): boolean {
return mode === 'break-paths' || mode === 'break-paths-keep-domains';
}