vega 0.2.6 → 0.2.7

Sign up to get free protection for your applications and to get access to all the features.
@@ -15,6 +15,11 @@
15
15
  ];
16
16
  var homepage = "https://vega.github.io/vega-lite/";
17
17
  var description$1 = "Vega-Lite is a concise high-level language for interactive visualization.";
18
+ var keywords = [
19
+ "vega",
20
+ "chart",
21
+ "visualization"
22
+ ];
18
23
  var main$1 = "build/vega-lite.js";
19
24
  var unpkg = "build/vega-lite.min.js";
20
25
  var jsdelivr = "build/vega-lite.min.js";
@@ -26,9 +31,6 @@
26
31
  vl2pdf: "./bin/vl2pdf",
27
32
  vl2vg: "./bin/vl2vg"
28
33
  };
29
- var directories = {
30
- test: "test"
31
- };
32
34
  var files = [
33
35
  "bin",
34
36
  "build",
@@ -72,7 +74,10 @@
72
74
  "test:runtime:generate": "yarn build:only && del-cli test-runtime/resources && VL_GENERATE_TESTS=true yarn test:runtime",
73
75
  watch: "tsc -p tsconfig.build.json -w",
74
76
  "watch:site": "yarn build:site -w",
75
- "watch:test": "yarn jest --watch test/"
77
+ "watch:test": "yarn jest --watch test/",
78
+ "watch:test:runtime": "NODE_OPTIONS=--experimental-vm-modules TZ=America/Los_Angeles npx jest --watch test-runtime/ --config test-runtime/jest-config.json",
79
+ release: "yarn run prebuild && yarn build && yarn shipit",
80
+ shipit: "auto shipit"
76
81
  };
77
82
  var repository = {
78
83
  type: "git",
@@ -83,53 +88,56 @@
83
88
  url: "https://github.com/vega/vega-lite/issues"
84
89
  };
85
90
  var devDependencies = {
86
- "@babel/core": "^7.16.0",
87
- "@babel/preset-env": "^7.16.0",
88
- "@babel/preset-typescript": "^7.16.0",
89
- "@rollup/plugin-alias": "^3.1.8",
90
- "@rollup/plugin-babel": "^5.3.0",
91
- "@rollup/plugin-commonjs": "^21.0.1",
91
+ "@auto-it/conventional-commits": "^10.34.1",
92
+ "@auto-it/first-time-contributor": "^10.34.1",
93
+ "@babel/core": "^7.17.5",
94
+ "@babel/preset-env": "^7.16.11",
95
+ "@babel/preset-typescript": "^7.16.7",
96
+ "@rollup/plugin-alias": "^3.1.9",
97
+ "@rollup/plugin-babel": "^5.3.1",
98
+ "@rollup/plugin-commonjs": "^22.0.0",
92
99
  "@rollup/plugin-json": "^4.1.0",
93
- "@rollup/plugin-node-resolve": "^13.0.6",
94
- "@types/chai": "^4.2.22",
100
+ "@rollup/plugin-node-resolve": "^13.1.3",
101
+ "@types/chai": "^4.3.0",
95
102
  "@types/d3": "^7.1.0",
96
- "@types/jest": "^27.0.2",
103
+ "@types/jest": "^27.4.1",
97
104
  "@types/mkdirp": "^1.0.2",
98
- "@types/pako": "^1.0.2",
99
- "@typescript-eslint/eslint-plugin": "^5.4.0",
100
- "@typescript-eslint/parser": "^5.4.0",
101
- ajv: "^8.8.0",
105
+ "@types/pako": "^2.0.0",
106
+ "@typescript-eslint/eslint-plugin": "^5.14.0",
107
+ "@typescript-eslint/parser": "^5.14.0",
108
+ ajv: "^8.10.0",
102
109
  "ajv-formats": "^2.1.1",
103
- chai: "^4.3.4",
110
+ auto: "^10.34.1",
111
+ chai: "^4.3.6",
104
112
  cheerio: "^1.0.0-rc.10",
105
- "conventional-changelog-cli": "^2.1.1",
106
- d3: "^7.1.1",
107
- "del-cli": "^4.0.1",
108
- eslint: "^8.2.0",
109
- "eslint-config-prettier": "^8.3.0",
110
- "eslint-plugin-jest": "^25.2.4",
113
+ "conventional-changelog-cli": "^2.2.2",
114
+ d3: "^7.4.4",
115
+ "del-cli": "^5.0.0",
116
+ eslint: "^8.11.0",
117
+ "eslint-config-prettier": "^8.5.0",
118
+ "eslint-plugin-jest": "^26.1.1",
111
119
  "eslint-plugin-prettier": "^4.0.0",
112
- "gh-pages": "^3.2.3",
113
- "highlight.js": "^11.3.1",
114
- jest: "^27.3.1",
115
- "jest-dev-server": "^6.0.0",
120
+ "gh-pages": "^4.0.0",
121
+ "highlight.js": "^11.5.0",
122
+ jest: "^27.5.1",
123
+ "jest-dev-server": "^6.0.3",
116
124
  mkdirp: "^1.0.4",
117
125
  pako: "^2.0.4",
118
- prettier: "^2.4.1",
119
- puppeteer: "^11.0.0",
120
- rollup: "^2.60.0",
126
+ prettier: "^2.5.1",
127
+ puppeteer: "^15.0.0",
128
+ rollup: "^2.70.1",
121
129
  "rollup-plugin-bundle-size": "^1.0.3",
122
130
  "rollup-plugin-sourcemaps": "^0.6.3",
123
131
  "rollup-plugin-terser": "^7.0.2",
124
- serve: "^13.0.2",
125
- terser: "^5.10.0",
126
- "ts-jest": "^27.0.7",
127
- "ts-json-schema-generator": "^0.97.0",
128
- typescript: "~4.5.2",
129
- "vega-cli": "^5.21.0",
130
- "vega-datasets": "~2.2.0",
131
- "vega-embed": "^6.20.2",
132
- "vega-tooltip": "^0.27.0",
132
+ serve: "^14.0.1",
133
+ terser: "^5.12.1",
134
+ "ts-jest": "^27.1.3",
135
+ "ts-json-schema-generator": "^1.0.0",
136
+ "vega-cli": "^5.22.0",
137
+ typescript: "~4.7.2",
138
+ "vega-datasets": "~2.4.0",
139
+ "vega-embed": "^6.20.8",
140
+ "vega-tooltip": "^0.28.0",
133
141
  "yaml-front-matter": "^4.1.1"
134
142
  };
135
143
  var dependencies = {
@@ -139,14 +147,14 @@
139
147
  "fast-deep-equal": "~3.1.3",
140
148
  "fast-json-stable-stringify": "~2.1.0",
141
149
  "json-stringify-pretty-compact": "~3.0.0",
142
- tslib: "~2.3.1",
150
+ tslib: "~2.4.0",
143
151
  "vega-event-selector": "~3.0.0",
144
152
  "vega-expression": "~5.0.0",
145
153
  "vega-util": "~1.17.0",
146
- yargs: "~17.2.1"
154
+ yargs: "~17.5.1"
147
155
  };
