ggaction 0.0.10 → 0.0.12
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 +97 -0
- package/README.md +5 -3
- package/knowledge/action-card.schema.json +1 -0
- package/knowledge/action-cards.json +1 -10941
- package/knowledge/action-cards.schema.json +1 -0
- package/knowledge/intent-taxonomy.json +1 -183
- package/knowledge/intent-taxonomy.schema.json +1 -0
- package/knowledge/mcp-resources.json +1 -95
- package/knowledge/mcp-resources.schema.json +1 -0
- package/knowledge/task-packet.schema.json +1 -159
- package/knowledge/task-resolver.js +1 -1230
- package/package.json +18 -2
- package/src/actions/boxPlots/edit.js +45 -298
- package/src/actions/boxPlots/options.js +46 -77
- package/src/actions/boxPlots/resolve.js +1 -1
- package/src/actions/charts/bar.js +3 -0
- package/src/actions/charts/heatmap.js +73 -83
- package/src/actions/charts/index.js +1 -1
- package/src/actions/charts/parallel.js +35 -1
- package/src/actions/charts/shared.js +20 -0
- package/src/actions/composition/actions.js +46 -49
- package/src/actions/data/bin2d.js +105 -2
- package/src/actions/data/box.js +17 -17
- package/src/actions/data/density.js +42 -78
- package/src/actions/data/gradientProfile.js +22 -52
- package/src/actions/data/horizon.js +16 -41
- package/src/actions/data/index.js +10 -10
- package/src/actions/data/interval.js +16 -38
- package/src/actions/data/intervalEdit.js +55 -0
- package/src/actions/data/regression.js +7 -17
- package/src/actions/data/shared.js +47 -0
- package/src/actions/data/timeUnit.js +14 -38
- package/src/actions/data/window.js +14 -38
- package/src/actions/distributions/revision.js +154 -34
- package/src/actions/encodings/angle.js +9 -10
- package/src/actions/encodings/appearance.js +17 -51
- package/src/actions/encodings/density/resolve.js +3 -1
- package/src/actions/encodings/density.js +1 -15
- package/src/actions/encodings/horizon/resolve.js +13 -3
- package/src/actions/encodings/horizon.js +8 -7
- package/src/actions/encodings/index.js +9 -9
- package/src/actions/encodings/offset.js +41 -45
- package/src/actions/encodings/parallel.js +9 -10
- package/src/actions/encodings/pathOrder.js +6 -13
- package/src/actions/encodings/position/apply.js +30 -0
- package/src/actions/encodings/position/policies/arc.js +23 -2
- package/src/actions/encodings/position/policies/index.js +4 -4
- package/src/actions/encodings/position/policies/line.js +47 -17
- package/src/actions/encodings/position/resolve.js +36 -7
- package/src/actions/encodings/ranged.js +18 -23
- package/src/actions/encodings/remove.js +15 -25
- package/src/actions/encodings/ruleAppearance.js +9 -24
- package/src/actions/encodings/shared.js +37 -0
- package/src/actions/encodings/strokeDash.js +8 -23
- package/src/actions/encodings/text.js +9 -10
- package/src/actions/errorBands/create.js +105 -39
- package/src/actions/errorBands/edit.js +89 -93
- package/src/actions/errorBands/index.js +1 -2
- package/src/actions/errorBars/create.js +212 -30
- package/src/actions/errorBars/edit.js +91 -48
- package/src/actions/errorBars/index.js +1 -2
- package/src/actions/facets/actions.js +45 -69
- package/src/actions/facets/derive.js +38 -53
- package/src/actions/facets/replay.js +0 -1
- package/src/actions/gradientPlots/components.js +59 -48
- package/src/actions/gradientPlots/edit.js +35 -216
- package/src/actions/gradientPlots/index.js +11 -10
- package/src/actions/gradientPlots/materialize.js +21 -35
- package/src/actions/gradientPlots/options.js +5 -7
- package/src/actions/gradientPlots/paint.js +9 -6
- package/src/actions/gradientPlots/resolve.js +1 -1
- package/src/actions/guides/axes/index.js +3 -3
- package/src/actions/guides/axes/labels.js +68 -26
- package/src/actions/guides/axes/lines.js +22 -2
- package/src/actions/guides/axes/policy.js +28 -8
- package/src/actions/guides/axes/ticks.js +27 -9
- package/src/actions/guides/axes/titles.js +113 -65
- package/src/actions/guides/grids/resolve.js +14 -0
- package/src/actions/guides/guides.js +2 -4
- package/src/actions/guides/index.js +2 -2
- package/src/actions/guides/legends/categorical/actions.js +44 -68
- package/src/actions/guides/legends/categorical/components.js +6 -1
- package/src/actions/guides/legends/categorical/index.js +2 -2
- package/src/actions/guides/legends/categorical/layout.js +148 -175
- package/src/actions/guides/legends/categorical/recipes.js +5 -0
- package/src/actions/guides/legends/categorical/resolve.js +8 -1
- package/src/actions/guides/legends/continuous/common.js +117 -66
- package/src/actions/guides/legends/continuous/gradient.js +38 -37
- package/src/actions/guides/legends/continuous/interval.js +97 -76
- package/src/actions/guides/legends/continuous/opacity.js +28 -38
- package/src/actions/guides/legends/edit.js +14 -1
- package/src/actions/guides/legends/index.js +1 -1
- package/src/actions/guides/legends/lane.js +2 -1
- package/src/actions/guides/legends/remove.js +8 -0
- package/src/actions/guides/legends/size.js +36 -43
- package/src/actions/guides/legends/strokeWidth.js +20 -26
- package/src/actions/guides/polar/axes/labels.js +17 -1
- package/src/actions/guides/polar/axes/shared.js +7 -1
- package/src/actions/guides/polar/axes/titles.js +19 -2
- package/src/actions/guides/polar/grids.js +4 -0
- package/src/actions/guides/polar/resolve.js +6 -0
- package/src/actions/index.js +13 -13
- package/src/actions/intervals/resolve.js +87 -117
- package/src/actions/marks/arc/actions.js +31 -36
- package/src/actions/marks/area/actions.js +23 -31
- package/src/actions/marks/index.js +6 -6
- package/src/actions/marks/line/actions.js +33 -52
- package/src/actions/marks/line/materialize.js +7 -5
- package/src/actions/marks/point/materialize.js +38 -16
- package/src/actions/marks/remove.js +21 -0
- package/src/actions/marks/rule/actions.js +79 -54
- package/src/actions/marks/shared.js +8 -4
- package/src/actions/marks/text/actions.js +14 -6
- package/src/actions/marks/text/layout.js +21 -45
- package/src/actions/marks/tick/actions.js +22 -21
- package/src/actions/primitives/createGraphics.js +4 -0
- package/src/actions/primitives/editGraphics.js +4 -0
- package/src/actions/primitives/index.js +3 -3
- package/src/actions/primitives/semantic.js +1 -1
- package/src/actions/primitives/semanticValidation/index.js +2 -2
- package/src/actions/primitives/semanticValidation/layer.js +1 -1
- package/src/actions/regression/edit.js +3 -43
- package/src/actions/scales/consumers/families.js +24 -4
- package/src/actions/scales/consumers/index.js +1 -1
- package/src/actions/scales/consumers/seriesLayout.js +17 -0
- package/src/actions/scales/definitions.js +100 -103
- package/src/actions/scales/materialize.js +5 -0
- package/src/actions/selection/actions.js +79 -121
- package/src/actions/titles/actions.js +48 -94
- package/src/actions/titles/resolve.js +14 -27
- package/src/actions/violinPlots/create.js +37 -44
- package/src/core/textMetrics.js +74 -37
- package/src/core/validation.js +18 -0
- package/src/core/vocabulary.js +2 -2
- package/src/grammar/aggregate.js +48 -28
- package/src/grammar/arcs.js +170 -32
- package/src/grammar/areaSeries.js +14 -16
- package/src/grammar/bin2d.js +37 -23
- package/src/grammar/boxPlot.js +14 -13
- package/src/grammar/categoricalDensity.js +14 -14
- package/src/grammar/categoryOrder.js +8 -14
- package/src/grammar/curveCommands.js +87 -20
- package/src/grammar/density.js +162 -141
- package/src/grammar/facets/index.js +14 -0
- package/src/grammar/facets/scales.js +7 -4
- package/src/grammar/gradientProfile.js +12 -15
- package/src/grammar/histogram.js +145 -83
- package/src/grammar/horizon.js +60 -23
- package/src/grammar/interval.js +14 -13
- package/src/grammar/lineSeries.js +91 -61
- package/src/grammar/numeric.js +290 -0
- package/src/grammar/paint.js +3 -4
- package/src/grammar/palettes.js +21 -32
- package/src/grammar/pathCommands.js +6 -0
- package/src/grammar/polarPaths.js +5 -5
- package/src/grammar/positionCompatibility.js +1 -1
- package/src/grammar/regression/derive.js +48 -9
- package/src/grammar/regression/models.js +248 -69
- package/src/grammar/regression/parameters.js +8 -0
- package/src/grammar/rules.js +2 -0
- package/src/grammar/scales/color.js +35 -26
- package/src/grammar/scales/continuous.js +71 -24
- package/src/grammar/scales/definition.js +1 -1
- package/src/grammar/scales/discretized.js +42 -12
- package/src/grammar/scales/fields.js +21 -4
- package/src/grammar/scales/ordinal.js +139 -60
- package/src/grammar/scales/temporal.js +40 -11
- package/src/grammar/scales/transformed.js +199 -52
- package/src/grammar/schemas/graphicBounds.js +270 -79
- package/src/grammar/seriesLayout.js +50 -18
- package/src/grammar/ticks.js +123 -53
- package/src/grammar/timeUnit.js +18 -8
- package/src/grammar/transforms.js +4 -1
- package/src/grammar/window.js +70 -57
- package/src/index.js +1 -1
- package/src/layout/canvas.js +4 -8
- package/src/layout/composition.js +39 -40
- package/src/layout/facets.js +55 -30
- package/src/layout/labels.js +91 -15
- package/src/layout/legend.js +22 -20
- package/src/layout/legendLane.js +54 -40
- package/src/layout/title.js +7 -7
- package/src/materialization/bars/aggregate.js +14 -40
- package/src/materialization/bars/grouped.js +7 -18
- package/src/materialization/bars/histogram.js +2 -19
- package/src/materialization/bars/ranged.js +20 -15
- package/src/materialization/bars/resolve.js +21 -0
- package/src/materialization/facetGuides/legacyCategorical.js +9 -2
- package/src/materialization/facetGuides/placement.js +49 -19
- package/src/materialization/facetGuides/preparation.js +35 -6
- package/src/materialization/facets.js +42 -28
- package/src/materialization/guides/resources.js +2 -1
- package/src/materialization/marks/capabilities.js +15 -4
- package/src/materialization/marks/index.js +29 -6
- package/src/materialization/rowEncoding.js +57 -1
- package/src/materialization/scales/policies/bar.js +61 -102
- package/src/materialization/scales/policies/binnedPosition.js +34 -0
- package/src/materialization/scales/policies/offset.js +54 -0
- package/src/materialization/scales/policies/series.js +13 -7
- package/src/materialization/scales/resolve.js +6 -9
- package/src/materialization/selection/items/arc.js +16 -2
- package/src/materialization/selection/items/bar.js +4 -2
- package/src/materialization/selection/items/common.js +21 -1
- package/src/materialization/selection/items/path.js +19 -2
- package/src/materialization/selection/items/point.js +4 -16
- package/src/materialization/selection/items/tick.js +13 -21
- package/src/materialization/selection/point.js +11 -4
- package/src/materialization/selection/styles.js +19 -27
- package/src/materialization/text.js +4 -1
- package/src/mcp/adapter.js +8 -3
- package/src/renderers/canvas/fill.js +2 -2
- package/src/renderers/canvas/index.js +35 -2
- package/src/renderers/canvas/native.js +160 -0
- package/src/renderers/pdf.js +14 -0
- package/src/renderers/svg.js +37 -4
- package/types/index.d.ts +3 -0
- package/types/program.d.ts +523 -131
- package/types/svg.d.ts +1 -0
- package/src/actions/errorBands/components.js +0 -81
- package/src/actions/errorBands/options.js +0 -39
- package/src/actions/errorBands/resolve.js +0 -28
- package/src/actions/errorBars/components.js +0 -62
- package/src/actions/errorBars/options.js +0 -58
- package/src/actions/errorBars/resolve.js +0 -25
|
@@ -5,15 +5,13 @@ import { validateKeys } from "../../core/validation.js";
|
|
|
5
5
|
import { planDerivedDataRevision } from "../../materialization/dataProvenance.js";
|
|
6
6
|
import { findDataset } from "../../selectors/datasets.js";
|
|
7
7
|
import { findLayer } from "../../selectors/layers.js";
|
|
8
|
+
import { removeOwnedMark } from "../marks/remove.js";
|
|
8
9
|
import { GRADIENT_PROFILE_FIELDS } from "../../grammar/gradientProfile.js";
|
|
9
10
|
import { removeGradientPlotLegend } from "./components.js";
|
|
10
11
|
import {
|
|
11
|
-
|
|
12
|
-
clearCartesianPositions,
|
|
13
|
-
rebindDistributionGuides,
|
|
14
|
-
resolveDistributionScalePlan,
|
|
12
|
+
resolveDistributionRoles,
|
|
15
13
|
setCartesianPosition,
|
|
16
|
-
|
|
14
|
+
updateDistributionPositions
|
|
17
15
|
} from "../distributions/revision.js";
|
|
18
16
|
import {
|
|
19
17
|
resolveGradientAppearance,
|
|
@@ -39,140 +37,20 @@ function patch(value, label) {
|
|
|
39
37
|
}
|
|
40
38
|
|
|
41
39
|
function removeCenter(program, id) {
|
|
42
|
-
|
|
43
|
-
const selections = Object.entries(
|
|
44
|
-
program.materializationConfigs.selections ?? {}
|
|
45
|
-
).filter(([, config]) => config.target === id).map(([selection]) => selection);
|
|
46
|
-
for (const [highlight, config] of Object.entries(
|
|
47
|
-
program.materializationConfigs.highlights ?? {}
|
|
48
|
-
)) {
|
|
49
|
-
if (config.target === id || selections.includes(config.selection)) {
|
|
50
|
-
next = next._withoutMaterializationConfig(["highlights", highlight]);
|
|
51
|
-
}
|
|
52
|
-
}
|
|
53
|
-
for (const selection of selections) {
|
|
54
|
-
next = next._withoutMaterializationConfig(["selections", selection]);
|
|
55
|
-
}
|
|
56
|
-
if (findLayer(next, id) !== undefined) {
|
|
57
|
-
next = next.editSemantic({ property: `layer[${id}]`, remove: true });
|
|
58
|
-
}
|
|
59
|
-
if (next.graphicSpec.objects[id] !== undefined) {
|
|
60
|
-
next = next.editGraphics({ target: id, remove: true });
|
|
61
|
-
}
|
|
62
|
-
return next
|
|
63
|
-
._withoutMaterializationConfig(["marks", id])
|
|
64
|
-
._withContext({
|
|
65
|
-
...(program.context.currentMark === id ? { currentMark: undefined } : {}),
|
|
66
|
-
...(selections.includes(program.context.currentSelection)
|
|
67
|
-
? { currentSelection: undefined }
|
|
68
|
-
: {})
|
|
69
|
-
});
|
|
70
|
-
}
|
|
71
|
-
|
|
72
|
-
function currentGradientPositions(owner, current) {
|
|
73
|
-
const categoryChannel = current.orientation === "vertical" ? "x" : "y";
|
|
74
|
-
const measureChannel = current.orientation === "vertical" ? "y" : "x";
|
|
75
|
-
const categoryEncoding = owner.encoding[categoryChannel];
|
|
76
|
-
const measureEncoding = owner.encoding[measureChannel];
|
|
77
|
-
return {
|
|
78
|
-
x: current.orientation === "vertical"
|
|
79
|
-
? {
|
|
80
|
-
field: current.category,
|
|
81
|
-
fieldType: current.categoryType,
|
|
82
|
-
scale: categoryEncoding.scale
|
|
83
|
-
}
|
|
84
|
-
: {
|
|
85
|
-
field: current.measure,
|
|
86
|
-
fieldType: "quantitative",
|
|
87
|
-
scale: measureEncoding.scale
|
|
88
|
-
},
|
|
89
|
-
y: current.orientation === "vertical"
|
|
90
|
-
? {
|
|
91
|
-
field: current.measure,
|
|
92
|
-
fieldType: "quantitative",
|
|
93
|
-
scale: measureEncoding.scale
|
|
94
|
-
}
|
|
95
|
-
: {
|
|
96
|
-
field: current.category,
|
|
97
|
-
fieldType: current.categoryType,
|
|
98
|
-
scale: categoryEncoding.scale
|
|
99
|
-
},
|
|
100
|
-
categoryScale: categoryEncoding.scale,
|
|
101
|
-
measureScale: measureEncoding.scale
|
|
102
|
-
};
|
|
103
|
-
}
|
|
104
|
-
|
|
105
|
-
function requirePositionField(position, label) {
|
|
106
|
-
if (typeof position?.field !== "string" || position.field.length === 0) {
|
|
107
|
-
throw new TypeError(`${label} field must be a non-empty string.`);
|
|
108
|
-
}
|
|
109
|
-
return position;
|
|
40
|
+
return removeOwnedMark(program, id, true);
|
|
110
41
|
}
|
|
111
42
|
|
|
112
43
|
function roleCandidate(program, owner, current, args) {
|
|
113
|
-
const previous = currentGradientPositions(owner, current);
|
|
114
|
-
const positions = normalizeGradientPositionTypes(
|
|
115
|
-
requirePositionField(
|
|
116
|
-
Object.hasOwn(args, "x")
|
|
117
|
-
? resolveGradientPosition(args.x, "x", "editGradientPlot")
|
|
118
|
-
: previous.x,
|
|
119
|
-
"editGradientPlot x"
|
|
120
|
-
),
|
|
121
|
-
requirePositionField(
|
|
122
|
-
Object.hasOwn(args, "y")
|
|
123
|
-
? resolveGradientPosition(args.y, "y", "editGradientPlot")
|
|
124
|
-
: previous.y,
|
|
125
|
-
"editGradientPlot y"
|
|
126
|
-
)
|
|
127
|
-
);
|
|
128
|
-
if (positions.orientation === undefined) {
|
|
129
|
-
throw new Error(
|
|
130
|
-
"editGradientPlot requires one categorical axis and one quantitative axis."
|
|
131
|
-
);
|
|
132
|
-
}
|
|
133
|
-
const xRoleScale = positions.orientation === "vertical"
|
|
134
|
-
? previous.categoryScale
|
|
135
|
-
: previous.measureScale;
|
|
136
|
-
const yRoleScale = positions.orientation === "vertical"
|
|
137
|
-
? previous.measureScale
|
|
138
|
-
: previous.categoryScale;
|
|
139
|
-
const xScale = resolveDistributionScalePlan(program, {
|
|
140
|
-
channel: "x",
|
|
141
|
-
fieldType: positions.x.fieldType,
|
|
142
|
-
requested: positions.x.scale,
|
|
143
|
-
fallback: xRoleScale,
|
|
144
|
-
defaults: ["ordinal", "nominal"].includes(positions.x.fieldType)
|
|
145
|
-
? { discreteType: "band" }
|
|
146
|
-
: {}
|
|
147
|
-
});
|
|
148
|
-
const yScale = resolveDistributionScalePlan(program, {
|
|
149
|
-
channel: "y",
|
|
150
|
-
fieldType: positions.y.fieldType,
|
|
151
|
-
requested: positions.y.scale,
|
|
152
|
-
fallback: yRoleScale,
|
|
153
|
-
defaults: ["ordinal", "nominal"].includes(positions.y.fieldType)
|
|
154
|
-
? { discreteType: "band" }
|
|
155
|
-
: {}
|
|
156
|
-
});
|
|
157
44
|
return {
|
|
158
45
|
source: Object.hasOwn(args, "data")
|
|
159
46
|
? validateUserId(args.data, "Gradient-plot data id")
|
|
160
47
|
: current.source,
|
|
161
|
-
|
|
162
|
-
|
|
163
|
-
|
|
164
|
-
|
|
165
|
-
|
|
166
|
-
|
|
167
|
-
? positions.x.field
|
|
168
|
-
: positions.y.field,
|
|
169
|
-
categoryType: positions.orientation === "vertical"
|
|
170
|
-
? positions.x.fieldType
|
|
171
|
-
: positions.y.fieldType,
|
|
172
|
-
measure: positions.orientation === "vertical"
|
|
173
|
-
? positions.y.field
|
|
174
|
-
: positions.x.field,
|
|
175
|
-
previous
|
|
48
|
+
...resolveDistributionRoles(program, owner, current, args, {
|
|
49
|
+
operation: "editGradientPlot",
|
|
50
|
+
resolvePosition: resolveGradientPosition,
|
|
51
|
+
normalize: normalizeGradientPositionTypes,
|
|
52
|
+
quantitativeDefaults: {}
|
|
53
|
+
})
|
|
176
54
|
};
|
|
177
55
|
}
|
|
178
56
|
|
|
@@ -190,46 +68,27 @@ function sameRoleCandidate(current, candidate) {
|
|
|
190
68
|
|
|
191
69
|
function updateGradientPositions(program, owner, current, candidate, hasCenter) {
|
|
192
70
|
const owned = [owner.id, ...(hasCenter ? [current.centerId] : [])];
|
|
193
|
-
|
|
194
|
-
|
|
195
|
-
|
|
196
|
-
|
|
197
|
-
|
|
198
|
-
|
|
199
|
-
|
|
200
|
-
|
|
201
|
-
|
|
202
|
-
|
|
203
|
-
|
|
204
|
-
|
|
205
|
-
const category = candidate.orientation === "vertical" ? candidate.x : candidate.y;
|
|
206
|
-
const measure = candidate.orientation === "vertical" ? candidate.y : candidate.x;
|
|
207
|
-
const categoryChannel = candidate.orientation === "vertical" ? "x" : "y";
|
|
208
|
-
const measureChannel = candidate.orientation === "vertical" ? "y" : "x";
|
|
209
|
-
next = setCartesianPosition(next, owner.id, categoryChannel, {
|
|
210
|
-
field: candidate.category,
|
|
211
|
-
fieldType: candidate.categoryType,
|
|
212
|
-
scale: category.scale
|
|
213
|
-
});
|
|
214
|
-
next = setCartesianRange(
|
|
215
|
-
next,
|
|
216
|
-
owner.id,
|
|
217
|
-
measureChannel,
|
|
218
|
-
GRADIENT_PROFILE_FIELDS.lower,
|
|
219
|
-
GRADIENT_PROFILE_FIELDS.upper,
|
|
220
|
-
measure.scale
|
|
221
|
-
);
|
|
222
|
-
if (hasCenter) {
|
|
223
|
-
next = setCartesianPosition(next, current.centerId, categoryChannel, {
|
|
71
|
+
return updateDistributionPositions(
|
|
72
|
+
program,
|
|
73
|
+
owner,
|
|
74
|
+
current,
|
|
75
|
+
candidate,
|
|
76
|
+
{
|
|
77
|
+
owned,
|
|
78
|
+
lower: GRADIENT_PROFILE_FIELDS.lower,
|
|
79
|
+
upper: GRADIENT_PROFILE_FIELDS.upper,
|
|
80
|
+
update(next, { category, measure, categoryChannel, measureChannel }) {
|
|
81
|
+
if (!hasCenter) return next;
|
|
82
|
+
next = setCartesianPosition(next, current.centerId, categoryChannel, {
|
|
224
83
|
field: candidate.category,
|
|
225
84
|
fieldType: candidate.categoryType,
|
|
226
85
|
scale: category.scale
|
|
227
86
|
});
|
|
228
|
-
|
|
87
|
+
return setCartesianPosition(next, current.centerId, measureChannel, {
|
|
229
88
|
field: GRADIENT_PROFILE_FIELDS.center,
|
|
230
89
|
fieldType: "quantitative",
|
|
231
90
|
scale: measure.scale
|
|
232
|
-
|
|
91
|
+
})._withMarkConfig(current.centerId, {
|
|
233
92
|
...next.markConfigs[current.centerId],
|
|
234
93
|
fixedSpan: {
|
|
235
94
|
...next.markConfigs[current.centerId].fixedSpan,
|
|
@@ -237,27 +96,10 @@ function updateGradientPositions(program, owner, current, candidate, hasCenter)
|
|
|
237
96
|
? "horizontal"
|
|
238
97
|
: "vertical"
|
|
239
98
|
}
|
|
240
|
-
|
|
241
|
-
|
|
242
|
-
|
|
243
|
-
|
|
244
|
-
}
|
|
245
|
-
next = rebindDistributionGuides(next, {
|
|
246
|
-
oldXScale: candidate.previous.x.scale,
|
|
247
|
-
oldYScale: candidate.previous.y.scale,
|
|
248
|
-
newXScale: candidate.xScale.id,
|
|
249
|
-
newYScale: candidate.yScale.id,
|
|
250
|
-
oldXTitle: candidate.previous.x.field,
|
|
251
|
-
oldYTitle: candidate.previous.y.field,
|
|
252
|
-
newXTitle: candidate.x.field,
|
|
253
|
-
newYTitle: candidate.y.field,
|
|
254
|
-
oldMeasureChannel: current.orientation === "vertical" ? "y" : "x",
|
|
255
|
-
newMeasureChannel: candidate.orientation === "vertical" ? "y" : "x"
|
|
256
|
-
});
|
|
257
|
-
for (const scale of [candidate.xScale, candidate.yScale]) {
|
|
258
|
-
if (scale.edit !== undefined) next = next.editScale(scale.edit);
|
|
259
|
-
}
|
|
260
|
-
return next;
|
|
99
|
+
});
|
|
100
|
+
}
|
|
101
|
+
}
|
|
102
|
+
);
|
|
261
103
|
}
|
|
262
104
|
|
|
263
105
|
export const editGradientPlot = action(
|
|
@@ -301,7 +143,10 @@ export const editGradientPlot = action(
|
|
|
301
143
|
key => Object.hasOwn(args, key)
|
|
302
144
|
);
|
|
303
145
|
const changesRoles = !sameRoleCandidate(current, candidate);
|
|
304
|
-
|
|
146
|
+
const statistical = JSON.stringify(density) !== JSON.stringify(current.density) ||
|
|
147
|
+
center !== false && current.center !== false &&
|
|
148
|
+
center.type !== current.center.type;
|
|
149
|
+
if (changesRoles || statistical) {
|
|
305
150
|
const hadCenter = findLayer(this, current.centerId) !== undefined;
|
|
306
151
|
const revision = planDerivedDataRevision(this, {
|
|
307
152
|
owner: owner.id,
|
|
@@ -404,7 +249,6 @@ export const editGradientPlot = action(
|
|
|
404
249
|
currentData: candidate.source
|
|
405
250
|
});
|
|
406
251
|
};
|
|
407
|
-
applyEdit(this);
|
|
408
252
|
return applyEdit(this);
|
|
409
253
|
}
|
|
410
254
|
if (roleRequested && !OPTIONS.slice(4).some(
|
|
@@ -415,33 +259,8 @@ export const editGradientPlot = action(
|
|
|
415
259
|
currentData: current.source
|
|
416
260
|
});
|
|
417
261
|
}
|
|
418
|
-
const densityChanged = JSON.stringify(density) !== JSON.stringify(current.density);
|
|
419
|
-
const centerTypeChanged = center !== false && current.center !== false &&
|
|
420
|
-
center.type !== current.center.type;
|
|
421
|
-
const statistical = densityChanged || centerTypeChanged;
|
|
422
262
|
let next = this;
|
|
423
|
-
|
|
424
|
-
if (statistical) {
|
|
425
|
-
const consumers = [owner.id, ...(findLayer(next, current.centerId) ? [current.centerId] : [])];
|
|
426
|
-
const revision = planDerivedDataRevision(next, {
|
|
427
|
-
owner: owner.id,
|
|
428
|
-
role: "ProfileData",
|
|
429
|
-
previous: current.profileId,
|
|
430
|
-
consumers
|
|
431
|
-
});
|
|
432
|
-
profileId = revision.id;
|
|
433
|
-
next = next.createGradientProfileData({
|
|
434
|
-
id: profileId,
|
|
435
|
-
source: current.source,
|
|
436
|
-
category: current.category,
|
|
437
|
-
field: current.measure,
|
|
438
|
-
...density,
|
|
439
|
-
center: center === false ? "median" : center.type
|
|
440
|
-
});
|
|
441
|
-
for (const rebind of revision.rebinds) next = next.rebindLayerData(rebind);
|
|
442
|
-
next = next.releaseDerivedData(revision.release);
|
|
443
|
-
}
|
|
444
|
-
const profile = findDataset(next, profileId);
|
|
263
|
+
const profile = findDataset(next, current.profileId);
|
|
445
264
|
next = next._withMarkConfig(owner.id, {
|
|
446
265
|
...next.markConfigs[owner.id],
|
|
447
266
|
gradientPlot: {
|
|
@@ -450,7 +269,7 @@ export const editGradientPlot = action(
|
|
|
450
269
|
width,
|
|
451
270
|
gradient,
|
|
452
271
|
center,
|
|
453
|
-
profileId,
|
|
272
|
+
profileId: current.profileId,
|
|
454
273
|
intensityDomain: profile.transform[0].resolved.intensityDomain
|
|
455
274
|
}
|
|
456
275
|
});
|
|
@@ -463,7 +282,7 @@ export const editGradientPlot = action(
|
|
|
463
282
|
next = next.createGradientPlotCenter({
|
|
464
283
|
id: current.centerId,
|
|
465
284
|
owner: owner.id,
|
|
466
|
-
data: profileId,
|
|
285
|
+
data: current.profileId,
|
|
467
286
|
category: current.category,
|
|
468
287
|
categoryType: current.categoryType,
|
|
469
288
|
coordinate: owner.coordinate,
|
|
@@ -5,20 +5,21 @@ import {
|
|
|
5
5
|
} from "./components.js";
|
|
6
6
|
import { createGradientPlot } from "./create.js";
|
|
7
7
|
import { editGradientPlot } from "./edit.js";
|
|
8
|
+
import { rebindGradientPlotProfile } from "./rebind.js";
|
|
8
9
|
import {
|
|
9
10
|
materializeGradientPlot,
|
|
10
11
|
materializeGradientPlotFill
|
|
11
12
|
} from "./materialize.js";
|
|
12
|
-
import { rebindGradientPlotProfile } from "./rebind.js";
|
|
13
13
|
|
|
14
14
|
export function registerGradientPlotActions(ProgramClass) {
|
|
15
|
-
ProgramClass.prototype
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
rematerializeGradientPlotLegend
|
|
23
|
-
|
|
15
|
+
Object.assign(ProgramClass.prototype, {
|
|
16
|
+
createGradientPlot,
|
|
17
|
+
editGradientPlot,
|
|
18
|
+
materializeGradientPlot,
|
|
19
|
+
materializeGradientPlotFill,
|
|
20
|
+
createGradientPlotCenter,
|
|
21
|
+
createGradientPlotLegend,
|
|
22
|
+
rematerializeGradientPlotLegend,
|
|
23
|
+
rebindGradientPlotProfile
|
|
24
|
+
});
|
|
24
25
|
}
|
|
@@ -23,10 +23,6 @@ function position(values, scale) {
|
|
|
23
23
|
: mapContinuousScaleValues(values, scale);
|
|
24
24
|
}
|
|
25
25
|
|
|
26
|
-
function profileValue(row, key) {
|
|
27
|
-
return row[GRADIENT_PROFILE_FIELDS[key]];
|
|
28
|
-
}
|
|
29
|
-
|
|
30
26
|
function axisWithTitle(option, text) {
|
|
31
27
|
if (option === false) return false;
|
|
32
28
|
const axis = option ?? {};
|
|
@@ -56,20 +52,22 @@ function gradientAxesOptions(config) {
|
|
|
56
52
|
}
|
|
57
53
|
|
|
58
54
|
function bodyItems(program, layer, dataset, config) {
|
|
59
|
-
const
|
|
60
|
-
const
|
|
55
|
+
const vertical = config.orientation === "vertical";
|
|
56
|
+
const categoryChannel = vertical ? "x" : "y";
|
|
57
|
+
const measureChannel = vertical ? "y" : "x";
|
|
61
58
|
const categoryEncoding = layer.encoding[categoryChannel];
|
|
62
59
|
const measureEncoding = layer.encoding[measureChannel];
|
|
63
60
|
const categoryScale = program.resolvedScales[categoryEncoding.scale];
|
|
64
61
|
const measureScale = program.resolvedScales[measureEncoding.scale];
|
|
65
|
-
const
|
|
62
|
+
const rows = dataset.values;
|
|
63
|
+
const categories = rows.map(row => row[config.category]);
|
|
66
64
|
const centers = position(categories, categoryScale);
|
|
67
65
|
const lower = position(
|
|
68
|
-
|
|
66
|
+
rows.map(row => row[GRADIENT_PROFILE_FIELDS.lower]),
|
|
69
67
|
measureScale
|
|
70
68
|
);
|
|
71
69
|
const upper = position(
|
|
72
|
-
|
|
70
|
+
rows.map(row => row[GRADIENT_PROFILE_FIELDS.upper]),
|
|
73
71
|
measureScale
|
|
74
72
|
);
|
|
75
73
|
const categoryColors = resolveGradientPlotCategoryColors(
|
|
@@ -81,10 +79,10 @@ function bodyItems(program, layer, dataset, config) {
|
|
|
81
79
|
if (!Number.isFinite(thickness) || thickness <= 0) {
|
|
82
80
|
throw new Error(`Gradient plot "${layer.id}" requires a positive band width.`);
|
|
83
81
|
}
|
|
84
|
-
return
|
|
82
|
+
return rows.map((row, index) => {
|
|
85
83
|
const a = lower[index];
|
|
86
84
|
const b = upper[index];
|
|
87
|
-
const geometry =
|
|
85
|
+
const geometry = vertical
|
|
88
86
|
? {
|
|
89
87
|
x: centers[index] - thickness / 2,
|
|
90
88
|
y: Math.min(a, b),
|
|
@@ -102,8 +100,8 @@ function bodyItems(program, layer, dataset, config) {
|
|
|
102
100
|
properties: {
|
|
103
101
|
...geometry,
|
|
104
102
|
fill: createGradientPlotPaint({
|
|
105
|
-
values:
|
|
106
|
-
intensities:
|
|
103
|
+
values: row[GRADIENT_PROFILE_FIELDS.values],
|
|
104
|
+
intensities: row[GRADIENT_PROFILE_FIELDS.intensities]
|
|
107
105
|
}, {
|
|
108
106
|
orientation: config.orientation,
|
|
109
107
|
valueScale: measureScale,
|
|
@@ -223,28 +221,16 @@ export const materializeGradientPlot = action(
|
|
|
223
221
|
}
|
|
224
222
|
});
|
|
225
223
|
const measureChannel = orientation === "vertical" ? "y" : "x";
|
|
226
|
-
const
|
|
227
|
-
|
|
228
|
-
.
|
|
229
|
-
|
|
230
|
-
|
|
231
|
-
}
|
|
232
|
-
.
|
|
233
|
-
|
|
234
|
-
|
|
235
|
-
|
|
236
|
-
.editSemantic({
|
|
237
|
-
property: `layer[${owner}].encoding.${secondaryChannel}.field`,
|
|
238
|
-
value: GRADIENT_PROFILE_FIELDS.upper
|
|
239
|
-
})
|
|
240
|
-
.editSemantic({
|
|
241
|
-
property: `layer[${owner}].encoding.${secondaryChannel}.fieldType`,
|
|
242
|
-
value: "quantitative"
|
|
243
|
-
})
|
|
244
|
-
.editSemantic({
|
|
245
|
-
property: `layer[${owner}].encoding.${secondaryChannel}.scale`,
|
|
246
|
-
value: measure.scale
|
|
247
|
-
});
|
|
224
|
+
const path = `layer[${owner}].encoding.`;
|
|
225
|
+
for (const [property, value] of [
|
|
226
|
+
[`${path}${measureChannel}.field`, GRADIENT_PROFILE_FIELDS.lower],
|
|
227
|
+
[`${path}${measureChannel}.fieldType`, "quantitative"],
|
|
228
|
+
[`${path}${measureChannel}2.field`, GRADIENT_PROFILE_FIELDS.upper],
|
|
229
|
+
[`${path}${measureChannel}2.fieldType`, "quantitative"],
|
|
230
|
+
[`${path}${measureChannel}2.scale`, measure.scale]
|
|
231
|
+
]) {
|
|
232
|
+
next = next.editSemantic({ property, value });
|
|
233
|
+
}
|
|
248
234
|
next = next.materializeGradientPlotFill({ id: owner });
|
|
249
235
|
if (config.center !== false) {
|
|
250
236
|
const categoryScale = next.resolvedScales[category.scale];
|
|
@@ -1,8 +1,7 @@
|
|
|
1
|
-
import { isPlainObject } from "../../core/immutable.js";
|
|
2
1
|
import {
|
|
3
|
-
validateKeys,
|
|
4
2
|
validateNonEmptyString,
|
|
5
3
|
validateNonNegativeFinite,
|
|
4
|
+
validateOptionObject,
|
|
6
5
|
validateUnitInterval
|
|
7
6
|
} from "../../core/validation.js";
|
|
8
7
|
import { normalizePalette } from "../../grammar/palettes.js";
|
|
@@ -14,11 +13,10 @@ export const GRADIENT_PLOT_OPTIONS = Object.freeze([
|
|
|
14
13
|
|
|
15
14
|
function plain(value, keys, label, operation) {
|
|
16
15
|
if (value === undefined) return {};
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
return value;
|
|
16
|
+
const context = `${operation} ${label}`;
|
|
17
|
+
return validateOptionObject(value, keys, context, {
|
|
18
|
+
plainObjectMessage: `${context} must be a plain object.`
|
|
19
|
+
});
|
|
22
20
|
}
|
|
23
21
|
|
|
24
22
|
export function resolveGradientPosition(value, label, operation = "createGradientPlot") {
|
|
@@ -1,12 +1,12 @@
|
|
|
1
1
|
import { resolveContinuousPalette } from "../../grammar/palettes.js";
|
|
2
|
+
import { inverseLerp } from "../../grammar/numeric.js";
|
|
2
3
|
import { mapScaleConsumerValues } from "../../materialization/scales/map.js";
|
|
3
4
|
|
|
4
5
|
function parseHex(value) {
|
|
5
6
|
const match = value.match(/^#([0-9a-f]{6})$/i);
|
|
6
7
|
if (!match) throw new Error(`Gradient plot requires a six-digit hex color, received "${value}".`);
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
);
|
|
8
|
+
const color = Number.parseInt(match[1], 16);
|
|
9
|
+
return [color >> 16, color >> 8 & 255, color & 255];
|
|
10
10
|
}
|
|
11
11
|
|
|
12
12
|
function interpolate(left, right, amount) {
|
|
@@ -23,8 +23,11 @@ function paletteColor(colors, amount) {
|
|
|
23
23
|
const bounded = Math.max(0, Math.min(1, amount));
|
|
24
24
|
const scaled = bounded * (colors.length - 1);
|
|
25
25
|
const left = Math.floor(scaled);
|
|
26
|
-
|
|
27
|
-
|
|
26
|
+
return interpolate(
|
|
27
|
+
parseHex(colors[left]),
|
|
28
|
+
parseHex(colors[Math.min(colors.length - 1, left + 1)]),
|
|
29
|
+
scaled - left
|
|
30
|
+
);
|
|
28
31
|
}
|
|
29
32
|
|
|
30
33
|
function categoricalRamp(base) {
|
|
@@ -75,7 +78,7 @@ export function createGradientPlotPaint(profile, {
|
|
|
75
78
|
const stops = values.map((_, index) => {
|
|
76
79
|
const fraction = intensities[index] / maximum;
|
|
77
80
|
const offset = Number(
|
|
78
|
-
(
|
|
81
|
+
inverseLerp(mapped[index], startPosition, endPosition).toFixed(12)
|
|
79
82
|
);
|
|
80
83
|
return {
|
|
81
84
|
offset: Object.is(offset, -0) ? 0 : offset,
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
import { resolveOptionalUserId, validateUserId } from "../../core/identifiers.js";
|
|
2
2
|
import { findLayer, hasLayer } from "../../selectors/layers.js";
|
|
3
3
|
|
|
4
|
-
const CATEGORICAL = Object.freeze(["nominal", "ordinal"
|
|
4
|
+
const CATEGORICAL = Object.freeze(["nominal", "ordinal"]);
|
|
5
5
|
|
|
6
6
|
export function resolveGradientOrientation(x, y) {
|
|
7
7
|
const xType = x?.fieldType;
|
|
@@ -1,17 +1,17 @@
|
|
|
1
|
-
import {
|
|
1
|
+
import { registerAxisTickGroupActions } from "./tickGroups.js";
|
|
2
|
+
import { registerCompleteAxisEditActions } from "./edit.js";
|
|
2
3
|
import { registerAxisLabelActions } from "./labels.js";
|
|
3
4
|
import { registerAxisLineActions } from "./lines.js";
|
|
4
|
-
import { registerAxisTickGroupActions } from "./tickGroups.js";
|
|
5
5
|
import { registerAxisTickActions } from "./ticks.js";
|
|
6
6
|
import { registerAxisTitleActions } from "./titles.js";
|
|
7
7
|
import { registerAxisActions } from "./axis.js";
|
|
8
|
-
import { registerCompleteAxisEditActions } from "./edit.js";
|
|
9
8
|
import {
|
|
10
9
|
removeRadialAxis,
|
|
11
10
|
removeThetaAxis,
|
|
12
11
|
removeXAxis,
|
|
13
12
|
removeYAxis
|
|
14
13
|
} from "./remove.js";
|
|
14
|
+
import { registerAxisCollectionActions } from "./axes.js";
|
|
15
15
|
import { registerParallelAxisActions } from "./parallel.js";
|
|
16
16
|
|
|
17
17
|
export function registerBasicCartesianAxisActions(ProgramClass) {
|