diff --git a/build/vega-lite-schema.json b/build/vega-lite-schema.json
index 4a36f8bb6b4..e8fb892c217 100644
--- a/build/vega-lite-schema.json
+++ b/build/vega-lite-schema.json
@@ -21632,6 +21632,10 @@
}
],
"description": "Reverse x-scale by default (useful for right-to-left charts)."
+ },
+ "zero": {
+ "description": "Default `scale.zero` for [`continuous`](https://vega.github.io/vega-lite/docs/scale.html#continuous) scales except for (1) x/y-scales of non-ranged bar or area charts and (2) size scales.\n\n__Default value:__ `true`",
+ "type": "boolean"
}
},
"type": "object"
diff --git a/examples/compiled/bar_config_no_zero.png b/examples/compiled/bar_config_no_zero.png
new file mode 100644
index 00000000000..01a1312af20
Binary files /dev/null and b/examples/compiled/bar_config_no_zero.png differ
diff --git a/examples/compiled/bar_config_no_zero.svg b/examples/compiled/bar_config_no_zero.svg
new file mode 100644
index 00000000000..9e458ba5253
--- /dev/null
+++ b/examples/compiled/bar_config_no_zero.svg
@@ -0,0 +1 @@
+
\ No newline at end of file
diff --git a/examples/compiled/bar_config_no_zero.vg.json b/examples/compiled/bar_config_no_zero.vg.json
new file mode 100644
index 00000000000..a7403201ada
--- /dev/null
+++ b/examples/compiled/bar_config_no_zero.vg.json
@@ -0,0 +1,122 @@
+{
+ "$schema": "https://vega.github.io/schema/vega/v5.json",
+ "description": "A simple bar chart with embedded data.",
+ "background": "white",
+ "padding": 5,
+ "height": 200,
+ "style": "cell",
+ "data": [
+ {
+ "name": "source_0",
+ "values": [
+ {"a": "A", "b": 28},
+ {"a": "B", "b": 55},
+ {"a": "C", "b": 43},
+ {"a": "D", "b": 91},
+ {"a": "E", "b": 81},
+ {"a": "F", "b": 53},
+ {"a": "G", "b": 19},
+ {"a": "H", "b": 87},
+ {"a": "I", "b": 52}
+ ]
+ },
+ {
+ "name": "data_0",
+ "source": "source_0",
+ "transform": [
+ {
+ "type": "stack",
+ "groupby": ["a"],
+ "field": "b",
+ "sort": {"field": [], "order": []},
+ "as": ["b_start", "b_end"],
+ "offset": "zero"
+ },
+ {
+ "type": "filter",
+ "expr": "isValid(datum[\"b\"]) && isFinite(+datum[\"b\"])"
+ }
+ ]
+ }
+ ],
+ "signals": [
+ {"name": "x_step", "value": 20},
+ {
+ "name": "width",
+ "update": "bandspace(domain('x').length, 0.1, 0.05) * x_step"
+ }
+ ],
+ "marks": [
+ {
+ "name": "marks",
+ "type": "rect",
+ "style": ["bar"],
+ "from": {"data": "data_0"},
+ "encode": {
+ "update": {
+ "fill": {"value": "#4c78a8"},
+ "ariaRoleDescription": {"value": "bar"},
+ "description": {
+ "signal": "\"a: \" + (isValid(datum[\"a\"]) ? datum[\"a\"] : \"\"+datum[\"a\"]) + \"; b: \" + (format(datum[\"b\"], \"\"))"
+ },
+ "x": {"scale": "x", "field": "a"},
+ "width": {"signal": "max(0.25, bandwidth('x'))"},
+ "y": {"scale": "y", "field": "b_end"},
+ "y2": {"scale": "y", "field": "b_start"}
+ }
+ }
+ }
+ ],
+ "scales": [
+ {
+ "name": "x",
+ "type": "band",
+ "domain": {"data": "data_0", "field": "a", "sort": true},
+ "range": {"step": {"signal": "x_step"}},
+ "paddingInner": 0.1,
+ "paddingOuter": 0.05
+ },
+ {
+ "name": "y",
+ "type": "linear",
+ "domain": {"data": "data_0", "fields": ["b_start", "b_end"]},
+ "range": [{"signal": "height"}, 0],
+ "nice": true,
+ "zero": true
+ }
+ ],
+ "axes": [
+ {
+ "scale": "y",
+ "orient": "left",
+ "gridScale": "x",
+ "grid": true,
+ "tickCount": {"signal": "ceil(height/40)"},
+ "domain": false,
+ "labels": false,
+ "aria": false,
+ "maxExtent": 0,
+ "minExtent": 0,
+ "ticks": false,
+ "zindex": 0
+ },
+ {
+ "scale": "x",
+ "orient": "bottom",
+ "grid": false,
+ "title": "a",
+ "labelAngle": 0,
+ "labelBaseline": "top",
+ "zindex": 0
+ },
+ {
+ "scale": "y",
+ "orient": "left",
+ "grid": false,
+ "title": "b",
+ "labelOverlap": true,
+ "tickCount": {"signal": "ceil(height/40)"},
+ "zindex": 0
+ }
+ ]
+}
diff --git a/examples/compiled/bar_gantt_config_no_zero.png b/examples/compiled/bar_gantt_config_no_zero.png
new file mode 100644
index 00000000000..96b20dd9409
Binary files /dev/null and b/examples/compiled/bar_gantt_config_no_zero.png differ
diff --git a/examples/compiled/bar_gantt_config_no_zero.svg b/examples/compiled/bar_gantt_config_no_zero.svg
new file mode 100644
index 00000000000..d31602a5377
--- /dev/null
+++ b/examples/compiled/bar_gantt_config_no_zero.svg
@@ -0,0 +1,5 @@
+<<<<<<< Updated upstream
+
+=======
+
+>>>>>>> Stashed changes
diff --git a/examples/compiled/bar_gantt_config_no_zero.vg.json b/examples/compiled/bar_gantt_config_no_zero.vg.json
new file mode 100644
index 00000000000..47a431f9b68
--- /dev/null
+++ b/examples/compiled/bar_gantt_config_no_zero.vg.json
@@ -0,0 +1,107 @@
+{
+ "$schema": "https://vega.github.io/schema/vega/v5.json",
+ "description": "A simple bar chart with ranged data (aka Gantt Chart).",
+ "background": "white",
+ "padding": 5,
+ "width": 200,
+ "style": "cell",
+ "data": [
+ {
+ "name": "source_0",
+ "values": [
+ {"task": "A", "start": 1, "end": 3},
+ {"task": "B", "start": 3, "end": 8},
+ {"task": "C", "start": 8, "end": 10}
+ ]
+ },
+ {
+ "name": "data_0",
+ "source": "source_0",
+ "transform": [
+ {
+ "type": "filter",
+ "expr": "isValid(datum[\"start\"]) && isFinite(+datum[\"start\"])"
+ }
+ ]
+ }
+ ],
+ "signals": [
+ {"name": "y_step", "value": 20},
+ {
+ "name": "height",
+ "update": "bandspace(domain('y').length, 0.1, 0.05) * y_step"
+ }
+ ],
+ "marks": [
+ {
+ "name": "marks",
+ "type": "rect",
+ "style": ["bar"],
+ "from": {"data": "data_0"},
+ "encode": {
+ "update": {
+ "fill": {"value": "#4c78a8"},
+ "ariaRoleDescription": {"value": "bar"},
+ "description": {
+ "signal": "\"start: \" + (format(datum[\"start\"], \"\")) + \"; task: \" + (isValid(datum[\"task\"]) ? datum[\"task\"] : \"\"+datum[\"task\"]) + \"; end: \" + (format(datum[\"end\"], \"\"))"
+ },
+ "x": {"scale": "x", "field": "start"},
+ "x2": {"scale": "x", "field": "end"},
+ "y": {"scale": "y", "field": "task"},
+ "height": {"signal": "max(0.25, bandwidth('y'))"}
+ }
+ }
+ }
+ ],
+ "scales": [
+ {
+ "name": "x",
+ "type": "linear",
+ "domain": {"data": "data_0", "fields": ["start", "end"]},
+ "range": [0, {"signal": "width"}],
+ "nice": true,
+ "zero": false
+ },
+ {
+ "name": "y",
+ "type": "band",
+ "domain": {"data": "data_0", "field": "task", "sort": true},
+ "range": {"step": {"signal": "y_step"}},
+ "paddingInner": 0.1,
+ "paddingOuter": 0.05
+ }
+ ],
+ "axes": [
+ {
+ "scale": "x",
+ "orient": "bottom",
+ "gridScale": "y",
+ "grid": true,
+ "tickCount": {"signal": "ceil(width/40)"},
+ "domain": false,
+ "labels": false,
+ "aria": false,
+ "maxExtent": 0,
+ "minExtent": 0,
+ "ticks": false,
+ "zindex": 0
+ },
+ {
+ "scale": "x",
+ "orient": "bottom",
+ "grid": false,
+ "title": "start, end",
+ "labelFlush": true,
+ "labelOverlap": true,
+ "tickCount": {"signal": "ceil(width/40)"},
+ "zindex": 0
+ },
+ {
+ "scale": "y",
+ "orient": "left",
+ "grid": false,
+ "title": "task",
+ "zindex": 0
+ }
+ ]
+}
diff --git a/examples/compiled/point_2d_config_no_zero.png b/examples/compiled/point_2d_config_no_zero.png
new file mode 100644
index 00000000000..868a9d1b5c9
Binary files /dev/null and b/examples/compiled/point_2d_config_no_zero.png differ
diff --git a/examples/compiled/point_2d_config_no_zero.svg b/examples/compiled/point_2d_config_no_zero.svg
new file mode 100644
index 00000000000..80ccd7f99b4
--- /dev/null
+++ b/examples/compiled/point_2d_config_no_zero.svg
@@ -0,0 +1,5 @@
+<<<<<<< Updated upstream
+
+=======
+
+>>>>>>> Stashed changes
diff --git a/examples/compiled/point_2d_config_no_zero.vg.json b/examples/compiled/point_2d_config_no_zero.vg.json
new file mode 100644
index 00000000000..b6de1de0d23
--- /dev/null
+++ b/examples/compiled/point_2d_config_no_zero.vg.json
@@ -0,0 +1,110 @@
+{
+ "$schema": "https://vega.github.io/schema/vega/v5.json",
+ "description": "A scatterplot showing horsepower and miles per gallons for various cars.",
+ "background": "white",
+ "padding": 5,
+ "width": 200,
+ "height": 200,
+ "style": "cell",
+ "data": [
+ {
+ "name": "source_0",
+ "url": "data/cars.json",
+ "format": {"type": "json"},
+ "transform": [
+ {
+ "type": "filter",
+ "expr": "isValid(datum[\"Horsepower\"]) && isFinite(+datum[\"Horsepower\"]) && isValid(datum[\"Miles_per_Gallon\"]) && isFinite(+datum[\"Miles_per_Gallon\"])"
+ }
+ ]
+ }
+ ],
+ "marks": [
+ {
+ "name": "marks",
+ "type": "symbol",
+ "style": ["point"],
+ "from": {"data": "source_0"},
+ "encode": {
+ "update": {
+ "opacity": {"value": 0.7},
+ "fill": {"value": "transparent"},
+ "stroke": {"value": "#4c78a8"},
+ "ariaRoleDescription": {"value": "point"},
+ "description": {
+ "signal": "\"Horsepower: \" + (format(datum[\"Horsepower\"], \"\")) + \"; Miles_per_Gallon: \" + (format(datum[\"Miles_per_Gallon\"], \"\"))"
+ },
+ "x": {"scale": "x", "field": "Horsepower"},
+ "y": {"scale": "y", "field": "Miles_per_Gallon"}
+ }
+ }
+ }
+ ],
+ "scales": [
+ {
+ "name": "x",
+ "type": "linear",
+ "domain": {"data": "source_0", "field": "Horsepower"},
+ "range": [0, {"signal": "width"}],
+ "nice": true,
+ "zero": false
+ },
+ {
+ "name": "y",
+ "type": "linear",
+ "domain": {"data": "source_0", "field": "Miles_per_Gallon"},
+ "range": [{"signal": "height"}, 0],
+ "nice": true,
+ "zero": false
+ }
+ ],
+ "axes": [
+ {
+ "scale": "x",
+ "orient": "bottom",
+ "gridScale": "y",
+ "grid": true,
+ "tickCount": {"signal": "ceil(width/40)"},
+ "domain": false,
+ "labels": false,
+ "aria": false,
+ "maxExtent": 0,
+ "minExtent": 0,
+ "ticks": false,
+ "zindex": 0
+ },
+ {
+ "scale": "y",
+ "orient": "left",
+ "gridScale": "x",
+ "grid": true,
+ "tickCount": {"signal": "ceil(height/40)"},
+ "domain": false,
+ "labels": false,
+ "aria": false,
+ "maxExtent": 0,
+ "minExtent": 0,
+ "ticks": false,
+ "zindex": 0
+ },
+ {
+ "scale": "x",
+ "orient": "bottom",
+ "grid": false,
+ "title": "Horsepower",
+ "labelFlush": true,
+ "labelOverlap": true,
+ "tickCount": {"signal": "ceil(width/40)"},
+ "zindex": 0
+ },
+ {
+ "scale": "y",
+ "orient": "left",
+ "grid": false,
+ "title": "Miles_per_Gallon",
+ "labelOverlap": true,
+ "tickCount": {"signal": "ceil(height/40)"},
+ "zindex": 0
+ }
+ ]
+}
diff --git a/examples/specs/bar_config_no_zero.vl.json b/examples/specs/bar_config_no_zero.vl.json
new file mode 100644
index 00000000000..4a155b00d7c
--- /dev/null
+++ b/examples/specs/bar_config_no_zero.vl.json
@@ -0,0 +1,17 @@
+{
+ "$schema": "https://vega.github.io/schema/vega-lite/v5.json",
+ "description": "A simple bar chart with embedded data.",
+ "data": {
+ "values": [
+ {"a": "A", "b": 28}, {"a": "B", "b": 55}, {"a": "C", "b": 43},
+ {"a": "D", "b": 91}, {"a": "E", "b": 81}, {"a": "F", "b": 53},
+ {"a": "G", "b": 19}, {"a": "H", "b": 87}, {"a": "I", "b": 52}
+ ]
+ },
+ "mark": "bar",
+ "encoding": {
+ "x": {"field": "a", "type": "nominal", "axis": {"labelAngle": 0}},
+ "y": {"field": "b", "type": "quantitative"}
+ },
+ "config": { "scale": { "zero": false } }
+}
diff --git a/examples/specs/bar_gantt_config_no_zero.vl.json b/examples/specs/bar_gantt_config_no_zero.vl.json
new file mode 100644
index 00000000000..66a0b32e138
--- /dev/null
+++ b/examples/specs/bar_gantt_config_no_zero.vl.json
@@ -0,0 +1,18 @@
+{
+ "$schema": "https://vega.github.io/schema/vega-lite/v5.json",
+ "description": "A simple bar chart with ranged data (aka Gantt Chart).",
+ "data": {
+ "values": [
+ {"task": "A", "start": 1, "end": 3},
+ {"task": "B", "start": 3, "end": 8},
+ {"task": "C", "start": 8, "end": 10}
+ ]
+ },
+ "mark": "bar",
+ "encoding": {
+ "y": {"field": "task", "type": "ordinal"},
+ "x": {"field": "start", "type": "quantitative"},
+ "x2": {"field": "end"}
+ },
+ "config": { "scale": { "zero": false } }
+}
diff --git a/examples/specs/point_2d_config_no_zero.vl.json b/examples/specs/point_2d_config_no_zero.vl.json
new file mode 100644
index 00000000000..977c8553c71
--- /dev/null
+++ b/examples/specs/point_2d_config_no_zero.vl.json
@@ -0,0 +1,11 @@
+{
+ "$schema": "https://vega.github.io/schema/vega-lite/v5.json",
+ "description": "A scatterplot showing horsepower and miles per gallons for various cars.",
+ "data": { "url": "data/cars.json" },
+ "mark": "point",
+ "encoding": {
+ "x": { "field": "Horsepower", "type": "quantitative" },
+ "y": { "field": "Miles_per_Gallon", "type": "quantitative" }
+ },
+ "config": { "scale": { "zero": false } }
+}
diff --git a/site/docs/encoding/scale.md b/site/docs/encoding/scale.md
index 847a2d6316b..1b12563b277 100644
--- a/site/docs/encoding/scale.md
+++ b/site/docs/encoding/scale.md
@@ -452,7 +452,7 @@ To provide themes for all scales, the scale config (`config: {scale: {...}}`) ca
#### Other
-{% include table.html props="clamp,round,xReverse,useUnaggregatedDomain" source="ScaleConfig" %}
+{% include table.html props="clamp,round,xReverse,useUnaggregatedDomain,zero" source="ScaleConfig" %}
{:#range-config}
diff --git a/src/compile/scale/properties.ts b/src/compile/scale/properties.ts
index 501e9dfe3ff..e4463fdd34c 100644
--- a/src/compile/scale/properties.ts
+++ b/src/compile/scale/properties.ts
@@ -4,6 +4,7 @@ import {isBinned, isBinning, isBinParams} from '../../bin';
import {
COLOR,
FILL,
+ getSecondaryRangeChannel,
isXorY,
isXorYOffset,
POLAR_POSITION_SCALE_CHANNELS,
@@ -120,7 +121,8 @@ function parseUnitScaleProperty(model: UnitModel, property: Exclude;
config: Config;
+ hasSecondaryRangeChannel: boolean;
}
export const scaleRules: {
@@ -169,8 +172,8 @@ export const scaleRules: {
const sort = isFieldDef(fieldOrDatumDef) ? fieldOrDatumDef.sort : undefined;
return reverse(scaleType, sort, channel, config.scale);
},
- zero: ({channel, fieldOrDatumDef, domain, markDef, scaleType}) =>
- zero(channel, fieldOrDatumDef, domain, markDef, scaleType)
+ zero: ({channel, fieldOrDatumDef, domain, markDef, scaleType, config, hasSecondaryRangeChannel}) =>
+ zero(channel, fieldOrDatumDef, domain, markDef, scaleType, config.scale, hasSecondaryRangeChannel)
};
// This method is here rather than in range.ts to avoid circular dependency.
@@ -399,7 +402,9 @@ export function zero(
fieldDef: TypedFieldDef | ScaleDatumDef,
specifiedDomain: Domain,
markDef: MarkDef,
- scaleType: ScaleType
+ scaleType: ScaleType,
+ scaleConfig: ScaleConfig,
+ hasSecondaryRangeChannel: boolean
) {
// If users explicitly provide a domain, we should not augment zero as that will be unexpected.
const hasCustomDomain = !!specifiedDomain && specifiedDomain !== 'unaggregated';
@@ -418,7 +423,7 @@ export function zero(
}
}
- // If there is no custom domain, return true only for the following cases:
+ // If there is no custom domain, return configZero value (=`true` as default) only for the following cases:
// 1) using quantitative field with size
// While this can be either ratio or interval fields, our assumption is that
@@ -430,6 +435,7 @@ export function zero(
// 2) non-binned, quantitative x-scale or y-scale
// (For binning, we should not include zero by default because binning are calculated without zero.)
+ // (For area/bar charts with ratio scale chart, we should always include zero.)
if (
!(isFieldDef(fieldDef) && fieldDef.bin) &&
util.contains([...POSITION_SCALE_CHANNELS, ...POLAR_POSITION_SCALE_CHANNELS], channel)
@@ -441,7 +447,12 @@ export function zero(
}
}
- return true;
+ if (contains(['bar', 'area'], type) && !hasSecondaryRangeChannel) {
+ return true;
+ }
+
+ return scaleConfig?.zero;
}
+
return false;
}
diff --git a/src/scale.ts b/src/scale.ts
index a9bfd382f19..c90e7b13421 100644
--- a/src/scale.ts
+++ b/src/scale.ts
@@ -415,6 +415,14 @@ export interface ScaleConfig {
* Reverse x-scale by default (useful for right-to-left charts).
*/
xReverse?: boolean | ES;
+
+ /**
+ * Default `scale.zero` for [`continuous`](https://vega.github.io/vega-lite/docs/scale.html#continuous) scales except for (1) x/y-scales of non-ranged bar or area charts and (2) size scales.
+ *
+ * __Default value:__ `true`
+ *
+ */
+ zero?: boolean;
}
export const defaultScaleConfig: ScaleConfig = {
@@ -439,7 +447,9 @@ export const defaultScaleConfig: ScaleConfig = {
minStrokeWidth: 1,
maxStrokeWidth: 4,
quantileCount: 4,
- quantizeCount: 4
+ quantizeCount: 4,
+
+ zero: true
};
export interface SchemeParams {
diff --git a/test/compile/scale/properties.test.ts b/test/compile/scale/properties.test.ts
index 82676906fc7..1129cfc0fa7 100644
--- a/test/compile/scale/properties.test.ts
+++ b/test/compile/scale/properties.test.ts
@@ -199,35 +199,63 @@ describe('compile/scale', () => {
});
describe('zero', () => {
- it('should return true when mapping a quantitative field to x with scale.domain = "unaggregated"', () => {
+ it('should return default (undefined) when mapping a quantitative field to x with scale.domain = "unaggregated"', () => {
expect(
- rules.zero('x', {field: 'a', type: 'quantitative'}, 'unaggregated', {type: 'point'}, 'linear')
- ).toBeTruthy();
+ rules.zero('x', {field: 'a', type: 'quantitative'}, 'unaggregated', {type: 'point'}, 'linear', undefined, false)
+ ).toBeUndefined();
});
it('should return true when mapping a quantitative field to size', () => {
- expect(rules.zero('size', {field: 'a', type: 'quantitative'}, undefined, {type: 'point'}, 'linear')).toBeTruthy();
+ expect(
+ rules.zero('size', {field: 'a', type: 'quantitative'}, undefined, {type: 'point'}, 'linear', undefined, false)
+ ).toBeTruthy();
});
it('should return false when mapping a ordinal field to size', () => {
- expect(!rules.zero('size', {field: 'a', type: 'ordinal'}, undefined, {type: 'point'}, 'linear')).toBeTruthy();
+ expect(
+ !rules.zero('size', {field: 'a', type: 'ordinal'}, undefined, {type: 'point'}, 'linear', undefined, false)
+ ).toBeTruthy();
});
- it('should return true when mapping a non-binned quantitative field to x/y of point', () => {
+ it('should return default (undefined) when mapping a non-binned quantitative field to x/y of point', () => {
for (const channel of ['x', 'y'] as const) {
expect(
- rules.zero(channel, {field: 'a', type: 'quantitative'}, undefined, {type: 'point'}, 'linear')
- ).toBeTruthy();
+ rules.zero(
+ channel,
+ {field: 'a', type: 'quantitative'},
+ undefined,
+ {type: 'point'},
+ 'linear',
+ undefined,
+ false
+ )
+ ).toBeUndefined();
}
});
it('should return false when mapping a quantitative field to dimension axis of bar, line, and area', () => {
for (const mark of [BAR, AREA, LINE]) {
expect(
- rules.zero('x', {field: 'a', type: 'quantitative'}, undefined, {type: mark, orient: 'vertical'}, 'linear')
+ rules.zero(
+ 'x',
+ {field: 'a', type: 'quantitative'},
+ undefined,
+ {type: mark, orient: 'vertical'},
+ 'linear',
+ undefined,
+ false
+ )
).toBe(false);
expect(
- rules.zero('y', {field: 'a', type: 'quantitative'}, undefined, {type: mark, orient: 'horizontal'}, 'linear')
+ rules.zero(
+ 'y',
+ {field: 'a', type: 'quantitative'},
+ undefined,
+ {type: mark, orient: 'horizontal'},
+ 'linear',
+ undefined,
+ false
+ )
).toBe(false);
}
});
@@ -235,7 +263,15 @@ describe('compile/scale', () => {
it('should return false when mapping a binned quantitative field to x/y', () => {
for (const channel of ['x', 'y'] as const) {
expect(
- !rules.zero(channel, {bin: true, field: 'a', type: 'quantitative'}, undefined, {type: 'point'}, 'linear')
+ !rules.zero(
+ channel,
+ {bin: true, field: 'a', type: 'quantitative'},
+ undefined,
+ {type: 'point'},
+ 'linear',
+ undefined,
+ false
+ )
).toBeTruthy();
}
});
@@ -252,10 +288,78 @@ describe('compile/scale', () => {
},
[3, 5],
{type: 'point'},
- 'linear'
+ 'linear',
+ undefined,
+ false
)
).toBeTruthy();
}
});
+
+ it(`should return config.scale.zero instead of true if it is specified`, () => {
+ const configZero = false;
+ for (const channel of ['x', 'y'] as const) {
+ expect(
+ rules.zero(
+ channel,
+ {field: 'a', type: 'quantitative'},
+ undefined,
+ {type: 'point'},
+ 'linear',
+ {zero: configZero},
+ false
+ )
+ ).toBe(configZero);
+ }
+
+ expect(
+ rules.zero(
+ 'size',
+ {field: 'a', type: 'ordinal'},
+ undefined,
+ {type: 'point'},
+ 'linear',
+ {zero: configZero},
+ false
+ )
+ ).toBe(configZero);
+
+ // ranged bar/area should take default configZero
+ expect(
+ rules.zero('x', {field: 'a', type: 'quantitative'}, undefined, {type: BAR}, 'linear', {zero: configZero}, true)
+ ).toBe(configZero);
+ });
+
+ it(`should return true for x/y scales of the non-ranged area/bar charts regardless to config`, () => {
+ for (const mark of [BAR, AREA]) {
+ for (const channel of ['x', 'y'] as const) {
+ expect(
+ rules.zero(
+ channel,
+ {field: 'a', type: 'quantitative'},
+ undefined,
+ {type: mark},
+ 'linear',
+ {zero: false},
+ false
+ )
+ ).toBe(true);
+ }
+ }
+ });
+
+ it(`should return true for the continuous & quantitative size scale regardless to config`, () => {
+ expect(
+ rules.zero(
+ 'size',
+ {field: 'a', type: 'quantitative'},
+ undefined,
+ {type: 'point'},
+ 'linear',
+ {zero: false},
+ false
+ )
+ ).toBe(true);
+ });
});
});