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
|
@@ -4,10 +4,14 @@ import { readQuantitativeField } from "../../grammar/scales/index.js";
|
|
|
4
4
|
import { BAR_GRAINS, resolveBarGrain } from "../../grammar/bars/policy.js";
|
|
5
5
|
import { resolveFacetScaleDomains } from "../../grammar/facets/scales.js";
|
|
6
6
|
import {
|
|
7
|
+
applyLayerEmptyDataView,
|
|
7
8
|
applyMaterializationPlan,
|
|
8
9
|
planScaleGuideRematerialization
|
|
9
10
|
} from "../../materialization/dependencies.js";
|
|
10
|
-
import {
|
|
11
|
+
import {
|
|
12
|
+
getLayerScaleIds,
|
|
13
|
+
getMarkMaterializationStep
|
|
14
|
+
} from "../../materialization/marks/index.js";
|
|
11
15
|
import { buildMaterializationPlan } from "../../materialization/planner.js";
|
|
12
16
|
import { requireDataset } from "../../selectors/datasets.js";
|
|
13
17
|
import { requireLayer } from "../../selectors/layers.js";
|
|
@@ -56,7 +60,7 @@ function applySharedHistogramBoundaries(program, layerId, boundaries) {
|
|
|
56
60
|
});
|
|
57
61
|
}
|
|
58
62
|
|
|
59
|
-
function
|
|
63
|
+
function buildFacetCellCandidate(
|
|
60
64
|
base,
|
|
61
65
|
definition,
|
|
62
66
|
cell,
|
|
@@ -81,12 +85,6 @@ function deriveCellProgram(
|
|
|
81
85
|
});
|
|
82
86
|
source = id;
|
|
83
87
|
}
|
|
84
|
-
if (requireDataset(child, cell.data).values.length === 0) {
|
|
85
|
-
while (child.semanticSpec.layers.length > 0) {
|
|
86
|
-
child = child.removeMark({ target: child.semanticSpec.layers[0].id });
|
|
87
|
-
}
|
|
88
|
-
return child;
|
|
89
|
-
}
|
|
90
88
|
const datasets = new Map([[definition.data, cell.data]]);
|
|
91
89
|
for (const replay of definition.dependencies.replay) {
|
|
92
90
|
const source = datasets.get(replay.source);
|
|
@@ -108,6 +106,7 @@ function deriveCellProgram(
|
|
|
108
106
|
});
|
|
109
107
|
datasets.set(replay.id, id);
|
|
110
108
|
}
|
|
109
|
+
const reboundData = new Map();
|
|
111
110
|
for (const layer of definition.dependencies.layers) {
|
|
112
111
|
const data = datasets.get(layer.data);
|
|
113
112
|
if (data === undefined) {
|
|
@@ -115,6 +114,14 @@ function deriveCellProgram(
|
|
|
115
114
|
`Facet layer "${layer.id}" has no replayed dataset in cell "${cell.id}".`
|
|
116
115
|
);
|
|
117
116
|
}
|
|
117
|
+
reboundData.set(layer.id, data);
|
|
118
|
+
const statistical = child.markConfigs[layer.id]?.statisticalReference;
|
|
119
|
+
if (statistical !== undefined) {
|
|
120
|
+
child = child._withMarkConfig(layer.id, {
|
|
121
|
+
...child.markConfigs[layer.id],
|
|
122
|
+
statisticalReference: { ...statistical, dataId: data }
|
|
123
|
+
});
|
|
124
|
+
}
|
|
118
125
|
child = child.rebindLayerData({ id: layer.id, data });
|
|
119
126
|
child = applySharedHistogramBoundaries(
|
|
120
127
|
child,
|
|
@@ -134,20 +141,35 @@ function deriveCellProgram(
|
|
|
134
141
|
}
|
|
135
142
|
child = child.rebindGradientPlotProfile({ id, profile, source });
|
|
136
143
|
}
|
|
137
|
-
const
|
|
138
|
-
|
|
139
|
-
|
|
140
|
-
|
|
141
|
-
|
|
142
|
-
|
|
144
|
+
const primaryLayers = definition.dependencies.primaryLayers ??
|
|
145
|
+
definition.dependencies.layers.map(layer => layer.id);
|
|
146
|
+
const populated = primaryLayers.some(id => {
|
|
147
|
+
const data = reboundData.get(id);
|
|
148
|
+
return data !== undefined && requireDataset(child, data).values.length > 0;
|
|
149
|
+
});
|
|
150
|
+
if (!populated) {
|
|
151
|
+
for (const layer of definition.dependencies.layers) {
|
|
152
|
+
child = applyLayerEmptyDataView(child, layer.id);
|
|
153
|
+
}
|
|
154
|
+
return { program: child, populated: false };
|
|
155
|
+
}
|
|
156
|
+
const scaleIds = [...new Set(child.semanticSpec.layers.flatMap(getLayerScaleIds))];
|
|
157
|
+
const program = applyMaterializationPlan(child, buildMaterializationPlan({
|
|
143
158
|
scales: scaleIds.map(id => ({
|
|
144
159
|
op: "rematerializeScale",
|
|
145
160
|
args: { id, guides: false, marks: false }
|
|
146
161
|
}))
|
|
147
162
|
}));
|
|
163
|
+
return { program, populated: true };
|
|
148
164
|
}
|
|
149
165
|
|
|
150
|
-
function applyResolvedDomains(
|
|
166
|
+
function applyResolvedDomains(
|
|
167
|
+
program,
|
|
168
|
+
childId,
|
|
169
|
+
resolution,
|
|
170
|
+
baseResolved,
|
|
171
|
+
{ marks: materializeMarks = true } = {}
|
|
172
|
+
) {
|
|
151
173
|
let next = program;
|
|
152
174
|
for (const [id, scaleResolution] of Object.entries(resolution.scales)) {
|
|
153
175
|
const current = next.resolvedScales[id];
|
|
@@ -157,19 +179,22 @@ function applyResolvedDomains(program, childId, resolution, baseResolved) {
|
|
|
157
179
|
const shared = scaleResolution.policy === "shared"
|
|
158
180
|
? baseResolved?.[id]
|
|
159
181
|
: undefined;
|
|
182
|
+
const semanticDomain = findSemanticScale(next, id)?.domain;
|
|
183
|
+
const domain = scaleResolution.childDomains[childId] ??
|
|
184
|
+
scaleResolution.domain ?? semanticDomain;
|
|
160
185
|
next = next._withResolvedScale(id, {
|
|
161
186
|
...current,
|
|
162
187
|
...shared,
|
|
163
|
-
domain
|
|
188
|
+
domain
|
|
164
189
|
});
|
|
165
190
|
}
|
|
166
|
-
const marks = next.semanticSpec.layers.flatMap(layer => {
|
|
191
|
+
const marks = materializeMarks ? next.semanticSpec.layers.flatMap(layer => {
|
|
167
192
|
const step = getMarkMaterializationStep(next, layer);
|
|
168
193
|
if (step === undefined) return [];
|
|
169
|
-
return ["bar", "line", "area"].includes(layer.mark?.type)
|
|
194
|
+
return ["bar", "line", "area", "arc"].includes(layer.mark?.type)
|
|
170
195
|
? [{ ...step, args: { ...step.args, scales: false } }]
|
|
171
196
|
: [step];
|
|
172
|
-
});
|
|
197
|
+
}) : [];
|
|
173
198
|
const guides = Object.keys(resolution.scales).flatMap(id =>
|
|
174
199
|
planScaleGuideRematerialization(next, id)
|
|
175
200
|
);
|
|
@@ -179,6 +204,22 @@ function applyResolvedDomains(program, childId, resolution, baseResolved) {
|
|
|
179
204
|
);
|
|
180
205
|
}
|
|
181
206
|
|
|
207
|
+
function materializeFacetCell(
|
|
208
|
+
child,
|
|
209
|
+
childId,
|
|
210
|
+
resolution,
|
|
211
|
+
baseResolved,
|
|
212
|
+
populated
|
|
213
|
+
) {
|
|
214
|
+
return applyResolvedDomains(
|
|
215
|
+
child,
|
|
216
|
+
childId,
|
|
217
|
+
resolution,
|
|
218
|
+
baseResolved,
|
|
219
|
+
{ marks: populated }
|
|
220
|
+
);
|
|
221
|
+
}
|
|
222
|
+
|
|
182
223
|
export function deriveFacetChildren(
|
|
183
224
|
base,
|
|
184
225
|
definition,
|
|
@@ -196,16 +237,23 @@ export function deriveFacetChildren(
|
|
|
196
237
|
const bins = xPolicy === "shared"
|
|
197
238
|
? sharedHistogramBoundaries(template)
|
|
198
239
|
: new Map();
|
|
199
|
-
const
|
|
240
|
+
const candidates = Object.fromEntries(definition.cells.map(cell => [
|
|
200
241
|
cell.id,
|
|
201
|
-
|
|
242
|
+
buildFacetCellCandidate(template, definition, cell, bins, scales)
|
|
202
243
|
]));
|
|
244
|
+
const independentlyResolved = Object.fromEntries(Object.entries(candidates).map(
|
|
245
|
+
([id, candidate]) => [id, candidate.program]
|
|
246
|
+
));
|
|
247
|
+
const populatedIds = new Set(Object.entries(candidates).flatMap(
|
|
248
|
+
([id, candidate]) => candidate.populated ? [id] : []
|
|
249
|
+
));
|
|
203
250
|
return resolveFacetChildrenScales(
|
|
204
251
|
template,
|
|
205
252
|
definition.cells.map(cell => cell.id),
|
|
206
253
|
independentlyResolved,
|
|
207
254
|
scales,
|
|
208
|
-
closeInheritedAction
|
|
255
|
+
closeInheritedAction,
|
|
256
|
+
populatedIds
|
|
209
257
|
);
|
|
210
258
|
}
|
|
211
259
|
|
|
@@ -214,14 +262,18 @@ export function resolveFacetChildrenScales(
|
|
|
214
262
|
cellIds,
|
|
215
263
|
independentlyResolved,
|
|
216
264
|
scales = {},
|
|
217
|
-
closeInheritedAction = false
|
|
265
|
+
closeInheritedAction = false,
|
|
266
|
+
populatedIds = undefined
|
|
218
267
|
) {
|
|
219
268
|
const populated = Object.fromEntries(cellIds.flatMap(id => {
|
|
220
269
|
const child = independentlyResolved[id];
|
|
221
270
|
if (child === undefined) {
|
|
222
271
|
throw new Error(`Facet derivation is missing child "${id}".`);
|
|
223
272
|
}
|
|
224
|
-
|
|
273
|
+
const populated = populatedIds === undefined
|
|
274
|
+
? child.semanticSpec.layers.length > 0
|
|
275
|
+
: populatedIds.has(id);
|
|
276
|
+
return populated ? [[id, child]] : [];
|
|
225
277
|
}));
|
|
226
278
|
if (Object.keys(populated).length === 0) {
|
|
227
279
|
throw new Error("Facet derivation requires at least one populated cell.");
|
|
@@ -235,17 +287,30 @@ export function resolveFacetChildrenScales(
|
|
|
235
287
|
scales,
|
|
236
288
|
template.resolvedScales
|
|
237
289
|
);
|
|
290
|
+
const emptyIds = cellIds.filter(id => !Object.hasOwn(populated, id));
|
|
291
|
+
const scalesById = new Map(template.semanticSpec.scales.map(scale => [scale.id, scale]));
|
|
292
|
+
for (const childId of emptyIds) {
|
|
293
|
+
const unresolved = Object.entries(resolution.scales).find(([id, value]) =>
|
|
294
|
+
value.policy === "independent" && scalesById.get(id)?.domain === "auto"
|
|
295
|
+
);
|
|
296
|
+
if (unresolved !== undefined) {
|
|
297
|
+
throw new Error(
|
|
298
|
+
`Facet child "${childId}" cannot resolve independent scale "${unresolved[0]}" from an empty partition.`
|
|
299
|
+
);
|
|
300
|
+
}
|
|
301
|
+
}
|
|
238
302
|
const resolvedChildren = Object.fromEntries(
|
|
239
303
|
cellIds.map(id => {
|
|
240
304
|
const child = independentlyResolved[id];
|
|
241
305
|
if (child.semanticSpec.layers.length === 0) {
|
|
242
306
|
return [id, closeInheritedAction ? child._exitAction() : child];
|
|
243
307
|
}
|
|
244
|
-
const resolved =
|
|
308
|
+
const resolved = materializeFacetCell(
|
|
245
309
|
child,
|
|
246
310
|
id,
|
|
247
311
|
resolution,
|
|
248
|
-
template.resolvedScales
|
|
312
|
+
template.resolvedScales,
|
|
313
|
+
Object.hasOwn(populated, id)
|
|
249
314
|
);
|
|
250
315
|
return [id, closeInheritedAction ? resolved._exitAction() : resolved];
|
|
251
316
|
})
|
|
@@ -2,6 +2,10 @@ import { assertGuideOptions, guideConflict } from "../guides/reuse.js";
|
|
|
2
2
|
import { action } from "../../core/action.js";
|
|
3
3
|
import { validateKeys } from "../../core/validation.js";
|
|
4
4
|
import { GRADIENT_PROFILE_FIELDS } from "../../grammar/gradientProfile.js";
|
|
5
|
+
import {
|
|
6
|
+
requestedStrokeDetails,
|
|
7
|
+
STROKE_STYLE_PROPERTIES
|
|
8
|
+
} from "../../grammar/strokeStyle.js";
|
|
5
9
|
import { resolveGraphicBounds } from "../../layout/canvas.js";
|
|
6
10
|
import { findLayer } from "../../selectors/layers.js";
|
|
7
11
|
import { createDensityLegendPaint } from "./paint.js";
|
|
@@ -9,7 +13,7 @@ import { createDensityLegendPaint } from "./paint.js";
|
|
|
9
13
|
const CENTER_OPTIONS = Object.freeze([
|
|
10
14
|
"id", "owner", "data", "category", "categoryType", "coordinate",
|
|
11
15
|
"categoryScale", "measureScale", "orientation", "size", "stroke",
|
|
12
|
-
"strokeWidth"
|
|
16
|
+
"strokeWidth", ...STROKE_STYLE_PROPERTIES
|
|
13
17
|
]);
|
|
14
18
|
const LEGEND_OPTIONS = Object.freeze(["owner", "title", "position"]);
|
|
15
19
|
|
|
@@ -23,7 +27,11 @@ export const createGradientPlotCenter = action(
|
|
|
23
27
|
const categoryAction = args.orientation === "vertical" ? "encodeX" : "encodeY";
|
|
24
28
|
const measureAction = args.orientation === "vertical" ? "encodeY" : "encodeX";
|
|
25
29
|
const spanOrientation = args.orientation === "vertical" ? "horizontal" : "vertical";
|
|
26
|
-
let next = this.createRuleMark({
|
|
30
|
+
let next = this.createRuleMark({
|
|
31
|
+
id: args.id,
|
|
32
|
+
data: args.data,
|
|
33
|
+
...requestedStrokeDetails(args, "createGradientPlotCenter")
|
|
34
|
+
});
|
|
27
35
|
next = next[categoryAction]({
|
|
28
36
|
target: args.id,
|
|
29
37
|
field: args.category,
|
|
@@ -7,6 +7,7 @@ import { findDataset } from "../../selectors/datasets.js";
|
|
|
7
7
|
import { findLayer } from "../../selectors/layers.js";
|
|
8
8
|
import { removeOwnedMark } from "../marks/remove.js";
|
|
9
9
|
import { GRADIENT_PROFILE_FIELDS } from "../../grammar/gradientProfile.js";
|
|
10
|
+
import { requestedStrokeDetails } from "../../grammar/strokeStyle.js";
|
|
10
11
|
import { removeGradientPlotLegend } from "./components.js";
|
|
11
12
|
import {
|
|
12
13
|
resolveDistributionRoles,
|
|
@@ -40,6 +41,13 @@ function removeCenter(program, id) {
|
|
|
40
41
|
return removeOwnedMark(program, id, true);
|
|
41
42
|
}
|
|
42
43
|
|
|
44
|
+
function editCenterStrokeDetails(program, id, center) {
|
|
45
|
+
const details = requestedStrokeDetails(center, "Gradient plot center");
|
|
46
|
+
return Object.keys(details).length === 0
|
|
47
|
+
? program
|
|
48
|
+
: program.editRuleMark({ target: id, ...details });
|
|
49
|
+
}
|
|
50
|
+
|
|
43
51
|
function roleCandidate(program, owner, current, args) {
|
|
44
52
|
return {
|
|
45
53
|
source: Object.hasOwn(args, "data")
|
|
@@ -219,10 +227,11 @@ export const editGradientPlot = action(
|
|
|
219
227
|
orientation: candidate.orientation,
|
|
220
228
|
size: spanSize,
|
|
221
229
|
stroke: center.stroke,
|
|
222
|
-
strokeWidth: center.strokeWidth
|
|
230
|
+
strokeWidth: center.strokeWidth,
|
|
231
|
+
...requestedStrokeDetails(center, "Gradient plot center")
|
|
223
232
|
});
|
|
224
233
|
} else if (retainedCenter) {
|
|
225
|
-
next = next
|
|
234
|
+
next = editCenterStrokeDetails(next, current.centerId, center)
|
|
226
235
|
.encodeStroke({ target: current.centerId, value: center.stroke })
|
|
227
236
|
.encodeStrokeWidth({
|
|
228
237
|
target: current.centerId,
|
|
@@ -291,10 +300,11 @@ export const editGradientPlot = action(
|
|
|
291
300
|
orientation: current.orientation,
|
|
292
301
|
size: 1,
|
|
293
302
|
stroke: center.stroke,
|
|
294
|
-
strokeWidth: center.strokeWidth
|
|
303
|
+
strokeWidth: center.strokeWidth,
|
|
304
|
+
...requestedStrokeDetails(center, "Gradient plot center")
|
|
295
305
|
});
|
|
296
306
|
} else if (center !== false) {
|
|
297
|
-
next = next
|
|
307
|
+
next = editCenterStrokeDetails(next, current.centerId, center)
|
|
298
308
|
.encodeStroke({ target: current.centerId, value: center.stroke })
|
|
299
309
|
.encodeStrokeWidth({ target: current.centerId, value: center.strokeWidth });
|
|
300
310
|
}
|
|
@@ -4,6 +4,7 @@ import { action } from "../../core/action.js";
|
|
|
4
4
|
import { validateUserId } from "../../core/identifiers.js";
|
|
5
5
|
import { isPlainObject } from "../../core/immutable.js";
|
|
6
6
|
import { GRADIENT_PROFILE_FIELDS } from "../../grammar/gradientProfile.js";
|
|
7
|
+
import { requestedStrokeDetails } from "../../grammar/strokeStyle.js";
|
|
7
8
|
import {
|
|
8
9
|
mapContinuousScaleValues,
|
|
9
10
|
mapOrdinalPositionValues
|
|
@@ -248,7 +249,8 @@ export const materializeGradientPlot = action(
|
|
|
248
249
|
orientation,
|
|
249
250
|
size: Math.max(1, categoryScale.bandwidth * config.width.band - 16),
|
|
250
251
|
stroke: config.center.stroke,
|
|
251
|
-
strokeWidth: config.center.strokeWidth
|
|
252
|
+
strokeWidth: config.center.strokeWidth,
|
|
253
|
+
...requestedStrokeDetails(config.center, "Gradient plot center")
|
|
252
254
|
});
|
|
253
255
|
}
|
|
254
256
|
const guides = config.guides;
|
|
@@ -5,6 +5,10 @@ import {
|
|
|
5
5
|
validateUnitInterval
|
|
6
6
|
} from "../../core/validation.js";
|
|
7
7
|
import { normalizePalette } from "../../grammar/palettes.js";
|
|
8
|
+
import {
|
|
9
|
+
requestedStrokeDetails,
|
|
10
|
+
STROKE_STYLE_PROPERTIES
|
|
11
|
+
} from "../../grammar/strokeStyle.js";
|
|
8
12
|
|
|
9
13
|
export const GRADIENT_PLOT_OPTIONS = Object.freeze([
|
|
10
14
|
"id", "target", "data", "x", "y", "coordinate", "density", "width",
|
|
@@ -90,7 +94,7 @@ export function resolveGradientCenter(
|
|
|
90
94
|
if (value === false) return false;
|
|
91
95
|
const options = plain(
|
|
92
96
|
value,
|
|
93
|
-
["type", "stroke", "strokeWidth"],
|
|
97
|
+
["type", "stroke", "strokeWidth", ...STROKE_STYLE_PROPERTIES],
|
|
94
98
|
"center",
|
|
95
99
|
operation
|
|
96
100
|
);
|
|
@@ -108,7 +112,11 @@ export function resolveGradientCenter(
|
|
|
108
112
|
: validateNonNegativeFinite(
|
|
109
113
|
options.strokeWidth,
|
|
110
114
|
`${operation} center.strokeWidth`
|
|
111
|
-
)
|
|
115
|
+
),
|
|
116
|
+
...requestedStrokeDetails(
|
|
117
|
+
{ ...(previous ?? {}), ...options },
|
|
118
|
+
`${operation} center`
|
|
119
|
+
)
|
|
112
120
|
});
|
|
113
121
|
}
|
|
114
122
|
|
|
@@ -51,6 +51,8 @@ export function hasInferableLegend(program, layers = program.semanticSpec.layers
|
|
|
51
51
|
isOpacityLegendLayer(layer) ||
|
|
52
52
|
(layer.mark?.type === "point" &&
|
|
53
53
|
layer.encoding?.size?.scale !== undefined) ||
|
|
54
|
+
(layer.mark?.type === "point" &&
|
|
55
|
+
layer.encoding?.stroke?.scale !== undefined) ||
|
|
54
56
|
(layer.mark?.type === "point" &&
|
|
55
57
|
layer.encoding?.color?.scale !== undefined &&
|
|
56
58
|
(layer.encoding?.shape?.scale !== undefined ||
|
|
@@ -58,11 +60,15 @@ export function hasInferableLegend(program, layers = program.semanticSpec.layers
|
|
|
58
60
|
findSemanticScale(program, layer.encoding.color.scale)?.type
|
|
59
61
|
))) ||
|
|
60
62
|
(layer.mark?.type === "line" &&
|
|
61
|
-
["color", "strokeDash"].some(
|
|
63
|
+
["color", "stroke", "strokeDash"].some(
|
|
62
64
|
channel => layer.encoding?.[channel]?.scale !== undefined
|
|
63
65
|
)) ||
|
|
64
66
|
(["bar", "area", "arc", "rect"].includes(layer.mark?.type) &&
|
|
65
|
-
|
|
67
|
+
["color", "stroke"].some(
|
|
68
|
+
channel => layer.encoding?.[channel]?.scale !== undefined
|
|
69
|
+
)) ||
|
|
70
|
+
(["rule", "tick"].includes(layer.mark?.type) &&
|
|
71
|
+
layer.encoding?.stroke?.scale !== undefined)
|
|
66
72
|
)
|
|
67
73
|
);
|
|
68
74
|
}
|
|
@@ -9,7 +9,7 @@ import {
|
|
|
9
9
|
validateNonNegativeFinite,
|
|
10
10
|
validatePositiveFinite
|
|
11
11
|
} from "../../../core/validation.js";
|
|
12
|
-
import {
|
|
12
|
+
import { resolveGuideCoordinateBounds } from "../../../materialization/coordinateBounds.js";
|
|
13
13
|
import {
|
|
14
14
|
isTransformedScaleType,
|
|
15
15
|
mapContinuousScaleValues,
|
|
@@ -38,11 +38,15 @@ import {
|
|
|
38
38
|
import { resolveConcreteGraphicBounds } from
|
|
39
39
|
"../../../grammar/schemas/graphicBounds.js";
|
|
40
40
|
import { wrapText } from "../../../layout/text.js";
|
|
41
|
+
import {
|
|
42
|
+
normalizeDisplayLabelMap,
|
|
43
|
+
resolveDisplayLabel
|
|
44
|
+
} from "../../../grammar/displayLabels.js";
|
|
41
45
|
|
|
42
46
|
const OPTIONS = [
|
|
43
47
|
"scale", "position", "count", "values", "offset", "format", "color",
|
|
44
48
|
"fontSize", "fontFamily", "fontWeight", "rotation", "maxWidth", "wrap",
|
|
45
|
-
"lineHeight", "overlap"
|
|
49
|
+
"lineHeight", "overlap", "labelMap"
|
|
46
50
|
];
|
|
47
51
|
|
|
48
52
|
const DEFAULTS = {
|
|
@@ -136,6 +140,24 @@ function validateConfig(channel, config) {
|
|
|
136
140
|
}
|
|
137
141
|
}
|
|
138
142
|
|
|
143
|
+
function normalizeAxisLabelMap(program, config, args, operation) {
|
|
144
|
+
if (!Object.hasOwn(args, "labelMap")) return config;
|
|
145
|
+
const scale = program.resolvedScales[config.scale];
|
|
146
|
+
if (!["ordinal", "band", "point"].includes(scale?.type)) {
|
|
147
|
+
throw new Error(`${operation} labelMap requires a categorical scale.`);
|
|
148
|
+
}
|
|
149
|
+
const next = { ...config };
|
|
150
|
+
if (args.labelMap === "auto") {
|
|
151
|
+
delete next.labelMap;
|
|
152
|
+
} else {
|
|
153
|
+
next.labelMap = normalizeDisplayLabelMap(
|
|
154
|
+
args.labelMap,
|
|
155
|
+
`${operation} labelMap`
|
|
156
|
+
);
|
|
157
|
+
}
|
|
158
|
+
return next;
|
|
159
|
+
}
|
|
160
|
+
|
|
139
161
|
function assertTickCompatibility(ticks, config, operation) {
|
|
140
162
|
if (!ticks) return;
|
|
141
163
|
if (ticks.scale !== config.scale || ticks.mode !== config.mode) throw new Error(`${operation} conflicts with axis ticks.`);
|
|
@@ -198,8 +220,15 @@ function unionLabelBounds(records) {
|
|
|
198
220
|
|
|
199
221
|
function resolve(program, channel, config) {
|
|
200
222
|
const scale = program.resolvedScales[config.scale];
|
|
201
|
-
const bounds =
|
|
223
|
+
const bounds = resolveGuideCoordinateBounds(program, {
|
|
224
|
+
coordinate: program.semanticSpec.guides.axis?.[channel]?.coordinate,
|
|
225
|
+
scale: config.scale,
|
|
226
|
+
channel
|
|
227
|
+
});
|
|
202
228
|
const discrete = ["ordinal", "band", "point"].includes(scale?.type);
|
|
229
|
+
if (config.labelMap !== undefined && !discrete) {
|
|
230
|
+
throw new Error("Axis labelMap requires a categorical scale.");
|
|
231
|
+
}
|
|
203
232
|
if ((
|
|
204
233
|
!["linear", "time", "ordinal", "band", "point"].includes(scale?.type) &&
|
|
205
234
|
!isTransformedScaleType(scale?.type)
|
|
@@ -217,9 +246,7 @@ function resolve(program, channel, config) {
|
|
|
217
246
|
const positions = discrete
|
|
218
247
|
? mapOrdinalPositionValues(values, scale)
|
|
219
248
|
: mapContinuousScaleValues(values, scale);
|
|
220
|
-
const
|
|
221
|
-
? formatTimeTicks(values, scale.domain)
|
|
222
|
-
: values.map(value => formatAxisValue(
|
|
249
|
+
const fallback = value => formatAxisValue(
|
|
223
250
|
value,
|
|
224
251
|
scale.type,
|
|
225
252
|
config.format,
|
|
@@ -228,7 +255,12 @@ function resolve(program, channel, config) {
|
|
|
228
255
|
: isTransformedScaleType(scale.type)
|
|
229
256
|
? formatTransformedTick(scale.type, item)
|
|
230
257
|
: String(item)
|
|
231
|
-
)
|
|
258
|
+
);
|
|
259
|
+
const text = discrete
|
|
260
|
+
? values.map(value => resolveDisplayLabel(value, config.labelMap, fallback))
|
|
261
|
+
: scale.type === "time" && config.format === "auto"
|
|
262
|
+
? formatTimeTicks(values, scale.domain)
|
|
263
|
+
: values.map(fallback);
|
|
232
264
|
const geometry = {
|
|
233
265
|
values,
|
|
234
266
|
...resolveAxisLabelGeometry({
|
|
@@ -294,13 +326,14 @@ function makeEdit(channel) {
|
|
|
294
326
|
const mode = Object.hasOwn(args, "values") || inferredValues !== undefined
|
|
295
327
|
? "values"
|
|
296
328
|
: Object.hasOwn(args, "count") ? "count" : previous.mode;
|
|
297
|
-
|
|
329
|
+
let config = normalizeLabelLayout({
|
|
298
330
|
...previous,
|
|
299
331
|
...args,
|
|
300
332
|
...(inferredValues === undefined ? {} : { values: inferredValues }),
|
|
301
333
|
...(explicitMode ? { inferredValues: false } : {}),
|
|
302
334
|
mode
|
|
303
335
|
}, args, op);
|
|
336
|
+
config = normalizeAxisLabelMap(this, config, args, op);
|
|
304
337
|
if (mode === "values") delete config.count; else delete config.values;
|
|
305
338
|
validateConfig(channel, config);
|
|
306
339
|
assertTickCompatibility(this.guideConfigs.axis?.[channel]?.ticks, config, op);
|
|
@@ -349,8 +382,15 @@ function makeCreate(channel) {
|
|
|
349
382
|
const ticks = this.guideConfigs.axis?.[channel]?.ticks;
|
|
350
383
|
const hasValues = Object.hasOwn(args, "values");
|
|
351
384
|
const hasCount = Object.hasOwn(args, "count");
|
|
352
|
-
const
|
|
353
|
-
const
|
|
385
|
+
const resolvedScale = this.resolvedScales[scale];
|
|
386
|
+
const inferredDiscreteValues = !hasValues && !hasCount && ticks === undefined &&
|
|
387
|
+
["ordinal", "band", "point"].includes(resolvedScale?.type)
|
|
388
|
+
? resolvedScale.domain
|
|
389
|
+
: undefined;
|
|
390
|
+
const mode = hasValues || inferredDiscreteValues !== undefined
|
|
391
|
+
? "values"
|
|
392
|
+
: hasCount ? "count" : ticks?.mode ?? "count";
|
|
393
|
+
let config = normalizeLabelLayout({
|
|
354
394
|
scale,
|
|
355
395
|
position: defaultAxisPosition(channel),
|
|
356
396
|
offset: channel === "x" ? 18 : 12,
|
|
@@ -362,10 +402,16 @@ function makeCreate(channel) {
|
|
|
362
402
|
rotation: DEFAULTS.rotation,
|
|
363
403
|
overlap: DEFAULTS.overlap,
|
|
364
404
|
...args,
|
|
365
|
-
inferredValues: !hasValues && !hasCount &&
|
|
405
|
+
inferredValues: !hasValues && !hasCount &&
|
|
406
|
+
(ticks?.inferredValues === true || inferredDiscreteValues !== undefined),
|
|
366
407
|
mode
|
|
367
408
|
}, args, op);
|
|
368
|
-
|
|
409
|
+
config = normalizeAxisLabelMap(this, config, args, op);
|
|
410
|
+
if (mode === "values") {
|
|
411
|
+
config.values ??= ticks?.values ?? inferredDiscreteValues;
|
|
412
|
+
} else {
|
|
413
|
+
config.count ??= ticks?.count ?? DEFAULTS.count;
|
|
414
|
+
}
|
|
369
415
|
validateConfig(channel, config);
|
|
370
416
|
assertTickCompatibility(ticks, config, op);
|
|
371
417
|
resolve(this, channel, config);
|
|
@@ -7,7 +7,7 @@ import {
|
|
|
7
7
|
validateNonEmptyString,
|
|
8
8
|
validateNonNegativeFinite
|
|
9
9
|
} from "../../../core/validation.js";
|
|
10
|
-
import {
|
|
10
|
+
import { resolveGuideCoordinateBounds } from "../../../materialization/coordinateBounds.js";
|
|
11
11
|
import { DEFAULT_COLORS } from "../../../theme/defaults.js";
|
|
12
12
|
import {
|
|
13
13
|
defaultAxisPosition,
|
|
@@ -53,7 +53,11 @@ function resolveGeometry(program, channel, scaleId, position) {
|
|
|
53
53
|
|
|
54
54
|
const resolvedScale = program.resolvedScales[scaleId];
|
|
55
55
|
const range = resolvedScale?.range;
|
|
56
|
-
const bounds =
|
|
56
|
+
const bounds = resolveGuideCoordinateBounds(program, {
|
|
57
|
+
coordinate: program.semanticSpec.guides.axis?.[channel]?.coordinate,
|
|
58
|
+
scale: scaleId,
|
|
59
|
+
channel
|
|
60
|
+
});
|
|
57
61
|
|
|
58
62
|
if (!Array.isArray(range) || range.length !== 2 || !range.every(Number.isFinite)) {
|
|
59
63
|
throw new Error(`Axis line requires a resolved numeric scale "${scaleId}".`);
|
|
@@ -6,7 +6,7 @@ import {
|
|
|
6
6
|
transformedTicks
|
|
7
7
|
} from "../../../../grammar/scales/index.js";
|
|
8
8
|
import { niceTicks } from "../../../../grammar/ticks.js";
|
|
9
|
-
import {
|
|
9
|
+
import { resolveCoordinateBounds } from "../../../../materialization/coordinateBounds.js";
|
|
10
10
|
import { findCoordinate } from "../../../../selectors/coordinates.js";
|
|
11
11
|
import { findLayer } from "../../../../selectors/layers.js";
|
|
12
12
|
import { formatAxisValue } from "../policy.js";
|
|
@@ -85,7 +85,11 @@ function componentValues(program, dimension, config) {
|
|
|
85
85
|
}
|
|
86
86
|
|
|
87
87
|
export function resolveStyledParallelAxes(program, dimensions) {
|
|
88
|
-
const
|
|
88
|
+
const stored = program.guideConfigs.axis?.parallel?.axes;
|
|
89
|
+
const layer = stored === undefined
|
|
90
|
+
? undefined
|
|
91
|
+
: findLayer(program, stored.target);
|
|
92
|
+
const bounds = resolveCoordinateBounds(program, layer?.coordinate);
|
|
89
93
|
const step = bounds.width / (dimensions.length - 1);
|
|
90
94
|
const configs = resolveParallelAxisConfigs(program, dimensions);
|
|
91
95
|
const titles = program.semanticSpec.guides.axis?.parallel?.titles ?? [];
|
|
@@ -30,7 +30,8 @@ const LABEL_OPTIONS = Object.freeze([
|
|
|
30
30
|
"maxWidth",
|
|
31
31
|
"wrap",
|
|
32
32
|
"lineHeight",
|
|
33
|
-
"overlap"
|
|
33
|
+
"overlap",
|
|
34
|
+
"labelMap"
|
|
34
35
|
]);
|
|
35
36
|
const SHARED_CREATE = Object.freeze(["scale", "position", "count", "values"]);
|
|
36
37
|
const SHARED_EDIT = Object.freeze(["position", "count", "values"]);
|
|
@@ -7,7 +7,7 @@ import {
|
|
|
7
7
|
validateNonNegativeFinite,
|
|
8
8
|
validateOptionObject
|
|
9
9
|
} from "../../../core/validation.js";
|
|
10
|
-
import {
|
|
10
|
+
import { resolveGuideCoordinateBounds } from "../../../materialization/coordinateBounds.js";
|
|
11
11
|
import {
|
|
12
12
|
isTransformedScaleType,
|
|
13
13
|
mapContinuousScaleValues,
|
|
@@ -69,7 +69,11 @@ function validateConfig(channel, config) {
|
|
|
69
69
|
|
|
70
70
|
function geometry(program, channel, config) {
|
|
71
71
|
const scale = program.resolvedScales[config.scale];
|
|
72
|
-
const bounds =
|
|
72
|
+
const bounds = resolveGuideCoordinateBounds(program, {
|
|
73
|
+
coordinate: program.semanticSpec.guides.axis?.[channel]?.coordinate,
|
|
74
|
+
scale: config.scale,
|
|
75
|
+
channel
|
|
76
|
+
});
|
|
73
77
|
const discrete = ["ordinal", "band", "point"].includes(scale?.type);
|
|
74
78
|
if ((
|
|
75
79
|
!["linear", "time", "ordinal", "band", "point"].includes(scale?.type) &&
|
|
@@ -7,7 +7,7 @@ import {
|
|
|
7
7
|
validateNonEmptyString,
|
|
8
8
|
validateNonNegativeFinite
|
|
9
9
|
} from "../../../core/validation.js";
|
|
10
|
-
import {
|
|
10
|
+
import { resolveGuideCoordinateBounds } from "../../../materialization/coordinateBounds.js";
|
|
11
11
|
import {
|
|
12
12
|
isTransformedScaleType,
|
|
13
13
|
mapContinuousScaleValues,
|
|
@@ -50,7 +50,11 @@ function titleBounds(geometry, config, text) {
|
|
|
50
50
|
}
|
|
51
51
|
|
|
52
52
|
function inferredTitleOffset(program, channel, config) {
|
|
53
|
-
const plot =
|
|
53
|
+
const plot = resolveGuideCoordinateBounds(program, {
|
|
54
|
+
coordinate: program.semanticSpec.guides.axis?.[channel]?.coordinate,
|
|
55
|
+
scale: config.scale,
|
|
56
|
+
channel
|
|
57
|
+
});
|
|
54
58
|
const canvas = findCanvasGraphic(program)?.properties;
|
|
55
59
|
const labels = program.graphicSpec.objects[`${channel}AxisLabels`]
|
|
56
60
|
? resolveConcreteGraphicBounds(program.graphicSpec, `${channel}AxisLabels`)
|
|
@@ -151,7 +155,11 @@ export function inferAxisTitleText(program, channel, scaleId) {
|
|
|
151
155
|
|
|
152
156
|
function resolveGeometry(program, channel, config) {
|
|
153
157
|
const scale = program.resolvedScales[config.scale];
|
|
154
|
-
const bounds =
|
|
158
|
+
const bounds = resolveGuideCoordinateBounds(program, {
|
|
159
|
+
coordinate: program.semanticSpec.guides.axis?.[channel]?.coordinate,
|
|
160
|
+
scale: config.scale,
|
|
161
|
+
channel
|
|
162
|
+
});
|
|
155
163
|
const discrete = ["ordinal", "band", "point"].includes(scale?.type);
|
|
156
164
|
if ((
|
|
157
165
|
!["linear", "time", "ordinal", "band", "point"].includes(scale?.type) &&
|