ggaction 0.0.13 → 0.0.15
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 +78 -0
- package/README.md +20 -11
- package/knowledge/action-cards.json +1 -1
- package/knowledge/intent-taxonomy.json +1 -1
- package/knowledge/mcp-resources.json +1 -1
- package/package.json +8 -3
- package/src/actions/basic.js +2 -2
- package/src/actions/boxPlots/components.js +14 -4
- package/src/actions/boxPlots/edit.js +31 -5
- package/src/actions/boxPlots/materialize.js +11 -3
- package/src/actions/boxPlots/options.js +48 -16
- package/src/actions/categoryOrder/index.js +15 -4
- package/src/actions/charts/area.js +5 -1
- package/src/actions/charts/bar.js +2 -1
- package/src/actions/charts/density.js +6 -2
- package/src/actions/charts/ecdf.js +4 -1
- package/src/actions/charts/endpoints.js +25 -3
- package/src/actions/charts/heatmap.js +2 -1
- package/src/actions/charts/histogram.js +4 -3
- package/src/actions/charts/horizon.js +3 -1
- package/src/actions/charts/interval-regression.js +5 -2
- package/src/actions/charts/line.js +3 -1
- package/src/actions/charts/parallel.js +8 -2
- package/src/actions/charts/pie.js +10 -2
- package/src/actions/charts/polar.js +15 -4
- package/src/actions/charts/radar.js +8 -2
- package/src/actions/charts/radial.js +10 -2
- package/src/actions/charts/rug-strip.js +6 -2
- package/src/actions/charts/scatter.js +3 -1
- package/src/actions/composition/actions.js +13 -4
- package/src/actions/coordinates/actions.js +1 -1
- package/src/actions/coordinates/edit.js +76 -0
- package/src/actions/data/bin.js +1 -1
- package/src/actions/data/bin2d.js +57 -185
- package/src/actions/data/complete.js +26 -0
- package/src/actions/data/computed.js +2 -2
- package/src/actions/data/create.js +2 -2
- package/src/actions/data/density.js +12 -20
- package/src/actions/data/derived.js +47 -17
- package/src/actions/data/edit.js +539 -0
- package/src/actions/data/filter.js +14 -2
- package/src/actions/data/impute.js +26 -0
- package/src/actions/data/index.js +14 -0
- package/src/actions/data/normalize.js +27 -0
- package/src/actions/data/regression.js +16 -21
- package/src/actions/data/revisionBindings.js +145 -0
- package/src/actions/data/shared.js +20 -4
- package/src/actions/data/summary.js +1 -1
- package/src/actions/data/timeUnit.js +4 -1
- package/src/actions/data/window.js +1 -1
- package/src/actions/encodings/channels.js +415 -0
- package/src/actions/encodings/color/index.js +2 -1
- package/src/actions/encodings/density.js +5 -2
- package/src/actions/encodings/histogram.js +3 -2
- package/src/actions/encodings/index.js +4 -0
- package/src/actions/encodings/offset.js +20 -13
- package/src/actions/encodings/position/apply.js +53 -7
- package/src/actions/encodings/position/index.js +10 -2
- package/src/actions/encodings/position/policies/bar.js +9 -0
- package/src/actions/encodings/position/resolve.js +24 -7
- package/src/actions/encodings/remove.js +9 -4
- package/src/actions/encodings/ruleAppearance.js +1 -23
- package/src/actions/encodings/seriesLayout.js +1 -0
- package/src/actions/encodings/shared.js +82 -14
- package/src/actions/encodings/stroke.js +226 -0
- package/src/actions/errorBands/create.js +23 -3
- package/src/actions/errorBands/edit.js +21 -6
- package/src/actions/errorBars/create.js +35 -7
- package/src/actions/errorBars/edit.js +19 -4
- package/src/actions/facets/actions.js +237 -57
- package/src/actions/facets/derive.js +91 -26
- package/src/actions/gradientPlots/components.js +10 -2
- package/src/actions/gradientPlots/edit.js +14 -4
- package/src/actions/gradientPlots/materialize.js +3 -1
- package/src/actions/gradientPlots/options.js +10 -2
- package/src/actions/guides/applicability.js +8 -2
- package/src/actions/guides/axes/labels.js +58 -12
- package/src/actions/guides/axes/lines.js +6 -2
- package/src/actions/guides/axes/parallel/resolve.js +6 -2
- package/src/actions/guides/axes/tickGroups.js +2 -1
- package/src/actions/guides/axes/ticks.js +6 -2
- package/src/actions/guides/axes/titles.js +11 -3
- package/src/actions/guides/grids/resolve.js +7 -2
- package/src/actions/guides/guides.js +19 -3
- package/src/actions/guides/legends/blocks.js +426 -0
- package/src/actions/guides/legends/categorical/actions.js +134 -48
- package/src/actions/guides/legends/categorical/components.js +17 -12
- package/src/actions/guides/legends/categorical/index.js +37 -33
- package/src/actions/guides/legends/categorical/layout.js +97 -15
- package/src/actions/guides/legends/categorical/options.js +2 -2
- package/src/actions/guides/legends/categorical/recipes.js +111 -20
- package/src/actions/guides/legends/categorical/resolve.js +12 -8
- package/src/actions/guides/legends/categorical/symbols.js +85 -30
- package/src/actions/guides/legends/continuous/common.js +30 -12
- package/src/actions/guides/legends/continuous/gradient.js +10 -7
- package/src/actions/guides/legends/continuous/index.js +2 -0
- package/src/actions/guides/legends/continuous/interval.js +8 -3
- package/src/actions/guides/legends/continuous/opacity.js +8 -5
- package/src/actions/guides/legends/continuous/stroke.js +525 -0
- package/src/actions/guides/legends/creation.js +14 -1
- package/src/actions/guides/legends/edit.js +158 -59
- package/src/actions/guides/legends/index.js +2 -0
- package/src/actions/guides/legends/lane.js +54 -19
- package/src/actions/guides/legends/lifecycle.js +19 -8
- package/src/actions/guides/legends/remove.js +13 -3
- package/src/actions/guides/legends/sampling.js +140 -0
- package/src/actions/guides/legends/size.js +93 -40
- package/src/actions/guides/legends/strokeWidth.js +34 -28
- package/src/actions/guides/legends/target.js +112 -1
- package/src/actions/guides/legends/transition.js +165 -16
- package/src/actions/guides/polar/axes/facade.js +4 -4
- package/src/actions/guides/polar/axes/labels.js +24 -5
- package/src/actions/guides/polar/axes/lines.js +10 -4
- package/src/actions/guides/polar/axes/shared.js +16 -0
- package/src/actions/guides/polar/axes/ticks.js +1 -1
- package/src/actions/guides/polar/axes/titles.js +1 -1
- package/src/actions/guides/polar/grids.js +1 -1
- package/src/actions/guides/polar/resolve.js +12 -8
- package/src/actions/index.js +14 -3
- package/src/actions/marks/arc/actions.js +77 -19
- package/src/actions/marks/area/actions.js +34 -9
- package/src/actions/marks/area/materialize.js +17 -1
- package/src/actions/marks/bar/create.js +11 -2
- package/src/actions/marks/bar/edit.js +20 -3
- package/src/actions/marks/bar/materialize.js +22 -2
- package/src/actions/marks/index.js +10 -1
- package/src/actions/marks/line/actions.js +37 -14
- package/src/actions/marks/line/materialize.js +29 -10
- package/src/actions/marks/point/create.js +8 -2
- package/src/actions/marks/point/edit.js +18 -6
- package/src/actions/marks/point/materialize.js +49 -15
- package/src/actions/marks/rect/actions.js +33 -12
- package/src/actions/marks/references.js +601 -30
- package/src/actions/marks/remove.js +71 -1
- package/src/actions/marks/rule/actions.js +47 -10
- package/src/actions/marks/shared.js +1 -1
- package/src/actions/marks/text/actions.js +74 -9
- package/src/actions/marks/text/index.js +4 -0
- package/src/actions/marks/text/layout.js +154 -6
- package/src/actions/marks/text/removal.js +173 -0
- package/src/actions/marks/text/selection.js +73 -0
- package/src/actions/marks/tick/actions.js +22 -5
- package/src/actions/primitives/editGraphics.js +26 -0
- package/src/actions/primitives/semantic.js +2 -1
- package/src/actions/primitives/semanticAction.js +83 -10
- package/src/actions/primitives/semanticValidation/guide.js +1 -1
- package/src/actions/primitives/semanticValidation/index.js +9 -1
- package/src/actions/primitives/semanticValidation/layer.js +5 -0
- package/src/actions/primitives/semanticValidation/scale.js +28 -7
- package/src/actions/regression/components.js +26 -11
- package/src/actions/regression/create.js +10 -2
- package/src/actions/regression/edit.js +21 -7
- package/src/actions/resources/index.js +7 -0
- package/src/actions/resources/remove.js +172 -0
- package/src/actions/scales/channels.js +212 -0
- package/src/actions/scales/consumers/common.js +1 -1
- package/src/actions/scales/consumers/families.js +3 -2
- package/src/actions/scales/consumers/index.js +19 -2
- package/src/actions/scales/consumers/seriesLayout.js +28 -14
- package/src/actions/scales/create.js +54 -22
- package/src/actions/scales/definitions.js +94 -40
- package/src/actions/scales/edit.js +66 -11
- package/src/actions/scales/editPolicy.js +81 -11
- package/src/actions/scales/index.js +6 -0
- package/src/actions/scales/materialize.js +4 -3
- package/src/actions/scales/offset.js +48 -0
- package/src/actions/scales/parallel.js +71 -0
- package/src/actions/scales/preview.js +111 -10
- package/src/actions/selection/actions.js +154 -30
- package/src/actions/selection/index.js +3 -0
- package/src/actions/theme/actions.js +68 -13
- package/src/actions/theme/composition.js +238 -0
- package/src/actions/theme/index.js +9 -2
- package/src/actions/theme/reconcile.js +315 -67
- package/src/actions/theme/state.js +160 -0
- package/src/actions/violinPlots/create.js +5 -2
- package/src/actions/violinPlots/edit.js +1 -0
- package/src/core/action.js +10 -0
- package/src/core/compositionState.js +6 -1
- package/src/core/programState.js +20 -0
- package/src/core/resourceReferences.js +332 -0
- package/src/core/vocabulary.js +16 -3
- package/src/grammar/bars/aggregate.js +4 -1
- package/src/grammar/bars/geometry.js +44 -0
- package/src/grammar/bin.js +54 -9
- package/src/grammar/complete.js +279 -0
- package/src/grammar/computed.js +265 -64
- package/src/grammar/coordinates.js +37 -0
- package/src/grammar/density.js +239 -37
- package/src/grammar/displayLabels.js +57 -0
- package/src/grammar/facets/dependencies.js +133 -1
- package/src/grammar/facets/guides.js +3 -0
- package/src/grammar/facets/index.js +7 -47
- package/src/grammar/facets/scales.js +15 -18
- package/src/grammar/impute.js +340 -0
- package/src/grammar/markLabelSelection.js +57 -0
- package/src/grammar/markLabels.js +18 -1
- package/src/grammar/normalize.js +366 -0
- package/src/grammar/pathSeries.js +26 -8
- package/src/grammar/pointShapes.js +13 -4
- package/src/grammar/polar.js +90 -8
- package/src/grammar/regression/index.js +1 -0
- package/src/grammar/regression/parameters.js +23 -0
- package/src/grammar/roundedRect.js +180 -0
- package/src/grammar/rules.js +1 -0
- package/src/grammar/scales/colorConsumers.js +20 -1
- package/src/grammar/scales/continuous.js +2 -2
- package/src/grammar/scales/definition.js +27 -4
- package/src/grammar/scales/index.js +1 -0
- package/src/grammar/scales/ordinal.js +12 -3
- package/src/grammar/scales/policies.js +2 -2
- package/src/grammar/scales/size.js +456 -0
- package/src/grammar/schemas/concreteGraphic.js +14 -2
- package/src/grammar/schemas/graphic.js +15 -0
- package/src/grammar/schemas/graphicBounds.js +179 -30
- package/src/grammar/schemas/semanticPath.js +7 -2
- package/src/grammar/statisticalReference.js +103 -0
- package/src/grammar/strokeStyle.js +77 -0
- package/src/grammar/summary.js +78 -16
- package/src/grammar/timeUnit.js +216 -5
- package/src/grammar/transformTopology.js +4 -0
- package/src/grammar/transforms.js +394 -28
- package/src/grammar/weightedStatistics.js +374 -0
- package/src/grammar/window.js +221 -16
- package/src/layout/aspect.js +80 -0
- package/src/layout/facets.js +59 -5
- package/src/layout/labels.js +343 -0
- package/src/materialization/bars/aggregate.js +25 -2
- package/src/materialization/bars/histogram.js +84 -24
- package/src/materialization/bars/ranged.js +19 -3
- package/src/materialization/bars/resolve.js +7 -4
- package/src/materialization/composition.js +3 -1
- package/src/materialization/coordinateBounds.js +204 -0
- package/src/materialization/dependencies.js +36 -0
- package/src/materialization/facetGuides/legacyCategorical.js +3 -0
- package/src/materialization/facetGuides/placement.js +8 -2
- package/src/materialization/facetGuides/preparation.js +12 -7
- package/src/materialization/facetHeaders.js +346 -0
- package/src/materialization/facets.js +15 -65
- package/src/materialization/guides/resources.js +26 -0
- package/src/materialization/legends.js +1 -1
- package/src/materialization/marks/index.js +11 -5
- package/src/materialization/marks/policies.js +2 -1
- package/src/materialization/rect.js +25 -12
- package/src/materialization/rectConfig.js +5 -1
- package/src/materialization/scales/map.js +5 -3
- package/src/materialization/scales/policies/binnedPosition.js +2 -2
- package/src/materialization/scales/policies/offset.js +50 -8
- package/src/materialization/scales/policies/series.js +4 -1
- package/src/materialization/scales/resolve.js +22 -6
- package/src/materialization/selection/items/arc.js +28 -4
- package/src/materialization/selection/items/bar.js +30 -3
- package/src/materialization/selection/items/common.js +19 -4
- package/src/materialization/selection/items/rect.js +28 -4
- package/src/materialization/selection/path.js +1 -1
- package/src/materialization/selection/point.js +3 -1
- package/src/materialization/text.js +265 -14
- package/src/renderers/canvas/circle.js +2 -3
- package/src/renderers/canvas/line.js +2 -3
- package/src/renderers/canvas/native.js +4 -4
- package/src/renderers/canvas/path.js +2 -3
- package/src/renderers/canvas/rect.js +2 -3
- package/src/renderers/canvas/stroke.js +11 -0
- package/src/renderers/svg.js +19 -0
- package/src/selectors/datasets.js +32 -1
- package/src/selectors/layers.js +4 -0
- package/src/theme/defaults.js +101 -0
- package/types/basic.d.ts +6 -0
- package/types/index.d.ts +85 -0
- package/types/program.d.ts +910 -117
|
@@ -9,19 +9,27 @@ import {
|
|
|
9
9
|
REGRESSION_UPPER_FIELD
|
|
10
10
|
} from "../../grammar/regression/index.js";
|
|
11
11
|
import { validateAreaCreateOutline } from "../marks/area/index.js";
|
|
12
|
+
import {
|
|
13
|
+
requestedStrokeDetails,
|
|
14
|
+
STROKE_STYLE_PROPERTIES
|
|
15
|
+
} from "../../grammar/strokeStyle.js";
|
|
12
16
|
|
|
13
17
|
const BAND_OPTIONS = Object.freeze([
|
|
14
18
|
"id", "data", "x", "lower", "upper", "groupBy", "coordinate", "xScale", "yScale",
|
|
15
|
-
"color", "opacity", "stroke", "strokeWidth", "curve"
|
|
19
|
+
"color", "opacity", "stroke", "strokeWidth", "curve",
|
|
20
|
+
...STROKE_STYLE_PROPERTIES
|
|
16
21
|
]);
|
|
17
22
|
const LINE_OPTIONS = Object.freeze([
|
|
18
23
|
"id", "data", "x", "y", "groupBy", "coordinate", "xScale", "yScale", "colorScale",
|
|
19
|
-
"strokeWidth", "curve"
|
|
24
|
+
"strokeWidth", "curve", ...STROKE_STYLE_PROPERTIES
|
|
20
25
|
]);
|
|
21
26
|
const EDIT_BAND_OPTIONS = Object.freeze([
|
|
22
|
-
"target", "color", "opacity", "stroke", "strokeWidth", "curve"
|
|
27
|
+
"target", "color", "opacity", "stroke", "strokeWidth", "curve",
|
|
28
|
+
...STROKE_STYLE_PROPERTIES
|
|
29
|
+
]);
|
|
30
|
+
const EDIT_LINE_OPTIONS = Object.freeze([
|
|
31
|
+
"target", "strokeWidth", "curve", ...STROKE_STYLE_PROPERTIES
|
|
23
32
|
]);
|
|
24
|
-
const EDIT_LINE_OPTIONS = Object.freeze(["target", "strokeWidth", "curve"]);
|
|
25
33
|
|
|
26
34
|
function isRegressionLayer(program, layer, type) {
|
|
27
35
|
const dataset = findDataset(program, layer.data);
|
|
@@ -93,7 +101,8 @@ export const createRegressionBand = action(
|
|
|
93
101
|
coordinate: args.coordinate,
|
|
94
102
|
fill: args.color ?? DEFAULT_COLORS.regressionBand,
|
|
95
103
|
opacity: args.opacity ?? 0.18,
|
|
96
|
-
...(args.curve === undefined ? {} : { curve: args.curve })
|
|
104
|
+
...(args.curve === undefined ? {} : { curve: args.curve }),
|
|
105
|
+
...requestedStrokeDetails(args, "createRegressionBand")
|
|
97
106
|
})
|
|
98
107
|
.editSemantic({
|
|
99
108
|
property: `layer[${id}].encoding.y.title`,
|
|
@@ -119,7 +128,10 @@ export const editRegressionBand = action(
|
|
|
119
128
|
},
|
|
120
129
|
function (args = {}) {
|
|
121
130
|
validateKeys(args, EDIT_BAND_OPTIONS, "editRegressionBand");
|
|
122
|
-
const changes = [
|
|
131
|
+
const changes = [
|
|
132
|
+
"color", "opacity", "stroke", "strokeWidth", "curve",
|
|
133
|
+
...STROKE_STYLE_PROPERTIES
|
|
134
|
+
];
|
|
123
135
|
if (!changes.some(key => Object.hasOwn(args, key))) {
|
|
124
136
|
throw new Error(
|
|
125
137
|
"editRegressionBand requires color, opacity, stroke, strokeWidth, or curve."
|
|
@@ -139,7 +151,8 @@ export const editRegressionBand = action(
|
|
|
139
151
|
...(Object.hasOwn(args, "strokeWidth")
|
|
140
152
|
? { strokeWidth: args.strokeWidth }
|
|
141
153
|
: {}),
|
|
142
|
-
...(Object.hasOwn(args, "curve") ? { curve: args.curve } : {})
|
|
154
|
+
...(Object.hasOwn(args, "curve") ? { curve: args.curve } : {}),
|
|
155
|
+
...requestedStrokeDetails(args, "editRegressionBand")
|
|
143
156
|
});
|
|
144
157
|
}
|
|
145
158
|
);
|
|
@@ -152,8 +165,8 @@ export const editRegressionLine = action(
|
|
|
152
165
|
function (args = {}) {
|
|
153
166
|
validateKeys(args, EDIT_LINE_OPTIONS, "editRegressionLine");
|
|
154
167
|
if (
|
|
155
|
-
!
|
|
156
|
-
|
|
168
|
+
!["strokeWidth", "curve", ...STROKE_STYLE_PROPERTIES]
|
|
169
|
+
.some(property => Object.hasOwn(args, property))
|
|
157
170
|
) {
|
|
158
171
|
throw new Error("editRegressionLine requires strokeWidth or curve.");
|
|
159
172
|
}
|
|
@@ -168,7 +181,8 @@ export const editRegressionLine = action(
|
|
|
168
181
|
...(Object.hasOwn(args, "strokeWidth")
|
|
169
182
|
? { strokeWidth: args.strokeWidth }
|
|
170
183
|
: {}),
|
|
171
|
-
...(Object.hasOwn(args, "curve") ? { curve: args.curve } : {})
|
|
184
|
+
...(Object.hasOwn(args, "curve") ? { curve: args.curve } : {}),
|
|
185
|
+
...requestedStrokeDetails(args, "editRegressionLine")
|
|
172
186
|
});
|
|
173
187
|
}
|
|
174
188
|
);
|
|
@@ -186,7 +200,8 @@ export const createRegressionLine = action(
|
|
|
186
200
|
id,
|
|
187
201
|
data: args.data,
|
|
188
202
|
strokeWidth: args.strokeWidth ?? 3,
|
|
189
|
-
...(args.curve === undefined ? {} : { curve: args.curve })
|
|
203
|
+
...(args.curve === undefined ? {} : { curve: args.curve }),
|
|
204
|
+
...requestedStrokeDetails(args, "createRegressionLine")
|
|
190
205
|
})
|
|
191
206
|
.encodeX({
|
|
192
207
|
target: id,
|
|
@@ -1,6 +1,7 @@
|
|
|
1
1
|
import { action } from "../../core/action.js";
|
|
2
2
|
import { validateKeys } from "../../core/validation.js";
|
|
3
3
|
import { normalizeRegressionParameters } from "../../grammar/regression/index.js";
|
|
4
|
+
import { STROKE_STYLE_PROPERTIES } from "../../grammar/strokeStyle.js";
|
|
4
5
|
import {
|
|
5
6
|
findRegressionPoint,
|
|
6
7
|
inferRegressionGroup,
|
|
@@ -49,11 +50,18 @@ export const createRegression = action(
|
|
|
49
50
|
if (band !== false) {
|
|
50
51
|
validateKeys(
|
|
51
52
|
band,
|
|
52
|
-
[
|
|
53
|
+
[
|
|
54
|
+
"color", "opacity", "stroke", "strokeWidth", "curve",
|
|
55
|
+
...STROKE_STYLE_PROPERTIES
|
|
56
|
+
],
|
|
53
57
|
"regression band"
|
|
54
58
|
);
|
|
55
59
|
}
|
|
56
|
-
validateKeys(
|
|
60
|
+
validateKeys(
|
|
61
|
+
line,
|
|
62
|
+
["strokeWidth", "curve", ...STROKE_STYLE_PROPERTIES],
|
|
63
|
+
"regression line"
|
|
64
|
+
);
|
|
57
65
|
const colorEncoding = point.encoding?.color;
|
|
58
66
|
const namespace = point.id;
|
|
59
67
|
const dataId = `${namespace}RegressionData`;
|
|
@@ -9,6 +9,10 @@ import {
|
|
|
9
9
|
} from "../../core/validation.js";
|
|
10
10
|
import { normalizeRegressionParameters } from "../../grammar/regression/index.js";
|
|
11
11
|
import { validateCurveInterpolation } from "../../grammar/curveCommands.js";
|
|
12
|
+
import {
|
|
13
|
+
requestedStrokeDetails,
|
|
14
|
+
STROKE_STYLE_PROPERTIES
|
|
15
|
+
} from "../../grammar/strokeStyle.js";
|
|
12
16
|
import { planDerivedDataRevision } from
|
|
13
17
|
"../../materialization/dataProvenance.js";
|
|
14
18
|
import { findLayer } from "../../selectors/layers.js";
|
|
@@ -21,9 +25,12 @@ const OPTIONS = Object.freeze([
|
|
|
21
25
|
"confidenceMethod", "level", "confidence", "interval", "band", "line"
|
|
22
26
|
]);
|
|
23
27
|
const BAND_OPTIONS = Object.freeze([
|
|
24
|
-
"color", "opacity", "stroke", "strokeWidth", "curve"
|
|
28
|
+
"color", "opacity", "stroke", "strokeWidth", "curve",
|
|
29
|
+
...STROKE_STYLE_PROPERTIES
|
|
30
|
+
]);
|
|
31
|
+
const LINE_OPTIONS = Object.freeze([
|
|
32
|
+
"strokeWidth", "curve", ...STROKE_STYLE_PROPERTIES
|
|
25
33
|
]);
|
|
26
|
-
const LINE_OPTIONS = Object.freeze(["strokeWidth", "curve"]);
|
|
27
34
|
|
|
28
35
|
function resolveRegressionOwner(program, requested) {
|
|
29
36
|
const eligible = program.semanticSpec.layers.filter(
|
|
@@ -80,6 +87,7 @@ function validateBandPatch(value) {
|
|
|
80
87
|
if (Object.hasOwn(patch, "curve")) {
|
|
81
88
|
validateCurveInterpolation(patch.curve);
|
|
82
89
|
}
|
|
90
|
+
requestedStrokeDetails(patch, "editRegression band");
|
|
83
91
|
return patch;
|
|
84
92
|
}
|
|
85
93
|
|
|
@@ -94,6 +102,7 @@ function validateLinePatch(value) {
|
|
|
94
102
|
if (Object.hasOwn(patch, "curve")) {
|
|
95
103
|
validateCurveInterpolation(patch.curve);
|
|
96
104
|
}
|
|
105
|
+
requestedStrokeDetails(patch, "editRegression line");
|
|
97
106
|
return patch;
|
|
98
107
|
}
|
|
99
108
|
|
|
@@ -325,7 +334,11 @@ export const editRegression = action(
|
|
|
325
334
|
const bandConfig = next.markConfigs[bandId];
|
|
326
335
|
next = next._withMarkConfig(bandId, {
|
|
327
336
|
...bandConfig,
|
|
328
|
-
errorBand: {
|
|
337
|
+
errorBand: {
|
|
338
|
+
...bandConfig.errorBand,
|
|
339
|
+
source: dataId,
|
|
340
|
+
data: dataId
|
|
341
|
+
}
|
|
329
342
|
});
|
|
330
343
|
}
|
|
331
344
|
|
|
@@ -356,10 +369,7 @@ export const editRegression = action(
|
|
|
356
369
|
next = next.rematerializeLineMark({ id: current.lineId });
|
|
357
370
|
}
|
|
358
371
|
|
|
359
|
-
|
|
360
|
-
next = next.releaseDerivedData(revision.release);
|
|
361
|
-
}
|
|
362
|
-
return next._withMarkConfig(owner.id, {
|
|
372
|
+
next = next._withMarkConfig(owner.id, {
|
|
363
373
|
...next.markConfigs[owner.id],
|
|
364
374
|
regression: {
|
|
365
375
|
...current,
|
|
@@ -373,6 +383,10 @@ export const editRegression = action(
|
|
|
373
383
|
parameters
|
|
374
384
|
}
|
|
375
385
|
});
|
|
386
|
+
if (changesStatistics) {
|
|
387
|
+
next = next.releaseDerivedData(revision.release);
|
|
388
|
+
}
|
|
389
|
+
return next;
|
|
376
390
|
};
|
|
377
391
|
return applyEdit(this);
|
|
378
392
|
}
|
|
@@ -0,0 +1,7 @@
|
|
|
1
|
+
import { removeCoordinate, removeData, removeScale } from "./remove.js";
|
|
2
|
+
|
|
3
|
+
export function registerResourceActions(ProgramClass) {
|
|
4
|
+
ProgramClass.prototype.removeData = removeData;
|
|
5
|
+
ProgramClass.prototype.removeScale = removeScale;
|
|
6
|
+
ProgramClass.prototype.removeCoordinate = removeCoordinate;
|
|
7
|
+
}
|
|
@@ -0,0 +1,172 @@
|
|
|
1
|
+
import { action } from "../../core/action.js";
|
|
2
|
+
import { validateUserId } from "../../core/identifiers.js";
|
|
3
|
+
import { validateOptionObject } from "../../core/validation.js";
|
|
4
|
+
import {
|
|
5
|
+
canonicalResourcePath,
|
|
6
|
+
collectResourceReferences
|
|
7
|
+
} from "../../core/resourceReferences.js";
|
|
8
|
+
import { releaseNamedResourceOwnership } from "../../core/programState.js";
|
|
9
|
+
import { findCoordinate } from "../../selectors/coordinates.js";
|
|
10
|
+
import { findDataset } from "../../selectors/datasets.js";
|
|
11
|
+
import { findLayer } from "../../selectors/layers.js";
|
|
12
|
+
import { findSemanticScale } from "../../selectors/scales.js";
|
|
13
|
+
|
|
14
|
+
const OPTIONS = Object.freeze(["id"]);
|
|
15
|
+
|
|
16
|
+
function dataOwners(program) {
|
|
17
|
+
return Object.entries(program.materializationConfigs.data ?? {}).flatMap(
|
|
18
|
+
([family, owners]) => Object.entries(owners ?? {}).flatMap(([owner, config]) =>
|
|
19
|
+
typeof config?.current === "string"
|
|
20
|
+
? [{ family, owner, current: config.current }]
|
|
21
|
+
: []
|
|
22
|
+
)
|
|
23
|
+
);
|
|
24
|
+
}
|
|
25
|
+
|
|
26
|
+
function ownedGeneratedDatasetIds(program) {
|
|
27
|
+
const result = new Set();
|
|
28
|
+
for (const [id, config] of Object.entries(program.markConfigs)) {
|
|
29
|
+
const layer = findLayer(program, id);
|
|
30
|
+
for (const value of [
|
|
31
|
+
config.errorBar?.data,
|
|
32
|
+
config.errorBand?.data,
|
|
33
|
+
config.regression?.dataId,
|
|
34
|
+
config.boxPlot?.summaryId,
|
|
35
|
+
config.boxPlot?.outlierDataId,
|
|
36
|
+
config.gradientPlot?.profileId,
|
|
37
|
+
config.violinPlot?.materialized === true ? layer?.data : undefined,
|
|
38
|
+
config.ecdfPlot?.data,
|
|
39
|
+
config.endpointPlot?.data,
|
|
40
|
+
config.statisticalReference?.dataId
|
|
41
|
+
]) {
|
|
42
|
+
if (typeof value === "string") result.add(value);
|
|
43
|
+
}
|
|
44
|
+
const dataset = findDataset(program, layer?.data);
|
|
45
|
+
if (dataset?.transform?.[0]?.type === "markFilter") result.add(dataset.id);
|
|
46
|
+
}
|
|
47
|
+
return Object.freeze([...result].sort());
|
|
48
|
+
}
|
|
49
|
+
|
|
50
|
+
function exactResource(program, kind, id) {
|
|
51
|
+
if (kind === "data") return findDataset(program, id);
|
|
52
|
+
if (kind === "scale") return findSemanticScale(program, id);
|
|
53
|
+
return findCoordinate(program, id);
|
|
54
|
+
}
|
|
55
|
+
|
|
56
|
+
function existingKind(program, id) {
|
|
57
|
+
if (findDataset(program, id) !== undefined ||
|
|
58
|
+
dataOwners(program).some(owner => owner.owner === id)) return "data";
|
|
59
|
+
if (findSemanticScale(program, id) !== undefined) return "scale";
|
|
60
|
+
if (findCoordinate(program, id) !== undefined) {
|
|
61
|
+
return "coordinate";
|
|
62
|
+
}
|
|
63
|
+
if (findLayer(program, id) !== undefined) return "mark";
|
|
64
|
+
return undefined;
|
|
65
|
+
}
|
|
66
|
+
|
|
67
|
+
export function resolveResourceOwnership(program, { kind, id }) {
|
|
68
|
+
const resource = exactResource(program, kind, id);
|
|
69
|
+
if (kind !== "data") {
|
|
70
|
+
if (resource !== undefined) return { ownership: "named", resource };
|
|
71
|
+
const other = existingKind(program, id);
|
|
72
|
+
if (other !== undefined) {
|
|
73
|
+
throw new Error(`Resource "${id}" exists as ${other}, not ${kind}.`);
|
|
74
|
+
}
|
|
75
|
+
throw new Error(`Unknown ${kind} "${id}".`);
|
|
76
|
+
}
|
|
77
|
+
|
|
78
|
+
const owners = dataOwners(program).filter(owner => owner.owner === id);
|
|
79
|
+
if (owners.length > 1) {
|
|
80
|
+
throw new Error(`Data resource "${id}" has ambiguous logical ownership.`);
|
|
81
|
+
}
|
|
82
|
+
if (owners.length === 1) {
|
|
83
|
+
const owner = owners[0];
|
|
84
|
+
const current = exactResource(program, "data", owner.current);
|
|
85
|
+
if (current === undefined) {
|
|
86
|
+
throw new Error(`Data owner "${id}" has no current dataset.`);
|
|
87
|
+
}
|
|
88
|
+
return { ownership: "standalone", resource: current, dataOwner: owner };
|
|
89
|
+
}
|
|
90
|
+
if (resource !== undefined) {
|
|
91
|
+
if (ownedGeneratedDatasetIds(program).includes(id) ||
|
|
92
|
+
dataOwners(program).some(owner => owner.current === id)) {
|
|
93
|
+
throw new Error(
|
|
94
|
+
`Dataset "${id}" is chart-owned; use its owning resource action.`
|
|
95
|
+
);
|
|
96
|
+
}
|
|
97
|
+
return { ownership: "named", resource };
|
|
98
|
+
}
|
|
99
|
+
const other = existingKind(program, id);
|
|
100
|
+
if (other !== undefined) {
|
|
101
|
+
throw new Error(`Resource "${id}" exists as ${other}, not data.`);
|
|
102
|
+
}
|
|
103
|
+
throw new Error(`Unknown data "${id}".`);
|
|
104
|
+
}
|
|
105
|
+
|
|
106
|
+
function assertSupportedProgram(program, operation) {
|
|
107
|
+
if (program.compositionSpec !== undefined && program.compositionSpec.type !== "facet") {
|
|
108
|
+
throw new Error(`${operation} supports unit and facet composition programs.`);
|
|
109
|
+
}
|
|
110
|
+
}
|
|
111
|
+
|
|
112
|
+
function formatReference(value) {
|
|
113
|
+
return `${value.ownerKind} "${value.ownerId}" at ` +
|
|
114
|
+
canonicalResourcePath(value.path);
|
|
115
|
+
}
|
|
116
|
+
|
|
117
|
+
export function planResourceRemoval(program, { kind, id, operation }) {
|
|
118
|
+
assertSupportedProgram(program, operation);
|
|
119
|
+
const resolved = resolveResourceOwnership(program, { kind, id });
|
|
120
|
+
const actualId = resolved.resource.id;
|
|
121
|
+
const references = collectResourceReferences(program, { kind, id: actualId });
|
|
122
|
+
const live = references.filter(value => value.strength === "live" && !(
|
|
123
|
+
resolved.ownership === "standalone" &&
|
|
124
|
+
value.ownerKind === "dataOwner" &&
|
|
125
|
+
value.ownerId === resolved.dataOwner.owner &&
|
|
126
|
+
value.path.at(-1) === "current"
|
|
127
|
+
));
|
|
128
|
+
if (live.length > 0) {
|
|
129
|
+
throw new Error(
|
|
130
|
+
`Cannot remove ${kind} "${id}"; live references: ` +
|
|
131
|
+
live.map(formatReference).join("; ")
|
|
132
|
+
);
|
|
133
|
+
}
|
|
134
|
+
return Object.freeze({
|
|
135
|
+
kind,
|
|
136
|
+
id,
|
|
137
|
+
semanticIds: Object.freeze([actualId]),
|
|
138
|
+
...(resolved.dataOwner === undefined
|
|
139
|
+
? {}
|
|
140
|
+
: { dataOwner: Object.freeze({ ...resolved.dataOwner }) })
|
|
141
|
+
});
|
|
142
|
+
}
|
|
143
|
+
|
|
144
|
+
function removeResource(kind, operation, description) {
|
|
145
|
+
return action(
|
|
146
|
+
{ op: operation, description, scope: "any" },
|
|
147
|
+
function (args = {}) {
|
|
148
|
+
validateOptionObject(args, OPTIONS, operation);
|
|
149
|
+
const id = validateUserId(args.id, `${operation} id`);
|
|
150
|
+
const plan = planResourceRemoval(this, { kind, id, operation });
|
|
151
|
+
// Release a validated logical owner before removing its physical revision.
|
|
152
|
+
// The primitive then checks the remaining consumers without mistaking the
|
|
153
|
+
// owner's own replay entry for an independently chart-owned resource.
|
|
154
|
+
let next = releaseNamedResourceOwnership(this, plan);
|
|
155
|
+
const selector = kind === "data" ? "dataset" : kind;
|
|
156
|
+
for (const semanticId of plan.semanticIds) {
|
|
157
|
+
next = next.editSemantic({ property: `${selector}[${semanticId}]`, remove: true });
|
|
158
|
+
}
|
|
159
|
+
return next;
|
|
160
|
+
}
|
|
161
|
+
);
|
|
162
|
+
}
|
|
163
|
+
|
|
164
|
+
export const removeData = removeResource(
|
|
165
|
+
"data", "removeData", "Remove one unreferenced named dataset."
|
|
166
|
+
);
|
|
167
|
+
export const removeScale = removeResource(
|
|
168
|
+
"scale", "removeScale", "Remove one unreferenced named scale."
|
|
169
|
+
);
|
|
170
|
+
export const removeCoordinate = removeResource(
|
|
171
|
+
"coordinate", "removeCoordinate", "Remove one unreferenced named coordinate."
|
|
172
|
+
);
|
|
@@ -0,0 +1,212 @@
|
|
|
1
|
+
import { action } from "../../core/action.js";
|
|
2
|
+
import { validateUserId } from "../../core/identifiers.js";
|
|
3
|
+
import { validateOptionObject } from "../../core/validation.js";
|
|
4
|
+
import { normalizePositionScaleChannel } from "../../core/vocabulary.js";
|
|
5
|
+
import { findLayer } from "../../selectors/layers.js";
|
|
6
|
+
import { requireSemanticScale } from "../../selectors/scales.js";
|
|
7
|
+
import { findScaleConsumers } from "./consumers/index.js";
|
|
8
|
+
|
|
9
|
+
const DEFINITIONS = Object.freeze({
|
|
10
|
+
editXScale: Object.freeze({
|
|
11
|
+
channel: "x",
|
|
12
|
+
options: Object.freeze([
|
|
13
|
+
"type", "domain", "range", "nice", "zero", "clamp", "reverse",
|
|
14
|
+
"base", "exponent", "constant", "paddingInner", "paddingOuter",
|
|
15
|
+
"padding", "align", "unknown"
|
|
16
|
+
])
|
|
17
|
+
}),
|
|
18
|
+
editYScale: Object.freeze({
|
|
19
|
+
channel: "y",
|
|
20
|
+
options: Object.freeze([
|
|
21
|
+
"type", "domain", "range", "nice", "zero", "clamp", "reverse",
|
|
22
|
+
"base", "exponent", "constant", "paddingInner", "paddingOuter",
|
|
23
|
+
"padding", "align", "unknown"
|
|
24
|
+
])
|
|
25
|
+
}),
|
|
26
|
+
editThetaScale: Object.freeze({
|
|
27
|
+
channel: "theta",
|
|
28
|
+
options: Object.freeze([
|
|
29
|
+
"type", "domain", "range", "nice", "zero", "clamp", "reverse",
|
|
30
|
+
"paddingInner", "paddingOuter", "padding", "align"
|
|
31
|
+
])
|
|
32
|
+
}),
|
|
33
|
+
editRScale: Object.freeze({
|
|
34
|
+
channel: "radius",
|
|
35
|
+
options: Object.freeze([
|
|
36
|
+
"type", "domain", "range", "nice", "zero", "clamp", "reverse",
|
|
37
|
+
"base", "exponent", "constant", "radialMapping"
|
|
38
|
+
])
|
|
39
|
+
}),
|
|
40
|
+
editColorScale: Object.freeze({
|
|
41
|
+
channel: "color",
|
|
42
|
+
options: Object.freeze([
|
|
43
|
+
"type", "domain", "range", "clamp", "reverse", "palette",
|
|
44
|
+
"interpolate", "midpoint", "unknown"
|
|
45
|
+
])
|
|
46
|
+
}),
|
|
47
|
+
editStrokeScale: Object.freeze({
|
|
48
|
+
channel: "stroke",
|
|
49
|
+
targetOnly: true,
|
|
50
|
+
options: Object.freeze([
|
|
51
|
+
"type", "domain", "range", "clamp", "reverse", "palette",
|
|
52
|
+
"interpolate", "midpoint", "unknown"
|
|
53
|
+
])
|
|
54
|
+
}),
|
|
55
|
+
editSizeScale: Object.freeze({
|
|
56
|
+
channel: "size",
|
|
57
|
+
options: Object.freeze([
|
|
58
|
+
"type", "domain", "range", "unknown", "clamp", "reverse", "base",
|
|
59
|
+
"exponent"
|
|
60
|
+
])
|
|
61
|
+
}),
|
|
62
|
+
editOpacityScale: Object.freeze({
|
|
63
|
+
channel: "opacity",
|
|
64
|
+
options: Object.freeze([
|
|
65
|
+
"type", "domain", "range", "nice", "zero", "clamp", "reverse", "unknown"
|
|
66
|
+
])
|
|
67
|
+
}),
|
|
68
|
+
editShapeScale: Object.freeze({
|
|
69
|
+
channel: "shape",
|
|
70
|
+
options: Object.freeze(["type", "domain", "range", "unknown"])
|
|
71
|
+
}),
|
|
72
|
+
editStrokeWidthScale: Object.freeze({
|
|
73
|
+
channel: "strokeWidth",
|
|
74
|
+
options: Object.freeze([
|
|
75
|
+
"type", "domain", "range", "nice", "zero", "clamp", "reverse",
|
|
76
|
+
"base", "exponent", "constant"
|
|
77
|
+
])
|
|
78
|
+
}),
|
|
79
|
+
editStrokeDashScale: Object.freeze({
|
|
80
|
+
channel: "strokeDash",
|
|
81
|
+
options: Object.freeze(["type", "domain", "range"])
|
|
82
|
+
})
|
|
83
|
+
});
|
|
84
|
+
|
|
85
|
+
function scaleIdsForLayer(program, layer, channel) {
|
|
86
|
+
if (layer === undefined) return [];
|
|
87
|
+
return [...new Set(allConsumers(program)
|
|
88
|
+
.filter(consumer =>
|
|
89
|
+
consumer.layer.id === layer.id &&
|
|
90
|
+
normalizePositionScaleChannel(consumer.channel) === channel
|
|
91
|
+
)
|
|
92
|
+
.map(consumer => consumer.encoding.scale))];
|
|
93
|
+
}
|
|
94
|
+
|
|
95
|
+
function allConsumers(program) {
|
|
96
|
+
return program.semanticSpec.scales.flatMap(scale =>
|
|
97
|
+
findScaleConsumers(program, scale.id)
|
|
98
|
+
);
|
|
99
|
+
}
|
|
100
|
+
|
|
101
|
+
function channelScaleIds(program, channel) {
|
|
102
|
+
return [...new Set(allConsumers(program)
|
|
103
|
+
.filter(consumer => normalizePositionScaleChannel(consumer.channel) === channel)
|
|
104
|
+
.map(consumer => consumer.encoding.scale))];
|
|
105
|
+
}
|
|
106
|
+
|
|
107
|
+
function requireSingleScale(ids, operation, scope) {
|
|
108
|
+
if (ids.length === 1) return ids[0];
|
|
109
|
+
if (ids.length === 0) {
|
|
110
|
+
throw new Error(`${operation} could not find a ${scope} scale.`);
|
|
111
|
+
}
|
|
112
|
+
throw new Error(`${operation} ${scope} scale is ambiguous; provide id or target.`);
|
|
113
|
+
}
|
|
114
|
+
|
|
115
|
+
function validateScaleChannel(program, id, channel, operation) {
|
|
116
|
+
requireSemanticScale(program, id);
|
|
117
|
+
const consumers = findScaleConsumers(program, id);
|
|
118
|
+
if (consumers.length === 0) {
|
|
119
|
+
throw new Error(`${operation} requires a scale bound to the ${channel} channel.`);
|
|
120
|
+
}
|
|
121
|
+
const compatible = ["color", "stroke"].includes(channel)
|
|
122
|
+
? new Set(["color", "stroke"])
|
|
123
|
+
: new Set([channel]);
|
|
124
|
+
if (!consumers.some(consumer =>
|
|
125
|
+
normalizePositionScaleChannel(consumer.channel) === channel
|
|
126
|
+
) || consumers.some(consumer =>
|
|
127
|
+
!compatible.has(normalizePositionScaleChannel(consumer.channel))
|
|
128
|
+
)) {
|
|
129
|
+
throw new Error(
|
|
130
|
+
`Scale "${id}" must include a ${channel} channel consumer and no incompatible channel consumers.`
|
|
131
|
+
);
|
|
132
|
+
}
|
|
133
|
+
return id;
|
|
134
|
+
}
|
|
135
|
+
|
|
136
|
+
function resolveScaleId(program, args, channel, operation) {
|
|
137
|
+
const explicitId = args.id === undefined
|
|
138
|
+
? undefined
|
|
139
|
+
: validateUserId(args.id, "Scale id");
|
|
140
|
+
const target = args.target === undefined
|
|
141
|
+
? undefined
|
|
142
|
+
: validateUserId(args.target, "Mark id");
|
|
143
|
+
const targetLayer = target === undefined ? undefined : findLayer(program, target);
|
|
144
|
+
if (target !== undefined && targetLayer === undefined) {
|
|
145
|
+
throw new Error(`Unknown mark target "${target}".`);
|
|
146
|
+
}
|
|
147
|
+
const targetId = targetLayer === undefined
|
|
148
|
+
? undefined
|
|
149
|
+
: requireSingleScale(scaleIdsForLayer(program, targetLayer, channel), operation, `target ${channel}`);
|
|
150
|
+
if (explicitId !== undefined && targetId !== undefined && explicitId !== targetId) {
|
|
151
|
+
throw new Error(`${operation} id "${explicitId}" does not match target "${target}" scale "${targetId}".`);
|
|
152
|
+
}
|
|
153
|
+
if (explicitId !== undefined) {
|
|
154
|
+
return validateScaleChannel(program, explicitId, channel, operation);
|
|
155
|
+
}
|
|
156
|
+
if (targetId !== undefined) return validateScaleChannel(program, targetId, channel, operation);
|
|
157
|
+
|
|
158
|
+
const current = findLayer(program, program.context.currentMark);
|
|
159
|
+
const currentIds = scaleIdsForLayer(program, current, channel);
|
|
160
|
+
if (currentIds.length > 1) {
|
|
161
|
+
throw new Error(`${operation} current-mark ${channel} scale is ambiguous; provide id or target.`);
|
|
162
|
+
}
|
|
163
|
+
if (currentIds.length === 1) {
|
|
164
|
+
return validateScaleChannel(program, currentIds[0], channel, operation);
|
|
165
|
+
}
|
|
166
|
+
return validateScaleChannel(
|
|
167
|
+
program,
|
|
168
|
+
requireSingleScale(channelScaleIds(program, channel), operation, channel),
|
|
169
|
+
channel,
|
|
170
|
+
operation
|
|
171
|
+
);
|
|
172
|
+
}
|
|
173
|
+
|
|
174
|
+
function createChannelScaleEditor(operation, definition) {
|
|
175
|
+
return action(
|
|
176
|
+
{
|
|
177
|
+
op: operation,
|
|
178
|
+
description: `Edit the scale bound to the ${definition.channel} channel.`
|
|
179
|
+
},
|
|
180
|
+
function (args = {}) {
|
|
181
|
+
validateOptionObject(
|
|
182
|
+
args,
|
|
183
|
+
[...(definition.targetOnly === true ? [] : ["id"]), "target", ...definition.options],
|
|
184
|
+
operation
|
|
185
|
+
);
|
|
186
|
+
if (definition.targetOnly === true && args.target === undefined) {
|
|
187
|
+
throw new Error(`${operation} requires target.`);
|
|
188
|
+
}
|
|
189
|
+
if (!definition.options.some(property => Object.hasOwn(args, property))) {
|
|
190
|
+
throw new Error(`${operation} requires at least one editable property.`);
|
|
191
|
+
}
|
|
192
|
+
const id = resolveScaleId(this, args, definition.channel, operation);
|
|
193
|
+
const patch = Object.fromEntries(
|
|
194
|
+
Object.entries(args).filter(([property]) => property !== "target")
|
|
195
|
+
);
|
|
196
|
+
return this.editScale({ ...patch, id });
|
|
197
|
+
}
|
|
198
|
+
);
|
|
199
|
+
}
|
|
200
|
+
|
|
201
|
+
export const channelScaleEditors = Object.freeze(Object.fromEntries(
|
|
202
|
+
Object.entries(DEFINITIONS).map(([operation, definition]) => [
|
|
203
|
+
operation,
|
|
204
|
+
createChannelScaleEditor(operation, definition)
|
|
205
|
+
])
|
|
206
|
+
));
|
|
207
|
+
|
|
208
|
+
export function registerChannelScaleActions(ProgramClass) {
|
|
209
|
+
for (const [operation, editor] of Object.entries(channelScaleEditors)) {
|
|
210
|
+
ProgramClass.prototype[operation] = editor;
|
|
211
|
+
}
|
|
212
|
+
}
|
|
@@ -43,7 +43,7 @@ export function requireConsumerDataset(program, consumer) {
|
|
|
43
43
|
}
|
|
44
44
|
|
|
45
45
|
export function isDirectCategoricalConsumer(consumer) {
|
|
46
|
-
return ["color", "strokeDash", "xOffset", "yOffset", "shape"].includes(
|
|
46
|
+
return ["color", "stroke", "strokeDash", "xOffset", "yOffset", "shape"].includes(
|
|
47
47
|
consumer.channel
|
|
48
48
|
) && ["nominal", "ordinal"].includes(consumer.encoding.fieldType);
|
|
49
49
|
}
|
|
@@ -45,7 +45,7 @@ export function resolveMarkFamilyConsumerValues(program, consumer, dataset) {
|
|
|
45
45
|
}
|
|
46
46
|
const { layer, channel } = consumer;
|
|
47
47
|
const encoding = layer.encoding ?? {};
|
|
48
|
-
const appearance = ["strokeWidth", "opacity"].includes(channel);
|
|
48
|
+
const appearance = ["stroke", "strokeWidth", "opacity"].includes(channel);
|
|
49
49
|
if (
|
|
50
50
|
layer.mark?.type === "line" &&
|
|
51
51
|
((["x", "y"].includes(channel) && encoding.x !== undefined &&
|
|
@@ -69,7 +69,8 @@ export function resolveMarkFamilyConsumerValues(program, consumer, dataset) {
|
|
|
69
69
|
dataset.values,
|
|
70
70
|
derived.series,
|
|
71
71
|
consumer.encoding.field,
|
|
72
|
-
channel
|
|
72
|
+
channel,
|
|
73
|
+
consumer.encoding
|
|
73
74
|
)
|
|
74
75
|
: channel === "x" ? derived.xValues : derived.yValues
|
|
75
76
|
};
|
|
@@ -9,6 +9,8 @@ import {
|
|
|
9
9
|
} from "./common.js";
|
|
10
10
|
import { resolveMarkFamilyConsumerValues } from "./families.js";
|
|
11
11
|
import { CATEGORY_ORDER_CHANNELS, resolveCategoryOrder } from "../../../grammar/categoryOrder.js";
|
|
12
|
+
import { resolveHistogramInput } from
|
|
13
|
+
"../../../materialization/bars/histogram.js";
|
|
12
14
|
|
|
13
15
|
export { findScale, findScaleConsumers } from "./common.js";
|
|
14
16
|
export {
|
|
@@ -16,8 +18,7 @@ export {
|
|
|
16
18
|
resolveSeriesLayoutScaleValues
|
|
17
19
|
} from "./seriesLayout.js";
|
|
18
20
|
|
|
19
|
-
export function
|
|
20
|
-
const dataset = requireConsumerDataset(program, consumer);
|
|
21
|
+
export function resolveConsumerValuesForDataset(program, consumer, dataset) {
|
|
21
22
|
if (consumer.layer.mark.type === "rect") return resolveMarkFamilyConsumerValues(program, consumer, dataset).values;
|
|
22
23
|
if (Object.hasOwn(consumer.encoding, "datum")) {
|
|
23
24
|
if (consumer.layer.mark.type === "area") {
|
|
@@ -49,6 +50,14 @@ export function resolveConsumerValues(program, consumer) {
|
|
|
49
50
|
);
|
|
50
51
|
}
|
|
51
52
|
const scale = findScale(program, consumer.encoding.scale);
|
|
53
|
+
if (
|
|
54
|
+
consumer.layer.mark.type === "bar" &&
|
|
55
|
+
consumer.channel === "x" &&
|
|
56
|
+
consumer.encoding.bin !== undefined &&
|
|
57
|
+
consumer.encoding.weight !== undefined
|
|
58
|
+
) {
|
|
59
|
+
return resolveHistogramInput(dataset, consumer.encoding).values;
|
|
60
|
+
}
|
|
52
61
|
if (isDirectCategoricalConsumer(consumer)) {
|
|
53
62
|
return readConsumerFieldValues(program, consumer, dataset, scale);
|
|
54
63
|
}
|
|
@@ -58,6 +67,14 @@ export function resolveConsumerValues(program, consumer) {
|
|
|
58
67
|
: readConsumerFieldValues(program, consumer, dataset, scale);
|
|
59
68
|
}
|
|
60
69
|
|
|
70
|
+
export function resolveConsumerValues(program, consumer) {
|
|
71
|
+
return resolveConsumerValuesForDataset(
|
|
72
|
+
program,
|
|
73
|
+
consumer,
|
|
74
|
+
requireConsumerDataset(program, consumer)
|
|
75
|
+
);
|
|
76
|
+
}
|
|
77
|
+
|
|
61
78
|
export function resolveConsumerCategoryOrder(program, consumer) {
|
|
62
79
|
const order = consumer.encoding.categoryOrder;
|
|
63
80
|
if (order === undefined) return undefined;
|