ggaction 0.0.13 → 0.0.16
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 +146 -0
- package/README.md +41 -12
- package/knowledge/action-cards.json +1 -1
- package/knowledge/intent-taxonomy.json +1 -1
- package/knowledge/mcp-resources.json +1 -1
- package/knowledge/task-packet.schema.json +1 -1
- package/knowledge/task-resolver.js +1 -1
- package/package.json +39 -7
- package/src/BasicChartProgram.js +3 -1
- package/src/ChartProgram.js +2 -0
- package/src/accessibility.js +157 -0
- package/src/actions/basic.js +2 -2
- package/src/actions/boxPlots/components.js +20 -12
- package/src/actions/boxPlots/create.js +4 -5
- package/src/actions/boxPlots/edit.js +34 -9
- package/src/actions/boxPlots/materialize.js +12 -4
- package/src/actions/boxPlots/options.js +48 -16
- package/src/actions/canvas/actions.js +3 -3
- package/src/actions/canvas/fitting.js +1 -1
- package/src/actions/categoryOrder/index.js +21 -12
- package/src/actions/charts/area.js +6 -2
- package/src/actions/charts/bar.js +3 -2
- package/src/actions/charts/beeswarm.js +1 -1
- package/src/actions/charts/density.js +7 -3
- package/src/actions/charts/ecdf.js +6 -3
- package/src/actions/charts/endpoints.js +29 -7
- package/src/actions/charts/heatmap.js +3 -2
- package/src/actions/charts/histogram.js +5 -4
- package/src/actions/charts/horizon.js +4 -2
- package/src/actions/charts/interval-regression.js +7 -4
- package/src/actions/charts/line.js +4 -2
- package/src/actions/charts/parallel.js +9 -3
- package/src/actions/charts/pie.js +11 -3
- package/src/actions/charts/polar.js +17 -6
- package/src/actions/charts/radar.js +9 -3
- package/src/actions/charts/radial.js +12 -4
- package/src/actions/charts/raincloud.js +2 -2
- package/src/actions/charts/rug-strip.js +8 -4
- package/src/actions/charts/scatter.js +4 -2
- package/src/actions/composition/actions.js +29 -24
- package/src/actions/coordinates/actions.js +2 -2
- package/src/actions/coordinates/edit.js +76 -0
- package/src/actions/data/basicBin2d.js +4 -5
- package/src/actions/data/bin.js +3 -3
- package/src/actions/data/bin2d.js +63 -193
- package/src/actions/data/bin2dMaterialize.js +4 -5
- package/src/actions/data/box.js +4 -4
- package/src/actions/data/complete.js +26 -0
- package/src/actions/data/computed.js +4 -4
- package/src/actions/data/create.js +7 -14
- package/src/actions/data/density.js +15 -23
- package/src/actions/data/derived.js +57 -31
- package/src/actions/data/ecdf.js +2 -2
- package/src/actions/data/edit.js +551 -0
- package/src/actions/data/filter.js +28 -22
- package/src/actions/data/fold.js +2 -2
- package/src/actions/data/gradientProfile.js +2 -2
- package/src/actions/data/horizon.js +2 -2
- package/src/actions/data/impute.js +26 -0
- package/src/actions/data/index.js +62 -47
- package/src/actions/data/interval.js +2 -2
- package/src/actions/data/intervalEdit.js +26 -18
- package/src/actions/data/normalize.js +27 -0
- package/src/actions/data/regression.js +21 -27
- package/src/actions/data/revise.js +48 -0
- package/src/actions/data/revisionBindings.js +125 -0
- package/src/actions/data/shared.js +20 -4
- package/src/actions/data/stack.js +2 -2
- package/src/actions/data/summary.js +3 -3
- package/src/actions/data/timeUnit.js +6 -3
- package/src/actions/data/window.js +3 -3
- package/src/actions/encodings/angle.js +1 -1
- package/src/actions/encodings/appearance.js +4 -4
- package/src/actions/encodings/barWidth.js +1 -1
- package/src/actions/encodings/channels.js +415 -0
- package/src/actions/encodings/color/index.js +3 -2
- package/src/actions/encodings/density.js +7 -4
- package/src/actions/encodings/histogram.js +4 -3
- package/src/actions/encodings/horizon.js +6 -8
- package/src/actions/encodings/index.js +4 -0
- package/src/actions/encodings/offset.js +22 -15
- package/src/actions/encodings/parallel.js +4 -5
- package/src/actions/encodings/pathOrder.js +6 -11
- package/src/actions/encodings/position/apply.js +53 -7
- package/src/actions/encodings/position/index.js +14 -6
- package/src/actions/encodings/position/policies/bar.js +9 -0
- package/src/actions/encodings/position/resolve.js +24 -7
- package/src/actions/encodings/ranged.js +5 -5
- package/src/actions/encodings/remove.js +13 -9
- package/src/actions/encodings/ruleAppearance.js +2 -24
- package/src/actions/encodings/seriesLayout.js +2 -1
- package/src/actions/encodings/shared.js +82 -14
- package/src/actions/encodings/stroke.js +226 -0
- package/src/actions/encodings/strokeDash.js +2 -2
- package/src/actions/encodings/text.js +1 -1
- package/src/actions/errorBands/create.js +34 -20
- package/src/actions/errorBands/edit.js +34 -137
- package/src/actions/errorBars/create.js +43 -20
- package/src/actions/errorBars/edit.js +29 -125
- package/src/actions/facets/actions.js +267 -73
- package/src/actions/facets/derive.js +99 -28
- package/src/actions/facets/guides.js +4 -5
- package/src/actions/facets/replay.js +4 -5
- package/src/actions/gradientPlots/components.js +15 -8
- package/src/actions/gradientPlots/create.js +4 -5
- package/src/actions/gradientPlots/edit.js +18 -9
- package/src/actions/gradientPlots/materialize.js +5 -3
- package/src/actions/gradientPlots/options.js +10 -2
- package/src/actions/gradientPlots/rebind.js +4 -5
- package/src/actions/guides/applicability.js +8 -2
- package/src/actions/guides/axes/axes.js +23 -4
- package/src/actions/guides/axes/axis.js +2 -2
- package/src/actions/guides/axes/edit.js +2 -2
- package/src/actions/guides/axes/labels.js +67 -21
- package/src/actions/guides/axes/lines.js +15 -9
- package/src/actions/guides/axes/parallel/lifecycle.js +13 -13
- package/src/actions/guides/axes/parallel/resolve.js +6 -2
- package/src/actions/guides/axes/parallel.js +5 -5
- package/src/actions/guides/axes/remove.js +4 -4
- package/src/actions/guides/axes/tickGroups.js +6 -5
- package/src/actions/guides/axes/ticks.js +19 -6
- package/src/actions/guides/axes/titles.js +21 -13
- package/src/actions/guides/grids/grid.js +18 -29
- package/src/actions/guides/grids/resolve.js +7 -2
- package/src/actions/guides/guides.js +20 -4
- package/src/actions/guides/legends/blocks.js +426 -0
- package/src/actions/guides/legends/categorical/actions.js +138 -52
- package/src/actions/guides/legends/categorical/components.js +55 -45
- package/src/actions/guides/legends/categorical/index.js +37 -33
- package/src/actions/guides/legends/categorical/layout.js +98 -16
- 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 +104 -52
- package/src/actions/guides/legends/continuous/common.js +76 -20
- package/src/actions/guides/legends/continuous/gradient.js +95 -158
- package/src/actions/guides/legends/continuous/index.js +2 -0
- package/src/actions/guides/legends/continuous/interval.js +21 -16
- package/src/actions/guides/legends/continuous/opacity.js +37 -83
- package/src/actions/guides/legends/continuous/stroke.js +225 -0
- package/src/actions/guides/legends/creation.js +14 -1
- package/src/actions/guides/legends/edit.js +159 -60
- package/src/actions/guides/legends/focused.js +5 -5
- package/src/actions/guides/legends/index.js +2 -0
- package/src/actions/guides/legends/lane.js +59 -24
- package/src/actions/guides/legends/lifecycle.js +19 -8
- package/src/actions/guides/legends/remove.js +17 -8
- package/src/actions/guides/legends/sampling.js +140 -0
- package/src/actions/guides/legends/size.js +100 -108
- package/src/actions/guides/legends/strokeWidth.js +38 -92
- 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 +8 -8
- package/src/actions/guides/polar/axes/labels.js +29 -10
- package/src/actions/guides/polar/axes/lines.js +19 -19
- package/src/actions/guides/polar/axes/shared.js +16 -0
- package/src/actions/guides/polar/axes/ticks.js +10 -16
- package/src/actions/guides/polar/axes/titles.js +6 -6
- package/src/actions/guides/polar/grids.js +12 -14
- package/src/actions/guides/polar/resolve.js +12 -8
- package/src/actions/index.js +16 -3
- package/src/actions/intervals/revision.js +126 -0
- package/src/actions/marks/arc/actions.js +80 -22
- package/src/actions/marks/area/actions.js +38 -13
- package/src/actions/marks/area/materialize.js +17 -1
- package/src/actions/marks/bar/create.js +12 -3
- package/src/actions/marks/bar/edit.js +21 -4
- package/src/actions/marks/bar/materialize.js +34 -40
- package/src/actions/marks/index.js +10 -1
- package/src/actions/marks/line/actions.js +40 -17
- package/src/actions/marks/line/materialize.js +29 -10
- package/src/actions/marks/point/create.js +9 -3
- package/src/actions/marks/point/edit.js +19 -7
- package/src/actions/marks/point/jitter.js +6 -8
- package/src/actions/marks/point/materialize.js +48 -22
- package/src/actions/marks/point/packing.js +6 -8
- package/src/actions/marks/rect/actions.js +36 -15
- package/src/actions/marks/references.js +602 -33
- package/src/actions/marks/remove.js +67 -41
- package/src/actions/marks/rule/actions.js +51 -14
- package/src/actions/marks/shared.js +1 -1
- package/src/actions/marks/text/actions.js +79 -14
- package/src/actions/marks/text/index.js +4 -0
- package/src/actions/marks/text/layout.js +157 -17
- package/src/actions/marks/text/removal.js +173 -0
- package/src/actions/marks/text/selection.js +72 -0
- package/src/actions/marks/tick/actions.js +25 -8
- package/src/actions/primitives/createGraphics.js +5 -4
- package/src/actions/primitives/editGraphics.js +31 -4
- package/src/actions/primitives/graphicProperties.js +6 -0
- package/src/actions/primitives/semantic.js +11 -3
- package/src/actions/primitives/semanticAction.js +90 -14
- package/src/actions/primitives/semanticValidation/dataset.js +2 -4
- 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 +36 -25
- package/src/actions/regression/create.js +13 -6
- package/src/actions/regression/edit.js +24 -11
- package/src/actions/resources/index.js +7 -0
- package/src/actions/resources/remove.js +173 -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 +55 -23
- package/src/actions/scales/definitions.js +94 -40
- package/src/actions/scales/edit.js +67 -12
- package/src/actions/scales/editPolicy.js +81 -11
- package/src/actions/scales/index.js +6 -0
- package/src/actions/scales/materialize.js +5 -4
- 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/scales/quantitativeColor.js +4 -5
- package/src/actions/selection/actions.js +179 -66
- package/src/actions/selection/index.js +3 -0
- package/src/actions/textMetrics/index.js +56 -0
- package/src/actions/theme/actions.js +70 -15
- package/src/actions/theme/composition.js +238 -0
- package/src/actions/theme/index.js +9 -2
- package/src/actions/theme/reconcile.js +313 -121
- package/src/actions/theme/state.js +160 -0
- package/src/actions/titles/actions.js +8 -8
- package/src/actions/titles/resolve.js +3 -3
- package/src/actions/violinPlots/create.js +6 -3
- package/src/actions/violinPlots/edit.js +2 -1
- package/src/core/action.js +117 -35
- package/src/core/compositionState.js +6 -1
- package/src/core/diagnostics.js +16 -0
- package/src/core/extensionRegistry.js +27 -0
- package/src/core/font.js +18 -0
- package/src/core/identifiers.js +5 -4
- package/src/core/immutable.js +10 -3
- package/src/core/optionRequirements.js +8 -0
- package/src/core/programState.js +21 -1
- package/src/core/resourceReferences.js +341 -0
- package/src/core/textMetricProfile.js +28 -0
- package/src/core/textMetrics.js +24 -3
- package/src/core/validation.js +22 -10
- package/src/core/vocabulary.js +16 -3
- package/src/diagnostics.js +1 -0
- 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 +341 -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/scales/types.js +8 -0
- package/src/grammar/schemas/concreteGraphic.js +14 -2
- package/src/grammar/schemas/graphic.js +15 -0
- package/src/grammar/schemas/graphicBounds.js +190 -41
- 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 +351 -7
- package/src/layout/legend.js +4 -4
- package/src/layout/legendItems.js +6 -6
- package/src/layout/text.js +10 -9
- package/src/layout/title.js +9 -9
- 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 +9 -3
- package/src/materialization/facetGuides/preparation.js +13 -8
- package/src/materialization/facetHeaders.js +347 -0
- package/src/materialization/facets.js +15 -65
- package/src/materialization/guides/layout.js +3 -3
- 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/scaleGuideDependencies.js +10 -0
- 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 +20 -5
- 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/materialization/typography.js +31 -0
- package/src/mcp/cli.js +5 -3
- package/src/persistence/codec.js +65 -0
- package/src/persistence/validation.js +185 -0
- package/src/persistence.js +74 -0
- package/src/renderers/canvas/circle.js +2 -3
- package/src/renderers/canvas/index.js +5 -4
- 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/nativeBackend.js +10 -0
- package/src/renderers/options.js +13 -0
- package/src/renderers/pdf.js +25 -54
- package/src/renderers/png.js +22 -17
- package/src/renderers/svg.js +29 -14
- package/src/renderers/text.js +1 -11
- package/src/selectors/coordinates.js +3 -1
- package/src/selectors/datasets.js +38 -5
- package/src/selectors/layers.js +10 -4
- package/src/selectors/markOwners.js +46 -0
- package/src/selectors/scales.js +6 -4
- package/src/theme/defaults.js +103 -1
- package/src/version.js +2 -0
- package/types/accessibility.d.ts +37 -0
- package/types/basic.d.ts +10 -2
- package/types/diagnostics.d.ts +15 -0
- package/types/index.d.ts +90 -0
- package/types/pdf.d.ts +9 -0
- package/types/persistence.d.ts +7 -0
- package/types/png.d.ts +9 -0
- package/types/program.d.ts +944 -118
|
@@ -26,6 +26,11 @@ import {
|
|
|
26
26
|
resolveTarget,
|
|
27
27
|
sameValues
|
|
28
28
|
} from "./resolve.js";
|
|
29
|
+
import { readLegendSampling } from "../sampling.js";
|
|
30
|
+
import {
|
|
31
|
+
reconcileLegendBlockTitleGraphic,
|
|
32
|
+
resolveEffectiveLegendBlockConfig
|
|
33
|
+
} from "../blocks.js";
|
|
29
34
|
|
|
30
35
|
function finishLegend(program) {
|
|
31
36
|
return hasLegendLane(program) ? program.rematerializeLegend() : program;
|
|
@@ -45,30 +50,40 @@ function resolveStandaloneLegendStep(args, kind) {
|
|
|
45
50
|
return { op: kind === "size" ? "createSizeLegend" : "createStrokeWidthLegend", args: options };
|
|
46
51
|
}
|
|
47
52
|
|
|
48
|
-
export const rematerializeLegend = action(
|
|
53
|
+
export const rematerializeLegend = /* @__PURE__ */ action(
|
|
49
54
|
{ op: "rematerializeLegend", description: "Rematerialize every existing legend component." },
|
|
50
55
|
withGuideLayoutValidation(function (args = {}) {
|
|
51
56
|
noOptions(args, "rematerializeLegend");
|
|
52
57
|
let next = this;
|
|
53
|
-
const
|
|
54
|
-
this.guideConfigs.legend?.
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
const
|
|
58
|
-
const definition = resolveCurrentDefinition(
|
|
59
|
-
const symbol =
|
|
60
|
-
? normalizeRecipe(
|
|
61
|
-
|
|
62
|
-
|
|
58
|
+
const categoricalKinds = ["series", "color", "stroke"].filter(
|
|
59
|
+
kind => this.guideConfigs.legend?.[kind] !== undefined
|
|
60
|
+
);
|
|
61
|
+
for (const kind of categoricalKinds) {
|
|
62
|
+
const stored = next.guideConfigs.legend[kind];
|
|
63
|
+
const definition = resolveCurrentDefinition(next, stored);
|
|
64
|
+
const symbol = stored.inferredSymbol
|
|
65
|
+
? normalizeRecipe(
|
|
66
|
+
resolveLegendSymbol(
|
|
67
|
+
next,
|
|
68
|
+
findLayer(next, stored.target),
|
|
69
|
+
definition.channels,
|
|
70
|
+
undefined,
|
|
71
|
+
kind
|
|
72
|
+
),
|
|
73
|
+
kind,
|
|
74
|
+
{ internal: true }
|
|
75
|
+
)
|
|
76
|
+
: stored.symbol;
|
|
77
|
+
const symbolChanged = !sameGuideValue(symbol, stored.symbol);
|
|
63
78
|
const changed = symbolChanged ||
|
|
64
|
-
!sameValues(
|
|
65
|
-
!sameValues(
|
|
66
|
-
!sameValues(
|
|
67
|
-
|
|
68
|
-
|
|
79
|
+
!sameValues(stored.channels, definition.channels) ||
|
|
80
|
+
!sameValues(stored.domain, definition.domain) ||
|
|
81
|
+
!sameValues(stored.scales, definition.scales) ||
|
|
82
|
+
stored.field !== definition.field ||
|
|
83
|
+
stored.title !== definition.title;
|
|
69
84
|
next = changed
|
|
70
|
-
?
|
|
71
|
-
...
|
|
85
|
+
? next._withLegendConfig(kind, {
|
|
86
|
+
...stored,
|
|
72
87
|
symbol,
|
|
73
88
|
channels: definition.channels,
|
|
74
89
|
scales: definition.scales,
|
|
@@ -76,10 +91,17 @@ export const rematerializeLegend = action(
|
|
|
76
91
|
title: definition.title,
|
|
77
92
|
domain: definition.domain
|
|
78
93
|
})
|
|
79
|
-
:
|
|
94
|
+
: next;
|
|
95
|
+
const config = resolveEffectiveLegendBlockConfig(
|
|
96
|
+
next,
|
|
97
|
+
kind,
|
|
98
|
+
next.guideConfigs.legend[kind]
|
|
99
|
+
);
|
|
100
|
+
next = reconcileLegendBlockTitleGraphic(next, kind,
|
|
101
|
+
config.titleVisible !== false);
|
|
80
102
|
if (kind === "series") {
|
|
81
103
|
if (!sameValues(
|
|
82
|
-
|
|
104
|
+
next.semanticSpec.guides.legend.series.scales,
|
|
83
105
|
definition.scales
|
|
84
106
|
)) {
|
|
85
107
|
next = next.editSemantic({
|
|
@@ -87,45 +109,56 @@ export const rematerializeLegend = action(
|
|
|
87
109
|
value: definition.scales
|
|
88
110
|
});
|
|
89
111
|
}
|
|
90
|
-
if (
|
|
112
|
+
if (next.semanticSpec.guides.legend.series.title !== definition.title) {
|
|
91
113
|
next = next.editSemantic({
|
|
92
114
|
property: "guide.legend.series.title",
|
|
93
115
|
value: definition.title
|
|
94
116
|
});
|
|
95
117
|
}
|
|
96
118
|
} else {
|
|
97
|
-
if (
|
|
119
|
+
if (next.semanticSpec.guides.legend[kind].scale !== definition.scales[0]) {
|
|
98
120
|
next = next.editSemantic({
|
|
99
|
-
property:
|
|
121
|
+
property: `guide.legend.${kind}.scale`,
|
|
100
122
|
value: definition.scales[0]
|
|
101
123
|
});
|
|
102
124
|
}
|
|
103
|
-
if (
|
|
125
|
+
if (next.semanticSpec.guides.legend[kind].title !== definition.title) {
|
|
104
126
|
next = next.editSemantic({
|
|
105
|
-
property:
|
|
127
|
+
property: `guide.legend.${kind}.title`,
|
|
106
128
|
value: definition.title
|
|
107
129
|
});
|
|
108
130
|
}
|
|
109
131
|
}
|
|
110
132
|
if (symbolChanged) {
|
|
111
|
-
resolveLayout(next,
|
|
112
|
-
next = reconcileCategoricalSymbols(next,
|
|
133
|
+
resolveLayout(next, config);
|
|
134
|
+
next = reconcileCategoricalSymbols(next, stored, config);
|
|
135
|
+
}
|
|
136
|
+
if (config.border !== false) {
|
|
137
|
+
next = next.rematerializeLegendBackground({ kind });
|
|
113
138
|
}
|
|
114
|
-
if (config.border !== false) next = next.rematerializeLegendBackground();
|
|
115
139
|
next = next
|
|
116
|
-
.rematerializeLegendSymbols()
|
|
117
|
-
.rematerializeLegendLabels();
|
|
118
|
-
if (config.titleVisible !== false)
|
|
140
|
+
.rematerializeLegendSymbols({ kind })
|
|
141
|
+
.rematerializeLegendLabels({ kind });
|
|
142
|
+
if (config.titleVisible !== false) {
|
|
143
|
+
next = next.rematerializeLegendTitle({ kind });
|
|
144
|
+
}
|
|
119
145
|
const hasHighlight = Object.values(
|
|
120
146
|
next.materializationConfigs.highlights ?? {}
|
|
121
147
|
).some(highlight => highlight.target === config.target);
|
|
122
|
-
if (hasHighlight) next = next.rematerializeLegendHighlights();
|
|
148
|
+
if (hasHighlight) next = next.rematerializeLegendHighlights({ kind });
|
|
123
149
|
}
|
|
124
150
|
for (const policy of legendResourcePolicies()) {
|
|
125
151
|
if (
|
|
126
152
|
policy.rematerializeOp !== undefined &&
|
|
127
153
|
this.guideConfigs.legend?.[policy.kind] !== undefined
|
|
128
154
|
) {
|
|
155
|
+
const config = resolveEffectiveLegendBlockConfig(
|
|
156
|
+
next,
|
|
157
|
+
policy.kind,
|
|
158
|
+
next.guideConfigs.legend[policy.kind]
|
|
159
|
+
);
|
|
160
|
+
next = reconcileLegendBlockTitleGraphic(next, policy.kind,
|
|
161
|
+
config.titleVisible !== false);
|
|
129
162
|
next = next[policy.rematerializeOp]();
|
|
130
163
|
}
|
|
131
164
|
}
|
|
@@ -148,14 +181,21 @@ export function resolveCategoricalLegendConfig(program, args = {}) {
|
|
|
148
181
|
args.title,
|
|
149
182
|
args.order === undefined ? undefined : normalizeLegendOrder(args.order)
|
|
150
183
|
);
|
|
184
|
+
const inferredSymbol = args.symbol === undefined || args.symbol === "auto";
|
|
151
185
|
const options = normalizeOptions({ ...args,
|
|
152
|
-
symbol: resolveLegendSymbol(
|
|
153
|
-
|
|
186
|
+
symbol: resolveLegendSymbol(
|
|
187
|
+
program,
|
|
188
|
+
layer,
|
|
189
|
+
definition.channels,
|
|
190
|
+
args.symbol,
|
|
191
|
+
definition.kind
|
|
192
|
+
)
|
|
193
|
+
}, definition.kind, { internalSymbol: inferredSymbol });
|
|
154
194
|
const config = {
|
|
155
195
|
target: layer.id,
|
|
156
196
|
...definition,
|
|
157
197
|
inferredTitle: !Object.hasOwn(args, "title"),
|
|
158
|
-
inferredSymbol
|
|
198
|
+
inferredSymbol,
|
|
159
199
|
position: options.position,
|
|
160
200
|
align: options.align,
|
|
161
201
|
direction: options.direction,
|
|
@@ -173,15 +213,14 @@ export function resolveCategoricalLegendConfig(program, args = {}) {
|
|
|
173
213
|
return config;
|
|
174
214
|
}
|
|
175
215
|
|
|
176
|
-
export const createCategoricalLegend = action(
|
|
216
|
+
export const createCategoricalLegend = /* @__PURE__ */ action(
|
|
177
217
|
{ op: "createCategoricalLegend", description: "Create one categorical legend block." },
|
|
178
218
|
withGuideLayoutValidation(function (args = {}) {
|
|
179
219
|
const config = resolveCategoricalLegendConfig(this, args);
|
|
180
|
-
if (
|
|
181
|
-
|
|
182
|
-
|
|
183
|
-
|
|
184
|
-
throw new Error("createCategoricalLegend requires a missing legend.");
|
|
220
|
+
if (this.semanticSpec.guides.legend?.[config.kind] !== undefined) {
|
|
221
|
+
throw new Error(
|
|
222
|
+
`createCategoricalLegend requires a missing legend for ${config.kind}.`
|
|
223
|
+
);
|
|
185
224
|
}
|
|
186
225
|
resolveLayout(this, config);
|
|
187
226
|
return createCategoricalLegendFromConfig(this, config,
|
|
@@ -195,12 +234,12 @@ export function resolveLegendCreationPlan(program, args = {}, layers = program.s
|
|
|
195
234
|
const channels = args.channels;
|
|
196
235
|
if (channels !== undefined) validateLegendChannels(channels, "createLegend");
|
|
197
236
|
const standalone = [
|
|
198
|
-
["size", isSizeLegendPoint, ["color", "shape", "strokeDash", "opacity"]],
|
|
237
|
+
["size", isSizeLegendPoint, ["color", "stroke", "shape", "strokeDash", "opacity"]],
|
|
199
238
|
["strokeWidth", isStrokeWidthLegendLayer, args.target === undefined
|
|
200
|
-
? ["color", "shape", "strokeDash", "size", "opacity"]
|
|
201
|
-
: ["color", "shape", "strokeDash", "opacity"]],
|
|
239
|
+
? ["color", "stroke", "shape", "strokeDash", "size", "opacity"]
|
|
240
|
+
: ["color", "stroke", "shape", "strokeDash", "opacity"]],
|
|
202
241
|
["opacity", isOpacityLegendLayer,
|
|
203
|
-
["color", "shape", "strokeDash", "size"]]
|
|
242
|
+
["color", "stroke", "shape", "strokeDash", "size"]]
|
|
204
243
|
];
|
|
205
244
|
for (const [kind, eligible, otherChannels] of standalone) {
|
|
206
245
|
const explicit = channels?.length === 1 && channels[0] === kind;
|
|
@@ -240,6 +279,47 @@ export function resolveLegendCreationPlan(program, args = {}, layers = program.s
|
|
|
240
279
|
) {
|
|
241
280
|
return { steps: [{ op: "createIntervalLegend", args }], finish: "auto" };
|
|
242
281
|
}
|
|
282
|
+
const continuousStrokeCandidates = candidates.filter(layer => {
|
|
283
|
+
const scale = findSemanticScale(program, layer.encoding?.stroke?.scale);
|
|
284
|
+
return scale?.type === "sequential";
|
|
285
|
+
});
|
|
286
|
+
const continuousStroke = requestedCandidate(
|
|
287
|
+
program,
|
|
288
|
+
args.target,
|
|
289
|
+
continuousStrokeCandidates
|
|
290
|
+
);
|
|
291
|
+
if (
|
|
292
|
+
(channels?.length === 1 && channels[0] === "stroke" && continuousStroke) ||
|
|
293
|
+
(channels === undefined && continuousStroke &&
|
|
294
|
+
!["color", "shape", "strokeDash", "size", "opacity", "strokeWidth"].some(
|
|
295
|
+
channel => continuousStroke.encoding?.[channel]?.scale !== undefined
|
|
296
|
+
))
|
|
297
|
+
) {
|
|
298
|
+
return {
|
|
299
|
+
steps: [{ op: "createStrokeGradientLegend", args: {
|
|
300
|
+
...args,
|
|
301
|
+
channels: ["stroke"]
|
|
302
|
+
} }],
|
|
303
|
+
finish: "auto"
|
|
304
|
+
};
|
|
305
|
+
}
|
|
306
|
+
const intervalStrokeCandidates = candidates.filter(layer => {
|
|
307
|
+
const scale = findSemanticScale(program, layer.encoding?.stroke?.scale);
|
|
308
|
+
return ["quantize", "quantile", "threshold"].includes(scale?.type);
|
|
309
|
+
});
|
|
310
|
+
if (
|
|
311
|
+
(channels?.length === 1 && channels[0] === "stroke" &&
|
|
312
|
+
intervalStrokeCandidates.length > 0) ||
|
|
313
|
+
(channels === undefined && intervalStrokeCandidates.length === 1)
|
|
314
|
+
) {
|
|
315
|
+
return {
|
|
316
|
+
steps: [{ op: "createStrokeIntervalLegend", args: {
|
|
317
|
+
...args,
|
|
318
|
+
channels: ["stroke"]
|
|
319
|
+
} }],
|
|
320
|
+
finish: "auto"
|
|
321
|
+
};
|
|
322
|
+
}
|
|
243
323
|
const wantsShape = channels?.includes("shape") === true;
|
|
244
324
|
const wantsSize = channels?.includes("size") === true;
|
|
245
325
|
const pointCandidates = candidates.filter(layer =>
|
|
@@ -247,7 +327,7 @@ export function resolveLegendCreationPlan(program, args = {}, layers = program.s
|
|
|
247
327
|
(channels === undefined
|
|
248
328
|
? ["color", "shape"].some(channel => layer.encoding?.[channel]?.scale !== undefined)
|
|
249
329
|
: (wantsShape || wantsSize) && channels.every(channel =>
|
|
250
|
-
["color", "shape", "size"].includes(channel) && layer.encoding?.[channel]?.scale !== undefined))
|
|
330
|
+
["color", "stroke", "shape", "size"].includes(channel) && layer.encoding?.[channel]?.scale !== undefined))
|
|
251
331
|
);
|
|
252
332
|
const requestedPoint = requestedCandidate(program, args.target, pointCandidates);
|
|
253
333
|
const inferredSize = channels === undefined && pointCandidates.some(isSizeLegendPoint);
|
|
@@ -255,6 +335,11 @@ export function resolveLegendCreationPlan(program, args = {}, layers = program.s
|
|
|
255
335
|
throw new Error("Combined size legend requires one eligible point mark or an explicit target.");
|
|
256
336
|
}
|
|
257
337
|
if (requestedPoint !== undefined) {
|
|
338
|
+
if (Object.hasOwn(args, "values")) {
|
|
339
|
+
throw new Error(
|
|
340
|
+
"Combined and categorical legends require a channel block selector for exact values."
|
|
341
|
+
);
|
|
342
|
+
}
|
|
258
343
|
const { count, ...categoricalArgs } = args;
|
|
259
344
|
const combined = requestedPoint.encoding?.size?.scale !== undefined &&
|
|
260
345
|
(channels === undefined || wantsSize);
|
|
@@ -264,7 +349,7 @@ export function resolveLegendCreationPlan(program, args = {}, layers = program.s
|
|
|
264
349
|
if (combined && categoricalArgs.layout === "legacy-bottom") {
|
|
265
350
|
throw new Error('Combined size legends require layout "edge".');
|
|
266
351
|
}
|
|
267
|
-
const inferredChannels = ["color", "shape"].filter(
|
|
352
|
+
const inferredChannels = ["color", "stroke", "shape"].filter(
|
|
268
353
|
channel => requestedPoint.encoding?.[channel]?.scale !== undefined
|
|
269
354
|
);
|
|
270
355
|
const { format: sizeFormat, ...categoricalLabels } = categoricalArgs.labels ?? {};
|
|
@@ -294,7 +379,8 @@ export function resolveLegendCreationPlan(program, args = {}, layers = program.s
|
|
|
294
379
|
if (existing !== undefined && existing.target !== size.target) {
|
|
295
380
|
throw new Error("Combined point series legend requires the active size legend to share its target.");
|
|
296
381
|
}
|
|
297
|
-
if (existing !== undefined && count !== undefined &&
|
|
382
|
+
if (existing !== undefined && count !== undefined &&
|
|
383
|
+
readLegendSampling(existing).count !== count) {
|
|
298
384
|
throw new Error("Existing size legend count must be edited before recreating the categorical block.");
|
|
299
385
|
}
|
|
300
386
|
}
|
|
@@ -317,28 +403,28 @@ export function applyLegendCreationPlan(program, plan) {
|
|
|
317
403
|
: plan.finish === "auto" ? finishLegend(next) : next;
|
|
318
404
|
}
|
|
319
405
|
|
|
320
|
-
export const createLegend = action(
|
|
406
|
+
export const createLegend = /* @__PURE__ */ action(
|
|
321
407
|
{ op: "createLegend", description: "Create an inferred legend for selected channels." },
|
|
322
408
|
withGuideLayoutValidation(function (args = {}) {
|
|
323
409
|
return applyLegendCreationPlan(this, resolveLegendCreationPlan(this, args));
|
|
324
410
|
})
|
|
325
411
|
);
|
|
326
412
|
|
|
327
|
-
export const removeCategoricalLegend = action(
|
|
413
|
+
export const removeCategoricalLegend = /* @__PURE__ */ action(
|
|
328
414
|
{
|
|
329
415
|
op: "removeCategoricalLegend",
|
|
330
416
|
description: "Remove the active categorical legend and its concrete components."
|
|
331
417
|
},
|
|
332
418
|
withGuideLayoutValidation(function (args = {}) {
|
|
333
419
|
noOptions(args, "removeCategoricalLegend");
|
|
334
|
-
const entries = ["series", "color"]
|
|
420
|
+
const entries = ["series", "color", "stroke"]
|
|
335
421
|
.filter(kind => this.guideConfigs.legend?.[kind] !== undefined);
|
|
336
422
|
if (entries.length === 0) return this;
|
|
337
423
|
if (entries.length !== 1) {
|
|
338
424
|
throw new Error("removeCategoricalLegend requires one active categorical legend.");
|
|
339
425
|
}
|
|
340
426
|
const kind = entries[0];
|
|
341
|
-
const prefix = kind
|
|
427
|
+
const prefix = `${kind}Legend`;
|
|
342
428
|
const targets = Object.keys(this.graphicSpec.objects)
|
|
343
429
|
.filter(id => id.startsWith(prefix));
|
|
344
430
|
let next = this.editSemantic({
|
|
@@ -1,41 +1,49 @@
|
|
|
1
|
+
import { editGraphicProperties } from "../../../primitives/graphicProperties.js";
|
|
1
2
|
import { action } from "../../../../core/action.js";
|
|
2
|
-
import {
|
|
3
|
-
|
|
3
|
+
import {
|
|
4
|
+
activeConfig,
|
|
5
|
+
categoricalLegendLabels,
|
|
6
|
+
graphic,
|
|
7
|
+
noOptions,
|
|
8
|
+
resolveLayout
|
|
9
|
+
} from "./layout.js";
|
|
4
10
|
import { resolveCategoricalLegendPlacement } from "../lifecycle.js";
|
|
5
11
|
|
|
6
|
-
export const rematerializeLegendLabels = action(
|
|
12
|
+
export const rematerializeLegendLabels = /* @__PURE__ */ action(
|
|
7
13
|
{ op: "rematerializeLegendLabels", description: "Rematerialize categorical legend labels." },
|
|
8
14
|
function (args = {}) {
|
|
9
15
|
noOptions(args, "rematerializeLegendLabels");
|
|
10
|
-
const { config } = activeConfig(this);
|
|
16
|
+
const { config } = activeConfig(this, args.kind);
|
|
11
17
|
const id = graphic(config, "Labels");
|
|
12
18
|
if (this.graphicSpec.objects[id]?.type !== "text") {
|
|
13
19
|
throw new Error("rematerializeLegendLabels requires existing legend labels.");
|
|
14
20
|
}
|
|
15
21
|
const layout = resolveLayout(this, config);
|
|
16
|
-
return this
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
22
|
+
return editGraphicProperties(editGraphicProperties(this, id, {
|
|
23
|
+
length: config.domain.length,
|
|
24
|
+
x: layout.labelX,
|
|
25
|
+
y: layout.itemY
|
|
26
|
+
})
|
|
20
27
|
.editGraphics({
|
|
21
28
|
target: id,
|
|
22
29
|
property: "text",
|
|
23
|
-
value: config
|
|
24
|
-
})
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
30
|
+
value: categoricalLegendLabels(config)
|
|
31
|
+
}), id, {
|
|
32
|
+
fill: config.labels.color,
|
|
33
|
+
fontSize: config.labels.fontSize,
|
|
34
|
+
fontFamily: config.labels.fontFamily,
|
|
35
|
+
fontWeight: config.labels.fontWeight,
|
|
36
|
+
textAlign: "left",
|
|
37
|
+
textBaseline: "middle"
|
|
38
|
+
});
|
|
31
39
|
}
|
|
32
40
|
);
|
|
33
41
|
|
|
34
|
-
export const createLegendLabels = action(
|
|
42
|
+
export const createLegendLabels = /* @__PURE__ */ action(
|
|
35
43
|
{ op: "createLegendLabels", description: "Create categorical legend labels." },
|
|
36
44
|
function (args = {}) {
|
|
37
45
|
noOptions(args, "createLegendLabels");
|
|
38
|
-
const { config } = activeConfig(this);
|
|
46
|
+
const { config } = activeConfig(this, args.kind);
|
|
39
47
|
const id = graphic(config, "Labels");
|
|
40
48
|
if (this.graphicSpec.objects[id] !== undefined) {
|
|
41
49
|
throw new Error("createLegendLabels requires missing legend labels.");
|
|
@@ -47,28 +55,29 @@ export const createLegendLabels = action(
|
|
|
47
55
|
length: config.domain.length,
|
|
48
56
|
...resolveCategoricalLegendPlacement(this)
|
|
49
57
|
})
|
|
50
|
-
.rematerializeLegendLabels();
|
|
58
|
+
.rematerializeLegendLabels({ kind: config.kind });
|
|
51
59
|
}
|
|
52
60
|
);
|
|
53
61
|
|
|
54
|
-
export const rematerializeLegendTitle = action(
|
|
62
|
+
export const rematerializeLegendTitle = /* @__PURE__ */ action(
|
|
55
63
|
{ op: "rematerializeLegendTitle", description: "Rematerialize the categorical legend title." },
|
|
56
64
|
function (args = {}) {
|
|
57
65
|
noOptions(args, "rematerializeLegendTitle");
|
|
58
|
-
const { config } = activeConfig(this);
|
|
66
|
+
const { config } = activeConfig(this, args.kind);
|
|
59
67
|
const id = graphic(config, "Title");
|
|
60
68
|
if (this.graphicSpec.objects[id]?.type !== "text") {
|
|
61
69
|
throw new Error("rematerializeLegendTitle requires an existing legend title.");
|
|
62
70
|
}
|
|
63
71
|
const layout = resolveLayout(this, config);
|
|
64
|
-
return this
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
|
|
69
|
-
|
|
70
|
-
|
|
71
|
-
|
|
72
|
+
return editGraphicProperties(this, id, {
|
|
73
|
+
x: layout.titleX,
|
|
74
|
+
y: layout.titleY,
|
|
75
|
+
text: config.title,
|
|
76
|
+
fill: config.titleStyle.color,
|
|
77
|
+
fontSize: config.titleStyle.fontSize,
|
|
78
|
+
fontFamily: config.titleStyle.fontFamily,
|
|
79
|
+
fontWeight: config.titleStyle.fontWeight
|
|
80
|
+
})
|
|
72
81
|
.editGraphics({
|
|
73
82
|
target: id,
|
|
74
83
|
property: "textAlign",
|
|
@@ -81,11 +90,11 @@ export const rematerializeLegendTitle = action(
|
|
|
81
90
|
}
|
|
82
91
|
);
|
|
83
92
|
|
|
84
|
-
export const createLegendTitle = action(
|
|
93
|
+
export const createLegendTitle = /* @__PURE__ */ action(
|
|
85
94
|
{ op: "createLegendTitle", description: "Create the categorical legend title." },
|
|
86
95
|
function (args = {}) {
|
|
87
96
|
noOptions(args, "createLegendTitle");
|
|
88
|
-
const { config } = activeConfig(this);
|
|
97
|
+
const { config } = activeConfig(this, args.kind);
|
|
89
98
|
const id = graphic(config, "Title");
|
|
90
99
|
if (this.graphicSpec.objects[id] !== undefined) {
|
|
91
100
|
throw new Error("createLegendTitle requires a missing legend title.");
|
|
@@ -96,15 +105,15 @@ export const createLegendTitle = action(
|
|
|
96
105
|
type: "text",
|
|
97
106
|
...resolveCategoricalLegendPlacement(this)
|
|
98
107
|
})
|
|
99
|
-
.rematerializeLegendTitle();
|
|
108
|
+
.rematerializeLegendTitle({ kind: config.kind });
|
|
100
109
|
}
|
|
101
110
|
);
|
|
102
111
|
|
|
103
|
-
export const rematerializeLegendBackground = action(
|
|
112
|
+
export const rematerializeLegendBackground = /* @__PURE__ */ action(
|
|
104
113
|
{ op: "rematerializeLegendBackground", description: "Rematerialize the legend background." },
|
|
105
114
|
function (args = {}) {
|
|
106
115
|
noOptions(args, "rematerializeLegendBackground");
|
|
107
|
-
const { config } = activeConfig(this);
|
|
116
|
+
const { config } = activeConfig(this, args.kind);
|
|
108
117
|
if (config.border === false) {
|
|
109
118
|
throw new Error("rematerializeLegendBackground requires border configuration.");
|
|
110
119
|
}
|
|
@@ -113,22 +122,23 @@ export const rematerializeLegendBackground = action(
|
|
|
113
122
|
throw new Error("rematerializeLegendBackground requires an existing background.");
|
|
114
123
|
}
|
|
115
124
|
const layout = resolveLayout(this, config).background;
|
|
116
|
-
return this
|
|
117
|
-
|
|
118
|
-
|
|
119
|
-
|
|
120
|
-
|
|
121
|
-
|
|
122
|
-
|
|
123
|
-
|
|
125
|
+
return editGraphicProperties(this, id, {
|
|
126
|
+
x: layout.x,
|
|
127
|
+
y: layout.y,
|
|
128
|
+
width: layout.width,
|
|
129
|
+
height: layout.height,
|
|
130
|
+
fill: config.border.background,
|
|
131
|
+
stroke: config.border.color,
|
|
132
|
+
strokeWidth: config.border.lineWidth
|
|
133
|
+
});
|
|
124
134
|
}
|
|
125
135
|
);
|
|
126
136
|
|
|
127
|
-
export const createLegendBackground = action(
|
|
137
|
+
export const createLegendBackground = /* @__PURE__ */ action(
|
|
128
138
|
{ op: "createLegendBackground", description: "Create the legend background rect." },
|
|
129
139
|
function (args = {}) {
|
|
130
140
|
noOptions(args, "createLegendBackground");
|
|
131
|
-
const { config } = activeConfig(this);
|
|
141
|
+
const { config } = activeConfig(this, args.kind);
|
|
132
142
|
const id = graphic(config, "Background");
|
|
133
143
|
if (this.graphicSpec.objects[id] !== undefined) {
|
|
134
144
|
throw new Error("createLegendBackground requires a missing background.");
|
|
@@ -139,6 +149,6 @@ export const createLegendBackground = action(
|
|
|
139
149
|
type: "rect",
|
|
140
150
|
...resolveCategoricalLegendPlacement(this)
|
|
141
151
|
})
|
|
142
|
-
.rematerializeLegendBackground();
|
|
152
|
+
.rematerializeLegendBackground({ kind: config.kind });
|
|
143
153
|
}
|
|
144
154
|
);
|
|
@@ -68,40 +68,44 @@ function createLegendHighlightAction() {
|
|
|
68
68
|
},
|
|
69
69
|
function (args = {}) {
|
|
70
70
|
noOptions(args, "rematerializeLegendHighlights");
|
|
71
|
-
const
|
|
72
|
-
|
|
73
|
-
|
|
74
|
-
|
|
75
|
-
|
|
76
|
-
|
|
77
|
-
|
|
78
|
-
|
|
79
|
-
|
|
80
|
-
|
|
81
|
-
|
|
82
|
-
|
|
71
|
+
const kinds = args.kind === undefined
|
|
72
|
+
? ["series", "color", "stroke"].filter(
|
|
73
|
+
kind => this.guideConfigs.legend?.[kind] !== undefined
|
|
74
|
+
)
|
|
75
|
+
: [args.kind];
|
|
76
|
+
let next = this;
|
|
77
|
+
for (const kind of kinds) {
|
|
78
|
+
const { config } = activeConfig(next, kind);
|
|
79
|
+
const highlights = Object.values(
|
|
80
|
+
next.materializationConfigs.highlights ?? {}
|
|
81
|
+
).map(highlight => ({
|
|
82
|
+
highlight,
|
|
83
|
+
states: exactLegendSelection(next, config, highlight)
|
|
84
|
+
})).filter(entry => entry.states !== undefined);
|
|
85
|
+
if (highlights.length === 0) continue;
|
|
83
86
|
|
|
84
|
-
|
|
85
|
-
|
|
86
|
-
|
|
87
|
-
|
|
88
|
-
|
|
89
|
-
|
|
90
|
-
|
|
91
|
-
|
|
92
|
-
|
|
93
|
-
|
|
94
|
-
|
|
95
|
-
|
|
96
|
-
|
|
97
|
-
|
|
98
|
-
|
|
99
|
-
|
|
100
|
-
|
|
101
|
-
|
|
102
|
-
|
|
103
|
-
|
|
104
|
-
|
|
87
|
+
next = next.rematerializeLegendSymbols({ kind: config.kind });
|
|
88
|
+
for (const { highlight, states } of highlights) {
|
|
89
|
+
for (const layer of config.symbol.layers) {
|
|
90
|
+
const id = symbolGraphic(config, layer.type);
|
|
91
|
+
const graphic = next.graphicSpec.objects[id];
|
|
92
|
+
const selectedStyle = legendLayerStyle(layer, highlight.style);
|
|
93
|
+
const dimOpacity = highlight.dimOthers === false
|
|
94
|
+
? undefined
|
|
95
|
+
: highlight.dimOthers.opacity;
|
|
96
|
+
next = next.editGraphics({
|
|
97
|
+
target: id,
|
|
98
|
+
property: "items",
|
|
99
|
+
value: graphic.items.map((child, index) => ({
|
|
100
|
+
type: child.type ?? graphic.type,
|
|
101
|
+
properties: states[index]
|
|
102
|
+
? { ...child.properties, ...selectedStyle }
|
|
103
|
+
: dimOpacity === undefined
|
|
104
|
+
? child.properties
|
|
105
|
+
: { ...child.properties, opacity: dimOpacity }
|
|
106
|
+
}))
|
|
107
|
+
});
|
|
108
|
+
}
|
|
105
109
|
}
|
|
106
110
|
}
|
|
107
111
|
return next;
|