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
|
@@ -7,9 +7,12 @@ import {
|
|
|
7
7
|
} from "../../../core/validation.js";
|
|
8
8
|
import { deriveArcSectors } from "../../../grammar/arcs.js";
|
|
9
9
|
import { buildAnnularSectorCommands } from "../../../grammar/polarPaths.js";
|
|
10
|
-
import {
|
|
11
|
-
|
|
12
|
-
|
|
10
|
+
import {
|
|
11
|
+
mapOrdinalValues,
|
|
12
|
+
readScaleField
|
|
13
|
+
} from "../../../grammar/scales/index.js";
|
|
14
|
+
import { resolveCoordinatePolarFrame } from
|
|
15
|
+
"../../../materialization/coordinateBounds.js";
|
|
13
16
|
import {
|
|
14
17
|
canMaterializeArc,
|
|
15
18
|
getSourceDependentMarkSteps
|
|
@@ -19,7 +22,10 @@ import { findLayer, resolveEligibleLayer } from "../../../selectors/layers.js";
|
|
|
19
22
|
import { DEFAULT_COLORS } from "../../../theme/defaults.js";
|
|
20
23
|
import { resolveMarkGraphicPlacement } from
|
|
21
24
|
"../../../materialization/graphicHierarchy.js";
|
|
25
|
+
import { rematerializeExistingLegend } from "../../encodings/shared.js";
|
|
22
26
|
import { rematerializeHighlightBaseline } from "../lifecycle.js";
|
|
27
|
+
import { mapScaleConsumerValues } from
|
|
28
|
+
"../../../materialization/scales/map.js";
|
|
23
29
|
import {
|
|
24
30
|
assertMarkAvailable,
|
|
25
31
|
applyLayeredMarkInheritance,
|
|
@@ -30,13 +36,18 @@ import {
|
|
|
30
36
|
resolveMarkId,
|
|
31
37
|
validateMarkOptions
|
|
32
38
|
} from "../shared.js";
|
|
39
|
+
import {
|
|
40
|
+
requestedStrokeDetails,
|
|
41
|
+
STROKE_STYLE_PROPERTIES
|
|
42
|
+
} from "../../../grammar/strokeStyle.js";
|
|
33
43
|
|
|
34
44
|
const ARC_OPTIONS = Object.freeze([
|
|
35
|
-
"innerRadius", "padAngle", "fill", "opacity", "stroke", "strokeWidth"
|
|
45
|
+
"innerRadius", "padAngle", "fill", "opacity", "stroke", "strokeWidth",
|
|
46
|
+
...STROKE_STYLE_PROPERTIES
|
|
36
47
|
]);
|
|
37
48
|
const CREATE_OPTIONS = Object.freeze(["id", "data", ...ARC_OPTIONS]);
|
|
38
49
|
const EDIT_OPTIONS = Object.freeze(["target", ...ARC_OPTIONS]);
|
|
39
|
-
const REMATERIALIZE_OPTIONS = Object.freeze(["id"]);
|
|
50
|
+
const REMATERIALIZE_OPTIONS = Object.freeze(["id", "scales"]);
|
|
40
51
|
|
|
41
52
|
function validateInnerRadius(value) {
|
|
42
53
|
if (!Number.isFinite(value) || value < 0 || value >= 1) {
|
|
@@ -47,9 +58,14 @@ function validateInnerRadius(value) {
|
|
|
47
58
|
return value;
|
|
48
59
|
}
|
|
49
60
|
|
|
50
|
-
function normalizeConfig(
|
|
61
|
+
function normalizeConfig(
|
|
62
|
+
args,
|
|
63
|
+
previous = {},
|
|
64
|
+
{ allowStrokeRemoval = false, strokeDetails = {} } = {}
|
|
65
|
+
) {
|
|
51
66
|
let config = {
|
|
52
67
|
...previous,
|
|
68
|
+
...strokeDetails,
|
|
53
69
|
...(Object.hasOwn(args, "innerRadius")
|
|
54
70
|
? { innerRadius: validateInnerRadius(args.innerRadius), innerRadiusExplicit: true }
|
|
55
71
|
: {}),
|
|
@@ -93,6 +109,7 @@ const createArcMark = action(
|
|
|
93
109
|
},
|
|
94
110
|
function (args = {}) {
|
|
95
111
|
validateMarkOptions(args, CREATE_OPTIONS, "createArcMark");
|
|
112
|
+
const strokeDetails = requestedStrokeDetails(args, "createArcMark");
|
|
96
113
|
const id = resolveMarkId(this, args.id, {
|
|
97
114
|
defaultId: "arc",
|
|
98
115
|
label: "Arc mark id",
|
|
@@ -112,7 +129,7 @@ const createArcMark = action(
|
|
|
112
129
|
opacity: 1,
|
|
113
130
|
stroke: "#ffffff",
|
|
114
131
|
strokeWidth: 1
|
|
115
|
-
});
|
|
132
|
+
}, { strokeDetails });
|
|
116
133
|
let created = this
|
|
117
134
|
.editSemantic({ property: `layer[${id}].mark.type`, value: "arc" })
|
|
118
135
|
.editSemantic({ property: `layer[${id}].data`, value: data });
|
|
@@ -148,6 +165,9 @@ const rematerializeArcMark = action(
|
|
|
148
165
|
},
|
|
149
166
|
function (args = {}) {
|
|
150
167
|
validateMarkOptions(args, REMATERIALIZE_OPTIONS, "rematerializeArcMark");
|
|
168
|
+
if (args.scales !== undefined && typeof args.scales !== "boolean") {
|
|
169
|
+
throw new TypeError("rematerializeArcMark scales must be a boolean.");
|
|
170
|
+
}
|
|
151
171
|
const id = validateUserId(args.id, "Arc mark id");
|
|
152
172
|
const highlighted = rematerializeHighlightBaseline(this, {
|
|
153
173
|
target: id,
|
|
@@ -163,15 +183,21 @@ const rematerializeArcMark = action(
|
|
|
163
183
|
const thetaScaleId = layer.encoding.theta.scale;
|
|
164
184
|
const radiusScaleId = layer.encoding?.radius?.scale;
|
|
165
185
|
const colorScaleId = layer.encoding?.color?.scale;
|
|
166
|
-
|
|
167
|
-
|
|
186
|
+
const strokeScaleId = layer.encoding?.stroke?.scale;
|
|
187
|
+
let resolved = args.scales === false
|
|
188
|
+
? this
|
|
189
|
+
: this.rematerializeScale({ id: thetaScaleId });
|
|
190
|
+
if (radiusScaleId !== undefined && args.scales !== false) {
|
|
168
191
|
resolved = resolved.rematerializeScale({ id: radiusScaleId });
|
|
169
192
|
}
|
|
170
|
-
if (colorScaleId !== undefined) {
|
|
193
|
+
if (colorScaleId !== undefined && args.scales !== false) {
|
|
171
194
|
resolved = resolved.rematerializeScale({ id: colorScaleId });
|
|
172
195
|
}
|
|
196
|
+
if (strokeScaleId !== undefined && args.scales !== false) {
|
|
197
|
+
resolved = resolved.rematerializeScale({ id: strokeScaleId });
|
|
198
|
+
}
|
|
173
199
|
const config = resolved.markConfigs[id] ?? {};
|
|
174
|
-
const frame =
|
|
200
|
+
const frame = resolveCoordinatePolarFrame(resolved, layer.coordinate);
|
|
175
201
|
const derived = deriveArcSectors(dataset.values, layer, {
|
|
176
202
|
thetaScale: resolved.resolvedScales[thetaScaleId],
|
|
177
203
|
...(radiusScaleId === undefined
|
|
@@ -195,14 +221,37 @@ const rematerializeArcMark = action(
|
|
|
195
221
|
resolved.resolvedScales[colorScaleId].domain,
|
|
196
222
|
resolved.resolvedScales[colorScaleId].range
|
|
197
223
|
);
|
|
224
|
+
const strokeEncoding = layer.encoding?.stroke;
|
|
225
|
+
const strokeValues = strokeEncoding === undefined ? undefined : derived.sectors.map(
|
|
226
|
+
sector => {
|
|
227
|
+
const values = readScaleField(
|
|
228
|
+
sector.sourceIndices.map(index => dataset.values[index]),
|
|
229
|
+
strokeEncoding.field,
|
|
230
|
+
strokeEncoding.fieldType,
|
|
231
|
+
{ temporalUnit: strokeEncoding.temporalUnit }
|
|
232
|
+
);
|
|
233
|
+
if (new Set(values).size !== 1) {
|
|
234
|
+
throw new Error("Arc stroke requires one value within each sector.");
|
|
235
|
+
}
|
|
236
|
+
return values[0];
|
|
237
|
+
}
|
|
238
|
+
);
|
|
239
|
+
const strokes = strokeValues === undefined ? undefined : mapScaleConsumerValues(
|
|
240
|
+
strokeValues,
|
|
241
|
+
resolved.resolvedScales[strokeScaleId],
|
|
242
|
+
"stroke"
|
|
243
|
+
);
|
|
198
244
|
return editMarkGraphic(resolved, id, {
|
|
199
245
|
length: commands.length,
|
|
200
246
|
commands,
|
|
201
247
|
fill: fills,
|
|
202
248
|
opacity: config.opacity ?? 1,
|
|
203
|
-
stroke:
|
|
249
|
+
stroke: strokes ?? (
|
|
250
|
+
config.stroke === false ? "transparent" : config.stroke ?? "#ffffff"
|
|
251
|
+
),
|
|
204
252
|
strokeWidth: config.stroke === false ? 0 : config.strokeWidth ?? 1,
|
|
205
|
-
strokeDash: commands.map(() => [])
|
|
253
|
+
strokeDash: commands.map(() => []),
|
|
254
|
+
...requestedStrokeDetails(config, "Arc mark")
|
|
206
255
|
});
|
|
207
256
|
}
|
|
208
257
|
);
|
|
@@ -214,6 +263,7 @@ const editArcMark = action(
|
|
|
214
263
|
},
|
|
215
264
|
function (args = {}) {
|
|
216
265
|
validateMarkOptions(args, EDIT_OPTIONS, "editArcMark");
|
|
266
|
+
const strokeDetails = requestedStrokeDetails(args, "editArcMark");
|
|
217
267
|
if (Object.keys(args).every(key => key === "target")) {
|
|
218
268
|
throw new Error(
|
|
219
269
|
"editArcMark requires innerRadius, padAngle, fill, opacity, stroke, or strokeWidth."
|
|
@@ -230,6 +280,11 @@ const editArcMark = action(
|
|
|
230
280
|
if (Object.hasOwn(args, "fill") && layer.encoding?.color !== undefined) {
|
|
231
281
|
throw new Error("editArcMark fill cannot be combined with a color encoding.");
|
|
232
282
|
}
|
|
283
|
+
if (Object.hasOwn(args, "stroke") && layer.encoding?.stroke !== undefined) {
|
|
284
|
+
throw new Error(
|
|
285
|
+
"editArcMark stroke conflicts with a field encoding; use encodeStroke with value to replace it."
|
|
286
|
+
);
|
|
287
|
+
}
|
|
233
288
|
if (args.stroke === false && Object.hasOwn(args, "strokeWidth")) {
|
|
234
289
|
throw new Error(
|
|
235
290
|
"editArcMark cannot set strokeWidth while removing stroke."
|
|
@@ -245,15 +300,18 @@ const editArcMark = action(
|
|
|
245
300
|
const next = this._withMarkConfig(
|
|
246
301
|
layer.id,
|
|
247
302
|
normalizeConfig(args, this.markConfigs[layer.id], {
|
|
248
|
-
allowStrokeRemoval: true
|
|
303
|
+
allowStrokeRemoval: true,
|
|
304
|
+
strokeDetails
|
|
249
305
|
})
|
|
250
306
|
);
|
|
251
|
-
|
|
252
|
-
|
|
253
|
-
|
|
254
|
-
|
|
307
|
+
let materialized = next;
|
|
308
|
+
if (canMaterializeArc(next, layer)) {
|
|
309
|
+
materialized = next.rematerializeArcMark({ id: layer.id });
|
|
310
|
+
for (const step of getSourceDependentMarkSteps(materialized, layer.id)) {
|
|
311
|
+
materialized = materialized[step.op](step.args);
|
|
312
|
+
}
|
|
255
313
|
}
|
|
256
|
-
return
|
|
314
|
+
return rematerializeExistingLegend(materialized);
|
|
257
315
|
}
|
|
258
316
|
);
|
|
259
317
|
|
|
@@ -22,14 +22,20 @@ import { findLayer } from "../../../selectors/layers.js";
|
|
|
22
22
|
import { validateCurveInterpolation } from "../../../grammar/curveCommands.js";
|
|
23
23
|
import { resolveEligibleLayer } from "../../../selectors/layers.js";
|
|
24
24
|
import { canMaterializeArea } from "../../../materialization/marks/index.js";
|
|
25
|
+
import { rematerializeExistingLegend } from "../../encodings/shared.js";
|
|
25
26
|
import { findUpstreamTransform } from "../../../materialization/dataProvenance.js";
|
|
26
27
|
import { resolveMarkGraphicPlacement } from
|
|
27
28
|
"../../../materialization/graphicHierarchy.js";
|
|
28
29
|
import { rematerializeHighlightBaseline } from "../lifecycle.js";
|
|
29
30
|
import { resolveAreaMaterialization } from "./materialize.js";
|
|
31
|
+
import {
|
|
32
|
+
requestedStrokeDetails,
|
|
33
|
+
STROKE_STYLE_PROPERTIES
|
|
34
|
+
} from "../../../grammar/strokeStyle.js";
|
|
30
35
|
|
|
31
36
|
const AREA_OPTIONS = Object.freeze([
|
|
32
|
-
"fill", "opacity", "stroke", "strokeWidth", "curve"
|
|
37
|
+
"fill", "opacity", "stroke", "strokeWidth", "curve",
|
|
38
|
+
...STROKE_STYLE_PROPERTIES
|
|
33
39
|
]);
|
|
34
40
|
const CREATE_OPTIONS = Object.freeze(["id", "data", "missing", ...AREA_OPTIONS]);
|
|
35
41
|
const EDIT_OPTIONS = Object.freeze(["target", "missing", ...AREA_OPTIONS]);
|
|
@@ -58,6 +64,7 @@ const createAreaMark = action(
|
|
|
58
64
|
},
|
|
59
65
|
function (args = {}) {
|
|
60
66
|
validateMarkOptions(args, CREATE_OPTIONS, "createAreaMark");
|
|
67
|
+
const strokeDetails = requestedStrokeDetails(args, "createAreaMark");
|
|
61
68
|
const id = resolveMarkId(this, args.id, {
|
|
62
69
|
defaultId: "area",
|
|
63
70
|
label: "Area mark id",
|
|
@@ -95,7 +102,8 @@ const createAreaMark = action(
|
|
|
95
102
|
fill,
|
|
96
103
|
opacity,
|
|
97
104
|
...(Object.hasOwn(args, "curve") ? { curve } : {}),
|
|
98
|
-
...(stroke === undefined ? {} : { stroke, strokeWidth })
|
|
105
|
+
...(stroke === undefined ? {} : { stroke, strokeWidth }),
|
|
106
|
+
...strokeDetails
|
|
99
107
|
});
|
|
100
108
|
return materializeInheritedMark(created, id);
|
|
101
109
|
}
|
|
@@ -179,6 +187,7 @@ const rematerializeAreaMark = action(
|
|
|
179
187
|
);
|
|
180
188
|
}
|
|
181
189
|
const colorEncoding = layer.encoding?.color;
|
|
190
|
+
const strokeEncoding = layer.encoding?.stroke;
|
|
182
191
|
let resolved = args.scales === false
|
|
183
192
|
? this
|
|
184
193
|
: this
|
|
@@ -187,8 +196,11 @@ const rematerializeAreaMark = action(
|
|
|
187
196
|
if (args.scales !== false && colorEncoding?.scale !== undefined) {
|
|
188
197
|
resolved = resolved.rematerializeScale({ id: colorEncoding.scale });
|
|
189
198
|
}
|
|
199
|
+
if (args.scales !== false && strokeEncoding?.scale !== undefined) {
|
|
200
|
+
resolved = resolved.rematerializeScale({ id: strokeEncoding.scale });
|
|
201
|
+
}
|
|
190
202
|
const config = this.markConfigs[id];
|
|
191
|
-
const { paths, fills } = resolveAreaMaterialization({
|
|
203
|
+
const { paths, fills, strokes } = resolveAreaMaterialization({
|
|
192
204
|
rows: dataset.values,
|
|
193
205
|
layer,
|
|
194
206
|
densityTransform,
|
|
@@ -196,7 +208,8 @@ const rematerializeAreaMark = action(
|
|
|
196
208
|
config
|
|
197
209
|
});
|
|
198
210
|
const existingChildren = resolved.graphicSpec.objects[id].items ?? [];
|
|
199
|
-
const hasOutline =
|
|
211
|
+
const hasOutline = strokes !== undefined || config.stroke !== undefined ||
|
|
212
|
+
config.strokeFromFill === true;
|
|
200
213
|
const removesOutline = !hasOutline && existingChildren.some(
|
|
201
214
|
child => child.properties.stroke !== undefined
|
|
202
215
|
);
|
|
@@ -210,9 +223,10 @@ const rematerializeAreaMark = action(
|
|
|
210
223
|
fill: fills,
|
|
211
224
|
opacity: config.opacity,
|
|
212
225
|
...(hasOutline ? {
|
|
213
|
-
stroke: config.strokeFromFill === true ? fills : config.stroke,
|
|
214
|
-
strokeWidth: config.strokeWidth
|
|
215
|
-
} : {})
|
|
226
|
+
stroke: strokes ?? (config.strokeFromFill === true ? fills : config.stroke),
|
|
227
|
+
strokeWidth: config.strokeWidth ?? (strokes === undefined ? undefined : 1)
|
|
228
|
+
} : {}),
|
|
229
|
+
...requestedStrokeDetails(config, "Area mark")
|
|
216
230
|
});
|
|
217
231
|
}
|
|
218
232
|
);
|
|
@@ -224,7 +238,11 @@ const editAreaMark = action(
|
|
|
224
238
|
},
|
|
225
239
|
function (args = {}) {
|
|
226
240
|
validateMarkOptions(args, EDIT_OPTIONS, "editAreaMark");
|
|
227
|
-
const
|
|
241
|
+
const strokeDetails = requestedStrokeDetails(args, "editAreaMark");
|
|
242
|
+
const changes = [
|
|
243
|
+
"fill", "opacity", "stroke", "strokeWidth", "curve", "missing",
|
|
244
|
+
...STROKE_STYLE_PROPERTIES
|
|
245
|
+
];
|
|
228
246
|
if (!changes.some(key => Object.hasOwn(args, key))) {
|
|
229
247
|
throw new Error(
|
|
230
248
|
"editAreaMark requires fill, opacity, stroke, strokeWidth, or curve."
|
|
@@ -243,11 +261,17 @@ const editAreaMark = action(
|
|
|
243
261
|
"editAreaMark fill cannot be combined with a color encoding."
|
|
244
262
|
);
|
|
245
263
|
}
|
|
264
|
+
if (Object.hasOwn(args, "stroke") && layer.encoding?.stroke !== undefined) {
|
|
265
|
+
throw new Error(
|
|
266
|
+
"editAreaMark stroke conflicts with a field encoding; use encodeStroke with value to replace it."
|
|
267
|
+
);
|
|
268
|
+
}
|
|
246
269
|
if (args.stroke === false && Object.hasOwn(args, "strokeWidth")) {
|
|
247
270
|
throw new Error("editAreaMark cannot set strokeWidth while removing stroke.");
|
|
248
271
|
}
|
|
249
272
|
|
|
250
273
|
let config = { ...this.markConfigs[layer.id] };
|
|
274
|
+
Object.assign(config, strokeDetails);
|
|
251
275
|
if (Object.hasOwn(args, "fill")) {
|
|
252
276
|
config.fill = validateNonEmptyString(args.fill, "Area fill");
|
|
253
277
|
if (config.errorBand !== undefined) config.errorBand = { ...config.errorBand, fill: config.fill };
|
|
@@ -298,9 +322,10 @@ const editAreaMark = action(
|
|
|
298
322
|
}
|
|
299
323
|
next = next.editSemantic({ property: `layer[${layer.id}].mark.missing`, value: missing });
|
|
300
324
|
}
|
|
301
|
-
|
|
325
|
+
const materialized = canMaterializeArea(next, layer)
|
|
302
326
|
? next.rematerializeAreaMark({ id: layer.id })
|
|
303
327
|
: next;
|
|
328
|
+
return rematerializeExistingLegend(materialized);
|
|
304
329
|
}
|
|
305
330
|
);
|
|
306
331
|
|
|
@@ -8,6 +8,8 @@ import {
|
|
|
8
8
|
mapContinuousScaleValues,
|
|
9
9
|
mapOrdinalValues
|
|
10
10
|
} from "../../../grammar/scales/index.js";
|
|
11
|
+
import { mapScaleConsumerValues } from
|
|
12
|
+
"../../../materialization/scales/map.js";
|
|
11
13
|
import { buildAreaCurvePathCommands } from
|
|
12
14
|
"../../../grammar/curveCommands.js";
|
|
13
15
|
import { buildLinearPathCommands } from
|
|
@@ -171,5 +173,19 @@ export function resolveAreaMaterialization({
|
|
|
171
173
|
resolvedScales[colorEncoding.scale].domain,
|
|
172
174
|
resolvedScales[colorEncoding.scale].range
|
|
173
175
|
);
|
|
174
|
-
|
|
176
|
+
const strokeEncoding = layer.encoding?.stroke;
|
|
177
|
+
const strokes = strokeEncoding?.scale === undefined
|
|
178
|
+
? undefined
|
|
179
|
+
: mapScaleConsumerValues(
|
|
180
|
+
derivePathSeriesFieldValues(
|
|
181
|
+
rows,
|
|
182
|
+
derived.series,
|
|
183
|
+
strokeEncoding.field,
|
|
184
|
+
"stroke",
|
|
185
|
+
strokeEncoding
|
|
186
|
+
),
|
|
187
|
+
resolvedScales[strokeEncoding.scale],
|
|
188
|
+
"stroke"
|
|
189
|
+
);
|
|
190
|
+
return { paths, fills, strokes };
|
|
175
191
|
}
|
|
@@ -10,9 +10,14 @@ import {
|
|
|
10
10
|
} from "../shared.js";
|
|
11
11
|
import { resolveMarkGraphicPlacement } from
|
|
12
12
|
"../../../materialization/graphicHierarchy.js";
|
|
13
|
+
import { requestedRectStyleDetails } from
|
|
14
|
+
"../../../grammar/roundedRect.js";
|
|
15
|
+
import { STROKE_STYLE_PROPERTIES } from
|
|
16
|
+
"../../../grammar/strokeStyle.js";
|
|
13
17
|
|
|
14
18
|
const CREATE_OPTIONS = Object.freeze([
|
|
15
|
-
"id", "data", "fill", "opacity", "stroke", "strokeWidth"
|
|
19
|
+
"id", "data", "fill", "opacity", "stroke", "strokeWidth",
|
|
20
|
+
"cornerRadius", ...STROKE_STYLE_PROPERTIES
|
|
16
21
|
]);
|
|
17
22
|
|
|
18
23
|
export const createBarMark = action(
|
|
@@ -22,6 +27,7 @@ export const createBarMark = action(
|
|
|
22
27
|
},
|
|
23
28
|
function (args = {}) {
|
|
24
29
|
validateMarkOptions(args, CREATE_OPTIONS, "createBarMark");
|
|
30
|
+
requestedRectStyleDetails(args, "createBarMark");
|
|
25
31
|
const id = resolveMarkId(this, args.id, {
|
|
26
32
|
defaultId: "bar",
|
|
27
33
|
label: "Bar mark id",
|
|
@@ -56,7 +62,10 @@ export const createBarMark = action(
|
|
|
56
62
|
});
|
|
57
63
|
created = materializeInheritedMark(created, id);
|
|
58
64
|
const appearance = Object.fromEntries(
|
|
59
|
-
[
|
|
65
|
+
[
|
|
66
|
+
"fill", "opacity", "stroke", "strokeWidth", "cornerRadius",
|
|
67
|
+
...STROKE_STYLE_PROPERTIES
|
|
68
|
+
]
|
|
60
69
|
.filter(property => Object.hasOwn(args, property))
|
|
61
70
|
.map(property => [property, args[property]])
|
|
62
71
|
);
|
|
@@ -9,9 +9,15 @@ import { canMaterializeBar } from "../../../materialization/marks/index.js";
|
|
|
9
9
|
import { DEFAULT_BAR_STROKE_WIDTH } from "../../../materialization/bars/resolve.js";
|
|
10
10
|
import { resolveEligibleLayer } from "../../../selectors/layers.js";
|
|
11
11
|
import { validateMarkOptions } from "../shared.js";
|
|
12
|
+
import { requestedRectStyleDetails } from
|
|
13
|
+
"../../../grammar/roundedRect.js";
|
|
14
|
+
import { STROKE_STYLE_PROPERTIES } from
|
|
15
|
+
"../../../grammar/strokeStyle.js";
|
|
16
|
+
import { rematerializeExistingLegend } from "../../encodings/shared.js";
|
|
12
17
|
|
|
13
18
|
const EDIT_OPTIONS = Object.freeze([
|
|
14
|
-
"target", "fill", "opacity", "stroke", "strokeWidth"
|
|
19
|
+
"target", "fill", "opacity", "stroke", "strokeWidth", "cornerRadius",
|
|
20
|
+
...STROKE_STYLE_PROPERTIES
|
|
15
21
|
]);
|
|
16
22
|
|
|
17
23
|
export const editBarMark = action(
|
|
@@ -21,7 +27,11 @@ export const editBarMark = action(
|
|
|
21
27
|
},
|
|
22
28
|
function (args = {}) {
|
|
23
29
|
validateMarkOptions(args, EDIT_OPTIONS, "editBarMark");
|
|
24
|
-
const
|
|
30
|
+
const styleDetails = requestedRectStyleDetails(args, "editBarMark");
|
|
31
|
+
const changes = [
|
|
32
|
+
"fill", "opacity", "stroke", "strokeWidth", "cornerRadius",
|
|
33
|
+
...STROKE_STYLE_PROPERTIES
|
|
34
|
+
];
|
|
25
35
|
if (!changes.some(key => Object.hasOwn(args, key))) {
|
|
26
36
|
throw new Error(
|
|
27
37
|
"editBarMark requires fill, opacity, stroke, or strokeWidth."
|
|
@@ -40,6 +50,11 @@ export const editBarMark = action(
|
|
|
40
50
|
"editBarMark fill cannot be combined with a color encoding."
|
|
41
51
|
);
|
|
42
52
|
}
|
|
53
|
+
if (Object.hasOwn(args, "stroke") && layer.encoding?.stroke !== undefined) {
|
|
54
|
+
throw new Error(
|
|
55
|
+
"editBarMark stroke conflicts with a field encoding; use encodeStroke with value to replace it."
|
|
56
|
+
);
|
|
57
|
+
}
|
|
43
58
|
if (args.stroke === false && Object.hasOwn(args, "strokeWidth")) {
|
|
44
59
|
throw new Error(
|
|
45
60
|
"editBarMark cannot set strokeWidth while removing stroke."
|
|
@@ -48,6 +63,7 @@ export const editBarMark = action(
|
|
|
48
63
|
|
|
49
64
|
const config = { ...this.markConfigs[layer.id] };
|
|
50
65
|
const appearance = { ...config.barAppearance };
|
|
66
|
+
Object.assign(appearance, styleDetails);
|
|
51
67
|
if (Object.hasOwn(args, "fill")) {
|
|
52
68
|
appearance.fill = validateNonEmptyString(args.fill, "Bar fill");
|
|
53
69
|
}
|
|
@@ -83,8 +99,9 @@ export const editBarMark = action(
|
|
|
83
99
|
...config,
|
|
84
100
|
barAppearance: appearance
|
|
85
101
|
});
|
|
86
|
-
|
|
102
|
+
const materialized = canMaterializeBar(next, layer)
|
|
87
103
|
? next.rematerializeBarMark({ id: layer.id })
|
|
88
104
|
: next;
|
|
105
|
+
return rematerializeExistingLegend(materialized);
|
|
89
106
|
}
|
|
90
107
|
);
|
|
@@ -12,10 +12,26 @@ import {
|
|
|
12
12
|
import { rematerializeHighlightBaseline } from "../lifecycle.js";
|
|
13
13
|
import { offsetCategoryRectangles } from
|
|
14
14
|
"../../../materialization/categorySlotOffset.js";
|
|
15
|
+
import { materializeRectItem } from "../../../grammar/roundedRect.js";
|
|
16
|
+
import { STROKE_STYLE_PROPERTIES } from
|
|
17
|
+
"../../../grammar/strokeStyle.js";
|
|
18
|
+
import { replaceGraphicItems } from "../../primitives/editGraphics.js";
|
|
15
19
|
|
|
16
20
|
const REMATERIALIZE_OPTIONS = Object.freeze(["id", "scales"]);
|
|
17
21
|
|
|
18
22
|
function editRectangles(program, id, rectangles) {
|
|
23
|
+
const appearance = program.markConfigs[id]?.barAppearance ?? {};
|
|
24
|
+
const hasShapeStyle = ["cornerRadius", ...STROKE_STYLE_PROPERTIES]
|
|
25
|
+
.some(property => Object.hasOwn(appearance, property));
|
|
26
|
+
if (hasShapeStyle) {
|
|
27
|
+
const radius = appearance.cornerRadius ?? 0;
|
|
28
|
+
return replaceGraphicItems(
|
|
29
|
+
program,
|
|
30
|
+
id,
|
|
31
|
+
"rect",
|
|
32
|
+
rectangles.map(rectangle => materializeRectItem(rectangle, radius))
|
|
33
|
+
);
|
|
34
|
+
}
|
|
19
35
|
let next = program
|
|
20
36
|
.editGraphics({ target: id, property: "length", value: rectangles.length })
|
|
21
37
|
.editGraphics({
|
|
@@ -81,8 +97,8 @@ export const rematerializeBarMark = action(
|
|
|
81
97
|
const highlighted = rematerializeHighlightBaseline(this, {
|
|
82
98
|
target: id,
|
|
83
99
|
operation: "rematerializeBarMark",
|
|
84
|
-
resetProperty: "
|
|
85
|
-
resetValue:
|
|
100
|
+
resetProperty: "items",
|
|
101
|
+
resetValue: []
|
|
86
102
|
});
|
|
87
103
|
if (highlighted !== undefined) return highlighted;
|
|
88
104
|
const required = requireCompleteBar(this, id);
|
|
@@ -97,6 +113,10 @@ export const rematerializeBarMark = action(
|
|
|
97
113
|
if (colorScaleId !== undefined && args.scales !== false) {
|
|
98
114
|
resolved = resolved.rematerializeScale({ id: colorScaleId });
|
|
99
115
|
}
|
|
116
|
+
const strokeScaleId = required.layer.encoding?.stroke?.scale;
|
|
117
|
+
if (strokeScaleId !== undefined && args.scales !== false) {
|
|
118
|
+
resolved = resolved.rematerializeScale({ id: strokeScaleId });
|
|
119
|
+
}
|
|
100
120
|
|
|
101
121
|
if (required.materialization === "aggregate") {
|
|
102
122
|
const offsetChannel = resolveBarOffsetChannel(required.layer);
|
|
@@ -1,5 +1,10 @@
|
|
|
1
1
|
import { removeMark } from "./remove.js";
|
|
2
|
-
import {
|
|
2
|
+
import {
|
|
3
|
+
createReferenceLine,
|
|
4
|
+
createReferenceBand,
|
|
5
|
+
materializeStatisticalReferenceData,
|
|
6
|
+
rematerializeStatisticalReference
|
|
7
|
+
} from "./references.js";
|
|
3
8
|
import { registerRuleMarkActions } from "./rule/index.js";
|
|
4
9
|
import { registerAreaMarkActions } from "./area/index.js";
|
|
5
10
|
import { registerTickMarkActions } from "./tick/index.js";
|
|
@@ -29,4 +34,8 @@ export function registerMarkActions(ProgramClass) {
|
|
|
29
34
|
ProgramClass.prototype.removeMark = removeMark;
|
|
30
35
|
ProgramClass.prototype.createReferenceLine = createReferenceLine;
|
|
31
36
|
ProgramClass.prototype.createReferenceBand = createReferenceBand;
|
|
37
|
+
ProgramClass.prototype.materializeStatisticalReferenceData =
|
|
38
|
+
materializeStatisticalReferenceData;
|
|
39
|
+
ProgramClass.prototype.rematerializeStatisticalReference =
|
|
40
|
+
rematerializeStatisticalReference;
|
|
32
41
|
}
|