ggaction 0.0.11 → 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 +80 -0
- package/README.md +3 -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 +33 -27
- package/src/actions/encodings/parallel.js +2 -8
- package/src/actions/encodings/position/apply.js +40 -4
- package/src/actions/encodings/position/index.js +43 -5
- package/src/actions/encodings/position/policies/arc.js +37 -2
- 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 +79 -24
- 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 +153 -11
- package/src/actions/errorBars/edit.js +365 -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 +138 -14
- 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 +60 -4
- 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/core/vocabulary.js +2 -2
- package/src/grammar/aggregate.js +66 -23
- package/src/grammar/arcs.js +213 -65
- 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/positionCompatibility.js +1 -1
- 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 +9 -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/ordinal.js +23 -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 +86 -23
- 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/facetGuides/legacyCategorical.js +7 -1
- package/src/materialization/facetGuides/placement.js +16 -1
- package/src/materialization/facetGuides/preparation.js +26 -1
- package/src/materialization/facets.js +11 -2
- 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 +30 -7
- package/src/materialization/marks/grouping.js +52 -0
- package/src/materialization/marks/index.js +63 -25
- package/src/materialization/marks/policies.js +2 -0
- package/src/materialization/rect.js +33 -33
- package/src/materialization/rowEncoding.js +70 -14
- 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/bar.js +0 -43
- package/src/materialization/scales/policies/binnedPosition.js +7 -4
- package/src/materialization/scales/policies/offset.js +54 -0
- package/src/materialization/scales/policies/series.js +2 -1
- package/src/materialization/scales/resolve.js +48 -18
- 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 +1327 -124
- package/src/materialization/bars/grouped.js +0 -144
|
@@ -51,7 +51,7 @@ function normalizeConfig(args, previous = {}, { allowStrokeRemoval = false } = {
|
|
|
51
51
|
let config = {
|
|
52
52
|
...previous,
|
|
53
53
|
...(Object.hasOwn(args, "innerRadius")
|
|
54
|
-
? { innerRadius: validateInnerRadius(args.innerRadius) }
|
|
54
|
+
? { innerRadius: validateInnerRadius(args.innerRadius), innerRadiusExplicit: true }
|
|
55
55
|
: {}),
|
|
56
56
|
...(Object.hasOwn(args, "padAngle")
|
|
57
57
|
? { padAngle: validateNonNegativeFinite(args.padAngle, "Arc padAngle") }
|
|
@@ -1,3 +1,4 @@
|
|
|
1
|
+
import { validateAreaMissing } from "../../../grammar/areaEndpoints.js";
|
|
1
2
|
import { action } from "../../../core/action.js";
|
|
2
3
|
import { validateUserId } from "../../../core/identifiers.js";
|
|
3
4
|
import {
|
|
@@ -30,8 +31,8 @@ import { resolveAreaMaterialization } from "./materialize.js";
|
|
|
30
31
|
const AREA_OPTIONS = Object.freeze([
|
|
31
32
|
"fill", "opacity", "stroke", "strokeWidth", "curve"
|
|
32
33
|
]);
|
|
33
|
-
const CREATE_OPTIONS = Object.freeze(["id", "data", ...AREA_OPTIONS]);
|
|
34
|
-
const EDIT_OPTIONS = Object.freeze(["target", ...AREA_OPTIONS]);
|
|
34
|
+
const CREATE_OPTIONS = Object.freeze(["id", "data", "missing", ...AREA_OPTIONS]);
|
|
35
|
+
const EDIT_OPTIONS = Object.freeze(["target", "missing", ...AREA_OPTIONS]);
|
|
35
36
|
const REMATERIALIZE_OPTIONS = Object.freeze(["id", "scales"]);
|
|
36
37
|
const STROKE_FROM_FILL_OPTIONS = Object.freeze(["id", "strokeWidth"]);
|
|
37
38
|
|
|
@@ -69,6 +70,10 @@ const createAreaMark = action(
|
|
|
69
70
|
...(args.data === undefined && this.context.currentData === undefined &&
|
|
70
71
|
inherited?.data !== undefined ? { data: inherited.data } : {})
|
|
71
72
|
});
|
|
73
|
+
const missing = validateAreaMissing(args.missing);
|
|
74
|
+
if (missing === "break" && ["density", "horizon"].some(type => findUpstreamTransform(this, findDataset(this, data), type))) {
|
|
75
|
+
throw new Error("Area missing:break does not reinterpret density or horizon data.");
|
|
76
|
+
}
|
|
72
77
|
const fill = validateNonEmptyString(args.fill ?? DEFAULT_COLORS.mark, "Area fill");
|
|
73
78
|
const opacity = validateUnitInterval(args.opacity ?? 0.2, "Area opacity");
|
|
74
79
|
const curve = validateCurveInterpolation(args.curve ?? "linear");
|
|
@@ -77,6 +82,7 @@ const createAreaMark = action(
|
|
|
77
82
|
let created = this
|
|
78
83
|
.editSemantic({ property: `layer[${id}].mark.type`, value: "area" })
|
|
79
84
|
.editSemantic({ property: `layer[${id}].data`, value: data });
|
|
85
|
+
if (Object.hasOwn(args, "missing")) created = created.editSemantic({ property: `layer[${id}].mark.missing`, value: missing });
|
|
80
86
|
created = applyLayeredMarkInheritance(created, id, inherited);
|
|
81
87
|
created = created
|
|
82
88
|
.createGraphics({
|
|
@@ -218,7 +224,7 @@ const editAreaMark = action(
|
|
|
218
224
|
},
|
|
219
225
|
function (args = {}) {
|
|
220
226
|
validateMarkOptions(args, EDIT_OPTIONS, "editAreaMark");
|
|
221
|
-
const changes = ["fill", "opacity", "stroke", "strokeWidth", "curve"];
|
|
227
|
+
const changes = ["fill", "opacity", "stroke", "strokeWidth", "curve", "missing"];
|
|
222
228
|
if (!changes.some(key => Object.hasOwn(args, key))) {
|
|
223
229
|
throw new Error(
|
|
224
230
|
"editAreaMark requires fill, opacity, stroke, strokeWidth, or curve."
|
|
@@ -244,6 +250,7 @@ const editAreaMark = action(
|
|
|
244
250
|
let config = { ...this.markConfigs[layer.id] };
|
|
245
251
|
if (Object.hasOwn(args, "fill")) {
|
|
246
252
|
config.fill = validateNonEmptyString(args.fill, "Area fill");
|
|
253
|
+
if (config.errorBand !== undefined) config.errorBand = { ...config.errorBand, fill: config.fill };
|
|
247
254
|
}
|
|
248
255
|
if (Object.hasOwn(args, "opacity")) {
|
|
249
256
|
config.opacity = validateUnitInterval(args.opacity, "Area opacity");
|
|
@@ -283,7 +290,14 @@ const editAreaMark = action(
|
|
|
283
290
|
);
|
|
284
291
|
}
|
|
285
292
|
|
|
286
|
-
|
|
293
|
+
let next = this._withMarkConfig(layer.id, config);
|
|
294
|
+
if (Object.hasOwn(args, "missing")) {
|
|
295
|
+
const missing = validateAreaMissing(args.missing);
|
|
296
|
+
if (missing === "break" && ["density", "horizon"].some(type => findUpstreamTransform(this, findDataset(this, layer.data), type))) {
|
|
297
|
+
throw new Error("Area missing:break does not reinterpret density or horizon data.");
|
|
298
|
+
}
|
|
299
|
+
next = next.editSemantic({ property: `layer[${layer.id}].mark.missing`, value: missing });
|
|
300
|
+
}
|
|
287
301
|
return canMaterializeArea(next, layer)
|
|
288
302
|
? next.rematerializeAreaMark({ id: layer.id })
|
|
289
303
|
: next;
|
|
@@ -14,6 +14,7 @@ import { buildLinearPathCommands } from
|
|
|
14
14
|
"../../../grammar/pathCommands.js";
|
|
15
15
|
import { buildCategoricalDensityPaths } from
|
|
16
16
|
"../../../grammar/categoricalDensity.js";
|
|
17
|
+
import { derivePathSeriesFieldValues } from "../../../grammar/pathSeries.js";
|
|
17
18
|
|
|
18
19
|
function resolveAreaPaths({
|
|
19
20
|
derived,
|
|
@@ -135,7 +136,7 @@ export function resolveAreaMaterialization({
|
|
|
135
136
|
: deriveAreaSeries(rows, layer)
|
|
136
137
|
: deriveDensityAreaSeries(rows, layer, densityTransform);
|
|
137
138
|
const colorEncoding = layer.encoding?.color;
|
|
138
|
-
const layout = colorEncoding?.layout ?? "overlay";
|
|
139
|
+
const layout = layer.layout?.mode ?? colorEncoding?.layout ?? "overlay";
|
|
139
140
|
const categoricalDensity = densityTransform?.placement?.type === "category";
|
|
140
141
|
const derived = densityTransform === undefined || categoricalDensity
|
|
141
142
|
? rawDerived
|
|
@@ -164,7 +165,9 @@ export function resolveAreaMaterialization({
|
|
|
164
165
|
: colorEncoding?.scale === undefined
|
|
165
166
|
? paths.map(() => config.fill)
|
|
166
167
|
: mapOrdinalValues(
|
|
167
|
-
|
|
168
|
+
densityTransform !== undefined || centered
|
|
169
|
+
? derived.series.map(series => series.key[colorEncoding.field])
|
|
170
|
+
: derivePathSeriesFieldValues(rows, derived.series, colorEncoding.field, "color"),
|
|
168
171
|
resolvedScales[colorEncoding.scale].domain,
|
|
169
172
|
resolvedScales[colorEncoding.scale].range
|
|
170
173
|
);
|
|
@@ -10,6 +10,8 @@ import {
|
|
|
10
10
|
resolveBarOffsetChannel
|
|
11
11
|
} from "../../../grammar/bars/policy.js";
|
|
12
12
|
import { rematerializeHighlightBaseline } from "../lifecycle.js";
|
|
13
|
+
import { offsetCategoryRectangles } from
|
|
14
|
+
"../../../materialization/categorySlotOffset.js";
|
|
13
15
|
|
|
14
16
|
const REMATERIALIZE_OPTIONS = Object.freeze(["id", "scales"]);
|
|
15
17
|
|
|
@@ -103,22 +105,24 @@ export const rematerializeBarMark = action(
|
|
|
103
105
|
resolved = resolved.rematerializeScale({ id: offsetScaleId });
|
|
104
106
|
}
|
|
105
107
|
const width = resolved.markConfigs[id]?.barWidth;
|
|
106
|
-
return editRectangles(
|
|
107
|
-
resolved,
|
|
108
|
-
|
|
109
|
-
deriveAggregateRectangles(required, resolved, width)
|
|
110
|
-
);
|
|
108
|
+
return editRectangles(resolved, id, offsetCategoryRectangles(
|
|
109
|
+
resolved, required.layer, deriveAggregateRectangles(required, resolved, width)
|
|
110
|
+
));
|
|
111
111
|
}
|
|
112
112
|
|
|
113
113
|
if (required.materialization === BAR_GRAINS.ranged) {
|
|
114
114
|
const width = resolved.markConfigs[id]?.barWidth;
|
|
115
|
-
return editRectangles(resolved, id,
|
|
115
|
+
return editRectangles(resolved, id, offsetCategoryRectangles(
|
|
116
|
+
resolved, required.layer, deriveRangedRectangles(required, resolved, width)
|
|
117
|
+
));
|
|
116
118
|
}
|
|
117
119
|
|
|
118
120
|
return editRectangles(
|
|
119
121
|
resolved,
|
|
120
122
|
id,
|
|
121
|
-
|
|
123
|
+
offsetCategoryRectangles(
|
|
124
|
+
resolved, required.layer, deriveHistogramRectangles(required, resolved)
|
|
125
|
+
)
|
|
122
126
|
);
|
|
123
127
|
}
|
|
124
128
|
);
|
|
@@ -1,4 +1,5 @@
|
|
|
1
1
|
import { removeMark } from "./remove.js";
|
|
2
|
+
import { createReferenceLine, createReferenceBand } from "./references.js";
|
|
2
3
|
import { registerRuleMarkActions } from "./rule/index.js";
|
|
3
4
|
import { registerAreaMarkActions } from "./area/index.js";
|
|
4
5
|
import { registerTickMarkActions } from "./tick/index.js";
|
|
@@ -8,6 +9,7 @@ import { registerArcMarkActions } from "./arc/index.js";
|
|
|
8
9
|
import { registerRectMarkActions } from "./rect/index.js";
|
|
9
10
|
import {
|
|
10
11
|
registerPointJitterActions,
|
|
12
|
+
registerPointPackingActions,
|
|
11
13
|
registerPointMarkActions
|
|
12
14
|
} from "./point/index.js";
|
|
13
15
|
import { registerTextMarkActions } from "./text/index.js";
|
|
@@ -15,6 +17,7 @@ import { registerTextMarkActions } from "./text/index.js";
|
|
|
15
17
|
export function registerMarkActions(ProgramClass) {
|
|
16
18
|
registerPointMarkActions(ProgramClass);
|
|
17
19
|
registerPointJitterActions(ProgramClass);
|
|
20
|
+
registerPointPackingActions(ProgramClass);
|
|
18
21
|
registerRectMarkActions(ProgramClass);
|
|
19
22
|
registerAreaMarkActions(ProgramClass);
|
|
20
23
|
registerArcMarkActions(ProgramClass);
|
|
@@ -24,4 +27,6 @@ export function registerMarkActions(ProgramClass) {
|
|
|
24
27
|
registerTextMarkActions(ProgramClass);
|
|
25
28
|
registerTickMarkActions(ProgramClass);
|
|
26
29
|
ProgramClass.prototype.removeMark = removeMark;
|
|
30
|
+
ProgramClass.prototype.createReferenceLine = createReferenceLine;
|
|
31
|
+
ProgramClass.prototype.createReferenceBand = createReferenceBand;
|
|
27
32
|
}
|
|
@@ -71,14 +71,14 @@ function validatePolarLineConfig(layer, config) {
|
|
|
71
71
|
}
|
|
72
72
|
}
|
|
73
73
|
|
|
74
|
-
function applyLineMaterialization(program, id, materialization
|
|
74
|
+
function applyLineMaterialization(program, id, materialization) {
|
|
75
75
|
return editMarkGraphic(program, id, {
|
|
76
76
|
length: materialization.commands.length,
|
|
77
77
|
commands: materialization.commands,
|
|
78
78
|
stroke: materialization.strokes,
|
|
79
79
|
strokeWidth: materialization.strokeWidths,
|
|
80
80
|
strokeDash: materialization.strokeDashes,
|
|
81
|
-
...(
|
|
81
|
+
...(materialization.opacities === undefined ? {} : { opacity: materialization.opacities })
|
|
82
82
|
});
|
|
83
83
|
}
|
|
84
84
|
|
|
@@ -205,71 +205,34 @@ const rematerializeLineMark = action(
|
|
|
205
205
|
|
|
206
206
|
if (parallel !== undefined) {
|
|
207
207
|
validateParallelRows(dataset.values, parallel.dimensions, parallel);
|
|
208
|
-
let resolved = this;
|
|
209
|
-
if (args.scales !== false) {
|
|
210
|
-
for (const dimension of parallel.dimensions) {
|
|
211
|
-
resolved = resolved.rematerializeScale({ id: dimension.scale });
|
|
212
|
-
}
|
|
213
|
-
}
|
|
214
|
-
for (const channel of args.scales === false
|
|
215
|
-
? []
|
|
216
|
-
: ["color", "strokeDash", "strokeWidth"]) {
|
|
217
|
-
const scaleId = layer.encoding?.[channel]?.scale;
|
|
218
|
-
if (scaleId !== undefined) {
|
|
219
|
-
resolved = resolved.rematerializeScale({ id: scaleId });
|
|
220
|
-
}
|
|
221
|
-
}
|
|
222
|
-
const materialization = resolveParallelLineMaterialization({
|
|
223
|
-
rows: dataset.values,
|
|
224
|
-
parallel,
|
|
225
|
-
layer,
|
|
226
|
-
resolvedScales: resolved.resolvedScales,
|
|
227
|
-
bounds: resolveGraphicBounds(resolved),
|
|
228
|
-
config,
|
|
229
|
-
existingChildren,
|
|
230
|
-
defaults: { stroke: DEFAULT_LINE_STROKE, strokeWidth: DEFAULT_LINE_WIDTH }
|
|
231
|
-
});
|
|
232
|
-
return applyLineMaterialization(
|
|
233
|
-
resolved,
|
|
234
|
-
id,
|
|
235
|
-
materialization,
|
|
236
|
-
config.opacity
|
|
237
|
-
);
|
|
238
208
|
}
|
|
239
|
-
|
|
240
|
-
|
|
241
|
-
polar
|
|
242
|
-
|
|
243
|
-
|
|
244
|
-
) {
|
|
245
|
-
throw new Error(
|
|
246
|
-
polar
|
|
247
|
-
? `Line mark "${id}" requires theta and radius scales.`
|
|
248
|
-
: `Line mark "${id}" requires x and y scales.`
|
|
249
|
-
);
|
|
209
|
+
const positions = parallel !== undefined
|
|
210
|
+
? parallel.dimensions.map(dimension => dimension.scale)
|
|
211
|
+
: polar ? [thetaScaleId, radiusScaleId] : [xScaleId, yScaleId];
|
|
212
|
+
if (positions.some(scale => scale === undefined)) {
|
|
213
|
+
throw new Error(`Line mark "${id}" requires ${polar ? "theta and radius" : "x and y"} scales.`);
|
|
250
214
|
}
|
|
251
|
-
|
|
252
|
-
|
|
253
|
-
|
|
254
|
-
|
|
255
|
-
|
|
256
|
-
|
|
257
|
-
.rematerializeScale({ id: radiusScaleId })
|
|
258
|
-
: this
|
|
259
|
-
.rematerializeScale({ id: xScaleId })
|
|
260
|
-
.rematerializeScale({ id: yScaleId });
|
|
261
|
-
|
|
262
|
-
for (const channel of args.scales === false ? [] : ["color", "strokeDash", "strokeWidth"]) {
|
|
263
|
-
const scaleId = layer.encoding?.[channel]?.scale;
|
|
264
|
-
if (scaleId !== undefined) {
|
|
265
|
-
resolved = resolved.rematerializeScale({ id: scaleId });
|
|
215
|
+
let resolved = this;
|
|
216
|
+
if (args.scales !== false) {
|
|
217
|
+
const appearance = ["color", "strokeDash", "strokeWidth", "opacity"]
|
|
218
|
+
.map(channel => layer.encoding?.[channel]?.scale).filter(scale => scale !== undefined);
|
|
219
|
+
for (const scale of [...positions, ...appearance]) {
|
|
220
|
+
resolved = resolved.rematerializeScale({ id: scale });
|
|
266
221
|
}
|
|
267
222
|
}
|
|
223
|
+
const shared = {
|
|
224
|
+
rows: dataset.values, layer, config, existingChildren,
|
|
225
|
+
resolvedScales: resolved.resolvedScales,
|
|
226
|
+
bounds: resolveGraphicBounds(resolved),
|
|
227
|
+
defaults: { stroke: DEFAULT_LINE_STROKE, strokeWidth: DEFAULT_LINE_WIDTH }
|
|
228
|
+
};
|
|
229
|
+
if (parallel !== undefined) {
|
|
230
|
+
return applyLineMaterialization(resolved, id,
|
|
231
|
+
resolveParallelLineMaterialization({ ...shared, parallel }));
|
|
232
|
+
}
|
|
268
233
|
|
|
269
234
|
const materialization = resolvePositionedLineMaterialization({
|
|
270
|
-
|
|
271
|
-
layer,
|
|
272
|
-
resolvedScales: resolved.resolvedScales,
|
|
235
|
+
...shared,
|
|
273
236
|
xBinBoundaries: layer.encoding?.x?.bin === undefined
|
|
274
237
|
? undefined
|
|
275
238
|
: resolveLineBins(
|
|
@@ -277,18 +240,13 @@ const rematerializeLineMark = action(
|
|
|
277
240
|
layer,
|
|
278
241
|
requireSemanticScale(resolved, xScaleId)
|
|
279
242
|
).boundaries,
|
|
280
|
-
|
|
281
|
-
config,
|
|
282
|
-
existingChildren,
|
|
283
|
-
polar,
|
|
284
|
-
defaults: { stroke: DEFAULT_LINE_STROKE, strokeWidth: DEFAULT_LINE_WIDTH }
|
|
243
|
+
polar
|
|
285
244
|
});
|
|
286
245
|
|
|
287
246
|
return applyLineMaterialization(
|
|
288
247
|
resolved,
|
|
289
248
|
id,
|
|
290
|
-
materialization
|
|
291
|
-
config.opacity
|
|
249
|
+
materialization
|
|
292
250
|
);
|
|
293
251
|
}
|
|
294
252
|
);
|
|
@@ -300,16 +258,8 @@ const editLineMark = action(
|
|
|
300
258
|
},
|
|
301
259
|
function (args = {}) {
|
|
302
260
|
validateMarkOptions(args, EDIT_OPTIONS, "editLineMark");
|
|
303
|
-
if (
|
|
304
|
-
|
|
305
|
-
!Object.hasOwn(args, "strokeWidth") &&
|
|
306
|
-
!Object.hasOwn(args, "opacity") &&
|
|
307
|
-
!Object.hasOwn(args, "curve") &&
|
|
308
|
-
!Object.hasOwn(args, "closed")
|
|
309
|
-
) {
|
|
310
|
-
throw new Error(
|
|
311
|
-
"editLineMark requires stroke, strokeWidth, opacity, curve, or closed."
|
|
312
|
-
);
|
|
261
|
+
if (!EDIT_OPTIONS.slice(1).some(key => Object.hasOwn(args, key))) {
|
|
262
|
+
throw new Error("editLineMark requires stroke, strokeWidth, opacity, curve, or closed.");
|
|
313
263
|
}
|
|
314
264
|
const target = Object.hasOwn(args, "target")
|
|
315
265
|
? validateUserId(args.target, "Line mark id")
|
|
@@ -324,41 +274,26 @@ const editLineMark = action(
|
|
|
324
274
|
"editLineMark stroke cannot be combined with a color encoding."
|
|
325
275
|
);
|
|
326
276
|
}
|
|
277
|
+
for (const channel of ["strokeWidth", "opacity"]) {
|
|
278
|
+
if (Object.hasOwn(args, channel) && layer.encoding?.[channel]?.field !== undefined) {
|
|
279
|
+
throw new Error(`editLineMark ${channel} conflicts with a field encoding; use its encoder with value to replace it.`);
|
|
280
|
+
}
|
|
281
|
+
}
|
|
327
282
|
if (Object.hasOwn(args, "closed") && args.closed === true &&
|
|
328
283
|
(layer.encoding?.x !== undefined || isParallelLine(layer))) {
|
|
329
284
|
throw new Error("Line closed requires theta/radius Polar position encodings.");
|
|
330
285
|
}
|
|
331
|
-
|
|
332
|
-
|
|
333
|
-
|
|
286
|
+
const config = { ...this.markConfigs[layer.id] };
|
|
287
|
+
for (const [key, validate] of Object.entries({
|
|
288
|
+
stroke: validateNonEmptyString,
|
|
289
|
+
strokeWidth: validateNonNegativeFinite,
|
|
290
|
+
opacity: validateUnitInterval,
|
|
291
|
+
curve: validateCurveInterpolation,
|
|
292
|
+
closed: validateClosed
|
|
293
|
+
})) {
|
|
294
|
+
if (Object.hasOwn(args, key)) config[key] = validate(args[key], `Line ${key}`);
|
|
334
295
|
}
|
|
335
|
-
|
|
336
|
-
args.curve !== "linear") {
|
|
337
|
-
throw new Error("Parallel lines require curve \"linear\".");
|
|
338
|
-
}
|
|
339
|
-
const config = {
|
|
340
|
-
...this.markConfigs[layer.id],
|
|
341
|
-
...(Object.hasOwn(args, "stroke")
|
|
342
|
-
? { stroke: validateNonEmptyString(args.stroke, "Line stroke") }
|
|
343
|
-
: {}),
|
|
344
|
-
...(Object.hasOwn(args, "strokeWidth")
|
|
345
|
-
? {
|
|
346
|
-
strokeWidth: validateNonNegativeFinite(
|
|
347
|
-
args.strokeWidth,
|
|
348
|
-
"Line strokeWidth"
|
|
349
|
-
)
|
|
350
|
-
}
|
|
351
|
-
: {}),
|
|
352
|
-
...(Object.hasOwn(args, "opacity")
|
|
353
|
-
? { opacity: validateUnitInterval(args.opacity, "Line opacity") }
|
|
354
|
-
: {}),
|
|
355
|
-
...(Object.hasOwn(args, "curve")
|
|
356
|
-
? { curve: validateCurveInterpolation(args.curve) }
|
|
357
|
-
: {}),
|
|
358
|
-
...(Object.hasOwn(args, "closed")
|
|
359
|
-
? { closed: validateClosed(args.closed) }
|
|
360
|
-
: {})
|
|
361
|
-
};
|
|
296
|
+
validatePolarLineConfig(layer, config);
|
|
362
297
|
const next = this._withMarkConfig(layer.id, config);
|
|
363
298
|
return canMaterializeLine(next, layer)
|
|
364
299
|
? next.rematerializeLineMark({ id: layer.id })
|
|
@@ -1,10 +1,8 @@
|
|
|
1
1
|
import {
|
|
2
|
-
deriveLineSeries
|
|
3
|
-
deriveLineSeriesFieldValues
|
|
2
|
+
deriveLineSeries
|
|
4
3
|
} from "../../../grammar/lineSeries.js";
|
|
5
4
|
import {
|
|
6
5
|
mapContinuousScaleValues,
|
|
7
|
-
mapOrdinalValues,
|
|
8
6
|
normalizeStrokeDashPattern
|
|
9
7
|
} from "../../../grammar/scales/index.js";
|
|
10
8
|
import { buildCurvePathCommands } from
|
|
@@ -12,6 +10,7 @@ import { buildCurvePathCommands } from
|
|
|
12
10
|
import { buildPolarLinePathCommands } from
|
|
13
11
|
"../../../grammar/polarLineCommands.js";
|
|
14
12
|
import { resolvePolarFrame } from "../../../grammar/polar.js";
|
|
13
|
+
import { derivePathSeriesFieldValues } from "../../../grammar/pathSeries.js";
|
|
15
14
|
import { materializeParallelRows } from
|
|
16
15
|
"../../../grammar/parallelCoordinates.js";
|
|
17
16
|
import { mapScaleConsumerValues } from
|
|
@@ -21,6 +20,17 @@ function existingValue(children, index, property, fallback) {
|
|
|
21
20
|
return children[index]?.properties[property] ?? fallback;
|
|
22
21
|
}
|
|
23
22
|
|
|
23
|
+
function appearanceMapper(layer, scales, fieldValues) {
|
|
24
|
+
return (channel, fallback) => {
|
|
25
|
+
const encoding = layer.encoding?.[channel];
|
|
26
|
+
if (encoding?.datum !== undefined) {
|
|
27
|
+
return fallback.map(() => normalizeStrokeDashPattern(encoding.datum));
|
|
28
|
+
}
|
|
29
|
+
if (encoding?.scale === undefined) return fallback;
|
|
30
|
+
return mapScaleConsumerValues(fieldValues(encoding.field, channel), scales[encoding.scale], channel);
|
|
31
|
+
};
|
|
32
|
+
}
|
|
33
|
+
|
|
24
34
|
export function resolveParallelLineMaterialization({
|
|
25
35
|
rows,
|
|
26
36
|
parallel,
|
|
@@ -39,36 +49,25 @@ export function resolveParallelLineMaterialization({
|
|
|
39
49
|
parallel
|
|
40
50
|
);
|
|
41
51
|
const sourceRows = items.map(item => rows[item.sourceRowIndex]);
|
|
42
|
-
const mapAppearance = (
|
|
43
|
-
|
|
44
|
-
if (encoding?.datum !== undefined) {
|
|
45
|
-
return items.map(() => channel === "strokeDash"
|
|
46
|
-
? normalizeStrokeDashPattern(encoding.datum)
|
|
47
|
-
: encoding.datum);
|
|
48
|
-
}
|
|
49
|
-
if (encoding?.scale === undefined) return items.map(fallback);
|
|
50
|
-
return mapScaleConsumerValues(
|
|
51
|
-
sourceRows.map(row => row[encoding.field]),
|
|
52
|
-
resolvedScales[encoding.scale],
|
|
53
|
-
channel
|
|
54
|
-
);
|
|
55
|
-
};
|
|
52
|
+
const mapAppearance = appearanceMapper(layer, resolvedScales,
|
|
53
|
+
field => sourceRows.map(row => row[field]));
|
|
56
54
|
return {
|
|
57
55
|
commands: items.map(item => item.commands),
|
|
58
56
|
strokes: mapAppearance(
|
|
59
57
|
"color",
|
|
60
|
-
(_, index) => config.stroke ??
|
|
61
|
-
existingValue(existingChildren, index, "stroke", defaults.stroke)
|
|
58
|
+
items.map((_, index) => config.stroke ??
|
|
59
|
+
existingValue(existingChildren, index, "stroke", defaults.stroke))
|
|
62
60
|
),
|
|
63
61
|
strokeWidths: mapAppearance(
|
|
64
62
|
"strokeWidth",
|
|
65
|
-
(_, index) => config.strokeWidth ??
|
|
66
|
-
existingValue(existingChildren, index, "strokeWidth", defaults.strokeWidth)
|
|
63
|
+
items.map((_, index) => config.strokeWidth ??
|
|
64
|
+
existingValue(existingChildren, index, "strokeWidth", defaults.strokeWidth))
|
|
67
65
|
),
|
|
68
66
|
strokeDashes: mapAppearance(
|
|
69
67
|
"strokeDash",
|
|
70
|
-
(_, index) => existingValue(existingChildren, index, "strokeDash", [])
|
|
71
|
-
)
|
|
68
|
+
items.map((_, index) => existingValue(existingChildren, index, "strokeDash", []))
|
|
69
|
+
),
|
|
70
|
+
opacities: mapAppearance("opacity", config.opacity)
|
|
72
71
|
};
|
|
73
72
|
}
|
|
74
73
|
|
|
@@ -116,33 +115,16 @@ export function resolvePositionedLineMaterialization({
|
|
|
116
115
|
config.curve ?? "linear"
|
|
117
116
|
);
|
|
118
117
|
});
|
|
119
|
-
const
|
|
120
|
-
|
|
121
|
-
|
|
122
|
-
|
|
123
|
-
|
|
124
|
-
|
|
125
|
-
:
|
|
126
|
-
|
|
127
|
-
|
|
128
|
-
|
|
129
|
-
|
|
130
|
-
|
|
131
|
-
? commands.map((_, index) => config.strokeWidth ??
|
|
132
|
-
existingValue(existingChildren, index, "strokeWidth", defaults.strokeWidth))
|
|
133
|
-
: mapContinuousScaleValues(
|
|
134
|
-
deriveLineSeriesFieldValues(rows, layer, derived, widthEncoding.field),
|
|
135
|
-
resolvedScales[widthEncoding.scale]
|
|
136
|
-
);
|
|
137
|
-
const strokeDashes = dashEncoding?.datum !== undefined
|
|
138
|
-
? commands.map(() => normalizeStrokeDashPattern(dashEncoding.datum))
|
|
139
|
-
: dashEncoding?.scale === undefined
|
|
140
|
-
? commands.map((_, index) =>
|
|
141
|
-
existingValue(existingChildren, index, "strokeDash", []))
|
|
142
|
-
: mapOrdinalValues(
|
|
143
|
-
derived.series.map(series => series.key[dashEncoding.field]),
|
|
144
|
-
resolvedScales[dashEncoding.scale].domain,
|
|
145
|
-
resolvedScales[dashEncoding.scale].range
|
|
146
|
-
);
|
|
147
|
-
return { commands, strokes, strokeWidths, strokeDashes };
|
|
118
|
+
const appearance = appearanceMapper(layer, resolvedScales,
|
|
119
|
+
(field, channel) => derivePathSeriesFieldValues(rows, derived.series, field, channel));
|
|
120
|
+
return {
|
|
121
|
+
commands,
|
|
122
|
+
strokes: appearance("color", commands.map((_, index) => config.stroke ??
|
|
123
|
+
existingValue(existingChildren, index, "stroke", defaults.stroke))),
|
|
124
|
+
strokeWidths: appearance("strokeWidth", commands.map((_, index) => config.strokeWidth ??
|
|
125
|
+
existingValue(existingChildren, index, "strokeWidth", defaults.strokeWidth))),
|
|
126
|
+
strokeDashes: appearance("strokeDash", commands.map((_, index) =>
|
|
127
|
+
existingValue(existingChildren, index, "strokeDash", []))),
|
|
128
|
+
opacities: appearance("opacity", config.opacity)
|
|
129
|
+
};
|
|
148
130
|
}
|
|
@@ -6,7 +6,7 @@ import {
|
|
|
6
6
|
validateUnitInterval
|
|
7
7
|
} from "../../../core/validation.js";
|
|
8
8
|
import { validatePointShape } from "../../../grammar/pointShapes.js";
|
|
9
|
-
import {
|
|
9
|
+
import { resolveEligibleLayer } from "../../../selectors/layers.js";
|
|
10
10
|
import { rematerializeExistingLegend } from "../../encodings/shared.js";
|
|
11
11
|
import { validateMarkOptions } from "../shared.js";
|
|
12
12
|
|
|
@@ -27,20 +27,13 @@ export const editPointMark = action(
|
|
|
27
27
|
"editPointMark requires shape, fill, opacity, stroke, or strokeWidth."
|
|
28
28
|
);
|
|
29
29
|
}
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
const
|
|
37
|
-
? candidates[0].id
|
|
38
|
-
: undefined);
|
|
39
|
-
const id = validateUserId(inferred, "Point mark id");
|
|
40
|
-
const layer = findLayer(this, id);
|
|
41
|
-
if (layer?.mark?.type !== "point") {
|
|
42
|
-
throw new Error(`Unknown point mark "${id}".`);
|
|
43
|
-
}
|
|
30
|
+
if (args.target !== undefined) validateUserId(args.target, "Point mark id");
|
|
31
|
+
const layer = resolveEligibleLayer(this, {
|
|
32
|
+
target: args.target,
|
|
33
|
+
predicate: candidate => candidate.mark?.type === "point",
|
|
34
|
+
label: "point mark"
|
|
35
|
+
});
|
|
36
|
+
const id = layer.id;
|
|
44
37
|
if (Object.hasOwn(args, "shape") && layer.encoding?.shape !== undefined) {
|
|
45
38
|
throw new Error(
|
|
46
39
|
"editPointMark shape cannot be combined with a shape encoding."
|
|
@@ -51,6 +44,9 @@ export const editPointMark = action(
|
|
|
51
44
|
"editPointMark fill cannot be combined with a color encoding."
|
|
52
45
|
);
|
|
53
46
|
}
|
|
47
|
+
if (Object.hasOwn(args, "opacity") && layer.encoding?.opacity?.field !== undefined) {
|
|
48
|
+
throw new Error("editPointMark opacity conflicts with a field encoding; use encodeOpacity with value to replace it.");
|
|
49
|
+
}
|
|
54
50
|
const config = { ...this.markConfigs[id] };
|
|
55
51
|
if (Object.hasOwn(args, "shape")) {
|
|
56
52
|
config.shape = validatePointShape(args.shape);
|
|
@@ -3,6 +3,7 @@ import { editPointMark } from "./edit.js";
|
|
|
3
3
|
import { rematerializePointMark } from "./materialize.js";
|
|
4
4
|
|
|
5
5
|
export { registerPointJitterActions } from "./jitter.js";
|
|
6
|
+
export { registerPointPackingActions } from "./packing.js";
|
|
6
7
|
|
|
7
8
|
export function registerPointMarkActions(ProgramClass) {
|
|
8
9
|
ProgramClass.prototype.editPointMark = editPointMark;
|
|
@@ -37,6 +37,9 @@ export const jitterPoints = action(
|
|
|
37
37
|
validateKeys(args, JITTER_OPTIONS, "jitterPoints");
|
|
38
38
|
const policy = normalizePointJitterPolicy(args);
|
|
39
39
|
const layer = resolveJitterTarget(this, args.target, policy.channel);
|
|
40
|
+
if (this.materializationConfigs.pointPacking?.[layer.id] !== undefined) {
|
|
41
|
+
throw new Error(`Point jitter on "${layer.id}" conflicts with point packing.`);
|
|
42
|
+
}
|
|
40
43
|
return this
|
|
41
44
|
._withMaterializationConfig(["jitters", layer.id], policy)
|
|
42
45
|
.rematerializePointMark({ id: layer.id });
|