148
156
  var peerDependencies = {
149
- vega: "^5.21.0"
157
+ vega: "^5.22.0"
150
158
  };
151
159
  var engines = {
152
160
  node: ">=12"
@@ -158,13 +166,13 @@
158
166
  collaborators: collaborators,
159
167
  homepage: homepage,
160
168
  description: description$1,
169
+ keywords: keywords,
161
170
  main: main$1,
162
171
  unpkg: unpkg,
163
172
  jsdelivr: jsdelivr,
164
173
  module: module,
165
174
  types: types,
166
175
  bin: bin,
167
- directories: directories,
168
176
  files: files,
169
177
  scripts: scripts,
170
178
  repository: repository,
@@ -1739,7 +1747,7 @@
1739
1747
  }
1740
1748
 
1741
1749
  function isExprRef(o) {
1742
- return o && !!o['expr'];
1750
+ return !!(o !== null && o !== void 0 && o.expr);
1743
1751
  }
1744
1752
  function replaceExprRef(index) {
1745
1753
  const props = keys(index || {});
@@ -1835,7 +1843,7 @@
1835
1843
  }
1836
1844
 
1837
1845
  function isSignalRef(o) {
1838
- return o && !!o['signal'];
1846
+ return !!(o !== null && o !== void 0 && o.signal);
1839
1847
  } // TODO: add type of value (Make it VgValueRef<V extends ValueOrGradient> {value?:V ...})
1840
1848
 
1841
1849
  function isVgRangeStep(range) {
@@ -2866,19 +2874,19 @@
2866
2874
  return predicate === null || predicate === void 0 ? void 0 : predicate['param'];
2867
2875
  }
2868
2876
  function isFieldEqualPredicate(predicate) {
2869
- return predicate && !!predicate.field && predicate.equal !== undefined;
2877
+ return !!(predicate !== null && predicate !== void 0 && predicate.field) && predicate.equal !== undefined;
2870
2878
  }
2871
2879
  function isFieldLTPredicate(predicate) {
2872
- return predicate && !!predicate.field && predicate.lt !== undefined;
2880
+ return !!(predicate !== null && predicate !== void 0 && predicate.field) && predicate.lt !== undefined;
2873
2881
  }
2874
2882
  function isFieldLTEPredicate(predicate) {
2875
- return predicate && !!predicate.field && predicate.lte !== undefined;
2883
+ return !!(predicate !== null && predicate !== void 0 && predicate.field) && predicate.lte !== undefined;
2876
2884
  }
2877
2885
  function isFieldGTPredicate(predicate) {
2878
- return predicate && !!predicate.field && predicate.gt !== undefined;
2886
+ return !!(predicate !== null && predicate !== void 0 && predicate.field) && predicate.gt !== undefined;
2879
2887
  }
2880
2888
  function isFieldGTEPredicate(predicate) {
2881
- return predicate && !!predicate.field && predicate.gte !== undefined;
2889
+ return !!(predicate !== null && predicate !== void 0 && predicate.field) && predicate.gte !== undefined;
2882
2890
  }
