ggaction 0.0.12 → 0.0.13
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/CHANGELOG.md +49 -0
- package/README.md +2 -2
- package/knowledge/action-card.schema.json +1 -1
- package/knowledge/action-cards.json +1 -1
- package/knowledge/action-cards.schema.json +1 -1
- package/knowledge/extension-authoring.md +2 -1
- package/knowledge/intent-taxonomy.json +1 -1
- package/knowledge/mcp-resources.json +1 -1
- package/knowledge/task-resolver.js +1 -1
- package/package.json +4 -2
- package/src/actions/basic.js +2 -0
- package/src/actions/boxPlots/materialize.js +2 -1
- package/src/actions/canvas/actions.js +3 -1
- package/src/actions/canvas/fitting.js +211 -0
- package/src/actions/canvas/index.js +2 -0
- package/src/actions/categoryOrder/index.js +3 -2
- package/src/actions/charts/area.js +47 -0
- package/src/actions/charts/bar.js +11 -5
- package/src/actions/charts/beeswarm.js +70 -0
- package/src/actions/charts/density.js +44 -0
- package/src/actions/charts/ecdf.js +183 -0
- package/src/actions/charts/endpoints.js +451 -0
- package/src/actions/charts/heatmap.js +2 -2
- package/src/actions/charts/histogram.js +1 -1
- package/src/actions/charts/horizon.js +71 -0
- package/src/actions/charts/index.js +37 -0
- package/src/actions/charts/interval-regression.js +169 -0
- package/src/actions/charts/line.js +5 -5
- package/src/actions/charts/parallel.js +1 -1
- package/src/actions/charts/pie.js +44 -0
- package/src/actions/charts/polar.js +123 -0
- package/src/actions/charts/radar.js +299 -0
- package/src/actions/charts/radial.js +42 -0
- package/src/actions/charts/raincloud.js +422 -0
- package/src/actions/charts/rug-strip.js +279 -0
- package/src/actions/charts/scatter.js +9 -3
- package/src/actions/charts/shared.js +69 -10
- package/src/actions/composition/actions.js +118 -1
- package/src/actions/data/bin.js +29 -0
- package/src/actions/data/computed.js +24 -0
- package/src/actions/data/derived.js +66 -0
- package/src/actions/data/ecdf.js +38 -0
- package/src/actions/data/filter.js +212 -28
- package/src/actions/data/fold.js +24 -0
- package/src/actions/data/index.js +24 -0
- package/src/actions/data/interval.js +2 -0
- package/src/actions/data/intervalEdit.js +86 -4
- package/src/actions/data/regression.js +5 -2
- package/src/actions/data/stack.js +26 -0
- package/src/actions/data/summary.js +26 -0
- package/src/actions/data/timeUnit.js +1 -1
- package/src/actions/encodings/appearance.js +32 -13
- package/src/actions/encodings/barWidth.js +8 -0
- package/src/actions/encodings/basic.js +2 -0
- package/src/actions/encodings/color/continuous.js +19 -59
- package/src/actions/encodings/color/index.js +28 -22
- package/src/actions/encodings/color/layout.js +3 -97
- package/src/actions/encodings/color/policy.js +5 -8
- package/src/actions/encodings/density/resolve.js +37 -5
- package/src/actions/encodings/density.js +120 -33
- package/src/actions/encodings/horizon/resolve.js +8 -4
- package/src/actions/encodings/horizon.js +18 -8
- package/src/actions/encodings/index.js +2 -0
- package/src/actions/encodings/offset.js +10 -16
- package/src/actions/encodings/parallel.js +2 -8
- package/src/actions/encodings/position/apply.js +10 -4
- package/src/actions/encodings/position/index.js +43 -5
- package/src/actions/encodings/position/policies/arc.js +14 -0
- package/src/actions/encodings/position/policies/area.js +4 -42
- package/src/actions/encodings/position/policies/bar.js +48 -13
- package/src/actions/encodings/position/resolve.js +67 -22
- package/src/actions/encodings/ranged.js +123 -97
- package/src/actions/encodings/remove.js +37 -32
- package/src/actions/encodings/ruleAppearance.js +23 -9
- package/src/actions/encodings/seriesLayout.js +104 -0
- package/src/actions/encodings/shared.js +25 -23
- package/src/actions/encodings/strokeDash.js +9 -6
- package/src/actions/encodings/temporal.js +7 -0
- package/src/actions/encodings/text.js +30 -15
- package/src/actions/errorBands/create.js +18 -5
- package/src/actions/errorBands/edit.js +341 -21
- package/src/actions/errorBars/create.js +21 -10
- package/src/actions/errorBars/edit.js +355 -19
- package/src/actions/facets/actions.js +410 -12
- package/src/actions/facets/derive.js +57 -8
- package/src/actions/gradientPlots/components.js +33 -11
- package/src/actions/gradientPlots/materialize.js +5 -7
- package/src/actions/guides/applicability.js +20 -17
- package/src/actions/guides/axes/axes.js +4 -3
- package/src/actions/guides/axes/axis.js +18 -18
- package/src/actions/guides/axes/components.js +43 -0
- package/src/actions/guides/axes/edit.js +16 -51
- package/src/actions/guides/axes/labels.js +129 -19
- package/src/actions/guides/axes/lines.js +7 -5
- package/src/actions/guides/axes/parallel/lifecycle.js +117 -0
- package/src/actions/guides/axes/parallel/policy.js +137 -0
- package/src/actions/guides/axes/parallel/resolve.js +44 -23
- package/src/actions/guides/axes/parallel.js +93 -217
- package/src/actions/guides/axes/policy.js +21 -67
- package/src/actions/guides/axes/tickGroups.js +14 -8
- package/src/actions/guides/axes/ticks.js +5 -4
- package/src/actions/guides/axes/titles.js +21 -8
- package/src/actions/guides/basic.js +2 -0
- package/src/actions/guides/facade.js +106 -0
- package/src/actions/guides/facadeAxes.js +200 -0
- package/src/actions/guides/facadeLegend.js +63 -0
- package/src/actions/guides/grids/grid.js +37 -33
- package/src/actions/guides/grids/resolve.js +10 -2
- package/src/actions/guides/guides.js +35 -28
- package/src/actions/guides/legends/categorical/actions.js +193 -249
- package/src/actions/guides/legends/categorical/components.js +4 -5
- package/src/actions/guides/legends/categorical/layout.js +36 -349
- package/src/actions/guides/legends/categorical/options.js +30 -14
- package/src/actions/guides/legends/categorical/recipes.js +14 -0
- package/src/actions/guides/legends/categorical/resolve.js +21 -10
- package/src/actions/guides/legends/categorical/symbols.js +2 -3
- package/src/actions/guides/legends/continuous/common.js +69 -14
- package/src/actions/guides/legends/continuous/gradient.js +111 -83
- package/src/actions/guides/legends/continuous/index.js +6 -2
- package/src/actions/guides/legends/continuous/interval.js +71 -92
- package/src/actions/guides/legends/continuous/opacity.js +105 -84
- package/src/actions/guides/legends/creation.js +27 -0
- package/src/actions/guides/legends/edit.js +198 -66
- package/src/actions/guides/legends/focused.js +2 -2
- package/src/actions/guides/legends/lane.js +98 -86
- package/src/actions/guides/legends/lifecycle.js +132 -0
- package/src/actions/guides/legends/remove.js +31 -76
- package/src/actions/guides/legends/size.js +149 -105
- package/src/actions/guides/legends/strokeWidth.js +106 -64
- package/src/actions/guides/legends/target.js +12 -0
- package/src/actions/guides/legends/transition.js +43 -0
- package/src/actions/guides/polar/axes/facade.js +77 -62
- package/src/actions/guides/polar/axes/labels.js +5 -4
- package/src/actions/guides/polar/axes/lines.js +2 -1
- package/src/actions/guides/polar/axes/shared.js +6 -0
- package/src/actions/guides/polar/axes/ticks.js +5 -4
- package/src/actions/guides/polar/axes/titles.js +5 -4
- package/src/actions/guides/polar/grids.js +7 -7
- package/src/actions/guides/reuse.js +44 -0
- package/src/actions/guides/tickValues.js +19 -21
- package/src/actions/index.js +2 -0
- package/src/actions/intervals/resolve.js +35 -15
- package/src/actions/marks/arc/actions.js +1 -1
- package/src/actions/marks/area/actions.js +18 -4
- package/src/actions/marks/area/materialize.js +5 -2
- package/src/actions/marks/bar/materialize.js +11 -7
- package/src/actions/marks/index.js +5 -0
- package/src/actions/marks/line/actions.js +43 -108
- package/src/actions/marks/line/materialize.js +34 -52
- package/src/actions/marks/point/edit.js +11 -15
- package/src/actions/marks/point/index.js +1 -0
- package/src/actions/marks/point/jitter.js +3 -0
- package/src/actions/marks/point/materialize.js +106 -2
- package/src/actions/marks/point/packing.js +68 -0
- package/src/actions/marks/references.js +87 -0
- package/src/actions/marks/remove.js +17 -4
- package/src/actions/marks/rule/actions.js +34 -3
- package/src/actions/marks/rule/appearance.js +26 -0
- package/src/actions/marks/shared.js +12 -12
- package/src/actions/marks/text/actions.js +224 -6
- package/src/actions/marks/text/layout.js +2 -2
- package/src/actions/primitives/createGraphics.js +3 -1
- package/src/actions/primitives/semantic.js +1 -1
- package/src/actions/primitives/semanticAction.js +39 -2
- package/src/actions/primitives/semanticValidation/guide.js +10 -0
- package/src/actions/primitives/semanticValidation/layer.js +18 -1
- package/src/actions/primitives/semanticValidation/scale.js +10 -1
- package/src/actions/regression/create.js +1 -1
- package/src/actions/regression/edit.js +19 -6
- package/src/actions/regression/resolve.js +1 -1
- package/src/actions/scales/consumers/common.js +20 -53
- package/src/actions/scales/consumers/families.js +27 -14
- package/src/actions/scales/consumers/index.js +23 -2
- package/src/actions/scales/consumers/seriesLayout.js +33 -2
- package/src/actions/scales/create.js +4 -4
- package/src/actions/scales/definitions.js +19 -3
- package/src/actions/scales/edit.js +46 -34
- package/src/actions/scales/editPolicy.js +21 -31
- package/src/actions/scales/materialize.js +10 -46
- package/src/actions/scales/patch.js +1 -1
- package/src/actions/scales/preview.js +39 -0
- package/src/actions/scales/quantitativeColor.js +9 -5
- package/src/actions/theme/actions.js +43 -0
- package/src/actions/theme/index.js +9 -0
- package/src/actions/theme/reconcile.js +882 -0
- package/src/actions/titles/actions.js +11 -10
- package/src/actions/titles/resolve.js +1 -40
- package/src/actions/violinPlots/create.js +86 -42
- package/src/actions/violinPlots/edit.js +191 -0
- package/src/actions/violinPlots/index.js +2 -0
- package/src/core/ChartProgram.js +7 -0
- package/src/core/action.js +22 -2
- package/src/core/compositionState.js +136 -8
- package/src/grammar/aggregate.js +66 -23
- package/src/grammar/arcs.js +58 -1
- package/src/grammar/areaEndpoints.js +46 -0
- package/src/grammar/areaSeries.js +87 -41
- package/src/grammar/bars/aggregate.js +33 -12
- package/src/grammar/bars/policy.js +9 -7
- package/src/grammar/bin.js +181 -0
- package/src/grammar/categoryOrder.js +34 -0
- package/src/grammar/computed.js +150 -0
- package/src/grammar/ecdf.js +198 -0
- package/src/grammar/facets/index.js +117 -6
- package/src/grammar/fold.js +123 -0
- package/src/grammar/horizon.js +6 -4
- package/src/grammar/interval.js +37 -20
- package/src/grammar/lineSeries.js +20 -63
- package/src/grammar/markFilter.js +22 -4
- package/src/grammar/markLabels.js +93 -0
- package/src/grammar/parallelAxisTitles.js +16 -0
- package/src/grammar/pathSeries.js +91 -0
- package/src/grammar/pointPacking.js +183 -0
- package/src/grammar/positionDatum.js +12 -0
- package/src/grammar/rects.js +9 -1
- package/src/grammar/regression/derive.js +4 -0
- package/src/grammar/regression/index.js +7 -2
- package/src/grammar/regression/models.js +22 -7
- package/src/grammar/regression/parameters.js +40 -13
- package/src/grammar/rotation.js +29 -0
- package/src/grammar/rules.js +7 -21
- package/src/grammar/scales/color.js +23 -1
- package/src/grammar/scales/colorConsumers.js +38 -0
- package/src/grammar/scales/definition.js +15 -1
- package/src/grammar/scales/discretized.js +11 -5
- package/src/grammar/scales/fields.js +38 -8
- package/src/grammar/scales/mapping.js +2 -0
- package/src/grammar/scales/radial.js +55 -0
- package/src/grammar/scales/types.js +1 -0
- package/src/grammar/schemas/semanticPath.js +17 -3
- package/src/grammar/stack.js +170 -0
- package/src/grammar/statistics/confidenceInterval.js +101 -0
- package/src/grammar/summary.js +183 -0
- package/src/grammar/text.js +22 -16
- package/src/grammar/timeUnit.js +21 -11
- package/src/grammar/transformTopology.js +6 -0
- package/src/grammar/transforms.js +36 -0
- package/src/grammar/valueFormat.js +112 -0
- package/src/grammar/window.js +13 -7
- package/src/layout/facets.js +41 -7
- package/src/layout/guideCollisions.js +12 -0
- package/src/layout/legend.js +2 -10
- package/src/layout/legendItems.js +102 -0
- package/src/layout/legendLane.js +100 -11
- package/src/materialization/bars/aggregate.js +38 -152
- package/src/materialization/bars/histogram.js +24 -0
- package/src/materialization/categorySlotOffset.js +40 -0
- package/src/materialization/compositionSnapshot.js +1 -1
- package/src/materialization/dependencies.js +57 -16
- package/src/materialization/encodings.js +1 -1
- package/src/materialization/facets.js +8 -1
- package/src/materialization/guides/layout.js +57 -0
- package/src/materialization/guides/resources.js +2 -2
- package/src/materialization/legends.js +10 -1
- package/src/materialization/marks/capabilities.js +20 -5
- package/src/materialization/marks/grouping.js +52 -0
- package/src/materialization/marks/index.js +58 -23
- package/src/materialization/marks/policies.js +2 -0
- package/src/materialization/rect.js +33 -33
- package/src/materialization/rowEncoding.js +13 -13
- package/src/materialization/scaleGuideDependencies.js +8 -5
- package/src/materialization/scales/map.js +1 -0
- package/src/materialization/scales/policies/arc.js +42 -0
- package/src/materialization/scales/policies/binnedPosition.js +7 -4
- package/src/materialization/scales/policies/series.js +2 -1
- package/src/materialization/scales/resolve.js +46 -14
- package/src/materialization/selection/compatibility.js +11 -0
- package/src/materialization/selection/items/bar.js +12 -68
- package/src/materialization/selection/items/common.js +8 -2
- package/src/materialization/selection/items/path.js +3 -13
- package/src/materialization/selection/items/rect.js +7 -4
- package/src/materialization/text.js +64 -5
- package/src/mcp/adapter.js +2 -2
- package/src/selectors/datasets.js +13 -0
- package/src/selectors/layers.js +3 -2
- package/src/selectors/scales.js +6 -0
- package/src/theme/defaults.js +39 -0
- package/types/basic.d.ts +11 -2
- package/types/index.d.ts +126 -0
- package/types/program.d.ts +1320 -135
- package/src/materialization/bars/grouped.js +0 -144
|
@@ -46,20 +46,52 @@ export function resolveDensityTransitionScaleDefinitions(
|
|
|
46
46
|
layer,
|
|
47
47
|
transform,
|
|
48
48
|
placement,
|
|
49
|
-
rawPlacement
|
|
49
|
+
rawPlacement,
|
|
50
|
+
rawValueScale
|
|
50
51
|
) {
|
|
51
52
|
const valueScale = valueScaleForTransition(program, layer, transform);
|
|
52
53
|
if (valueScale === undefined) {
|
|
53
54
|
throw new Error(`Density area "${layer.id}" requires its value scale.`);
|
|
54
55
|
}
|
|
55
|
-
|
|
56
|
+
if (rawValueScale?.id !== undefined && rawValueScale.id !== valueScale.id) {
|
|
57
|
+
throw new Error("editDensity value scale cannot change its id.");
|
|
58
|
+
}
|
|
59
|
+
const { id: _valueId, range: _valueRange, ...storedValueDefinition } = valueScale;
|
|
56
60
|
void _valueId;
|
|
57
61
|
void _valueRange;
|
|
62
|
+
const valueDefinition = resolveDensityScaleOptions(
|
|
63
|
+
rawValueScale,
|
|
64
|
+
storedValueDefinition,
|
|
65
|
+
"Density valueScale"
|
|
66
|
+
);
|
|
67
|
+
delete valueDefinition.id;
|
|
68
|
+
delete valueDefinition.range;
|
|
58
69
|
const valueChannel = placement?.channel === "x" ? "y" : "x";
|
|
59
70
|
const companionChannel = valueChannel === "x" ? "y" : "x";
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
|
|
71
|
+
let companionDefinition;
|
|
72
|
+
if (placement === undefined) {
|
|
73
|
+
companionDefinition = {
|
|
74
|
+
type: "linear", domain: "auto", range: "auto", nice: true, zero: true
|
|
75
|
+
};
|
|
76
|
+
} else {
|
|
77
|
+
const currentCategoryChannel = transform.placement?.channel;
|
|
78
|
+
const currentCategoryScale = currentCategoryChannel === undefined
|
|
79
|
+
? undefined
|
|
80
|
+
: findSemanticScale(program, layer.encoding[currentCategoryChannel].scale);
|
|
81
|
+
const { id: _categoryId, range: _categoryRange, ...storedCategoryDefinition } =
|
|
82
|
+
currentCategoryScale ?? {};
|
|
83
|
+
void _categoryId;
|
|
84
|
+
void _categoryRange;
|
|
85
|
+
companionDefinition = resolveDensityCategoryScaleOptions({
|
|
86
|
+
domain: "auto",
|
|
87
|
+
range: "auto",
|
|
88
|
+
paddingInner: 0,
|
|
89
|
+
paddingOuter: 0,
|
|
90
|
+
align: 0.5,
|
|
91
|
+
...storedCategoryDefinition,
|
|
92
|
+
...(rawPlacement?.scale ?? {})
|
|
93
|
+
});
|
|
94
|
+
}
|
|
63
95
|
return {
|
|
64
96
|
[valueChannel]: { ...valueDefinition, range: "auto" },
|
|
65
97
|
[companionChannel]: companionDefinition
|
|
@@ -16,6 +16,8 @@ import { validateOptions } from "./shared.js";
|
|
|
16
16
|
import { normalizeDensityPlacement } from "../../grammar/density.js";
|
|
17
17
|
import { scaleEditPatch } from "../scales/patch.js";
|
|
18
18
|
import { removeOwnedColorLegends } from "../guides/legends/remove.js";
|
|
19
|
+
import { rebindDistributionGuides } from "../distributions/revision.js";
|
|
20
|
+
import { findSemanticScale } from "../../selectors/scales.js";
|
|
19
21
|
import {
|
|
20
22
|
requireDensityField,
|
|
21
23
|
resolveDensityCategoryScaleOptions,
|
|
@@ -31,9 +33,50 @@ const OPTIONS = Object.freeze([
|
|
|
31
33
|
]);
|
|
32
34
|
const EDIT_OPTIONS = Object.freeze([
|
|
33
35
|
"target", "source", "field", "groupBy", "bandwidth", "extent", "steps",
|
|
34
|
-
"kernel", "normalization", "placement"
|
|
36
|
+
"kernel", "normalization", "densityChannel", "valueScale", "placement"
|
|
35
37
|
]);
|
|
36
38
|
const EDITABLE = Object.freeze(EDIT_OPTIONS.filter(option => option !== "target"));
|
|
39
|
+
const SCALE_PROPERTIES = Object.freeze([
|
|
40
|
+
"type", "domain", "range", "nice", "zero", "clamp", "reverse",
|
|
41
|
+
"base", "exponent", "constant", "paddingInner", "paddingOuter",
|
|
42
|
+
"padding", "align", "interpolate", "midpoint", "unknown"
|
|
43
|
+
]);
|
|
44
|
+
|
|
45
|
+
function replaceScaleDefinition(program, id, definition) {
|
|
46
|
+
const current = findSemanticScale(program, id);
|
|
47
|
+
let next = program;
|
|
48
|
+
for (const property of SCALE_PROPERTIES) {
|
|
49
|
+
if (Object.hasOwn(current, property) && !Object.hasOwn(definition, property)) {
|
|
50
|
+
next = next.editSemantic({ property: `scale[${id}].${property}`, remove: true });
|
|
51
|
+
}
|
|
52
|
+
}
|
|
53
|
+
for (const property of SCALE_PROPERTIES) {
|
|
54
|
+
if (!Object.hasOwn(definition, property)) continue;
|
|
55
|
+
next = next.editSemantic({
|
|
56
|
+
property: `scale[${id}].${property}`,
|
|
57
|
+
value: definition[property]
|
|
58
|
+
});
|
|
59
|
+
}
|
|
60
|
+
return next;
|
|
61
|
+
}
|
|
62
|
+
|
|
63
|
+
function replaceDensityPositions(program, layerId, definition) {
|
|
64
|
+
let next = program;
|
|
65
|
+
for (const channel of ["x", "y"]) {
|
|
66
|
+
const value = definition[channel];
|
|
67
|
+
for (const [property, propertyValue] of Object.entries({
|
|
68
|
+
field: value.field,
|
|
69
|
+
fieldType: value.fieldType,
|
|
70
|
+
scale: typeof value.scale === "string" ? value.scale : value.scale.id
|
|
71
|
+
})) {
|
|
72
|
+
next = next.editSemantic({
|
|
73
|
+
property: `layer[${layerId}].encoding.${channel}.${property}`,
|
|
74
|
+
value: propertyValue
|
|
75
|
+
});
|
|
76
|
+
}
|
|
77
|
+
}
|
|
78
|
+
return next;
|
|
79
|
+
}
|
|
37
80
|
|
|
38
81
|
function findArea(program, requested) {
|
|
39
82
|
const areas = program.semanticSpec.layers.filter(layer => layer.mark?.type === "area");
|
|
@@ -80,7 +123,7 @@ const encodeDensity = action(
|
|
|
80
123
|
validateOptions(args, OPTIONS, "encodeDensity");
|
|
81
124
|
const layer = findArea(this, args.target);
|
|
82
125
|
const field = requireDensityField(args.field, "Density field");
|
|
83
|
-
const groupBy = args.groupBy === undefined
|
|
126
|
+
const groupBy = args.groupBy === undefined || args.groupBy === false
|
|
84
127
|
? undefined
|
|
85
128
|
: requireDensityField(args.groupBy, "Density groupBy");
|
|
86
129
|
const source = validateUserId(
|
|
@@ -241,17 +284,34 @@ const editDensity = action(
|
|
|
241
284
|
: transform.groupBy;
|
|
242
285
|
const changesGroup = groupBy !== transform.groupBy;
|
|
243
286
|
assertGroupingSelectionCompatibility(this, layer, changesGroup);
|
|
287
|
+
const currentDensityChannel = transform.placement?.channel ?? (
|
|
288
|
+
layer.encoding.x.field === transform.as[1] ? "x" : "y"
|
|
289
|
+
);
|
|
290
|
+
const changesPlacementMode = Object.hasOwn(args, "placement") &&
|
|
291
|
+
(transform.placement === undefined) !==
|
|
292
|
+
(args.placement?.type === "baseline");
|
|
293
|
+
const densityChannel = Object.hasOwn(args, "densityChannel")
|
|
294
|
+
? args.densityChannel
|
|
295
|
+
: changesPlacementMode
|
|
296
|
+
? currentDensityChannel === "x" ? "y" : "x"
|
|
297
|
+
: currentDensityChannel;
|
|
298
|
+
if (!["x", "y"].includes(densityChannel)) {
|
|
299
|
+
throw new Error(`Unsupported densityChannel "${densityChannel}".`);
|
|
300
|
+
}
|
|
301
|
+
const changesDensityChannel = densityChannel !== currentDensityChannel;
|
|
244
302
|
const categoryField = densityCategoryField(layer, transform, groupBy);
|
|
245
303
|
const requestedPlacement = Object.hasOwn(args, "placement")
|
|
246
304
|
? normalizeDensityPlacement(args.placement, {
|
|
247
|
-
densityChannel
|
|
305
|
+
densityChannel,
|
|
248
306
|
groupBy,
|
|
249
307
|
categoryField: categoryField ?? groupBy ??
|
|
250
308
|
`${layer.id}DensityCategory`
|
|
251
309
|
})
|
|
252
|
-
: transform.placement === undefined
|
|
310
|
+
: transform.placement === undefined
|
|
253
311
|
? transform.placement
|
|
254
|
-
:
|
|
312
|
+
: !changesGroup && !changesDensityChannel
|
|
313
|
+
? transform.placement
|
|
314
|
+
: normalizeDensityPlacement({
|
|
255
315
|
type: "category",
|
|
256
316
|
...(transform.placement.side === undefined
|
|
257
317
|
? {}
|
|
@@ -261,7 +321,7 @@ const editDensity = action(
|
|
|
261
321
|
? {}
|
|
262
322
|
: { split: transform.placement.split })
|
|
263
323
|
}, {
|
|
264
|
-
densityChannel
|
|
324
|
+
densityChannel,
|
|
265
325
|
groupBy,
|
|
266
326
|
categoryField
|
|
267
327
|
});
|
|
@@ -308,8 +368,7 @@ const editDensity = action(
|
|
|
308
368
|
? {}
|
|
309
369
|
: { placement: requestedPlacement })
|
|
310
370
|
};
|
|
311
|
-
const
|
|
312
|
-
(transform.placement === undefined) !== (requestedPlacement === undefined);
|
|
371
|
+
const rebuildsPositions = changesPlacementMode || changesDensityChannel;
|
|
313
372
|
const applyEdit = program => {
|
|
314
373
|
let next = requestedPlacement === undefined
|
|
315
374
|
? program.createDensityData(dataArgs)
|
|
@@ -360,7 +419,7 @@ const editDensity = action(
|
|
|
360
419
|
}
|
|
361
420
|
}
|
|
362
421
|
|
|
363
|
-
if (
|
|
422
|
+
if (rebuildsPositions) {
|
|
364
423
|
const xScaleId = layer.encoding?.x?.scale;
|
|
365
424
|
const yScaleId = layer.encoding?.y?.scale;
|
|
366
425
|
const scaleDefinitions = resolveDensityTransitionScaleDefinitions(
|
|
@@ -368,24 +427,18 @@ const editDensity = action(
|
|
|
368
427
|
layer,
|
|
369
428
|
transform,
|
|
370
429
|
requestedPlacement,
|
|
371
|
-
args.placement
|
|
372
|
-
|
|
373
|
-
next = next
|
|
374
|
-
.editSemantic({
|
|
375
|
-
property: `layer[${layer.id}].encoding.x`,
|
|
376
|
-
remove: true
|
|
377
|
-
})
|
|
378
|
-
.editSemantic({
|
|
379
|
-
property: `layer[${layer.id}].encoding.y`,
|
|
380
|
-
remove: true
|
|
381
|
-
});
|
|
382
|
-
next = next
|
|
383
|
-
.editScale(scaleEditPatch(xScaleId, scaleDefinitions.x))
|
|
384
|
-
.editScale(scaleEditPatch(yScaleId, scaleDefinitions.y));
|
|
385
|
-
const densityChannel = requestedPlacement?.channel ?? (
|
|
386
|
-
layer.encoding.x.field === transform.as[1] ? "x" : "y"
|
|
430
|
+
args.placement,
|
|
431
|
+
args.valueScale
|
|
387
432
|
);
|
|
388
|
-
|
|
433
|
+
if (
|
|
434
|
+
args.placement?.scale?.id !== undefined &&
|
|
435
|
+
args.placement.scale.id !== layer.encoding[requestedPlacement.channel].scale
|
|
436
|
+
) {
|
|
437
|
+
throw new Error("editDensity placement scale cannot change its id.");
|
|
438
|
+
}
|
|
439
|
+
next = replaceScaleDefinition(next, xScaleId, scaleDefinitions.x);
|
|
440
|
+
next = replaceScaleDefinition(next, yScaleId, scaleDefinitions.y);
|
|
441
|
+
const valueChannel = densityChannel === "x" ? "y" : "x";
|
|
389
442
|
const definition = resolveDensityPositionDefinition({
|
|
390
443
|
layer: { densityChannel },
|
|
391
444
|
output: transform.as,
|
|
@@ -393,23 +446,46 @@ const editDensity = action(
|
|
|
393
446
|
placement: requestedPlacement,
|
|
394
447
|
coordinate: layer.coordinate,
|
|
395
448
|
valueScale: {
|
|
396
|
-
|
|
397
|
-
|
|
449
|
+
...scaleDefinitions[valueChannel],
|
|
450
|
+
id: valueChannel === "y" ? yScaleId : xScaleId
|
|
398
451
|
},
|
|
399
452
|
densityScale: requestedPlacement === undefined
|
|
400
453
|
? {
|
|
401
|
-
|
|
402
|
-
|
|
454
|
+
...scaleDefinitions[densityChannel],
|
|
455
|
+
id: densityChannel === "x" ? xScaleId : yScaleId
|
|
403
456
|
}
|
|
404
457
|
: undefined,
|
|
405
458
|
placementScale: requestedPlacement === undefined
|
|
406
459
|
? undefined
|
|
407
460
|
: {
|
|
408
|
-
|
|
409
|
-
|
|
461
|
+
...scaleDefinitions[requestedPlacement.channel],
|
|
462
|
+
id: requestedPlacement.channel === "x" ? xScaleId : yScaleId
|
|
410
463
|
}
|
|
411
464
|
});
|
|
412
|
-
next =
|
|
465
|
+
next = replaceDensityPositions(next, layer.id, definition);
|
|
466
|
+
next = next.rematerializeScale({ id: xScaleId, marks: false, guides: false })
|
|
467
|
+
.rematerializeScale({ id: yScaleId, marks: false, guides: false });
|
|
468
|
+
const oldValueChannel = currentDensityChannel === "x" ? "y" : "x";
|
|
469
|
+
next = rebindDistributionGuides(next, {
|
|
470
|
+
oldXScale: xScaleId,
|
|
471
|
+
oldYScale: yScaleId,
|
|
472
|
+
newXScale: xScaleId,
|
|
473
|
+
newYScale: yScaleId,
|
|
474
|
+
oldXTitle: oldValueChannel === "x"
|
|
475
|
+
? transform.field
|
|
476
|
+
: transform.placement?.categoryField ?? transform.as[1],
|
|
477
|
+
oldYTitle: oldValueChannel === "y"
|
|
478
|
+
? transform.field
|
|
479
|
+
: transform.placement?.categoryField ?? transform.as[1],
|
|
480
|
+
newXTitle: valueChannel === "x"
|
|
481
|
+
? field
|
|
482
|
+
: requestedPlacement?.categoryField ?? transform.as[1],
|
|
483
|
+
newYTitle: valueChannel === "y"
|
|
484
|
+
? field
|
|
485
|
+
: requestedPlacement?.categoryField ?? transform.as[1],
|
|
486
|
+
oldMeasureChannel: oldValueChannel,
|
|
487
|
+
newMeasureChannel: valueChannel
|
|
488
|
+
});
|
|
413
489
|
} else if (
|
|
414
490
|
requestedPlacement !== undefined &&
|
|
415
491
|
Object.hasOwn(args.placement ?? {}, "scale")
|
|
@@ -425,6 +501,17 @@ const editDensity = action(
|
|
|
425
501
|
}
|
|
426
502
|
next = next.editScale(scaleEditPatch(scaleId, requestedScale));
|
|
427
503
|
}
|
|
504
|
+
if (!rebuildsPositions && Object.hasOwn(args, "valueScale")) {
|
|
505
|
+
const valueChannel = densityChannel === "x" ? "y" : "x";
|
|
506
|
+
const scaleId = layer.encoding[valueChannel].scale;
|
|
507
|
+
if (args.valueScale?.id !== undefined && args.valueScale.id !== scaleId) {
|
|
508
|
+
throw new Error("editDensity value scale cannot change its id.");
|
|
509
|
+
}
|
|
510
|
+
next = next.editScale(scaleEditPatch(scaleId, {
|
|
511
|
+
...args.valueScale,
|
|
512
|
+
id: scaleId
|
|
513
|
+
}));
|
|
514
|
+
}
|
|
428
515
|
|
|
429
516
|
next = applyMaterializationPlan(
|
|
430
517
|
next,
|
|
@@ -4,6 +4,7 @@ import { validateOptionObject } from "../../../core/validation.js";
|
|
|
4
4
|
import { resolvePalette } from "../../../grammar/palettes.js";
|
|
5
5
|
import {
|
|
6
6
|
normalizeTemporalValue,
|
|
7
|
+
resolveTemporalUnit,
|
|
7
8
|
readNominalField
|
|
8
9
|
} from "../../../grammar/scales/index.js";
|
|
9
10
|
import {
|
|
@@ -42,7 +43,7 @@ function fieldOption(value, role) {
|
|
|
42
43
|
}
|
|
43
44
|
validateOptionObject(
|
|
44
45
|
value,
|
|
45
|
-
["field", "fieldType", "scale"],
|
|
46
|
+
["field", "fieldType", "scale", "temporalUnit"],
|
|
46
47
|
`Horizon ${role}`
|
|
47
48
|
);
|
|
48
49
|
return value;
|
|
@@ -80,6 +81,7 @@ function uniqueStoredEncoding(program, dataset, role) {
|
|
|
80
81
|
JSON.stringify([
|
|
81
82
|
encoding.field,
|
|
82
83
|
encoding.fieldType,
|
|
84
|
+
encoding.temporalUnit,
|
|
83
85
|
encoding.scale,
|
|
84
86
|
encoding.title
|
|
85
87
|
]),
|
|
@@ -103,6 +105,7 @@ export function resolveHorizonField(program, layer, dataset, requested, role) {
|
|
|
103
105
|
return {
|
|
104
106
|
field: inferred.field,
|
|
105
107
|
fieldType: inferred.fieldType,
|
|
108
|
+
...(inferred.temporalUnit === undefined ? {} : { temporalUnit: inferred.temporalUnit }),
|
|
106
109
|
...(role === "x" && inferred.scale !== undefined
|
|
107
110
|
? { scale: { id: inferred.scale } }
|
|
108
111
|
: {}),
|
|
@@ -127,7 +130,9 @@ export function resolveHorizonField(program, layer, dataset, requested, role) {
|
|
|
127
130
|
`Horizon ${role} fieldType must be ${role === "x" ? "quantitative or temporal" : "quantitative"}.`
|
|
128
131
|
);
|
|
129
132
|
}
|
|
133
|
+
const temporalUnit = resolveTemporalUnit(option, fieldType, matching);
|
|
130
134
|
return {
|
|
135
|
+
...(temporalUnit === undefined ? {} : { temporalUnit }),
|
|
131
136
|
field: option.field,
|
|
132
137
|
fieldType,
|
|
133
138
|
...(option.scale !== undefined
|
|
@@ -140,9 +145,7 @@ export function resolveHorizonField(program, layer, dataset, requested, role) {
|
|
|
140
145
|
}
|
|
141
146
|
|
|
142
147
|
export function resolveHorizonGroupBy(layer, dataset, requested) {
|
|
143
|
-
if (requested === false)
|
|
144
|
-
throw new Error("encodeHorizon groupBy must be a field string when provided.");
|
|
145
|
-
}
|
|
148
|
+
if (requested === false) return undefined;
|
|
146
149
|
const value = requested ?? layer.encoding?.group?.field;
|
|
147
150
|
if (value === undefined) return undefined;
|
|
148
151
|
if (typeof value !== "string" || value.length === 0) {
|
|
@@ -262,6 +265,7 @@ export function resolveEditedHorizonField(
|
|
|
262
265
|
[role]: {
|
|
263
266
|
field: prior.field,
|
|
264
267
|
fieldType: prior.fieldType,
|
|
268
|
+
...(prior.temporalUnit === undefined ? {} : { temporalUnit: prior.temporalUnit }),
|
|
265
269
|
scale: layer.encoding[role].scale,
|
|
266
270
|
...(role === "x" && layer.encoding.x.title !== undefined
|
|
267
271
|
? { title: layer.encoding.x.title }
|
|
@@ -42,6 +42,8 @@ import {
|
|
|
42
42
|
validateUnusedHorizonEncodings
|
|
43
43
|
} from "./horizon/resolve.js";
|
|
44
44
|
|
|
45
|
+
import { applyTemporalUnit } from "./temporal.js";
|
|
46
|
+
|
|
45
47
|
const OPTIONS = Object.freeze([
|
|
46
48
|
"target", "source", "x", "y", "groupBy", "bands", "baseline", "extent",
|
|
47
49
|
"resolve", "missing", "overflow", "palette"
|
|
@@ -69,16 +71,17 @@ function applyHorizonEncoding(program, {
|
|
|
69
71
|
colorScale
|
|
70
72
|
}) {
|
|
71
73
|
let next = clearOwnedEncodings(program, layer)
|
|
74
|
+
.editSemantic({
|
|
75
|
+
property: `layer[${layer.id}].encoding.x.title`,
|
|
76
|
+
value: layer.encoding?.x?.title ?? inferHorizonTitle(transform.x.field)
|
|
77
|
+
})
|
|
72
78
|
.encodeX({
|
|
73
79
|
target: layer.id,
|
|
74
80
|
field: transform.as.x,
|
|
75
81
|
fieldType: transform.x.fieldType,
|
|
82
|
+
...(transform.x.fieldType === "temporal" ? { temporalUnit: "timestamp" } : {}),
|
|
76
83
|
scale: xScale
|
|
77
84
|
})
|
|
78
|
-
.editSemantic({
|
|
79
|
-
property: `layer[${layer.id}].encoding.x.title`,
|
|
80
|
-
value: layer.encoding?.x?.title ?? inferHorizonTitle(transform.x.field)
|
|
81
|
-
})
|
|
82
85
|
.encodeY({
|
|
83
86
|
target: layer.id,
|
|
84
87
|
field: transform.as.lower,
|
|
@@ -113,6 +116,9 @@ const editHorizon = action(
|
|
|
113
116
|
},
|
|
114
117
|
function (args = {}) {
|
|
115
118
|
validateOptionObject(args, EDIT_OPTIONS, "editHorizon");
|
|
119
|
+
if (Object.hasOwn(args, "groupBy") && args.groupBy === undefined) {
|
|
120
|
+
throw new Error("editHorizon groupBy requires a field string or false.");
|
|
121
|
+
}
|
|
116
122
|
if (!EDITABLE.some(option => Object.hasOwn(args, option))) {
|
|
117
123
|
throw new Error("editHorizon requires at least one Horizon option.");
|
|
118
124
|
}
|
|
@@ -145,7 +151,8 @@ const editHorizon = action(
|
|
|
145
151
|
);
|
|
146
152
|
const candidate = validateHorizonTransform({
|
|
147
153
|
type: "horizon",
|
|
148
|
-
x: { field: x.field, fieldType: x.fieldType
|
|
154
|
+
x: { field: x.field, fieldType: x.fieldType,
|
|
155
|
+
...(x.temporalUnit === undefined ? {} : { temporalUnit: x.temporalUnit }) },
|
|
149
156
|
y: { field: y.field, fieldType: y.fieldType },
|
|
150
157
|
...(groupBy === undefined ? {} : { groupBy }),
|
|
151
158
|
bands: args.bands ?? prior.bands,
|
|
@@ -189,6 +196,8 @@ const editHorizon = action(
|
|
|
189
196
|
value: x.fieldType
|
|
190
197
|
});
|
|
191
198
|
}
|
|
199
|
+
next = applyTemporalUnit(next, layer.id, "x",
|
|
200
|
+
x.fieldType === "temporal" ? "timestamp" : undefined, layer.encoding.x);
|
|
192
201
|
if (Object.hasOwn(args, "x")) {
|
|
193
202
|
next = next.editSemantic({
|
|
194
203
|
property: `layer[${layer.id}].encoding.x.title`,
|
|
@@ -210,7 +219,7 @@ const editHorizon = action(
|
|
|
210
219
|
requestedXScale.domain === undefined &&
|
|
211
220
|
currentX.domain === "auto"
|
|
212
221
|
? source.values.map((row, index) => x.fieldType === "temporal"
|
|
213
|
-
? normalizeTemporalValue(row[x.field], x.field, index)
|
|
222
|
+
? normalizeTemporalValue(row[x.field], x.field, index, x.temporalUnit)
|
|
214
223
|
: row[x.field])
|
|
215
224
|
: undefined;
|
|
216
225
|
const nextX = resolvePositionScaleDefinition(next, "x", x.fieldType, {
|
|
@@ -285,7 +294,8 @@ const encodeHorizon = action(
|
|
|
285
294
|
const as = horizonOutputFields(layer.id);
|
|
286
295
|
const transform = validateHorizonTransform({
|
|
287
296
|
type: "horizon",
|
|
288
|
-
x: { field: x.field, fieldType: x.fieldType
|
|
297
|
+
x: { field: x.field, fieldType: x.fieldType,
|
|
298
|
+
...(x.temporalUnit === undefined ? {} : { temporalUnit: x.temporalUnit }) },
|
|
289
299
|
y: { field: y.field, fieldType: y.fieldType },
|
|
290
300
|
...(groupBy === undefined ? {} : { groupBy }),
|
|
291
301
|
bands: args.bands ?? 3,
|
|
@@ -308,7 +318,7 @@ const encodeHorizon = action(
|
|
|
308
318
|
? {
|
|
309
319
|
domain: source.values.map((row, index) =>
|
|
310
320
|
x.fieldType === "temporal"
|
|
311
|
-
? normalizeTemporalValue(row[x.field], x.field, index)
|
|
321
|
+
? normalizeTemporalValue(row[x.field], x.field, index, x.temporalUnit)
|
|
312
322
|
: row[x.field]
|
|
313
323
|
)
|
|
314
324
|
}
|
|
@@ -1,3 +1,4 @@
|
|
|
1
|
+
import { registerSeriesLayoutAction } from "./seriesLayout.js";
|
|
1
2
|
import { registerDensityEncodingAction } from "./density.js";
|
|
2
3
|
import { registerPathOrderEncodingActions } from "./pathOrder.js";
|
|
3
4
|
import { registerHorizonEncodingAction } from "./horizon.js";
|
|
@@ -16,6 +17,7 @@ import { registerBarWidthEncodingAction } from "./barWidth.js";
|
|
|
16
17
|
import { registerEncodingRemovalAction } from "./remove.js";
|
|
17
18
|
|
|
18
19
|
export function registerEncodingActions(ProgramClass) {
|
|
20
|
+
registerSeriesLayoutAction(ProgramClass);
|
|
19
21
|
registerPositionEncodingActions(ProgramClass);
|
|
20
22
|
registerRangedEncodingActions(ProgramClass);
|
|
21
23
|
registerOffsetEncodingAction(ProgramClass);
|
|
@@ -1,3 +1,5 @@
|
|
|
1
|
+
import { inferSeriesGroup } from "./shared.js";
|
|
2
|
+
import { findSemanticScale } from "../../selectors/scales.js";
|
|
1
3
|
import { action } from "../../core/action.js";
|
|
2
4
|
import {
|
|
3
5
|
readNominalField,
|
|
@@ -13,7 +15,6 @@ import {
|
|
|
13
15
|
validateOptions
|
|
14
16
|
} from "./shared.js";
|
|
15
17
|
import {
|
|
16
|
-
resolveBarColorLayout,
|
|
17
18
|
resolveBarChannels,
|
|
18
19
|
resolveBarGrain
|
|
19
20
|
} from "../../grammar/bars/policy.js";
|
|
@@ -50,15 +51,7 @@ function createOffsetEncoding(channel) {
|
|
|
50
51
|
`${operation} requires a complete bar with a ${parentChannel} category encoding.`
|
|
51
52
|
);
|
|
52
53
|
}
|
|
53
|
-
|
|
54
|
-
layer.encoding?.color !== undefined &&
|
|
55
|
-
(resolveBarColorLayout(layer) !== "group" ||
|
|
56
|
-
layer.encoding.color.field !== args.field)
|
|
57
|
-
) {
|
|
58
|
-
throw new Error(
|
|
59
|
-
`${operation} field must match a grouped bar color field.`
|
|
60
|
-
);
|
|
61
|
-
}
|
|
54
|
+
|
|
62
55
|
} else {
|
|
63
56
|
const parent = layer.encoding?.[parentChannel];
|
|
64
57
|
if (
|
|
@@ -88,7 +81,8 @@ function createOffsetEncoding(channel) {
|
|
|
88
81
|
channel
|
|
89
82
|
);
|
|
90
83
|
|
|
91
|
-
|
|
84
|
+
const grouped = layer.mark.type === "bar" ? inferSeriesGroup(this, layer, args.field, "offset") : this;
|
|
85
|
+
let next = setEncodingProperties(grouped, target, channel, {
|
|
92
86
|
field: args.field,
|
|
93
87
|
fieldType,
|
|
94
88
|
scale: scale.id
|
|
@@ -99,12 +93,12 @@ function createOffsetEncoding(channel) {
|
|
|
99
93
|
next = applyEncodingScale(next, scale, requestedScale, {
|
|
100
94
|
reassignment: layer.encoding?.[channel]?.scale === scale.id
|
|
101
95
|
});
|
|
102
|
-
if (layer.mark.type === "bar"
|
|
103
|
-
|
|
104
|
-
|
|
105
|
-
|
|
96
|
+
if (layer.mark.type === "bar") {
|
|
97
|
+
if (findSemanticScale(this, scale.id) === undefined && args.scale?.id === undefined) next = next._withMarkConfig(target, { ...next.markConfigs[target], seriesOffsetScale: scale.id });
|
|
98
|
+
if (layer.layout?.mode !== "group" || layer.encoding?.group?.field !== args.field) return next.layoutSeries({ target, mode: "group" });
|
|
99
|
+
return rematerializeEncoding(next, target, channel, scale.id, layer);
|
|
106
100
|
}
|
|
107
|
-
return rematerializeEncoding(next, target, channel, scale.id);
|
|
101
|
+
return rematerializeEncoding(next, target, channel, scale.id, layer);
|
|
108
102
|
}
|
|
109
103
|
);
|
|
110
104
|
}
|
|
@@ -13,6 +13,7 @@ import {
|
|
|
13
13
|
setEncodingProperties
|
|
14
14
|
} from "./shared.js";
|
|
15
15
|
import { resolveParallelCoordinate } from "../coordinates/parallel.js";
|
|
16
|
+
import { applyLayerDataRematerialization } from "../../materialization/dependencies.js";
|
|
16
17
|
|
|
17
18
|
const OPTIONS = Object.freeze([
|
|
18
19
|
"target", "coordinate", "dimensions", "key", "missing"
|
|
@@ -98,14 +99,7 @@ export const encodeParallelCoordinates = action(
|
|
|
98
99
|
for (let index = 0; index < definitions.length; index += 1) {
|
|
99
100
|
next = applyEncodingScale(next, definitions[index], dimensions[index].scaleOptions);
|
|
100
101
|
}
|
|
101
|
-
|
|
102
|
-
next = next.rematerializeScale({
|
|
103
|
-
id: definition.id,
|
|
104
|
-
guides: false,
|
|
105
|
-
marks: false
|
|
106
|
-
});
|
|
107
|
-
}
|
|
108
|
-
return next.rematerializeLineMark({ id: target, scales: false });
|
|
102
|
+
return applyLayerDataRematerialization(next, target);
|
|
109
103
|
}
|
|
110
104
|
);
|
|
111
105
|
|
|
@@ -1,3 +1,5 @@
|
|
|
1
|
+
import { applyTemporalUnit } from "../temporal.js";
|
|
2
|
+
|
|
1
3
|
function replaceAlternateBinding(program, target, channel, previous, usesField) {
|
|
2
4
|
if (previous === undefined) return program;
|
|
3
5
|
const alternate = usesField ? "datum" : "field";
|
|
@@ -111,6 +113,7 @@ export function applyPositionSemantics(program, {
|
|
|
111
113
|
datum,
|
|
112
114
|
hasField,
|
|
113
115
|
fieldType,
|
|
116
|
+
temporalUnit,
|
|
114
117
|
bin,
|
|
115
118
|
aggregate,
|
|
116
119
|
stack,
|
|
@@ -128,16 +131,19 @@ export function applyPositionSemantics(program, {
|
|
|
128
131
|
channel,
|
|
129
132
|
previous,
|
|
130
133
|
hasField
|
|
131
|
-
)
|
|
132
|
-
|
|
134
|
+
);
|
|
135
|
+
if (hasField || datum !== undefined) {
|
|
136
|
+
next = next.editSemantic({
|
|
133
137
|
property: `layer[${target}].encoding.${channel}.${hasField ? "field" : "datum"}`,
|
|
134
138
|
value: hasField ? field : datum
|
|
135
|
-
})
|
|
136
|
-
|
|
139
|
+
});
|
|
140
|
+
}
|
|
141
|
+
next = next.editSemantic({
|
|
137
142
|
property: `layer[${target}].encoding.${channel}.fieldType`,
|
|
138
143
|
value: fieldType
|
|
139
144
|
});
|
|
140
145
|
|
|
146
|
+
next = applyTemporalUnit(next, target, channel, temporalUnit, previous);
|
|
141
147
|
next = applyBin(next, target, channel, previous, bin);
|
|
142
148
|
for (const [property, value] of Object.entries({ aggregate, stack })) {
|
|
143
149
|
if (value === undefined) continue;
|