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
|
@@ -1,5 +1,9 @@
|
|
|
1
1
|
import { validateUserId } from "../../../core/identifiers.js";
|
|
2
|
-
import {
|
|
2
|
+
import {
|
|
3
|
+
LEGEND_CHANNELS,
|
|
4
|
+
LEGEND_CONFIG_KINDS
|
|
5
|
+
} from "../../../core/vocabulary.js";
|
|
6
|
+
import { isDiscreteSizeScaleType } from "../../../grammar/scales/index.js";
|
|
3
7
|
|
|
4
8
|
export function validateLegendChannels(channels, operation) {
|
|
5
9
|
if (!Array.isArray(channels)) throw new TypeError(`${operation} channels must be an array.`);
|
|
@@ -35,3 +39,110 @@ export function resolveLegendTarget(program, requested, operation) {
|
|
|
35
39
|
}
|
|
36
40
|
return targets[0];
|
|
37
41
|
}
|
|
42
|
+
|
|
43
|
+
const CATEGORICAL_KINDS = Object.freeze(["series", "color", "stroke"]);
|
|
44
|
+
const SINGLE_CHANNELS = Object.freeze({
|
|
45
|
+
size: "size",
|
|
46
|
+
opacity: "opacity",
|
|
47
|
+
strokeWidth: "strokeWidth",
|
|
48
|
+
gradient: "color",
|
|
49
|
+
interval: "color",
|
|
50
|
+
strokeGradient: "stroke",
|
|
51
|
+
strokeInterval: "stroke"
|
|
52
|
+
});
|
|
53
|
+
|
|
54
|
+
const asciiCompare = (left, right) => left < right ? -1 : left > right ? 1 : 0;
|
|
55
|
+
|
|
56
|
+
export function legendBlockChannels(kind, config) {
|
|
57
|
+
const channels = CATEGORICAL_KINDS.includes(kind)
|
|
58
|
+
? config?.channels
|
|
59
|
+
: SINGLE_CHANNELS[kind] === undefined
|
|
60
|
+
? undefined
|
|
61
|
+
: [SINGLE_CHANNELS[kind]];
|
|
62
|
+
if (!Array.isArray(channels) || channels.length === 0) {
|
|
63
|
+
throw new Error(`Legend block ${kind} requires at least one channel.`);
|
|
64
|
+
}
|
|
65
|
+
validateLegendChannels(channels, `Legend block ${kind}`);
|
|
66
|
+
return Object.freeze([...channels].sort(asciiCompare));
|
|
67
|
+
}
|
|
68
|
+
|
|
69
|
+
export function legendBlockKey(channels) {
|
|
70
|
+
if (!Array.isArray(channels) || channels.length === 0) {
|
|
71
|
+
throw new TypeError("Legend block key requires a non-empty channel array.");
|
|
72
|
+
}
|
|
73
|
+
return JSON.stringify([...channels].sort(asciiCompare));
|
|
74
|
+
}
|
|
75
|
+
|
|
76
|
+
export function describeLegendBlock(program, kind, config) {
|
|
77
|
+
if (!LEGEND_CONFIG_KINDS.includes(kind)) {
|
|
78
|
+
throw new Error(`Unknown legend block kind "${kind}".`);
|
|
79
|
+
}
|
|
80
|
+
const channels = legendBlockChannels(kind, config);
|
|
81
|
+
const scaleIds = CATEGORICAL_KINDS.includes(kind)
|
|
82
|
+
? config?.scales
|
|
83
|
+
: [config?.scale];
|
|
84
|
+
if (!Array.isArray(scaleIds) || scaleIds.length === 0 ||
|
|
85
|
+
scaleIds.some(id => typeof id !== "string" || program.resolvedScales[id] === undefined)) {
|
|
86
|
+
throw new Error(`Legend block ${kind} requires resolved scales.`);
|
|
87
|
+
}
|
|
88
|
+
const family = CATEGORICAL_KINDS.includes(kind)
|
|
89
|
+
? "categorical"
|
|
90
|
+
: kind === "size"
|
|
91
|
+
? isDiscreteSizeScaleType(program.resolvedScales[scaleIds[0]].type)
|
|
92
|
+
? "discrete-size"
|
|
93
|
+
: "sampled"
|
|
94
|
+
: ["opacity", "strokeWidth"].includes(kind)
|
|
95
|
+
? "sampled"
|
|
96
|
+
: ["gradient", "strokeGradient"].includes(kind)
|
|
97
|
+
? "gradient"
|
|
98
|
+
: "interval";
|
|
99
|
+
return Object.freeze({
|
|
100
|
+
target: config.target,
|
|
101
|
+
kind,
|
|
102
|
+
family,
|
|
103
|
+
key: legendBlockKey(channels),
|
|
104
|
+
channels,
|
|
105
|
+
scaleIds: Object.freeze([...scaleIds]),
|
|
106
|
+
config
|
|
107
|
+
});
|
|
108
|
+
}
|
|
109
|
+
|
|
110
|
+
export function legendBlockDescriptors(program, target) {
|
|
111
|
+
const requested = validateUserId(target, "Legend target id");
|
|
112
|
+
const descriptors = LEGEND_CONFIG_KINDS.flatMap(kind => {
|
|
113
|
+
const config = program.guideConfigs.legend?.[kind];
|
|
114
|
+
return config?.target === requested
|
|
115
|
+
? [describeLegendBlock(program, kind, config)]
|
|
116
|
+
: [];
|
|
117
|
+
});
|
|
118
|
+
const seen = new Set();
|
|
119
|
+
for (const descriptor of descriptors) {
|
|
120
|
+
if (seen.has(descriptor.key)) {
|
|
121
|
+
throw new Error(
|
|
122
|
+
`Legend target "${requested}" has ambiguous block key ${descriptor.key}.`
|
|
123
|
+
);
|
|
124
|
+
}
|
|
125
|
+
seen.add(descriptor.key);
|
|
126
|
+
}
|
|
127
|
+
return Object.freeze(descriptors);
|
|
128
|
+
}
|
|
129
|
+
|
|
130
|
+
export function resolveLegendBlock(program, { target, channel }, operation = "editLegendBlock") {
|
|
131
|
+
const requested = resolveLegendTarget(program, target, operation);
|
|
132
|
+
if (!LEGEND_CHANNELS.includes(channel)) {
|
|
133
|
+
throw new Error(`${operation} has unsupported legend channel "${channel}".`);
|
|
134
|
+
}
|
|
135
|
+
const matches = legendBlockDescriptors(program, requested)
|
|
136
|
+
.filter(descriptor => descriptor.channels.includes(channel));
|
|
137
|
+
if (matches.length === 0) {
|
|
138
|
+
throw new Error(
|
|
139
|
+
`${operation} target "${requested}" has no legend block for channel "${channel}".`
|
|
140
|
+
);
|
|
141
|
+
}
|
|
142
|
+
if (matches.length !== 1) {
|
|
143
|
+
throw new Error(
|
|
144
|
+
`${operation} target "${requested}" has ambiguous channel "${channel}".`
|
|
145
|
+
);
|
|
146
|
+
}
|
|
147
|
+
return matches[0];
|
|
148
|
+
}
|
|
@@ -2,42 +2,191 @@ import { isDiscretizedColorScaleType } from "../../../grammar/scales/types.js";
|
|
|
2
2
|
import { normalizeContinuousLegend } from "./continuous/common.js";
|
|
3
3
|
import { DEFAULT_GRADIENT_SIZE } from "./continuous/gradient.js";
|
|
4
4
|
import { normalizeIntervalLegend } from "./continuous/interval.js";
|
|
5
|
+
import {
|
|
6
|
+
describeLegendBlock,
|
|
7
|
+
legendBlockDescriptors,
|
|
8
|
+
resolveLegendBlock
|
|
9
|
+
} from "./target.js";
|
|
10
|
+
import { validateLegendBlockOverride } from "./blocks.js";
|
|
5
11
|
|
|
6
|
-
const family = type => type === "sequential"
|
|
7
|
-
|
|
12
|
+
const family = (channel, type) => type === "sequential"
|
|
13
|
+
? channel === "stroke" ? "strokeGradient" : "gradient"
|
|
14
|
+
: isDiscretizedColorScaleType(type)
|
|
15
|
+
? channel === "stroke" ? "strokeInterval" : "interval"
|
|
16
|
+
: type === "ordinal"
|
|
17
|
+
? channel === "stroke" ? "stroke" : "color"
|
|
18
|
+
: undefined;
|
|
8
19
|
const same = (a, b) => JSON.stringify(a) === JSON.stringify(b);
|
|
9
20
|
|
|
10
|
-
|
|
11
|
-
const
|
|
21
|
+
function categoricalFamilyCustom(program, kind, stored) {
|
|
22
|
+
const side = ["left", "right"].includes(stored.position);
|
|
23
|
+
const direction = side ? "vertical" : "horizontal";
|
|
24
|
+
const itemGap = side ? 28 : stored.position === "top" ? 24 : 20;
|
|
25
|
+
const order = program.semanticSpec.guides.legend?.[kind]?.order;
|
|
26
|
+
return stored.inferredSymbol !== true ||
|
|
27
|
+
stored.direction !== direction ||
|
|
28
|
+
(stored.columns !== undefined && !(side && stored.columns === 1)) ||
|
|
29
|
+
stored.itemGap !== itemGap || stored.layout !== "edge" ||
|
|
30
|
+
order !== undefined;
|
|
31
|
+
}
|
|
32
|
+
|
|
33
|
+
function planChannelLegendTransition(program, scale, nextType, channel) {
|
|
34
|
+
const from = family(channel, scale.type), to = family(channel, nextType);
|
|
12
35
|
if (from === undefined || to === undefined || from === to) return undefined;
|
|
13
36
|
const stored = program.guideConfigs.legend?.[from];
|
|
14
|
-
if (stored?.scale !== scale.id) return undefined;
|
|
37
|
+
if ((stored?.scale ?? stored?.scales?.[0]) !== scale.id) return undefined;
|
|
38
|
+
const oldDescriptor = describeLegendBlock(program, from, stored);
|
|
39
|
+
const overrideKeys = Object.keys(stored.blockOverrides ?? {});
|
|
40
|
+
if (overrideKeys.some(key => key !== oldDescriptor.key)) {
|
|
41
|
+
throw new Error(`${channel} legend transition found stale legend block overrides.`);
|
|
42
|
+
}
|
|
43
|
+
const blockOverride = stored.blockOverrides?.[oldDescriptor.key];
|
|
15
44
|
const side = ["left", "right"].includes(stored.position);
|
|
16
|
-
const
|
|
45
|
+
const categorical = ["color", "stroke"].includes(from);
|
|
46
|
+
const gradientFamily = from.toLowerCase().endsWith("gradient");
|
|
47
|
+
const defaults = gradientFamily ? normalizeContinuousLegend({ position: stored.position }, "gradient")
|
|
17
48
|
: normalizeIntervalLegend({ position: stored.position });
|
|
18
|
-
const
|
|
49
|
+
const comparableSymbol = channel === "stroke" && stored.inferredStrokeWidth === true
|
|
50
|
+
? { ...stored.symbol, strokeWidth: defaults.symbol?.strokeWidth }
|
|
51
|
+
: stored.symbol;
|
|
52
|
+
const custom = categorical
|
|
53
|
+
? categoricalFamilyCustom(program, from, stored)
|
|
54
|
+
: gradientFamily
|
|
19
55
|
? stored.count !== defaults.count || !same(stored.gradient, DEFAULT_GRADIENT_SIZE) || stored.itemGap !== defaults.itemGap
|
|
20
|
-
: !same(
|
|
56
|
+
: !same(comparableSymbol, defaults.symbol) || stored.itemGap !== defaults.itemGap ||
|
|
21
57
|
stored.direction !== defaults.direction || (stored.columns !== undefined && !(side && stored.columns === 1));
|
|
22
58
|
if (custom) {
|
|
23
|
-
throw new Error(
|
|
59
|
+
throw new Error(`${channel} legend transition cannot discard custom family settings; remove and recreate the legend explicitly.`);
|
|
60
|
+
}
|
|
61
|
+
if (blockOverride?.title !== undefined) {
|
|
62
|
+
throw new Error(`${channel} legend transition cannot distribute a legend block title; edit the destination block explicitly.`);
|
|
63
|
+
}
|
|
64
|
+
if (blockOverride?.labelMap !== undefined) {
|
|
65
|
+
throw new Error(`${channel} legend transition cannot distribute a legend block labelMap; edit the destination block explicitly.`);
|
|
66
|
+
}
|
|
67
|
+
if (blockOverride?.symbol !== undefined && ["gradient", "strokeGradient"].includes(to)) {
|
|
68
|
+
throw new Error(`${channel} legend transition cannot apply symbol overrides to a gradient block.`);
|
|
24
69
|
}
|
|
25
70
|
const args = {
|
|
26
|
-
target: stored.target, channels: [
|
|
71
|
+
target: stored.target, channels: [channel], position: stored.position,
|
|
27
72
|
labels: stored.labels, titleStyle: stored.titleStyle, border: stored.border,
|
|
28
73
|
align: stored.align, offset: stored.offset, titlePosition: stored.titlePosition,
|
|
29
74
|
...(stored.inferredTitle ? {} : { title: stored.title })
|
|
30
75
|
};
|
|
31
76
|
try {
|
|
32
|
-
if (
|
|
33
|
-
|
|
77
|
+
if (["interval", "strokeInterval"].includes(to)) {
|
|
78
|
+
normalizeIntervalLegend({ ...args, channels: undefined });
|
|
79
|
+
}
|
|
80
|
+
else if (["gradient", "strokeGradient"].includes(to)) {
|
|
81
|
+
normalizeContinuousLegend(args, "gradient");
|
|
82
|
+
}
|
|
34
83
|
} catch (error) {
|
|
35
|
-
throw new Error(
|
|
84
|
+
throw new Error(`${channel} legend transition has incompatible layout or style: ${error.message}`);
|
|
36
85
|
}
|
|
37
|
-
return { args, titleVisible: stored.titleVisible !== false };
|
|
86
|
+
return { args, channel, titleVisible: stored.titleVisible !== false, blockOverride };
|
|
87
|
+
}
|
|
88
|
+
|
|
89
|
+
export function planColorLegendTransitions(program, scale, nextType) {
|
|
90
|
+
return ["color", "stroke"].flatMap(channel => {
|
|
91
|
+
const plan = planChannelLegendTransition(program, scale, nextType, channel);
|
|
92
|
+
return plan === undefined ? [] : [plan];
|
|
93
|
+
});
|
|
38
94
|
}
|
|
39
95
|
|
|
40
96
|
export function applyColorLegendTransition(program, plan) {
|
|
41
|
-
|
|
42
|
-
|
|
97
|
+
let next = program.createLegend(plan.args);
|
|
98
|
+
if (!plan.titleVisible) {
|
|
99
|
+
next = next.editLegend({ target: plan.args.target, title: false });
|
|
100
|
+
}
|
|
101
|
+
if (plan.blockOverride === undefined) return next;
|
|
102
|
+
const descriptor = resolveLegendBlock(next, {
|
|
103
|
+
target: plan.args.target,
|
|
104
|
+
channel: plan.channel
|
|
105
|
+
}, `${plan.channel} legend transition`);
|
|
106
|
+
validateLegendBlockOverride(descriptor, plan.blockOverride);
|
|
107
|
+
next = next._withLegendConfig(descriptor.kind, {
|
|
108
|
+
...descriptor.config,
|
|
109
|
+
blockOverrides: { [descriptor.key]: plan.blockOverride }
|
|
110
|
+
});
|
|
111
|
+
return next.rematerializeLegend();
|
|
112
|
+
}
|
|
113
|
+
|
|
114
|
+
function intersects(left, right) {
|
|
115
|
+
return left.channels.some(channel => right.channels.includes(channel));
|
|
116
|
+
}
|
|
117
|
+
|
|
118
|
+
function explicitOrder(program, descriptor) {
|
|
119
|
+
if (descriptor.family !== "categorical") return undefined;
|
|
120
|
+
return program.semanticSpec.guides.legend?.[descriptor.kind]?.order;
|
|
121
|
+
}
|
|
122
|
+
|
|
123
|
+
function sameBlockValue(left, right) {
|
|
124
|
+
if (Object.is(left, right)) return true;
|
|
125
|
+
if (Array.isArray(left) && Array.isArray(right)) {
|
|
126
|
+
return left.length === right.length &&
|
|
127
|
+
left.every((value, index) => sameBlockValue(value, right[index]));
|
|
128
|
+
}
|
|
129
|
+
if (left !== null && right !== null &&
|
|
130
|
+
typeof left === "object" && typeof right === "object" &&
|
|
131
|
+
!Array.isArray(left) && !Array.isArray(right)) {
|
|
132
|
+
const leftKeys = Object.keys(left).sort();
|
|
133
|
+
const rightKeys = Object.keys(right).sort();
|
|
134
|
+
return leftKeys.length === rightKeys.length &&
|
|
135
|
+
leftKeys.every((key, index) => key === rightKeys[index] &&
|
|
136
|
+
sameBlockValue(left[key], right[key]));
|
|
137
|
+
}
|
|
138
|
+
return false;
|
|
139
|
+
}
|
|
140
|
+
|
|
141
|
+
function transitionError(target, oldDescriptors, nextDescriptor, field) {
|
|
142
|
+
const oldKeys = oldDescriptors.map(item => item.key).join(", ");
|
|
143
|
+
throw new Error(
|
|
144
|
+
`Legend block transition for target "${target}" from ${oldKeys} to ${nextDescriptor.key} conflicts on ${field}.`
|
|
145
|
+
);
|
|
146
|
+
}
|
|
147
|
+
|
|
148
|
+
function withoutBlockOverrides(config) {
|
|
149
|
+
const { blockOverrides: _removed, ...rest } = config;
|
|
150
|
+
return rest;
|
|
151
|
+
}
|
|
152
|
+
|
|
153
|
+
export function planLegendBlockTransitions(program, target, plans) {
|
|
154
|
+
const oldDescriptors = legendBlockDescriptors(program, target);
|
|
155
|
+
const nextDescriptors = plans.map(plan =>
|
|
156
|
+
describeLegendBlock(program, plan.kind, plan.config));
|
|
157
|
+
return plans.map((plan, index) => {
|
|
158
|
+
const descriptor = nextDescriptors[index];
|
|
159
|
+
const incoming = oldDescriptors.filter(old => intersects(old, descriptor));
|
|
160
|
+
let override;
|
|
161
|
+
if (incoming.length === 1 && incoming[0].key === descriptor.key) {
|
|
162
|
+
override = incoming[0].config.blockOverrides?.[incoming[0].key];
|
|
163
|
+
} else if (incoming.length === 1) {
|
|
164
|
+
const old = incoming[0];
|
|
165
|
+
override = old.config.blockOverrides?.[old.key];
|
|
166
|
+
if (override?.title !== undefined) {
|
|
167
|
+
transitionError(target, incoming, descriptor, "title");
|
|
168
|
+
}
|
|
169
|
+
if (override?.labelMap !== undefined) {
|
|
170
|
+
transitionError(target, incoming, descriptor, "labelMap");
|
|
171
|
+
}
|
|
172
|
+
} else if (incoming.length > 1) {
|
|
173
|
+
const overrides = incoming.map(old => old.config.blockOverrides?.[old.key]);
|
|
174
|
+
if (!overrides.every(value => sameBlockValue(value, overrides[0]))) {
|
|
175
|
+
transitionError(target, incoming, descriptor, "block override");
|
|
176
|
+
}
|
|
177
|
+
const orders = incoming.map(old => explicitOrder(program, old));
|
|
178
|
+
if (!orders.every(value => sameBlockValue(value, orders[0]))) {
|
|
179
|
+
transitionError(target, incoming, descriptor, "order");
|
|
180
|
+
}
|
|
181
|
+
override = overrides[0];
|
|
182
|
+
}
|
|
183
|
+
if (override !== undefined) validateLegendBlockOverride(descriptor, override);
|
|
184
|
+
const config = withoutBlockOverrides(plan.config);
|
|
185
|
+
return {
|
|
186
|
+
...plan,
|
|
187
|
+
config: override === undefined
|
|
188
|
+
? config
|
|
189
|
+
: { ...config, blockOverrides: { [descriptor.key]: override } }
|
|
190
|
+
};
|
|
191
|
+
});
|
|
43
192
|
}
|
|
@@ -8,7 +8,7 @@ import {
|
|
|
8
8
|
validateEnabledAxisComponents
|
|
9
9
|
} from "../../axes/components.js";
|
|
10
10
|
import {
|
|
11
|
-
|
|
11
|
+
labelEditOptions,
|
|
12
12
|
LINE_EDIT_OPTIONS,
|
|
13
13
|
prefix,
|
|
14
14
|
resolveAngle,
|
|
@@ -54,7 +54,7 @@ export function validatePolarAxisArgs(kind, args, operation) {
|
|
|
54
54
|
if (Object.hasOwn(args.ticksAndLabels, "labels")) {
|
|
55
55
|
validateObject(
|
|
56
56
|
args.ticksAndLabels.labels,
|
|
57
|
-
|
|
57
|
+
labelEditOptions(kind).filter(key => !["count", "values"].includes(key)),
|
|
58
58
|
`${operation}.ticksAndLabels.labels`
|
|
59
59
|
);
|
|
60
60
|
}
|
|
@@ -131,7 +131,7 @@ function validateAxisEditArgs(kind, args, operation) {
|
|
|
131
131
|
validateModeOptions(args.ticks, `${operation}.ticks`);
|
|
132
132
|
}
|
|
133
133
|
if (Object.hasOwn(args, "labels") && args.labels !== false) {
|
|
134
|
-
validateObject(args.labels,
|
|
134
|
+
validateObject(args.labels, labelEditOptions(kind), `${operation}.labels`);
|
|
135
135
|
validateModeOptions(args.labels, `${operation}.labels`);
|
|
136
136
|
}
|
|
137
137
|
if (args.ticksAndLabels !== undefined &&
|
|
@@ -155,7 +155,7 @@ function validateAxisEditArgs(kind, args, operation) {
|
|
|
155
155
|
if (args.ticksAndLabels.labels !== undefined) {
|
|
156
156
|
validateObject(
|
|
157
157
|
args.ticksAndLabels.labels,
|
|
158
|
-
|
|
158
|
+
labelEditOptions(kind).filter(key => !["count", "values"].includes(key)),
|
|
159
159
|
`${operation}.ticksAndLabels.labels`
|
|
160
160
|
);
|
|
161
161
|
}
|
|
@@ -20,8 +20,8 @@ import {
|
|
|
20
20
|
} from "../resolve.js";
|
|
21
21
|
import {
|
|
22
22
|
componentResources,
|
|
23
|
-
|
|
24
|
-
|
|
23
|
+
labelCreateOptions,
|
|
24
|
+
labelEditOptions,
|
|
25
25
|
operations,
|
|
26
26
|
prefix,
|
|
27
27
|
resolveAngle,
|
|
@@ -30,9 +30,11 @@ import {
|
|
|
30
30
|
validateObject,
|
|
31
31
|
withAxisSemantics
|
|
32
32
|
} from "./shared.js";
|
|
33
|
+
import { normalizeDisplayLabelMap } from
|
|
34
|
+
"../../../../grammar/displayLabels.js";
|
|
33
35
|
|
|
34
36
|
function labelGeometry(program, kind, config, angle = resolveAngle(program, kind, {})) {
|
|
35
|
-
const frame = resolvePolarFrameForProgram(program);
|
|
37
|
+
const frame = resolvePolarFrameForProgram(program, config.coordinate);
|
|
36
38
|
const mapped = mapPolarGuideValues(program, config);
|
|
37
39
|
const text = formatPolarGuideValues(program, config, mapped.values);
|
|
38
40
|
const geometry = {
|
|
@@ -115,6 +117,23 @@ function resolveLabelConfig(program, kind, args, resources, previous) {
|
|
|
115
117
|
fontWeight: args.fontWeight ?? previous?.fontWeight ??
|
|
116
118
|
POLAR_AXIS_DEFAULTS.labels.fontWeight
|
|
117
119
|
};
|
|
120
|
+
const labelScale = program.resolvedScales[resources.scale];
|
|
121
|
+
if (Object.hasOwn(args, "labelMap")) {
|
|
122
|
+
if (kind !== "theta" || !["ordinal", "band", "point"].includes(labelScale?.type)) {
|
|
123
|
+
throw new Error(`${prefix(kind)} axis labelMap requires a categorical theta scale.`);
|
|
124
|
+
}
|
|
125
|
+
if (args.labelMap === "auto") delete config.labelMap;
|
|
126
|
+
else {
|
|
127
|
+
config.labelMap = normalizeDisplayLabelMap(
|
|
128
|
+
args.labelMap,
|
|
129
|
+
`${prefix(kind)} axis labelMap`
|
|
130
|
+
);
|
|
131
|
+
}
|
|
132
|
+
}
|
|
133
|
+
if (config.labelMap !== undefined &&
|
|
134
|
+
(kind !== "theta" || !["ordinal", "band", "point"].includes(labelScale?.type))) {
|
|
135
|
+
throw new Error(`${prefix(kind)} axis labelMap requires a categorical theta scale.`);
|
|
136
|
+
}
|
|
118
137
|
validatePolarTickConfig(config, `${kind}-axis labels`);
|
|
119
138
|
validateNonNegativeFinite(config.offset, "Polar axis label offset");
|
|
120
139
|
validatePolarLabelFormat(config.format);
|
|
@@ -128,7 +147,7 @@ function makeEditLabels(kind) {
|
|
|
128
147
|
op: operation.edit,
|
|
129
148
|
description: `Edit the Polar ${kind}-axis labels.`
|
|
130
149
|
}, function (args = {}) {
|
|
131
|
-
validateObject(args,
|
|
150
|
+
validateObject(args, labelEditOptions(kind), operation.edit);
|
|
132
151
|
validateModeOptions(args, operation.edit);
|
|
133
152
|
const names = polarGuideNames(kind);
|
|
134
153
|
const previous = this.guideConfigs.axis?.[kind]?.labels;
|
|
@@ -172,7 +191,7 @@ function makeCreateLabels(kind) {
|
|
|
172
191
|
op: operation.create,
|
|
173
192
|
description: `Create the Polar ${kind}-axis labels.`
|
|
174
193
|
}, function (args = {}) {
|
|
175
|
-
validateComponentCreateArgs(kind, args,
|
|
194
|
+
validateComponentCreateArgs(kind, args, labelCreateOptions(kind), operation.create);
|
|
176
195
|
validateModeOptions(args, operation.create);
|
|
177
196
|
const names = polarGuideNames(kind);
|
|
178
197
|
if (this.graphicSpec.objects[names.labels] !== undefined) {
|
|
@@ -23,8 +23,8 @@ import {
|
|
|
23
23
|
withAxisSemantics
|
|
24
24
|
} from "./shared.js";
|
|
25
25
|
|
|
26
|
-
function lineGeometry(program, kind, angle, scale) {
|
|
27
|
-
const frame = resolvePolarFrameForProgram(program);
|
|
26
|
+
function lineGeometry(program, kind, angle, scale, coordinate) {
|
|
27
|
+
const frame = resolvePolarFrameForProgram(program, coordinate);
|
|
28
28
|
if (kind === "theta") {
|
|
29
29
|
return { commands: buildPolarCircleCommands(frame, frame.availableRadius) };
|
|
30
30
|
}
|
|
@@ -52,7 +52,13 @@ function makeEditLine(kind) {
|
|
|
52
52
|
const config = { ...previous, ...args };
|
|
53
53
|
validatePolarLineStyle(config, `${prefix(kind)} axis line`);
|
|
54
54
|
const angle = resolveAngle(this, kind, {});
|
|
55
|
-
const geometry = lineGeometry(
|
|
55
|
+
const geometry = lineGeometry(
|
|
56
|
+
this,
|
|
57
|
+
kind,
|
|
58
|
+
angle,
|
|
59
|
+
previous.scale,
|
|
60
|
+
previous.coordinate
|
|
61
|
+
);
|
|
56
62
|
let next = this._withGuideConfig(kind, "line", config);
|
|
57
63
|
for (const [property, value] of Object.entries(geometry)) {
|
|
58
64
|
next = next.editGraphics({ target: names.line, property, value });
|
|
@@ -91,7 +97,7 @@ function makeCreateLine(kind) {
|
|
|
91
97
|
lineWidth: args.lineWidth ?? POLAR_AXIS_DEFAULTS.line.lineWidth
|
|
92
98
|
};
|
|
93
99
|
validatePolarLineStyle(config, `${prefix(kind)} axis line`);
|
|
94
|
-
lineGeometry(this, kind, angle, resources.scale);
|
|
100
|
+
lineGeometry(this, kind, angle, resources.scale, resources.coordinate);
|
|
95
101
|
let next = withAxisSemantics(this, kind, resources);
|
|
96
102
|
if (kind === "radius" &&
|
|
97
103
|
next.guideConfigs.axis?.radius?.layout === undefined) {
|
|
@@ -26,6 +26,22 @@ export const LABEL_EDIT_OPTIONS = Object.freeze([
|
|
|
26
26
|
"count", "values", "offset", "format", "color", "fontSize",
|
|
27
27
|
"fontFamily", "fontWeight"
|
|
28
28
|
]);
|
|
29
|
+
const THETA_LABEL_CREATE_OPTIONS = Object.freeze([
|
|
30
|
+
...LABEL_CREATE_OPTIONS,
|
|
31
|
+
"labelMap"
|
|
32
|
+
]);
|
|
33
|
+
const THETA_LABEL_EDIT_OPTIONS = Object.freeze([
|
|
34
|
+
...LABEL_EDIT_OPTIONS,
|
|
35
|
+
"labelMap"
|
|
36
|
+
]);
|
|
37
|
+
|
|
38
|
+
export function labelCreateOptions(kind) {
|
|
39
|
+
return kind === "theta" ? THETA_LABEL_CREATE_OPTIONS : LABEL_CREATE_OPTIONS;
|
|
40
|
+
}
|
|
41
|
+
|
|
42
|
+
export function labelEditOptions(kind) {
|
|
43
|
+
return kind === "theta" ? THETA_LABEL_EDIT_OPTIONS : LABEL_EDIT_OPTIONS;
|
|
44
|
+
}
|
|
29
45
|
export const TITLE_CREATE_OPTIONS = Object.freeze([
|
|
30
46
|
"scale", "coordinate", "angle", "text", "offset", "color", "fontSize",
|
|
31
47
|
"fontFamily", "fontWeight", "position"
|
|
@@ -29,7 +29,7 @@ import {
|
|
|
29
29
|
} from "./shared.js";
|
|
30
30
|
|
|
31
31
|
function tickGeometry(program, kind, config, angle = resolveAngle(program, kind, {})) {
|
|
32
|
-
const frame = resolvePolarFrameForProgram(program);
|
|
32
|
+
const frame = resolvePolarFrameForProgram(program, config.coordinate);
|
|
33
33
|
const mapped = mapPolarGuideValues(program, config);
|
|
34
34
|
return {
|
|
35
35
|
values: mapped.values,
|
|
@@ -30,7 +30,7 @@ import {
|
|
|
30
30
|
} from "./shared.js";
|
|
31
31
|
|
|
32
32
|
function titleGeometry(program, kind, config, angle = resolveAngle(program, kind, {})) {
|
|
33
|
-
const frame = resolvePolarFrameForProgram(program);
|
|
33
|
+
const frame = resolvePolarFrameForProgram(program, config.coordinate);
|
|
34
34
|
return kind === "theta"
|
|
35
35
|
? resolveThetaAxisTitle({ frame, offset: config.offset })
|
|
36
36
|
: resolveRadialAxisTitle({
|
|
@@ -103,7 +103,7 @@ function resolveConfig(program, kind, args, resources, previous) {
|
|
|
103
103
|
}
|
|
104
104
|
|
|
105
105
|
function resolveGeometry(program, kind, config) {
|
|
106
|
-
const frame = resolvePolarFrameForProgram(program);
|
|
106
|
+
const frame = resolvePolarFrameForProgram(program, config.coordinate);
|
|
107
107
|
const mapped = mapPolarGuideValues(program, config);
|
|
108
108
|
if (kind === "theta") {
|
|
109
109
|
return { values: mapped.values, ...resolveThetaSpokes({
|
|
@@ -5,7 +5,6 @@ import {
|
|
|
5
5
|
validateNonNegativeFinite,
|
|
6
6
|
validatePositiveFinite
|
|
7
7
|
} from "../../../core/validation.js";
|
|
8
|
-
import { resolvePolarFrame } from "../../../grammar/polar.js";
|
|
9
8
|
import {
|
|
10
9
|
formatTransformedTick,
|
|
11
10
|
isTransformedScaleType,
|
|
@@ -13,7 +12,8 @@ import {
|
|
|
13
12
|
mapOrdinalPositionValues
|
|
14
13
|
} from "../../../grammar/scales/index.js";
|
|
15
14
|
import { formatTimeTick, formatTimeTicks } from "../../../grammar/ticks.js";
|
|
16
|
-
import {
|
|
15
|
+
import { resolveCoordinatePolarFrame } from
|
|
16
|
+
"../../../materialization/coordinateBounds.js";
|
|
17
17
|
import { findCoordinate } from "../../../selectors/coordinates.js";
|
|
18
18
|
import { DEFAULT_COLORS, DEFAULT_FONT_FAMILY } from
|
|
19
19
|
"../../../theme/defaults.js";
|
|
@@ -23,6 +23,7 @@ import {
|
|
|
23
23
|
} from "../../../grammar/schemas/graphicTree.js";
|
|
24
24
|
import { valuesFromTickConfig } from "../tickValues.js";
|
|
25
25
|
import { formatAxisValue, validateAxisFormat } from "../axes/policy.js";
|
|
26
|
+
import { resolveDisplayLabel } from "../../../grammar/displayLabels.js";
|
|
26
27
|
|
|
27
28
|
export const POLAR_AXIS_DEFAULTS = Object.freeze({
|
|
28
29
|
angle: 90,
|
|
@@ -160,12 +161,8 @@ export function resolvePolarGuideResources(program, kind, args, operation) {
|
|
|
160
161
|
});
|
|
161
162
|
}
|
|
162
163
|
|
|
163
|
-
export function resolvePolarFrameForProgram(program) {
|
|
164
|
-
|
|
165
|
-
if (bounds === undefined) {
|
|
166
|
-
throw new Error("Polar guides require graphical Canvas bounds.");
|
|
167
|
-
}
|
|
168
|
-
return resolvePolarFrame(bounds);
|
|
164
|
+
export function resolvePolarFrameForProgram(program, coordinate) {
|
|
165
|
+
return resolveCoordinatePolarFrame(program, coordinate);
|
|
169
166
|
}
|
|
170
167
|
|
|
171
168
|
export function resolvePolarTickValues(program, config) {
|
|
@@ -203,6 +200,13 @@ export function mapPolarGuideValues(program, config) {
|
|
|
203
200
|
|
|
204
201
|
export function formatPolarGuideValues(program, config, values) {
|
|
205
202
|
const scale = program.resolvedScales[config.scale];
|
|
203
|
+
if (["ordinal", "band", "point"].includes(scale.type)) {
|
|
204
|
+
return values.map(value => resolveDisplayLabel(
|
|
205
|
+
value,
|
|
206
|
+
config.labelMap,
|
|
207
|
+
String
|
|
208
|
+
));
|
|
209
|
+
}
|
|
206
210
|
if (scale.type === "time" && config.format === "auto") {
|
|
207
211
|
return formatTimeTicks(values, scale.domain);
|
|
208
212
|
}
|
package/src/actions/index.js
CHANGED
|
@@ -5,7 +5,8 @@ import { registerCategoryOrderActions } from "./categoryOrder/index.js";
|
|
|
5
5
|
import { registerEncodingActions } from "./encodings/index.js";
|
|
6
6
|
import { registerScaleActions } from "./scales/index.js";
|
|
7
7
|
import { registerMarkActions } from "./marks/index.js";
|
|
8
|
-
import {
|
|
8
|
+
import { registerBasicCoordinateActions } from "./coordinates/actions.js";
|
|
9
|
+
import { registerCoordinateEditActions } from "./coordinates/edit.js";
|
|
9
10
|
import { registerFacetActions } from "./facets/index.js";
|
|
10
11
|
import { registerCompositionActions } from "./composition/index.js";
|
|
11
12
|
import { registerTitleActions } from "./titles/index.js";
|
|
@@ -19,9 +20,17 @@ import { registerViolinPlotActions } from "./violinPlots/index.js";
|
|
|
19
20
|
import { registerErrorBandActions } from "./errorBands/index.js";
|
|
20
21
|
import { registerChartActions } from "./charts/index.js";
|
|
21
22
|
import { registerThemeActions } from "./theme/index.js";
|
|
23
|
+
import { registerResourceActions } from "./resources/index.js";
|
|
24
|
+
import {
|
|
25
|
+
applyCompositionTheme,
|
|
26
|
+
removeCompositionTheme
|
|
27
|
+
} from "./theme/composition.js";
|
|
22
28
|
|
|
23
29
|
export function registerActions(ProgramClass) {
|
|
24
|
-
registerThemeActions(ProgramClass
|
|
30
|
+
registerThemeActions(ProgramClass, {
|
|
31
|
+
apply: applyCompositionTheme,
|
|
32
|
+
remove: removeCompositionTheme
|
|
33
|
+
});
|
|
25
34
|
registerPrimitiveActions(ProgramClass);
|
|
26
35
|
registerCompositionActions(ProgramClass);
|
|
27
36
|
registerFacetActions(ProgramClass);
|
|
@@ -30,7 +39,8 @@ export function registerActions(ProgramClass) {
|
|
|
30
39
|
registerMarkActions(ProgramClass);
|
|
31
40
|
registerScaleActions(ProgramClass);
|
|
32
41
|
registerEncodingActions(ProgramClass);
|
|
33
|
-
|
|
42
|
+
registerBasicCoordinateActions(ProgramClass);
|
|
43
|
+
registerCoordinateEditActions(ProgramClass);
|
|
34
44
|
registerGuideActions(ProgramClass);
|
|
35
45
|
registerTitleActions(ProgramClass);
|
|
36
46
|
registerRegressionActions(ProgramClass);
|
|
@@ -42,4 +52,5 @@ export function registerActions(ProgramClass) {
|
|
|
42
52
|
registerChartActions(ProgramClass);
|
|
43
53
|
registerCategoryOrderActions(ProgramClass);
|
|
44
54
|
registerSelectionActions(ProgramClass);
|
|
55
|
+
registerResourceActions(ProgramClass);
|
|
45
56
|
}
|