2883
2891
  function isFieldRangePredicate(predicate) {
2884
2892
  if (predicate !== null && predicate !== void 0 && predicate.field) {
@@ -2892,11 +2900,11 @@
2892
2900
  return false;
2893
2901
  }
2894
2902
  function isFieldOneOfPredicate(predicate) {
2895
- return predicate && !!predicate.field && (vega.isArray(predicate.oneOf) || vega.isArray(predicate.in)) // backward compatibility
2903
+ return !!(predicate !== null && predicate !== void 0 && predicate.field) && (vega.isArray(predicate.oneOf) || vega.isArray(predicate.in)) // backward compatibility
2896
2904
  ;
2897
2905
  }
2898
2906
  function isFieldValidPredicate(predicate) {
2899
- return predicate && !!predicate.field && predicate.valid !== undefined;
2907
+ return !!(predicate !== null && predicate !== void 0 && predicate.field) && predicate.valid !== undefined;
2900
2908
  }
2901
2909
  function isFieldPredicate(predicate) {
2902
2910
  return isFieldOneOfPredicate(predicate) || isFieldEqualPredicate(predicate) || isFieldRangePredicate(predicate) || isFieldLTPredicate(predicate) || isFieldGTPredicate(predicate) || isFieldLTEPredicate(predicate) || isFieldGTEPredicate(predicate);
@@ -3193,7 +3201,7 @@
3193
3201
  return domain === null || domain === void 0 ? void 0 : domain['param'];
3194
3202
  }
3195
3203
  function isDomainUnionWith(domain) {
3196
- return domain && domain['unionWith'];
3204
+ return domain === null || domain === void 0 ? void 0 : domain['unionWith'];
3197
3205
  }
3198
3206
  function isFieldRange(range) {
3199
3207
  return vega.isObject(range) && 'field' in range;
@@ -3304,7 +3312,7 @@
3304
3312
  case 'scheme':
3305
3313
  case 'domainMid':
3306
3314
  if (!isColorChannel(channel)) {
3307
- return cannotUseScalePropertyWithNonColor(channel);
3315
+ return cannotUseScalePropertyWithNonColor(propName);
3308
3316
  }
3309
3317
 
3310
3318
  return undefined;
@@ -3852,17 +3860,62 @@
3852
3860
  }
3853
3861
 
3854
3862
  const field = fieldToFormat(fieldOrDatumDef, expr, normalizeStack);
3863
+ const type = channelDefType(fieldOrDatumDef);
3864
+
3865
+ if (format === undefined && formatType === undefined && config.customFormatTypes) {
3866
+ if (type === 'quantitative') {
3867
+ if (normalizeStack && config.normalizedNumberFormatType) return formatCustomType({
3868
+ fieldOrDatumDef,
3869
+ format: config.normalizedNumberFormat,
3870
+ formatType: config.normalizedNumberFormatType,
3871
+ expr,
3872
+ config
3873
+ });
3874
+
3875
+ if (config.numberFormatType) {
3876
+ return formatCustomType({
3877
+ fieldOrDatumDef,
3878
+ format: config.numberFormat,
3879
+ formatType: config.numberFormatType,
3880
+ expr,
3881
+ config
3882
+ });
3883
+ }
3884
+ }
3885
+
3886
+ if (type === 'temporal' && config.timeFormatType && isFieldDef(fieldOrDatumDef) && fieldOrDatumDef.timeUnit === undefined) {
3887
+ return formatCustomType({
3888
+ fieldOrDatumDef,
3889
+ format: config.timeFormat,
3890
+ formatType: config.timeFormatType,
3891
+ expr,
3892
+ config
3893
+ });
3894
+ }
3895
+ }
3855
3896
 
3856
3897
  if (isFieldOrDatumDefForTimeFormat(fieldOrDatumDef)) {
3857
3898
  var _normalizeTimeUnit, _fieldOrDatumDef$scal;
3858
3899
 
3859
- const signal = timeFormatExpression(field, isFieldDef(fieldOrDatumDef) ? (_normalizeTimeUnit = normalizeTimeUnit(fieldOrDatumDef.timeUnit)) === null || _normalizeTimeUnit === void 0 ? void 0 : _normalizeTimeUnit.unit : undefined, format, config.timeFormat, isScaleFieldDef(fieldOrDatumDef) && ((_fieldOrDatumDef$scal = fieldOrDatumDef.scale) === null || _fieldOrDatumDef$scal === void 0 ? void 0 : _fieldOrDatumDef$scal.type) === ScaleType.UTC);
3900
+ const signal = timeFormatExpression({
3901
+ field,
3902
+ timeUnit: isFieldDef(fieldOrDatumDef) ? (_normalizeTimeUnit = normalizeTimeUnit(fieldOrDatumDef.timeUnit)) === null || _normalizeTimeUnit === void 0 ? void 0 : _normalizeTimeUnit.unit : undefined,
3903
+ format,
3904
+ formatType: config.timeFormatType,
3905
+ rawTimeFormat: config.timeFormat,
3906
+ isUTCScale: isScaleFieldDef(fieldOrDatumDef) && ((_fieldOrDatumDef$scal = fieldOrDatumDef.scale) === null || _fieldOrDatumDef$scal === void 0 ? void 0 : _fieldOrDatumDef$scal.type) === ScaleType.UTC
3907
+ });
3860
3908
  return signal ? {
3861
3909
  signal
3862
3910
  } : undefined;
3863
3911
  }
3864
3912
 
3865
- format = numberFormat(channelDefType(fieldOrDatumDef), format, config);
3913
+ format = numberFormat({
3914
+ type,
3915
+ specifiedFormat: format,
3916
+ config,
3917
+ normalizeStack
3918
+ });
3866
3919
 
3867
3920
  if (isFieldDef(fieldOrDatumDef) && isBinning(fieldOrDatumDef.bin)) {
3868
3921
  const endField = vgField(fieldOrDatumDef, {
@@ -3917,7 +3970,8 @@
3917
3970
  } = _ref2;
3918
3971
  (_field = field) !== null && _field !== void 0 ? _field : field = fieldToFormat(fieldOrDatumDef, expr, normalizeStack);
3919
3972
 
3920
- if (isFieldDef(fieldOrDatumDef) && isBinning(fieldOrDatumDef.bin)) {
3973
+ if (field !== 'datum.value' && // For axis/legend, we can't correctly know the end of the bin from `datum`
3974
+ isFieldDef(fieldOrDatumDef) && isBinning(fieldOrDatumDef.bin)) {
3921
3975
  const endField = vgField(fieldOrDatumDef, {
3922
3976
  expr,
3923
3977
  binSuffix: 'end'
@@ -3934,16 +3988,48 @@
3934
3988
  function guideFormat(fieldOrDatumDef, type, format, formatType, config, omitTimeFormatConfig) {
3935
3989
  if (isCustomFormatType(formatType)) {
3936
3990
  return undefined; // handled in encode block
3991
+ } else if (format === undefined && formatType === undefined && config.customFormatTypes) {
3992
+ if (channelDefType(fieldOrDatumDef) === 'quantitative') {
3993
+ if (config.normalizedNumberFormatType && isPositionFieldOrDatumDef(fieldOrDatumDef) && fieldOrDatumDef.stack === 'normalize') {
3994
+ return undefined; // handled in encode block
3995
+ }
3996
+
3997
+ if (config.numberFormatType) {
3998
+ return undefined; // handled in encode block
3999
+ }
4000
+ }
4001
+ }
4002
+
4003
+ if (isPositionFieldOrDatumDef(fieldOrDatumDef) && fieldOrDatumDef.stack === 'normalize' && config.normalizedNumberFormat) {
4004
+ return numberFormat({
4005
+ type: 'quantitative',
4006
+ config,
4007
+ normalizeStack: true
4008
+ });
3937
4009
  }
3938
4010
 
3939
4011
  if (isFieldOrDatumDefForTimeFormat(fieldOrDatumDef)) {
3940
4012
  var _normalizeTimeUnit2;
3941
4013
 
3942
4014
  const timeUnit = isFieldDef(fieldOrDatumDef) ? (_normalizeTimeUnit2 = normalizeTimeUnit(fieldOrDatumDef.timeUnit)) === null || _normalizeTimeUnit2 === void 0 ? void 0 : _normalizeTimeUnit2.unit : undefined;
3943
- return timeFormat(format, timeUnit, config, omitTimeFormatConfig);
4015
+
4016
+ if (timeUnit === undefined && config.customFormatTypes && config.timeFormatType) {
4017
+ return undefined; // hanlded in encode block
4018
+ }
4019
+
4020
+ return timeFormat({
4021
+ specifiedFormat: format,
4022
+ timeUnit,
4023
+ config,
4024
+ omitTimeFormatConfig
4025
+ });
3944
4026
  }
3945
4027
 
3946
- return numberFormat(type, format, config);
4028
+ return numberFormat({
4029
+ type,
4030
+ specifiedFormat: format,
4031
+ config
4032
+ });
3947
4033
  }
3948
4034
  function guideFormatType(formatType, fieldOrDatumDef, scaleType) {
3949
4035
  if (formatType && (isSignalRef(formatType) || formatType === 'number' || formatType === 'time')) {
@@ -3951,7 +4037,9 @@
3951
4037
  }
3952
4038
 
3953
4039
  if (isFieldOrDatumDefForTimeFormat(fieldOrDatumDef) && scaleType !== 'time' && scaleType !== 'utc') {
3954
- return 'time';
4040
+ var _normalizeTimeUnit3;
4041
+
4042
+ return isFieldDef(fieldOrDatumDef) && (_normalizeTimeUnit3 = normalizeTimeUnit(fieldOrDatumDef === null || fieldOrDatumDef === void 0 ? void 0 : fieldOrDatumDef.timeUnit)) !== null && _normalizeTimeUnit3 !== void 0 && _normalizeTimeUnit3.utc ? 'utc' : 'time';
3955
4043
  }
3956
4044
 
3957
4045
  return undefined;
@@ -3960,7 +4048,14 @@
3960
4048
  * Returns number format for a fieldDef.
3961
4049
  */
3962
4050
 
3963
- function numberFormat(type, specifiedFormat, config) {
4051
+ function numberFormat(_ref3) {
4052
+ let {
4053
+ type,
4054
+ specifiedFormat,
4055
+ config,
4056
+ normalizeStack
4057
+ } = _ref3;
4058
+
3964
4059
  // Specified format in axis/legend has higher precedence than fieldDef.format
3965
4060
  if (vega.isString(specifiedFormat)) {
3966
4061
  return specifiedFormat;
@@ -3968,7 +4063,7 @@
3968
4063
 
3969
4064
  if (type === QUANTITATIVE) {
3970
4065
  // we only apply the default if the field is quantitative
3971
- return config.numberFormat;
4066
+ return normalizeStack ? config.normalizedNumberFormat : config.numberFormat;
3972
4067
  }
3973
4068
 
3974
4069
  return undefined;
@@ -3977,7 +4072,14 @@
3977
4072
  * Returns time format for a fieldDef for use in guides.
3978
4073
  */
3979
4074
 
3980
- function timeFormat(specifiedFormat, timeUnit, config, omitTimeFormatConfig) {
4075
+ function timeFormat(_ref4) {
4076
+ let {
4077
+ specifiedFormat,
4078
+ timeUnit,
4079
+ config,
4080
+ omitTimeFormatConfig
4081
+ } = _ref4;
4082
+
3981
4083
  if (specifiedFormat) {
3982
4084
  return specifiedFormat;
3983
4085
  }
@@ -3996,16 +4098,20 @@
3996
4098
  }
3997
4099
 
3998
4100
  function binNumberFormatExpr(field, format, formatType, config) {
3999
- var _ref3;
4101
+ var _ref5;
4000
4102
 
4001
4103
  if (isCustomFormatType(formatType)) {
4002
4104
  return customFormatExpr(formatType, field, format);
4003
4105
  }
4004
4106
 
4005
- return formatExpr(field, (_ref3 = vega.isString(format) ? format : undefined) !== null && _ref3 !== void 0 ? _ref3 : config.numberFormat);
4107
+ return formatExpr(field, (_ref5 = vega.isString(format) ? format : undefined) !== null && _ref5 !== void 0 ? _ref5 : config.numberFormat);
4006
4108
  }
4007
4109
 
4008
4110
  function binFormatExpression(startField, endField, format, formatType, config) {
4111
+ if (format === undefined && formatType === undefined && config.customFormatTypes && config.numberFormatType) {
4112
+ return binFormatExpression(startField, endField, config.numberFormat, config.numberFormatType, config);
4113
+ }
4114
+
4009
4115
  const start = binNumberFormatExpr(startField, format, formatType, config);
4010
4116
  const end = binNumberFormatExpr(endField, format, formatType, config);
4011
4117
  return "".concat(fieldValidPredicate(startField, false), " ? \"null\" : ").concat(start, " + \"").concat(BIN_RANGE_DELIMITER, "\" + ").concat(end);
@@ -4014,10 +4120,22 @@
4014
4120
  * Returns the time expression used for axis/legend labels or text mark for a temporal field
4015
4121
  */
4016
4122
 
4017
- function timeFormatExpression(field, timeUnit, format, rawTimeFormat, // should be provided only for actual text and headers, not axis/legend labels
4018
- isUTCScale) {
4123
+ function timeFormatExpression(_ref6) {
4124
+ let {
4125
+ field,
4126
+ timeUnit,
4127
+ format,
4128
+ formatType,
4129
+ rawTimeFormat,
4130
+ isUTCScale
4131
+ } = _ref6;
4132
+
4019
4133
  if (!timeUnit || format) {
4020
4134
  // If there is no time unit, or if user explicitly specifies format for axis/legend/text.
4135
+ if (!timeUnit && formatType) {
4136
+ return "".concat(formatType, "(").concat(field, ", '").concat(format, "')");
4137
+ }
4138
+
4021
4139
  format = vega.isString(format) ? format : rawTimeFormat; // only use provided timeFormat if there is no timeUnit.
4022
4140
 
4023
4141
  return "".concat(isUTCScale ? 'utc' : 'time', "Format(").concat(field, ", '").concat(format, "')");
@@ -4049,13 +4167,13 @@
4049
4167
  return c in SORT_BY_CHANNEL_INDEX;
4050
4168
  }
4051
4169
  function isSortByEncoding(sort) {
4052
- return !!sort && !!sort['encoding'];
4170
+ return !!(sort !== null && sort !== void 0 && sort['encoding']);
4053
4171
  }
4054
4172
  function isSortField(sort) {
4055
- return !!sort && (sort['op'] === 'count' || !!sort['field']);
4173
+ return sort && (sort['op'] === 'count' || !!sort['field']);
4056
4174
  }
4057
4175
  function isSortArray(sort) {
4058
- return !!sort && vega.isArray(sort);
4176
+ return sort && vega.isArray(sort);
4059
4177
  }
4060
4178
 
4061
4179
  function isFacetMapping(f) {
@@ -4217,15 +4335,15 @@
4217
4335
  */
4218
4336
 
4219
4337
  function hasConditionalFieldDef(channelDef) {
4220
- const condition = channelDef && channelDef['condition'];
4338
+ const condition = channelDef === null || channelDef === void 0 ? void 0 : channelDef['condition'];
4221
4339
  return !!condition && !vega.isArray(condition) && isFieldDef(condition);
4222
4340
  }
4223
4341
  function hasConditionalFieldOrDatumDef(channelDef) {
4224
- const condition = channelDef && channelDef['condition'];
4342
+ const condition = channelDef === null || channelDef === void 0 ? void 0 : channelDef['condition'];
4225
4343
  return !!condition && !vega.isArray(condition) && isFieldOrDatumDef(condition);
4226
4344
  }
4227
4345
  function hasConditionalValueDef(channelDef) {
4228
- const condition = channelDef && channelDef['condition'];
4346
+ const condition = channelDef === null || channelDef === void 0 ? void 0 : channelDef['condition'];
4229
4347
  return !!condition && (vega.isArray(condition) || isValueDef(condition));
4230
4348
  }
4231
4349
  function isFieldDef(channelDef) {
@@ -4233,7 +4351,7 @@
4233
4351
  return channelDef && (!!channelDef['field'] || channelDef['aggregate'] === 'count');
4234
4352
  }
4235
4353
  function channelDefType(channelDef) {
4236
- return channelDef && channelDef['type'];
4354
+ return channelDef === null || channelDef === void 0 ? void 0 : channelDef['type'];
4237
4355
  }
4238
4356
  function isDatumDef(channelDef) {
4239
4357
  return channelDef && 'datum' in channelDef;
@@ -5082,7 +5200,7 @@
5082
5200
  }
5083
5201
  };
5084
5202
  function isConditionalAxisValue(v) {
5085
- return v && v['condition'];
5203
+ return v === null || v === void 0 ? void 0 : v.condition;
5086
5204
  }
5087
5205
  const AXIS_PARTS = ['domain', 'grid', 'labels', 'ticks', 'title'];
5088
5206
  /**
@@ -5955,7 +6073,7 @@
5955
6073
  ...(isMarkDef(partBaseSpec.mark) ? partBaseSpec.mark : {
5956
6074
  type: partBaseSpec.mark
5957
6075
  }),
5958
- style: "".concat(mark, "-").concat(part),
6076
+ style: "".concat(mark, "-").concat(String(part)),
5959
6077
  ...(vega.isBoolean(markDef[part]) ? {} : markDef[part])
5960
6078
  }
5961
6079
  }];
@@ -7047,13 +7165,13 @@
7047
7165
  }
7048
7166
  };
7049
7167
  function isLegendBinding(bind) {
7050
- return !!bind && (bind === 'legend' || !!bind.legend);
7168
+ return bind === 'legend' || !!(bind !== null && bind !== void 0 && bind.legend);
7051
7169
  }
7052
7170
  function isLegendStreamBinding(bind) {
7053
7171
  return isLegendBinding(bind) && vega.isObject(bind);
7054
7172
  }
7055
7173
  function isSelectionParameter(param) {
7056
- return !!param['select'];
7174
+ return !!(param !== null && param !== void 0 && param['select']);
7057
7175
  }
7058
7176
 
7059
7177
  function assembleParameterSignals(params) {
@@ -7122,34 +7240,6 @@
7122
7240
  return 'hconcat' in spec;
7123
7241
  }
7124
7242
 
7125
- function isFitType(autoSizeType) {
7126
- return autoSizeType === 'fit' || autoSizeType === 'fit-x' || autoSizeType === 'fit-y';
7127
- }
7128
- function getFitType(sizeType) {
7129
- return sizeType ? "fit-".concat(getPositionScaleChannel(sizeType)) : 'fit';
7130
- }
7131
- const TOP_LEVEL_PROPERTIES = ['background', 'padding' // We do not include "autosize" here as it is supported by only unit and layer specs and thus need to be normalized
7132
- ];
7133
- function extractTopLevelProperties(t, includeParams) {
7134
- const o = {};
7135
-
7136
- for (const p of TOP_LEVEL_PROPERTIES) {
7137
- if (t && t[p] !== undefined) {
7138
- o[p] = signalRefOrValue(t[p]);
7139
- }
7140
- }
7141
-
7142
- if (includeParams) {
7143
- o.params = t.params;
7144
- }
7145
-
7146
- return o;
7147
- }
7148
-
7149
- /**
7150
- * Common properties for all types of specification
7151
- */
7152
-
7153
7243
  function getStepFor(_ref) {
7154
7244
  let {
7155
7245
  step,
@@ -7318,7 +7408,8 @@
7318
7408
  },
7319
7409
  concat: {
7320
7410
  spacing: DEFAULT_SPACING
7321
- }
7411
+ },
7412
+ normalizedNumberFormat: '.0%'
7322
7413
  }; // Tableau10 color palette, copied from `vegaScale.scheme('tableau10')`
7323
7414
 
7324
7415
  const tab10 = ['#4c78a8', '#f58518', '#e45756', '#72b7b2', '#54a24b', '#eeca3b', '#b279a2', '#ff9da6', '#9d755d', '#bab0ac'];
@@ -7598,7 +7689,7 @@
7598
7689
  }
7599
7690
  const MARK_STYLES = new Set(['view', ...PRIMITIVE_MARKS]);
7600
7691
  const VL_ONLY_CONFIG_PROPERTIES = ['color', 'fontSize', 'background', // We apply background to the spec directly.
7601
- 'padding', 'facet', 'concat', 'numberFormat', 'timeFormat', 'countTitle', 'header', 'axisQuantitative', 'axisTemporal', 'axisDiscrete', 'axisPoint', 'axisXBand', 'axisXPoint', 'axisXDiscrete', 'axisXQuantitative', 'axisXTemporal', 'axisYBand', 'axisYPoint', 'axisYDiscrete', 'axisYQuantitative', 'axisYTemporal', 'scale', 'selection', 'overlay' // FIXME: Redesign and unhide this
7692
+ 'padding', 'facet', 'concat', 'numberFormat', 'numberFormatType', 'normalizedNumberFormat', 'normalizedNumberFormatType', 'timeFormat', 'countTitle', 'header', 'axisQuantitative', 'axisTemporal', 'axisDiscrete', 'axisPoint', 'axisXBand', 'axisXPoint', 'axisXDiscrete', 'axisXQuantitative', 'axisXTemporal', 'axisYBand', 'axisYPoint', 'axisYDiscrete', 'axisYQuantitative', 'axisYTemporal', 'scale', 'selection', 'overlay' // FIXME: Redesign and unhide this
7602
7693
  ];
7603
7694
  const VL_ONLY_ALL_MARK_SPECIFIC_CONFIG_PROPERTY_INDEX = {
7604
7695
  view: ['continuousWidth', 'continuousHeight', 'discreteWidth', 'discreteHeight', 'step'],
@@ -7907,14 +7998,11 @@
7907
7998
  case 'radius':
7908
7999
  return 'theta';
7909
8000
  }
7910
- } // Note: CompassQL uses this method and only pass in required properties of each argument object.
7911
- // If required properties change, make sure to update CompassQL.
7912
-
8001
+ }
7913
8002
 
7914
8003
  function stack(m, encoding) {
7915
8004
  var _stackedFieldDef$scal, _stackedFieldDef$scal2;
7916
8005
 
7917
- let opt = arguments.length > 2 && arguments[2] !== undefined ? arguments[2] : {};
7918
8006
  const mark = isMarkDef(m) ? m.type : m; // Should have stackable mark
7919
8007
 
7920
8008
  if (!STACKABLE_MARKS.has(mark)) {
@@ -8011,11 +8099,8 @@
8011
8099
 
8012
8100
 
8013
8101
  if (stackedFieldDef !== null && stackedFieldDef !== void 0 && (_stackedFieldDef$scal = stackedFieldDef.scale) !== null && _stackedFieldDef$scal !== void 0 && _stackedFieldDef$scal.type && (stackedFieldDef === null || stackedFieldDef === void 0 ? void 0 : (_stackedFieldDef$scal2 = stackedFieldDef.scale) === null || _stackedFieldDef$scal2 === void 0 ? void 0 : _stackedFieldDef$scal2.type) !== ScaleType.LINEAR) {
8014
- if (opt.disallowNonLinearStack) {
8015
- return null;
8016
- } else {
8017
- warn(cannotStackNonLinearScale(stackedFieldDef.scale.type));
8018
- }
8102
+ warn(cannotStackNonLinearScale(stackedFieldDef.scale.type));
8103
+ return null;
8019
8104
  } // Check if it is a ranged mark
8020
8105
 
8021
8106
 
@@ -9283,6 +9368,30 @@
9283
9368
  return autosize;
9284
9369
  }
9285
9370
 
9371
+ function isFitType(autoSizeType) {
9372
+ return autoSizeType === 'fit' || autoSizeType === 'fit-x' || autoSizeType === 'fit-y';
9373
+ }
9374
+ function getFitType(sizeType) {
9375
+ return sizeType ? "fit-".concat(getPositionScaleChannel(sizeType)) : 'fit';
9376
+ }
9377
+ const TOP_LEVEL_PROPERTIES = ['background', 'padding' // We do not include "autosize" here as it is supported by only unit and layer specs and thus need to be normalized
9378
+ ];
9379
+ function extractTopLevelProperties(t, includeParams) {
9380
+ const o = {};
9381
+
9382
+ for (const p of TOP_LEVEL_PROPERTIES) {
9383
+ if (t && t[p] !== undefined) {
9384
+ o[p] = signalRefOrValue(t[p]);
9385
+ }
9386
+ }
9387
+
9388
+ if (includeParams) {
9389
+ o.params = t.params;
9390
+ }
9391
+
9392
+ return o;
9393
+ }
9394
+
9286
9395
  /**
9287
9396
  * Generic class for storing properties that are explicitly specified
9288
9397
  * and implicitly determined by the compiler.
@@ -9602,14 +9711,26 @@
9602
9711
  }
9603
9712
  function assembleUnitSelectionData(model, data) {
9604
9713
  const dataCopy = [...data];
9714
+ const unit = unitName(model, {
9715
+ escape: false
9716
+ });
9605
9717
 
9606
9718
  for (const selCmpt of vals((_model$component$sele3 = model.component.selection) !== null && _model$component$sele3 !== void 0 ? _model$component$sele3 : {})) {
9607
9719
  var _model$component$sele3;
9608
9720
 
9609
- const init = {
9721
+ const store = {
9610
9722
  name: selCmpt.name + STORE
9611
9723
  };
9612
9724
 
9725
+ if (selCmpt.project.hasSelectionId) {
9726
+ store.transform = [{
9727
+ type: 'collect',
9728
+ sort: {
9729
+ field: SELECTION_ID
9730
+ }
9731
+ }];
9732
+ }
9733
+
9613
9734
  if (selCmpt.init) {
9614
9735
  const fields = selCmpt.project.items.map(proj => {
9615
9736
  const {
@@ -9618,10 +9739,11 @@
9618
9739
  } = proj;
9619
9740
  return rest;
9620
9741
  });
9621
- init.values = selCmpt.init.map(i => ({
9622
- unit: unitName(model, {
9623
- escape: false
9624
- }),
9742
+ store.values = selCmpt.project.hasSelectionId ? selCmpt.init.map(i => ({
9743
+ unit,
9744
+ [SELECTION_ID]: assembleInit(i, false)[0]
9745
+ })) : selCmpt.init.map(i => ({
9746
+ unit,
9625
9747
  fields,
9626
9748
  values: assembleInit(i, false)
9627
9749
  }));
@@ -9630,7 +9752,7 @@
9630
9752
  const contains = dataCopy.filter(d => d.name === selCmpt.name + STORE);
9631
9753
 
9632
9754
  if (!contains.length) {
9633
- dataCopy.push(init);
9755
+ dataCopy.push(store);
9634
9756
  }
9635
9757
  }
9636
9758
 
@@ -9787,9 +9909,10 @@
9787
9909
  this._children = []; // equivalent to removing every child link one by one
9788
9910
 
9789
9911
  parent.removeChild(this);
9790
- parent.parent.removeChild(parent); // swap two nodes
9912
+ const loc = parent.parent.removeChild(parent); // swap two nodes but maintain order in children
9791
9913
 
9792
- this.parent = newParent;
9914
+ this._parent = newParent;
9915
+ newParent.addChild(this, loc);
9793
9916
  parent.parent = this;
9794
9917
  }
9795
9918
 
@@ -10022,6 +10145,8 @@
10022
10145
 
10023
10146
  _defineProperty(this, "hasField", void 0);
10024
10147
 
10148
+ _defineProperty(this, "hasSelectionId", void 0);
10149
+
10025
10150
  _defineProperty(this, "timeUnit", void 0);
10026
10151
 
10027
10152
  _defineProperty(this, "items", void 0);
@@ -10033,6 +10158,7 @@
10033
10158
  this.items = items;
10034
10159
  this.hasChannel = {};
10035
10160
  this.hasField = {};
10161
+ this.hasSelectionId = false;
10036
10162
  }
10037
10163
 
10038
10164
  }
@@ -10164,6 +10290,7 @@
10164
10290
  };
10165
10291
  proj.items.push(parsed[field] = p);
10166
10292
  proj.hasField[field] = proj.hasChannel[channel] = parsed[field];
10293
+ proj.hasSelectionId = proj.hasSelectionId || field === SELECTION_ID;
10167
10294
  }
10168
10295
  } else {
10169
10296
  warn(cannotProjectOnChannelWithoutField(channel));
@@ -10182,6 +10309,7 @@
10182
10309
  };
10183
10310
  proj.items.push(p);
10184
10311
  proj.hasField[field] = p;
10312
+ proj.hasSelectionId = proj.hasSelectionId || field === SELECTION_ID;
10185
10313
  }
10186
10314
 
10187
10315
  if (init) {
@@ -10199,7 +10327,7 @@
10199
10327
  signals: (model, selCmpt, allSignals) => {
10200
10328
  const name = selCmpt.name + TUPLE_FIELDS;
10201
10329
  const hasSignal = allSignals.filter(s => s.name === name);
10202
- return hasSignal.length > 0 ? allSignals : allSignals.concat({
10330
+ return hasSignal.length > 0 || selCmpt.project.hasSelectionId ? allSignals : allSignals.concat({
10203
10331
  name,
10204
10332
  value: selCmpt.project.items.map(proj => {
10205
10333
  const {
@@ -10579,14 +10707,7 @@
10579
10707
  const name = selCmpt.name;
10580
10708
  const fieldsSg = name + TUPLE_FIELDS;
10581
10709
  const project = selCmpt.project;
10582
- const datum = '(item().isVoronoi ? datum.datum : datum)';
10583
- const values = project.items.map(p => {
10584
- const fieldDef = model.fieldDef(p.channel); // Binned fields should capture extents, for a range test against the raw field.
10585
-
10586
- return fieldDef !== null && fieldDef !== void 0 && fieldDef.bin ? "[".concat(datum, "[").concat(vega.stringValue(model.vgField(p.channel, {})), "], ") + "".concat(datum, "[").concat(vega.stringValue(model.vgField(p.channel, {
10587
- binSuffix: 'end'
10588
- })), "]]") : "".concat(datum, "[").concat(vega.stringValue(p.field), "]");
10589
- }).join(', '); // Only add a discrete selection to the store if a datum is present _and_
10710
+ const datum = '(item().isVoronoi ? datum.datum : datum)'; // Only add a discrete selection to the store if a datum is present _and_
10590
10711
  // the interaction isn't occurring on a group mark. This guards against
10591
10712
  // polluting interactive state with invalid values in faceted displays
10592
10713
  // as the group marks are also data-driven. We force the update to account
@@ -10594,17 +10715,31 @@
10594
10715
  // whitespace followed by a click in whitespace; the store should only
10595
10716
  // be cleared on the second click).
10596
10717
 
10597
- const update = "unit: ".concat(unitName(model), ", fields: ").concat(fieldsSg, ", values");
10598
- const events = selCmpt.events;
10599
10718
  const brushes = vals((_model$component$sele = model.component.selection) !== null && _model$component$sele !== void 0 ? _model$component$sele : {}).reduce((acc, cmpt) => {
10600
10719
  return cmpt.type === 'interval' ? acc.concat(cmpt.name + BRUSH) : acc;
10601
10720
  }, []).map(b => "indexof(item().mark.name, '".concat(b, "') < 0")).join(' && ');
10602
- const test = "datum && item().mark.marktype !== 'group'".concat(brushes ? " && ".concat(brushes) : '');
10721
+ const test = "datum && item().mark.marktype !== 'group' && indexof(item().mark.role, 'legend') < 0".concat(brushes ? " && ".concat(brushes) : '');
10722
+ let update = "unit: ".concat(unitName(model), ", ");
10723
+
10724
+ if (selCmpt.project.hasSelectionId) {
10725
+ update += "".concat(SELECTION_ID, ": ").concat(datum, "[").concat(vega.stringValue(SELECTION_ID), "]");
10726
+ } else {
10727
+ const values = project.items.map(p => {
10728
+ const fieldDef = model.fieldDef(p.channel); // Binned fields should capture extents, for a range test against the raw field.
10729
+
10730
+ return fieldDef !== null && fieldDef !== void 0 && fieldDef.bin ? "[".concat(datum, "[").concat(vega.stringValue(model.vgField(p.channel, {})), "], ") + "".concat(datum, "[").concat(vega.stringValue(model.vgField(p.channel, {
10731
+ binSuffix: 'end'
10732
+ })), "]]") : "".concat(datum, "[").concat(vega.stringValue(p.field), "]");
10733
+ }).join(', ');
10734
+ update += "fields: ".concat(fieldsSg, ", values: [").concat(values, "]");
10735
+ }
10736
+
10737
+ const events = selCmpt.events;
10603
10738
  return signals.concat([{
10604
10739
  name: name + TUPLE,
10605
10740
  on: events ? [{
10606
10741
  events,
10607
- update: "".concat(test, " ? {").concat(update, ": [").concat(values, "]} : null"),
10742
+ update: "".concat(test, " ? {").concat(update, "} : null"),
10608
10743
  force: true
10609
10744
  }] : []
10610
10745
  }]);
@@ -10785,22 +10920,24 @@
10785
10920
  } = getFormatMixins(fieldDef);
10786
10921
  value = binFormatExpression(startField, endField, format, formatType, config);
10787
10922
  toSkip[channel2] = true;
10788
- } else if (stack && stack.fieldChannel === channel && stack.offset === 'normalize') {
10789
- const {
10790
- format,
10791
- formatType
10792
- } = getFormatMixins(fieldDef);
10793
- value = formatSignalRef({
10794
- fieldOrDatumDef: fieldDef,
10795
- format,
10796
- formatType,
10797
- expr,
10798
- config,
10799
- normalizeStack: true
10800
- }).signal;
10801
10923
  }
10802
10924
  }
10803
10925
 
10926
+ if ((isXorY(channel) || channel === THETA || channel === RADIUS) && stack && stack.fieldChannel === channel && stack.offset === 'normalize') {
10927
+ const {
10928
+ format,
10929
+ formatType
10930
+ } = getFormatMixins(fieldDef);
10931
+ value = formatSignalRef({
10932
+ fieldOrDatumDef: fieldDef,
10933
+ format,
10934
+ formatType,
10935
+ expr,
10936
+ config,
10937
+ normalizeStack: true
10938
+ }).signal;
10939
+ }
10940
+
10804
10941
  (_value = value) !== null && _value !== void 0 ? _value : value = textRef(fieldDef, config, expr).signal;
10805
10942
  tuples.push({
10806
10943
  channel,
@@ -11576,9 +11713,15 @@
11576
11713
  const scaleType = scale.get('type');
11577
11714
 
11578
11715
  if (scaleType === 'band') {
11716
+ let bandWidth = "bandwidth('".concat(scaleName, "')");
11717
+
11718
+ if (bandSize.band !== 1) {
11719
+ bandWidth = "".concat(bandSize.band, " * ").concat(bandWidth);
11720
+ } // TODO(#8351): make 0.25 here configurable
11721
+
11722
+
11579
11723
  return {
11580
- scale: scaleName,
11581
- band: bandSize.band
11724
+ signal: "max(0.25, ".concat(bandWidth, ")")
11582
11725
  };
11583
11726
  } else if (bandSize.band !== 1) {
11584
11727
  warn(cannotUseRelativeBandSizeWithNonBandScale(scaleType));
@@ -11649,8 +11792,9 @@
11649
11792
  } else {
11650
11793
  warn(cannotApplySizeToNonOrientedMark(markDef.type));
11651
11794
  }
11652
- } // Otherwise, apply default value
11795
+ }
11653
11796
 
11797
+ const hasSizeFromMarkOrEncoding = !!sizeMixins; // Otherwise, apply default value
11654
11798
 
11655
11799
  const bandSize = getBandSize({
11656
11800
  channel,
@@ -11671,7 +11815,7 @@
11671
11815
  If band is 0.6, the the x/y position in such case should be `(1 - band) / 2` = 0.2
11672
11816
  */
11673
11817
 
11674
- const defaultBandAlign = (scale === null || scale === void 0 ? void 0 : scale.get('type')) !== 'band' || !('band' in sizeMixins[vgSizeChannel]) ? 'middle' : 'top';
11818
+ const defaultBandAlign = (scale === null || scale === void 0 ? void 0 : scale.get('type')) === 'band' && isRelativeBandSize(bandSize) && !hasSizeFromMarkOrEncoding ? 'top' : 'middle';
11675
11819
  const vgChannel = vgAlignedPositionChannel(channel, markDef, config, defaultBandAlign);
11676
11820
  const center = vgChannel === 'xc' || vgChannel === 'yc';
11677
11821
  const {
@@ -11991,9 +12135,12 @@
11991
12135
  const scaleComponent = model.getScaleComponent(channel);
11992
12136
 
11993
12137
  if (scaleComponent) {
12138
+ var _model$stack;
12139
+
11994
12140
  const scaleType = scaleComponent.get('type');
11995
12141
  const field = model.vgField(channel, {
11996
- expr: 'datum'
12142
+ expr: 'datum',
12143
+ binSuffix: (_model$stack = model.stack) !== null && _model$stack !== void 0 && _model$stack.impute ? 'mid' : undefined
11997
12144
  }); // While discrete domain scales can handle invalid values, continuous scales can't.
11998
12145
 
11999
12146
  if (field && hasContinuousDomain(scaleType)) {
@@ -12577,7 +12724,7 @@
12577
12724
  var _model$component$sele;
12578
12725
 
12579
12726
  return vals((_model$component$sele = model.component.selection) !== null && _model$component$sele !== void 0 ? _model$component$sele : {}).reduce((identifier, selCmpt) => {
12580
- return identifier || selCmpt.project.items.some(proj => proj.field === SELECTION_ID);
12727
+ return identifier || selCmpt.project.hasSelectionId;
12581
12728
  }, false);
12582
12729
  } // Binding a point selection to query widgets or legends disables default direct manipulation interaction.
12583
12730
  // A user can choose to re-enable it by explicitly specifying triggering input events.
@@ -12747,7 +12894,9 @@
12747
12894
  }
12748
12895
  }
12749
12896
 
12750
- const test = "vlSelectionTest(".concat(store, ", ").concat(datum).concat(selCmpt.resolve === 'global' ? ')' : ", ".concat(vega.stringValue(selCmpt.resolve), ")"));
12897
+ const fn = selCmpt.project.hasSelectionId ? 'vlSelectionIdTest(' : 'vlSelectionTest(';
12898
+ const resolve = selCmpt.resolve === 'global' ? ')' : ", ".concat(vega.stringValue(selCmpt.resolve), ")");
12899
+ const test = "".concat(fn).concat(store, ", ").concat(datum).concat(resolve);
12751
12900
  const length = "length(data(".concat(store, "))");
12752
12901
  return pred.empty === false ? "".concat(length, " && ").concat(test) : "!".concat(length, " || ").concat(test);
12753
12902
  }
@@ -14194,13 +14343,36 @@
14194
14343
  format,
14195
14344
  formatType
14196
14345
  } = legend;
14197
- const text = isCustomFormatType(formatType) ? formatCustomType({
14198
- fieldOrDatumDef,
14199
- field: 'datum.value',
14200
- format,
14201
- formatType,
14202
- config
14203
- }) : undefined;
14346
+ let text = undefined;
14347
+
14348
+ if (isCustomFormatType(formatType)) {
14349
+ text = formatCustomType({
14350
+ fieldOrDatumDef,
14351
+ field: 'datum.value',
14352
+ format,
14353
+ formatType,
14354
+ config
14355
+ });
14356
+ } else if (format === undefined && formatType === undefined && config.customFormatTypes) {
14357
+ if (fieldOrDatumDef.type === 'quantitative' && config.numberFormatType) {
14358
+ text = formatCustomType({
14359
+ fieldOrDatumDef,
14360
+ field: 'datum.value',
14361
+ format: config.numberFormat,
14362
+ formatType: config.numberFormatType,
14363
+ config
14364
+ });
14365
+ } else if (fieldOrDatumDef.type === 'temporal' && config.timeFormatType && isFieldDef(fieldOrDatumDef) && fieldOrDatumDef.timeUnit === undefined) {
14366
+ text = formatCustomType({
14367
+ fieldOrDatumDef,
14368
+ field: 'datum.value',
14369
+ format: config.timeFormat,
14370
+ formatType: config.timeFormatType,
14371
+ config
14372
+ });
14373
+ }
14374
+ }
14375
+
14204
14376
  const labelsSpec = { ...(opacity ? {
14205
14377
  opacity
14206
14378
  } : {}),
@@ -20152,7 +20324,11 @@
20152
20324
  this.transform = duplicate(transform); // duplicate to prevent side effects
20153
20325
 
20154
20326
  const specifiedAs = (_this$transform$as = this.transform.as) !== null && _this$transform$as !== void 0 ? _this$transform$as : [undefined, undefined];
20155
- this.transform.as = [(_specifiedAs$ = specifiedAs[0]) !== null && _specifiedAs$ !== void 0 ? _specifiedAs$ : 'value', (_specifiedAs$2 = specifiedAs[1]) !== null && _specifiedAs$2 !== void 0 ? _specifiedAs$2 : 'density'];
20327
+ this.transform.as = [(_specifiedAs$ = specifiedAs[0]) !== null && _specifiedAs$ !== void 0 ? _specifiedAs$ : 'value', (_specifiedAs$2 = specifiedAs[1]) !== null && _specifiedAs$2 !== void 0 ? _specifiedAs$2 : 'density']; // set steps when we are grouping so that we get consitent sampling points for imputing and grouping
20328
+
20329
+ if (transform.groupby && transform.minsteps == null && transform.maxsteps == null && transform.steps == null) {
20330
+ this.transform.steps = 200;
20331
+ }
20156
20332
  }
20157
20333
 
20158
20334
  dependentFields() {
@@ -22543,6 +22719,45 @@
22543
22719
  }),
22544
22720
  ...specifiedLabelsSpec
22545
22721
  };
22722
+ } else if (format === undefined && formatType === undefined && config.customFormatTypes) {
22723
+ if (channelDefType(fieldOrDatumDef) === 'quantitative') {
22724
+ if (isPositionFieldOrDatumDef(fieldOrDatumDef) && fieldOrDatumDef.stack === 'normalize' && config.normalizedNumberFormatType) {
22725
+ return {
22726
+ text: formatCustomType({
22727
+ fieldOrDatumDef,
22728
+ field: 'datum.value',
22729
+ format: config.normalizedNumberFormat,
22730
+ formatType: config.normalizedNumberFormatType,
22731
+ config
22732
+ }),
22733
+ ...specifiedLabelsSpec
22734
+ };
22735
+ } else if (config.numberFormatType) {
22736
+ return {
22737
+ text: formatCustomType({
22738
+ fieldOrDatumDef,
22739
+ field: 'datum.value',
22740
+ format: config.numberFormat,
22741
+ formatType: config.numberFormatType,
22742
+ config
22743
+ }),
22744
+ ...specifiedLabelsSpec
22745
+ };
22746
+ }
22747
+ }
22748
+
22749
+ if (channelDefType(fieldOrDatumDef) === 'temporal' && config.timeFormatType && isFieldDef(fieldOrDatumDef) && !fieldOrDatumDef.timeUnit) {
22750
+ return {
22751
+ text: formatCustomType({
22752
+ fieldOrDatumDef,
22753
+ field: 'datum.value',
22754
+ format: config.timeFormat,
22755
+ formatType: config.timeFormatType,
22756
+ config
22757
+ }),
22758
+ ...specifiedLabelsSpec
22759
+ };
22760
+ }
22546
22761
  }
22547
22762
 
22548
22763
  return specifiedLabelsSpec;