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
|
@@ -19,7 +19,11 @@ import { DEFAULT_COLORS } from "../../../theme/defaults.js";
|
|
|
19
19
|
import { findDataset } from "../../../selectors/datasets.js";
|
|
20
20
|
import { findLayer, resolveEligibleLayer } from "../../../selectors/layers.js";
|
|
21
21
|
import { validateCurveInterpolation } from "../../../grammar/curveCommands.js";
|
|
22
|
-
import {
|
|
22
|
+
import {
|
|
23
|
+
resolveCoordinateBounds,
|
|
24
|
+
resolveCoordinatePolarFrame
|
|
25
|
+
} from "../../../materialization/coordinateBounds.js";
|
|
26
|
+
import { rematerializeExistingLegend } from "../../encodings/shared.js";
|
|
23
27
|
import { canMaterializeLine } from "../../../materialization/marks/index.js";
|
|
24
28
|
import { resolveMarkGraphicPlacement } from
|
|
25
29
|
"../../../materialization/graphicHierarchy.js";
|
|
@@ -31,14 +35,20 @@ import {
|
|
|
31
35
|
} from "./materialize.js";
|
|
32
36
|
import { resolveLineBins } from "../../../grammar/lineSeries.js";
|
|
33
37
|
import { requireSemanticScale } from "../../../selectors/scales.js";
|
|
38
|
+
import {
|
|
39
|
+
requestedStrokeDetails,
|
|
40
|
+
STROKE_STYLE_PROPERTIES
|
|
41
|
+
} from "../../../grammar/strokeStyle.js";
|
|
34
42
|
|
|
35
43
|
const DEFAULT_LINE_STROKE = DEFAULT_COLORS.mark;
|
|
36
44
|
const DEFAULT_LINE_WIDTH = 2;
|
|
37
45
|
const CREATE_OPTIONS = Object.freeze([
|
|
38
|
-
"id", "data", "stroke", "strokeWidth", "opacity", "curve", "closed"
|
|
46
|
+
"id", "data", "stroke", "strokeWidth", "opacity", "curve", "closed",
|
|
47
|
+
...STROKE_STYLE_PROPERTIES
|
|
39
48
|
]);
|
|
40
49
|
const EDIT_OPTIONS = Object.freeze([
|
|
41
|
-
"target", "stroke", "strokeWidth", "opacity", "curve", "closed"
|
|
50
|
+
"target", "stroke", "strokeWidth", "opacity", "curve", "closed",
|
|
51
|
+
...STROKE_STYLE_PROPERTIES
|
|
42
52
|
]);
|
|
43
53
|
const REMATERIALIZE_OPTIONS = Object.freeze(["id", "scales"]);
|
|
44
54
|
|
|
@@ -71,14 +81,15 @@ function validatePolarLineConfig(layer, config) {
|
|
|
71
81
|
}
|
|
72
82
|
}
|
|
73
83
|
|
|
74
|
-
function applyLineMaterialization(program, id, materialization) {
|
|
84
|
+
function applyLineMaterialization(program, id, materialization, config) {
|
|
75
85
|
return editMarkGraphic(program, id, {
|
|
76
86
|
length: materialization.commands.length,
|
|
77
87
|
commands: materialization.commands,
|
|
78
88
|
stroke: materialization.strokes,
|
|
79
89
|
strokeWidth: materialization.strokeWidths,
|
|
80
90
|
strokeDash: materialization.strokeDashes,
|
|
81
|
-
...(materialization.opacities === undefined ? {} : { opacity: materialization.opacities })
|
|
91
|
+
...(materialization.opacities === undefined ? {} : { opacity: materialization.opacities }),
|
|
92
|
+
...requestedStrokeDetails(config, "Line mark")
|
|
82
93
|
});
|
|
83
94
|
}
|
|
84
95
|
|
|
@@ -89,6 +100,7 @@ const createLineMark = action(
|
|
|
89
100
|
},
|
|
90
101
|
function (args = {}) {
|
|
91
102
|
validateMarkOptions(args, CREATE_OPTIONS, "createLineMark");
|
|
103
|
+
const strokeDetails = requestedStrokeDetails(args, "createLineMark");
|
|
92
104
|
const id = resolveMarkId(this, args.id, {
|
|
93
105
|
defaultId: "line",
|
|
94
106
|
label: "Line mark id",
|
|
@@ -139,7 +151,8 @@ const createLineMark = action(
|
|
|
139
151
|
{
|
|
140
152
|
...(Object.hasOwn(args, "strokeWidth") ? { strokeWidth } : {}),
|
|
141
153
|
...(Object.hasOwn(args, "curve") ? { curve } : {}),
|
|
142
|
-
...(Object.hasOwn(args, "closed") ? { closed } : {})
|
|
154
|
+
...(Object.hasOwn(args, "closed") ? { closed } : {}),
|
|
155
|
+
...strokeDetails
|
|
143
156
|
}
|
|
144
157
|
);
|
|
145
158
|
created = materializeInheritedMark(created, id);
|
|
@@ -214,7 +227,7 @@ const rematerializeLineMark = action(
|
|
|
214
227
|
}
|
|
215
228
|
let resolved = this;
|
|
216
229
|
if (args.scales !== false) {
|
|
217
|
-
const appearance = ["color", "strokeDash", "strokeWidth", "opacity"]
|
|
230
|
+
const appearance = ["color", "stroke", "strokeDash", "strokeWidth", "opacity"]
|
|
218
231
|
.map(channel => layer.encoding?.[channel]?.scale).filter(scale => scale !== undefined);
|
|
219
232
|
for (const scale of [...positions, ...appearance]) {
|
|
220
233
|
resolved = resolved.rematerializeScale({ id: scale });
|
|
@@ -223,12 +236,12 @@ const rematerializeLineMark = action(
|
|
|
223
236
|
const shared = {
|
|
224
237
|
rows: dataset.values, layer, config, existingChildren,
|
|
225
238
|
resolvedScales: resolved.resolvedScales,
|
|
226
|
-
bounds:
|
|
239
|
+
bounds: resolveCoordinateBounds(resolved, layer.coordinate),
|
|
227
240
|
defaults: { stroke: DEFAULT_LINE_STROKE, strokeWidth: DEFAULT_LINE_WIDTH }
|
|
228
241
|
};
|
|
229
242
|
if (parallel !== undefined) {
|
|
230
243
|
return applyLineMaterialization(resolved, id,
|
|
231
|
-
resolveParallelLineMaterialization({ ...shared, parallel }));
|
|
244
|
+
resolveParallelLineMaterialization({ ...shared, parallel }), config);
|
|
232
245
|
}
|
|
233
246
|
|
|
234
247
|
const materialization = resolvePositionedLineMaterialization({
|
|
@@ -240,13 +253,17 @@ const rematerializeLineMark = action(
|
|
|
240
253
|
layer,
|
|
241
254
|
requireSemanticScale(resolved, xScaleId)
|
|
242
255
|
).boundaries,
|
|
243
|
-
polar
|
|
256
|
+
polar,
|
|
257
|
+
...(polar
|
|
258
|
+
? { polarFrame: resolveCoordinatePolarFrame(resolved, layer.coordinate) }
|
|
259
|
+
: {})
|
|
244
260
|
});
|
|
245
261
|
|
|
246
262
|
return applyLineMaterialization(
|
|
247
263
|
resolved,
|
|
248
264
|
id,
|
|
249
|
-
materialization
|
|
265
|
+
materialization,
|
|
266
|
+
config
|
|
250
267
|
);
|
|
251
268
|
}
|
|
252
269
|
);
|
|
@@ -258,6 +275,7 @@ const editLineMark = action(
|
|
|
258
275
|
},
|
|
259
276
|
function (args = {}) {
|
|
260
277
|
validateMarkOptions(args, EDIT_OPTIONS, "editLineMark");
|
|
278
|
+
const strokeDetails = requestedStrokeDetails(args, "editLineMark");
|
|
261
279
|
if (!EDIT_OPTIONS.slice(1).some(key => Object.hasOwn(args, key))) {
|
|
262
280
|
throw new Error("editLineMark requires stroke, strokeWidth, opacity, curve, or closed.");
|
|
263
281
|
}
|
|
@@ -269,9 +287,12 @@ const editLineMark = action(
|
|
|
269
287
|
predicate: candidate => candidate.mark?.type === "line",
|
|
270
288
|
label: "line mark"
|
|
271
289
|
});
|
|
272
|
-
if (Object.hasOwn(args, "stroke") &&
|
|
290
|
+
if (Object.hasOwn(args, "stroke") && (
|
|
291
|
+
layer.encoding?.color !== undefined ||
|
|
292
|
+
layer.encoding?.stroke !== undefined
|
|
293
|
+
)) {
|
|
273
294
|
throw new Error(
|
|
274
|
-
"editLineMark stroke cannot be combined with a color encoding."
|
|
295
|
+
"editLineMark stroke cannot be combined with a color encoding or a stroke encoding; use encodeStroke with value to replace it."
|
|
275
296
|
);
|
|
276
297
|
}
|
|
277
298
|
for (const channel of ["strokeWidth", "opacity"]) {
|
|
@@ -284,6 +305,7 @@ const editLineMark = action(
|
|
|
284
305
|
throw new Error("Line closed requires theta/radius Polar position encodings.");
|
|
285
306
|
}
|
|
286
307
|
const config = { ...this.markConfigs[layer.id] };
|
|
308
|
+
Object.assign(config, strokeDetails);
|
|
287
309
|
for (const [key, validate] of Object.entries({
|
|
288
310
|
stroke: validateNonEmptyString,
|
|
289
311
|
strokeWidth: validateNonNegativeFinite,
|
|
@@ -295,9 +317,10 @@ const editLineMark = action(
|
|
|
295
317
|
}
|
|
296
318
|
validatePolarLineConfig(layer, config);
|
|
297
319
|
const next = this._withMarkConfig(layer.id, config);
|
|
298
|
-
|
|
320
|
+
const materialized = canMaterializeLine(next, layer)
|
|
299
321
|
? next.rematerializeLineMark({ id: layer.id })
|
|
300
322
|
: next;
|
|
323
|
+
return rematerializeExistingLegend(materialized);
|
|
301
324
|
}
|
|
302
325
|
);
|
|
303
326
|
|
|
@@ -27,7 +27,11 @@ function appearanceMapper(layer, scales, fieldValues) {
|
|
|
27
27
|
return fallback.map(() => normalizeStrokeDashPattern(encoding.datum));
|
|
28
28
|
}
|
|
29
29
|
if (encoding?.scale === undefined) return fallback;
|
|
30
|
-
return mapScaleConsumerValues(
|
|
30
|
+
return mapScaleConsumerValues(
|
|
31
|
+
fieldValues(encoding.field, channel, encoding),
|
|
32
|
+
scales[encoding.scale],
|
|
33
|
+
channel
|
|
34
|
+
);
|
|
31
35
|
};
|
|
32
36
|
}
|
|
33
37
|
|
|
@@ -53,11 +57,15 @@ export function resolveParallelLineMaterialization({
|
|
|
53
57
|
field => sourceRows.map(row => row[field]));
|
|
54
58
|
return {
|
|
55
59
|
commands: items.map(item => item.commands),
|
|
56
|
-
strokes:
|
|
57
|
-
"
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
|
|
60
|
+
strokes: layer.encoding?.stroke?.scale !== undefined
|
|
61
|
+
? mapAppearance("stroke", items.map(() => defaults.stroke))
|
|
62
|
+
: config.stroke !== undefined
|
|
63
|
+
? items.map(() => config.stroke)
|
|
64
|
+
: mapAppearance(
|
|
65
|
+
"color",
|
|
66
|
+
items.map((_, index) =>
|
|
67
|
+
existingValue(existingChildren, index, "stroke", defaults.stroke))
|
|
68
|
+
),
|
|
61
69
|
strokeWidths: mapAppearance(
|
|
62
70
|
"strokeWidth",
|
|
63
71
|
items.map((_, index) => config.strokeWidth ??
|
|
@@ -80,6 +88,7 @@ export function resolvePositionedLineMaterialization({
|
|
|
80
88
|
config,
|
|
81
89
|
existingChildren,
|
|
82
90
|
polar,
|
|
91
|
+
polarFrame,
|
|
83
92
|
defaults
|
|
84
93
|
}) {
|
|
85
94
|
const xScaleId = layer.encoding?.x?.scale;
|
|
@@ -98,7 +107,7 @@ export function resolvePositionedLineMaterialization({
|
|
|
98
107
|
thetaFieldType: derived.thetaFieldType,
|
|
99
108
|
thetaScale: resolvedScales[thetaScaleId],
|
|
100
109
|
radiusScale: resolvedScales[radiusScaleId],
|
|
101
|
-
frame: resolvePolarFrame(bounds),
|
|
110
|
+
frame: polarFrame ?? resolvePolarFrame(bounds),
|
|
102
111
|
closed: config.closed ?? false
|
|
103
112
|
}))
|
|
104
113
|
: derived.series.map(series => {
|
|
@@ -116,11 +125,21 @@ export function resolvePositionedLineMaterialization({
|
|
|
116
125
|
);
|
|
117
126
|
});
|
|
118
127
|
const appearance = appearanceMapper(layer, resolvedScales,
|
|
119
|
-
(field, channel) => derivePathSeriesFieldValues(
|
|
128
|
+
(field, channel, encoding) => derivePathSeriesFieldValues(
|
|
129
|
+
rows,
|
|
130
|
+
derived.series,
|
|
131
|
+
field,
|
|
132
|
+
channel,
|
|
133
|
+
encoding
|
|
134
|
+
));
|
|
120
135
|
return {
|
|
121
136
|
commands,
|
|
122
|
-
strokes:
|
|
123
|
-
|
|
137
|
+
strokes: layer.encoding?.stroke?.scale !== undefined
|
|
138
|
+
? appearance("stroke", commands.map(() => defaults.stroke))
|
|
139
|
+
: config.stroke !== undefined
|
|
140
|
+
? commands.map(() => config.stroke)
|
|
141
|
+
: appearance("color", commands.map((_, index) =>
|
|
142
|
+
existingValue(existingChildren, index, "stroke", defaults.stroke))),
|
|
124
143
|
strokeWidths: appearance("strokeWidth", commands.map((_, index) => config.strokeWidth ??
|
|
125
144
|
existingValue(existingChildren, index, "strokeWidth", defaults.strokeWidth))),
|
|
126
145
|
strokeDashes: appearance("strokeDash", commands.map((_, index) =>
|
|
@@ -1,6 +1,10 @@
|
|
|
1
1
|
import { action } from "../../../core/action.js";
|
|
2
2
|
import { validatePointShape } from "../../../grammar/pointShapes.js";
|
|
3
3
|
import { getPointGraphicType } from "../../../grammar/schemas/mark.js";
|
|
4
|
+
import {
|
|
5
|
+
requestedStrokeDetails,
|
|
6
|
+
STROKE_STYLE_PROPERTIES
|
|
7
|
+
} from "../../../grammar/strokeStyle.js";
|
|
4
8
|
import { resolveMarkGraphicPlacement } from
|
|
5
9
|
"../../../materialization/graphicHierarchy.js";
|
|
6
10
|
import {
|
|
@@ -14,7 +18,8 @@ import {
|
|
|
14
18
|
} from "../shared.js";
|
|
15
19
|
|
|
16
20
|
const OPTIONS = Object.freeze([
|
|
17
|
-
"id", "data", "shape", "fill", "opacity", "stroke", "strokeWidth"
|
|
21
|
+
"id", "data", "shape", "fill", "opacity", "stroke", "strokeWidth",
|
|
22
|
+
...STROKE_STYLE_PROPERTIES
|
|
18
23
|
]);
|
|
19
24
|
|
|
20
25
|
export const createPointMark = action(
|
|
@@ -24,6 +29,7 @@ export const createPointMark = action(
|
|
|
24
29
|
},
|
|
25
30
|
function (args = {}) {
|
|
26
31
|
validateMarkOptions(args, OPTIONS, "createPointMark");
|
|
32
|
+
requestedStrokeDetails(args, "createPointMark");
|
|
27
33
|
const id = resolveMarkId(this, args.id, {
|
|
28
34
|
defaultId: "point",
|
|
29
35
|
label: "Point mark id",
|
|
@@ -65,7 +71,7 @@ export const createPointMark = action(
|
|
|
65
71
|
._withMarkConfig(id, { shape });
|
|
66
72
|
const created = materializeInheritedMark(next, id);
|
|
67
73
|
const appearance = Object.fromEntries(
|
|
68
|
-
["fill", "opacity", "stroke", "strokeWidth"]
|
|
74
|
+
["fill", "opacity", "stroke", "strokeWidth", ...STROKE_STYLE_PROPERTIES]
|
|
69
75
|
.filter(property => Object.hasOwn(args, property))
|
|
70
76
|
.map(property => [property, args[property]])
|
|
71
77
|
);
|
|
@@ -6,12 +6,17 @@ import {
|
|
|
6
6
|
validateUnitInterval
|
|
7
7
|
} from "../../../core/validation.js";
|
|
8
8
|
import { validatePointShape } from "../../../grammar/pointShapes.js";
|
|
9
|
+
import {
|
|
10
|
+
requestedStrokeDetails,
|
|
11
|
+
STROKE_STYLE_PROPERTIES
|
|
12
|
+
} from "../../../grammar/strokeStyle.js";
|
|
9
13
|
import { resolveEligibleLayer } from "../../../selectors/layers.js";
|
|
10
14
|
import { rematerializeExistingLegend } from "../../encodings/shared.js";
|
|
11
15
|
import { validateMarkOptions } from "../shared.js";
|
|
12
16
|
|
|
13
17
|
const OPTIONS = Object.freeze([
|
|
14
|
-
"target", "shape", "fill", "opacity", "stroke", "strokeWidth"
|
|
18
|
+
"target", "shape", "fill", "opacity", "stroke", "strokeWidth",
|
|
19
|
+
...STROKE_STYLE_PROPERTIES
|
|
15
20
|
]);
|
|
16
21
|
|
|
17
22
|
export const editPointMark = action(
|
|
@@ -21,7 +26,11 @@ export const editPointMark = action(
|
|
|
21
26
|
},
|
|
22
27
|
function (args = {}) {
|
|
23
28
|
validateMarkOptions(args, OPTIONS, "editPointMark");
|
|
24
|
-
const
|
|
29
|
+
const strokeDetails = requestedStrokeDetails(args, "editPointMark");
|
|
30
|
+
const editable = [
|
|
31
|
+
"shape", "fill", "opacity", "stroke", "strokeWidth",
|
|
32
|
+
...STROKE_STYLE_PROPERTIES
|
|
33
|
+
];
|
|
25
34
|
if (!editable.some(property => Object.hasOwn(args, property))) {
|
|
26
35
|
throw new Error(
|
|
27
36
|
"editPointMark requires shape, fill, opacity, stroke, or strokeWidth."
|
|
@@ -44,10 +53,16 @@ export const editPointMark = action(
|
|
|
44
53
|
"editPointMark fill cannot be combined with a color encoding."
|
|
45
54
|
);
|
|
46
55
|
}
|
|
56
|
+
if (Object.hasOwn(args, "stroke") && layer.encoding?.stroke !== undefined) {
|
|
57
|
+
throw new Error(
|
|
58
|
+
"editPointMark stroke conflicts with a field encoding; use encodeStroke with value to replace it."
|
|
59
|
+
);
|
|
60
|
+
}
|
|
47
61
|
if (Object.hasOwn(args, "opacity") && layer.encoding?.opacity?.field !== undefined) {
|
|
48
62
|
throw new Error("editPointMark opacity conflicts with a field encoding; use encodeOpacity with value to replace it.");
|
|
49
63
|
}
|
|
50
64
|
const config = { ...this.markConfigs[id] };
|
|
65
|
+
Object.assign(config, strokeDetails);
|
|
51
66
|
if (Object.hasOwn(args, "shape")) {
|
|
52
67
|
config.shape = validatePointShape(args.shape);
|
|
53
68
|
}
|
|
@@ -85,9 +100,6 @@ export const editPointMark = action(
|
|
|
85
100
|
const next = this
|
|
86
101
|
._withMarkConfig(id, config)
|
|
87
102
|
.rematerializePointMark({ id });
|
|
88
|
-
|
|
89
|
-
return legend?.target === id && legend.channels.includes("shape")
|
|
90
|
-
? rematerializeExistingLegend(next)
|
|
91
|
-
: next;
|
|
103
|
+
return rematerializeExistingLegend(next);
|
|
92
104
|
}
|
|
93
105
|
);
|
|
@@ -15,9 +15,12 @@ import {
|
|
|
15
15
|
normalizePointPackingPolicy,
|
|
16
16
|
resolvePointPacking
|
|
17
17
|
} from "../../../grammar/pointPacking.js";
|
|
18
|
-
import { polarToCartesian
|
|
18
|
+
import { polarToCartesian } from "../../../grammar/polar.js";
|
|
19
19
|
import { resolveDirectionValues } from "../../../grammar/direction.js";
|
|
20
|
-
import {
|
|
20
|
+
import {
|
|
21
|
+
resolveCoordinateBounds,
|
|
22
|
+
resolveCoordinatePolarFrame
|
|
23
|
+
} from "../../../materialization/coordinateBounds.js";
|
|
21
24
|
import { validateMarkOptions } from "../shared.js";
|
|
22
25
|
import {
|
|
23
26
|
DEFAULT_COLORS,
|
|
@@ -34,6 +37,8 @@ import {
|
|
|
34
37
|
"../../../materialization/rowEncoding.js";
|
|
35
38
|
import { offsetCategoryPositions } from
|
|
36
39
|
"../../../materialization/categorySlotOffset.js";
|
|
40
|
+
import { requestedStrokeDetails } from
|
|
41
|
+
"../../../grammar/strokeStyle.js";
|
|
37
42
|
|
|
38
43
|
const REMATERIALIZE_OPTIONS = Object.freeze(["id"]);
|
|
39
44
|
const DEFAULT_POINT_FILL = DEFAULT_COLORS.mark;
|
|
@@ -52,7 +57,7 @@ function resolvePointPositions(program, layer, dataset) {
|
|
|
52
57
|
if (theta === undefined || radius === undefined) {
|
|
53
58
|
return { x: undefined, y: undefined };
|
|
54
59
|
}
|
|
55
|
-
const frame =
|
|
60
|
+
const frame = resolveCoordinatePolarFrame(program, layer.coordinate);
|
|
56
61
|
const positions = theta.map((angle, index) => {
|
|
57
62
|
const distance = radius[index];
|
|
58
63
|
return Number.isFinite(angle) && Number.isFinite(distance)
|
|
@@ -76,7 +81,11 @@ function incompleteShapeGraphic(shape, properties, angle) {
|
|
|
76
81
|
? "path"
|
|
77
82
|
: getPointGraphicType(shape);
|
|
78
83
|
const incomplete = type === "path"
|
|
79
|
-
? {
|
|
84
|
+
? {
|
|
85
|
+
fill: properties.fill,
|
|
86
|
+
opacity: properties.opacity,
|
|
87
|
+
...requestedStrokeDetails(properties, "Point mark")
|
|
88
|
+
}
|
|
80
89
|
: properties;
|
|
81
90
|
return { type, properties: compactProperties(incomplete) };
|
|
82
91
|
}
|
|
@@ -180,7 +189,7 @@ function applyPointJitter(program, {
|
|
|
180
189
|
`Point jitter on "${id}" requires a resolved ${policy.channel} scale.`
|
|
181
190
|
);
|
|
182
191
|
}
|
|
183
|
-
const bounds =
|
|
192
|
+
const bounds = resolveCoordinateBounds(program, layer.coordinate);
|
|
184
193
|
const entries = resolveJitterEntries({
|
|
185
194
|
policy,
|
|
186
195
|
dataset,
|
|
@@ -270,7 +279,7 @@ function applyPointPacking(program, {
|
|
|
270
279
|
fixedHalfExtent: extent[policy.channel === "x" ? "y" : "x"]
|
|
271
280
|
}];
|
|
272
281
|
});
|
|
273
|
-
const bounds =
|
|
282
|
+
const bounds = resolveCoordinateBounds(program, layer.coordinate);
|
|
274
283
|
const resolution = resolvePointPacking({
|
|
275
284
|
target: id,
|
|
276
285
|
policy,
|
|
@@ -338,6 +347,7 @@ export const rematerializePointMark = action(
|
|
|
338
347
|
|
|
339
348
|
const positions = resolvePointPositions(resolved, layer, dataset);
|
|
340
349
|
const mappedFill = resolveRowEncodingValues(resolved, layer, dataset, "color");
|
|
350
|
+
const mappedStroke = resolveRowEncodingValues(resolved, layer, dataset, "stroke");
|
|
341
351
|
const area = resolveRowEncodingValues(resolved, layer, dataset, "size");
|
|
342
352
|
const encodedShape = resolveRowEncodingValues(resolved, layer, dataset, "shape");
|
|
343
353
|
const encodedOpacity = resolveRowEncodingValues(
|
|
@@ -348,6 +358,7 @@ export const rematerializePointMark = action(
|
|
|
348
358
|
);
|
|
349
359
|
const angles = resolveDirectionValues(dataset.values, layer.encoding?.angle);
|
|
350
360
|
const config = resolved.markConfigs[id] ?? {};
|
|
361
|
+
const strokeDetails = requestedStrokeDetails(config, "Point mark");
|
|
351
362
|
const fill = mappedFill ?? config.fill ?? DEFAULT_POINT_FILL;
|
|
352
363
|
const shapes = encodedShape ?? dataset.values.map(() => config.shape ?? "circle");
|
|
353
364
|
const existingChildren = graphic.items ?? [];
|
|
@@ -417,7 +428,8 @@ export const rematerializePointMark = action(
|
|
|
417
428
|
x: centerX,
|
|
418
429
|
y: centerY,
|
|
419
430
|
fill: color,
|
|
420
|
-
opacity
|
|
431
|
+
opacity,
|
|
432
|
+
...strokeDetails
|
|
421
433
|
}, angle);
|
|
422
434
|
}
|
|
423
435
|
return createPointShapeGraphic({
|
|
@@ -426,12 +438,15 @@ export const rematerializePointMark = action(
|
|
|
426
438
|
y: centerY,
|
|
427
439
|
area: resolvedArea,
|
|
428
440
|
fill: color,
|
|
429
|
-
...(typeof config.stroke === "string"
|
|
430
|
-
|
|
431
|
-
|
|
432
|
-
|
|
441
|
+
...(typeof (mappedStroke?.[index] ?? config.stroke) === "string"
|
|
442
|
+
? { stroke: mappedStroke?.[index] ?? config.stroke }
|
|
443
|
+
: {}),
|
|
444
|
+
...((mappedStroke !== undefined || config.strokeWidth !== undefined)
|
|
445
|
+
? { strokeWidth: config.strokeWidth ?? 1 }
|
|
446
|
+
: {}),
|
|
433
447
|
opacity,
|
|
434
|
-
angle
|
|
448
|
+
angle,
|
|
449
|
+
...strokeDetails
|
|
435
450
|
});
|
|
436
451
|
});
|
|
437
452
|
return jittered.program.editGraphics({
|
|
@@ -503,15 +518,31 @@ export const rematerializePointMark = action(
|
|
|
503
518
|
next = next
|
|
504
519
|
.editGraphics({ target: id, property: "width", value: sides })
|
|
505
520
|
.editGraphics({ target: id, property: "height", value: sides })
|
|
506
|
-
.editGraphics({
|
|
507
|
-
|
|
521
|
+
.editGraphics({
|
|
522
|
+
target: id,
|
|
523
|
+
property: "stroke",
|
|
524
|
+
value: mappedStroke ?? fill ?? DEFAULT_POINT_FILL
|
|
525
|
+
})
|
|
526
|
+
.editGraphics({
|
|
527
|
+
target: id,
|
|
528
|
+
property: "strokeWidth",
|
|
529
|
+
value: mappedStroke === undefined ? 0 : config.strokeWidth ?? 1
|
|
530
|
+
});
|
|
508
531
|
}
|
|
509
532
|
if (config.opacity !== undefined) {
|
|
510
533
|
next = next.editGraphics({ target: id, property: "opacity", value: config.opacity });
|
|
511
534
|
} else if (encodedOpacity !== undefined) {
|
|
512
535
|
next = next.editGraphics({ target: id, property: "opacity", value: encodedOpacity });
|
|
513
536
|
}
|
|
514
|
-
if (
|
|
537
|
+
if (mappedStroke !== undefined) {
|
|
538
|
+
next = next
|
|
539
|
+
.editGraphics({ target: id, property: "stroke", value: mappedStroke })
|
|
540
|
+
.editGraphics({
|
|
541
|
+
target: id,
|
|
542
|
+
property: "strokeWidth",
|
|
543
|
+
value: config.strokeWidth ?? 1
|
|
544
|
+
});
|
|
545
|
+
} else if (config.stroke === false) {
|
|
515
546
|
next = next
|
|
516
547
|
.editGraphics({ target: id, property: "stroke", value: "transparent" })
|
|
517
548
|
.editGraphics({ target: id, property: "strokeWidth", value: 0 });
|
|
@@ -523,6 +554,9 @@ export const rematerializePointMark = action(
|
|
|
523
554
|
value: config.strokeWidth
|
|
524
555
|
});
|
|
525
556
|
}
|
|
557
|
+
for (const [property, value] of Object.entries(strokeDetails)) {
|
|
558
|
+
next = next.editGraphics({ target: id, property, value });
|
|
559
|
+
}
|
|
526
560
|
return next;
|
|
527
561
|
}
|
|
528
562
|
);
|
|
@@ -19,12 +19,20 @@ import {
|
|
|
19
19
|
resolveMarkId,
|
|
20
20
|
validateMarkOptions
|
|
21
21
|
} from "../shared.js";
|
|
22
|
+
import { replaceGraphicItems } from "../../primitives/editGraphics.js";
|
|
22
23
|
import { resolveMarkGraphicPlacement } from
|
|
23
24
|
"../../../materialization/graphicHierarchy.js";
|
|
25
|
+
import { rematerializeExistingLegend } from "../../encodings/shared.js";
|
|
24
26
|
import { rematerializeHighlightBaseline } from "../lifecycle.js";
|
|
27
|
+
import {
|
|
28
|
+
requestedRectStyleDetails
|
|
29
|
+
} from "../../../grammar/roundedRect.js";
|
|
30
|
+
import { STROKE_STYLE_PROPERTIES } from
|
|
31
|
+
"../../../grammar/strokeStyle.js";
|
|
25
32
|
|
|
26
33
|
const STYLE_OPTIONS = Object.freeze([
|
|
27
|
-
"fill", "opacity", "stroke", "strokeWidth"
|
|
34
|
+
"fill", "opacity", "stroke", "strokeWidth", "cornerRadius",
|
|
35
|
+
...STROKE_STYLE_PROPERTIES
|
|
28
36
|
]);
|
|
29
37
|
const CREATE_OPTIONS = Object.freeze(["id", "data", ...STYLE_OPTIONS]);
|
|
30
38
|
const EDIT_OPTIONS = Object.freeze(["target", ...STYLE_OPTIONS]);
|
|
@@ -45,6 +53,7 @@ const createRectMark = action(
|
|
|
45
53
|
{ op: "createRectMark", description: "Create a semantic rectangular cell layer." },
|
|
46
54
|
function (args = {}) {
|
|
47
55
|
validateMarkOptions(args, CREATE_OPTIONS, "createRectMark");
|
|
56
|
+
requestedRectStyleDetails(args, "createRectMark");
|
|
48
57
|
const id = resolveMarkId(this, args.id, {
|
|
49
58
|
defaultId: "rect",
|
|
50
59
|
label: "Rect mark id",
|
|
@@ -99,7 +108,13 @@ const rematerializeRectMark = action(
|
|
|
99
108
|
const layer = findLayer(this, id);
|
|
100
109
|
const graphic = this.graphicSpec.objects[id];
|
|
101
110
|
if (layer?.mark?.type !== "rect") throw new Error(`Unknown rect mark "${id}".`);
|
|
102
|
-
|
|
111
|
+
const roundedCollection = graphic?.type === "collection" &&
|
|
112
|
+
Object.hasOwn(this.markConfigs[id] ?? {}, "cornerRadius") &&
|
|
113
|
+
graphic.items?.every(item => ["rect", "path"].includes(item.type));
|
|
114
|
+
if (
|
|
115
|
+
(graphic?.type !== "rect" && !roundedCollection) ||
|
|
116
|
+
!Array.isArray(graphic.items)
|
|
117
|
+
) {
|
|
103
118
|
throw new Error(`Rect mark "${id}" requires rect collection graphics.`);
|
|
104
119
|
}
|
|
105
120
|
if (this.markConfigs[id]?.gradientPlot?.materialized === true) {
|
|
@@ -110,13 +125,11 @@ const rematerializeRectMark = action(
|
|
|
110
125
|
throw new Error(`Rect mark "${id}" requires an existing dataset.`);
|
|
111
126
|
}
|
|
112
127
|
if (!canMaterializeRect(this, layer)) {
|
|
113
|
-
return
|
|
114
|
-
? this
|
|
115
|
-
: this.editGraphics({ target: id, property: "items", value: [] });
|
|
128
|
+
return replaceGraphicItems(this, id, "rect", []);
|
|
116
129
|
}
|
|
117
130
|
let next = this;
|
|
118
131
|
if (args.scales !== false) {
|
|
119
|
-
const ids = new Set(["x", "y", "x2", "y2", "color"].flatMap(channel => {
|
|
132
|
+
const ids = new Set(["x", "y", "x2", "y2", "color", "stroke"].flatMap(channel => {
|
|
120
133
|
const scale = layer.encoding?.[channel]?.scale;
|
|
121
134
|
return scale === undefined ? [] : [scale];
|
|
122
135
|
}));
|
|
@@ -124,11 +137,12 @@ const rematerializeRectMark = action(
|
|
|
124
137
|
next = next.rematerializeScale({ id: scale, marks: false });
|
|
125
138
|
}
|
|
126
139
|
}
|
|
127
|
-
return
|
|
128
|
-
|
|
129
|
-
|
|
130
|
-
|
|
131
|
-
|
|
140
|
+
return replaceGraphicItems(
|
|
141
|
+
next,
|
|
142
|
+
id,
|
|
143
|
+
"rect",
|
|
144
|
+
resolveRectGraphicItems(next, layer, dataset)
|
|
145
|
+
);
|
|
132
146
|
}
|
|
133
147
|
);
|
|
134
148
|
|
|
@@ -136,6 +150,7 @@ const editRectMark = action(
|
|
|
136
150
|
{ op: "editRectMark", description: "Edit rectangular cell appearance." },
|
|
137
151
|
function (args = {}) {
|
|
138
152
|
validateMarkOptions(args, EDIT_OPTIONS, "editRectMark");
|
|
153
|
+
requestedRectStyleDetails(args, "editRectMark");
|
|
139
154
|
if (!STYLE_OPTIONS.some(option => Object.hasOwn(args, option))) {
|
|
140
155
|
throw new Error("editRectMark requires at least one editable property.");
|
|
141
156
|
}
|
|
@@ -143,6 +158,11 @@ const editRectMark = action(
|
|
|
143
158
|
if (Object.hasOwn(args, "fill") && layer.encoding?.color !== undefined) {
|
|
144
159
|
throw new Error("editRectMark fill cannot be combined with a color encoding.");
|
|
145
160
|
}
|
|
161
|
+
if (Object.hasOwn(args, "stroke") && layer.encoding?.stroke !== undefined) {
|
|
162
|
+
throw new Error(
|
|
163
|
+
"editRectMark stroke conflicts with a field encoding; use encodeStroke with value to replace it."
|
|
164
|
+
);
|
|
165
|
+
}
|
|
146
166
|
const next = this._withMarkConfig(
|
|
147
167
|
layer.id,
|
|
148
168
|
{
|
|
@@ -155,9 +175,10 @@ const editRectMark = action(
|
|
|
155
175
|
: this.markConfigs[layer.id]?.fillExplicit ?? false
|
|
156
176
|
}
|
|
157
177
|
);
|
|
158
|
-
|
|
178
|
+
const materialized = canMaterializeRect(next, layer)
|
|
159
179
|
? next.rematerializeRectMark({ id: layer.id })
|
|
160
180
|
: next;
|
|
181
|
+
return rematerializeExistingLegend(materialized);
|
|
161
182
|
}
|
|
162
183
|
);
|
|
163
184
|
|