forked from vega/vega-lite
/
index.ts
132 lines (116 loc) · 4.16 KB
/
index.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
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
import {SignalRef} from 'vega';
import {isString} from 'vega-util';
import {Field} from '../channeldef';
import {Config, initConfig} from '../config';
import * as log from '../log';
import {
FacetedUnitSpec,
isFacetSpec,
isLayerSpec,
isUnitSpec,
LayoutSizeMixins,
NonNormalizedSpec,
NormalizedSpec,
RepeatSpec,
TopLevelSpec
} from '../spec';
import {AutoSizeParams, AutosizeType, TopLevel} from '../spec/toplevel';
import {deepEqual} from '../util';
import {NormalizerParams} from './base';
import {CoreNormalizer} from './core';
import {SelectionCompatibilityNormalizer} from './selectioncompat';
import {TopLevelSelectionsNormalizer} from './toplevelselection';
export function normalize(
spec: TopLevelSpec & LayoutSizeMixins,
config?: Config<SignalRef>
): TopLevel<NormalizedSpec> & LayoutSizeMixins {
if (config === undefined) {
config = initConfig(spec.config);
}
const normalizedSpec = normalizeGenericSpec(spec, config);
const {width, height} = spec;
const autosize = normalizeAutoSize(normalizedSpec, {width, height, autosize: spec.autosize}, config);
return {
...normalizedSpec,
...(autosize ? {autosize} : {})
};
}
const coreNormalizer = new CoreNormalizer();
const selectionCompatNormalizer = new SelectionCompatibilityNormalizer();
const topLevelSelectionNormalizer = new TopLevelSelectionsNormalizer();
/**
* Decompose extended unit specs into composition of pure unit specs.
* And push top-level selection definitions down to unit specs.
*/
function normalizeGenericSpec(
spec: NonNormalizedSpec | FacetedUnitSpec<Field, any> | RepeatSpec,
config: Config<SignalRef> = {}
) {
const normParams = {config};
return topLevelSelectionNormalizer.map(
coreNormalizer.map(selectionCompatNormalizer.map(spec, normParams), normParams),
normParams
);
}
function _normalizeAutoSize(autosize: AutosizeType | AutoSizeParams) {
return isString(autosize) ? {type: autosize} : autosize ?? {};
}
/**
* Normalize autosize and deal with width or height == "container".
*/
export function normalizeAutoSize(
spec: TopLevel<NormalizedSpec>,
sizeInfo: {autosize: AutosizeType | AutoSizeParams} & LayoutSizeMixins,
config?: Config
) {
let {width, height} = sizeInfo;
// A faceted view is only compatible with autosize === "fit" if a specific outer width and/or height is specified in the spec
const isFitCompatibleFacet = isFacetSpec(spec) && (spec.width || spec.height);
const isFitCompatible = isUnitSpec(spec) || isLayerSpec(spec) || isFitCompatibleFacet;
const autosizeDefault: AutoSizeParams = {};
if (!isFitCompatible) {
// If spec is not compatible with autosize == "fit", discard width/height == container
if (width == 'container') {
log.warn(log.message.containerSizeNonSingle('width'));
width = undefined;
}
if (height == 'container') {
log.warn(log.message.containerSizeNonSingle('height'));
height = undefined;
}
} else {
// Default autosize parameters to fit when width/height is "container"
if (width == 'container' && height == 'container') {
autosizeDefault.type = 'fit';
autosizeDefault.contains = 'padding';
} else if (width == 'container') {
autosizeDefault.type = 'fit-x';
autosizeDefault.contains = 'padding';
} else if (height == 'container') {
autosizeDefault.type = 'fit-y';
autosizeDefault.contains = 'padding';
}
}
const autosize: AutoSizeParams = {
type: 'pad',
...autosizeDefault,
...(config ? _normalizeAutoSize(config.autosize) : {}),
..._normalizeAutoSize(spec.autosize)
};
if (autosize.type === 'fit' && !isFitCompatible) {
log.warn(log.message.FIT_NON_SINGLE);
autosize.type = 'pad';
}
if (width == 'container' && !(autosize.type == 'fit' || autosize.type == 'fit-x')) {
log.warn(log.message.containerSizeNotCompatibleWithAutosize('width'));
}
if (height == 'container' && !(autosize.type == 'fit' || autosize.type == 'fit-y')) {
log.warn(log.message.containerSizeNotCompatibleWithAutosize('height'));
}
// Delete autosize property if it's Vega's default
if (deepEqual(autosize, {type: 'pad'})) {
return undefined;
}
return autosize;
}
export type {NormalizerParams};