ggaction 0.0.17 → 0.0.19
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 +96 -0
- package/README.md +6 -2
- package/knowledge/action-card.schema.json +1 -1
- package/knowledge/action-cards.json +1 -1
- package/knowledge/intent-taxonomy.json +1 -1
- package/knowledge/mcp-resources.json +1 -1
- package/knowledge/task-resolver.js +1 -1
- package/package.json +3 -3
- package/src/BasicChartProgram.js +1 -1
- package/src/accessibility.js +3 -2
- package/src/actions/boxPlots/create.js +14 -4
- package/src/actions/boxPlots/edit.js +39 -33
- package/src/actions/boxPlots/materialize.js +7 -3
- package/src/actions/boxPlots/options.js +37 -11
- package/src/actions/canvas/actions.js +70 -95
- package/src/actions/canvas/fitting.js +20 -1
- package/src/actions/canvas/index.js +3 -0
- package/src/actions/canvas/plotBorder.js +28 -0
- package/src/actions/charts/area.js +2 -2
- package/src/actions/charts/bar.js +34 -7
- package/src/actions/charts/ecdf.js +4 -18
- package/src/actions/charts/endpoints.js +4 -18
- package/src/actions/charts/heatmap.js +8 -7
- package/src/actions/charts/index.js +2 -0
- package/src/actions/charts/interval-regression.js +2 -2
- package/src/actions/charts/line.js +1 -1
- package/src/actions/charts/pie.js +3 -47
- package/src/actions/charts/radial.js +34 -12
- package/src/actions/charts/scatter.js +16 -2
- package/src/actions/charts/shared.js +2 -2
- package/src/actions/charts/text.js +35 -0
- package/src/actions/composition/actions.js +6 -2
- package/src/actions/data/box.js +2 -1
- package/src/actions/data/derived.js +11 -1
- package/src/actions/data/edit.js +3 -1
- package/src/actions/data/index.js +4 -0
- package/src/actions/data/regression.js +25 -16
- package/src/actions/data/regressionStatistics.js +73 -0
- package/src/actions/data/shared.js +8 -4
- package/src/actions/data/stack.js +3 -1
- package/src/actions/distributions/revision.js +24 -18
- package/src/actions/encodings/appearance.js +37 -29
- package/src/actions/encodings/barWidth.js +36 -11
- package/src/actions/encodings/channels.js +0 -1
- package/src/actions/encodings/color/continuous.js +1 -1
- package/src/actions/encodings/color/index.js +1 -1
- package/src/actions/encodings/color/policy.js +10 -3
- package/src/actions/encodings/density/resolve.js +1 -6
- package/src/actions/encodings/position/policies/arc.js +12 -10
- package/src/actions/encodings/position/policies/area.js +3 -3
- package/src/actions/encodings/position/policies/bar.js +15 -6
- package/src/actions/encodings/position/policies/line.js +17 -6
- package/src/actions/encodings/position/resolve.js +3 -2
- package/src/actions/encodings/ranged.js +17 -0
- package/src/actions/encodings/remove.js +14 -8
- package/src/actions/encodings/seriesLayout.js +1 -0
- package/src/actions/encodings/shared.js +26 -24
- package/src/actions/encodings/text.js +6 -3
- package/src/actions/errorBands/create.js +2 -2
- package/src/actions/errorBands/edit.js +2 -1
- package/src/actions/facets/actions.js +176 -247
- package/src/actions/facets/guides.js +2 -1
- package/src/actions/gradientPlots/resolve.js +2 -17
- package/src/actions/guides/applicability.js +1 -1
- package/src/actions/guides/axes/axes.js +30 -11
- package/src/actions/guides/axes/axis.js +72 -10
- package/src/actions/guides/axes/components.js +13 -13
- package/src/actions/guides/axes/edit.js +36 -24
- package/src/actions/guides/axes/labels.js +155 -71
- package/src/actions/guides/axes/lines.js +27 -24
- package/src/actions/guides/axes/parallel/lifecycle.js +1 -1
- package/src/actions/guides/axes/parallel/policy.js +8 -7
- package/src/actions/guides/axes/remove.js +13 -8
- package/src/actions/guides/axes/tickGroups.js +11 -7
- package/src/actions/guides/axes/ticks.js +36 -24
- package/src/actions/guides/axes/titles.js +107 -69
- package/src/actions/guides/basic.js +2 -0
- package/src/actions/guides/facadeAxes.js +33 -24
- package/src/actions/guides/facadeLegend.js +12 -4
- package/src/actions/guides/grids/grid.js +8 -2
- package/src/actions/guides/grids/resolve.js +102 -58
- package/src/actions/guides/legends/blocks.js +46 -20
- package/src/actions/guides/legends/categorical/actions.js +95 -19
- package/src/actions/guides/legends/categorical/components.js +15 -18
- package/src/actions/guides/legends/categorical/index.js +8 -0
- package/src/actions/guides/legends/categorical/layout.js +45 -20
- package/src/actions/guides/legends/categorical/options.js +39 -22
- package/src/actions/guides/legends/categorical/recipes.js +7 -3
- package/src/actions/guides/legends/categorical/resolve.js +11 -4
- package/src/actions/guides/legends/categorical/symbols.js +38 -18
- package/src/actions/guides/legends/categorical/validation.js +1 -6
- package/src/actions/guides/legends/colorSize.js +110 -0
- package/src/actions/guides/legends/combine.js +37 -0
- package/src/actions/guides/legends/continuous/colorSymbols.js +1 -0
- package/src/actions/guides/legends/continuous/common.js +1 -447
- package/src/actions/guides/legends/continuous/gradient.js +73 -46
- package/src/actions/guides/legends/continuous/interval.js +4 -4
- package/src/actions/guides/legends/continuous/opacity.js +33 -21
- package/src/actions/guides/legends/creation.js +2 -0
- package/src/actions/guides/legends/edit.js +1 -604
- package/src/actions/guides/legends/focused.js +8 -7
- package/src/actions/guides/legends/group.js +1 -0
- package/src/actions/guides/legends/lane.js +1 -516
- package/src/actions/guides/legends/lifecycle.js +2 -1
- package/src/actions/guides/legends/remove.js +9 -3
- package/src/actions/guides/legends/sampling.js +1 -1
- package/src/actions/guides/legends/size.js +65 -47
- package/src/actions/guides/legends/strokeWidth.js +13 -29
- package/src/actions/guides/legends/target.js +2 -79
- package/src/actions/guides/legends/transition.js +44 -11
- package/src/actions/guides/polar/axes/labels.js +4 -2
- package/src/actions/guides/polar/axes/titles.js +7 -5
- package/src/actions/guides/polar/resolve.js +6 -14
- package/src/actions/guides/tickValues.js +8 -5
- package/src/actions/index.js +16 -16
- package/src/actions/marks/arc/actions.js +3 -10
- package/src/actions/marks/area/actions.js +8 -5
- package/src/actions/marks/area/materialize.js +8 -9
- package/src/actions/marks/bar/create.js +10 -4
- package/src/actions/marks/bar/edit.js +29 -14
- package/src/actions/marks/bar/materialize.js +15 -7
- package/src/actions/marks/line/actions.js +11 -4
- package/src/actions/marks/line/materialize.js +9 -5
- package/src/actions/marks/point/edit.js +1 -1
- package/src/actions/marks/point/materialize.js +5 -1
- package/src/actions/marks/rect/actions.js +3 -3
- package/src/actions/marks/remove.js +12 -10
- package/src/actions/marks/rule/actions.js +7 -4
- package/src/actions/marks/text/actions.js +17 -5
- package/src/actions/marks/text/layout.js +3 -0
- package/src/actions/primitives/createGraphics.js +3 -2
- package/src/actions/primitives/editGraphics.js +15 -11
- package/src/actions/primitives/graphicProperties.js +1 -6
- package/src/actions/primitives/semanticAction.js +27 -1
- package/src/actions/primitives/semanticValidation/guide.js +11 -1
- package/src/actions/primitives/semanticValidation/layer.js +8 -0
- package/src/actions/regression/create.js +1 -1
- package/src/actions/regression/edit.js +18 -6
- package/src/actions/regression/resolve.js +2 -6
- package/src/actions/scales/channels.js +9 -4
- package/src/actions/scales/consumers/families.js +16 -5
- package/src/actions/scales/create.js +10 -5
- package/src/actions/scales/definitions.js +1 -425
- package/src/actions/scales/edit.js +3 -3
- package/src/actions/scales/editPolicy.js +12 -3
- package/src/actions/scales/materialize.js +1 -1
- package/src/actions/scales/patch.js +1 -1
- package/src/actions/scales/preview.js +21 -1
- package/src/actions/scales/quantitativeColor.js +8 -3
- package/src/actions/selection/actions.js +1 -13
- package/src/actions/theme/reconcile.js +126 -45
- package/src/actions/theme/state.js +12 -0
- package/src/actions/titles/actions.js +5 -18
- package/src/actions/titles/resolve.js +41 -19
- package/src/actions/violinPlots/edit.js +3 -20
- package/src/core/compositionState.js +6 -3
- package/src/core/font.js +9 -2
- package/src/core/graphicProperties.js +1 -0
- package/src/core/optionRequirements.js +1 -0
- package/src/core/programState.js +4 -0
- package/src/core/resourceReferences.js +5 -2
- package/src/core/textMetricProfile.js +3 -2
- package/src/core/textMetrics.js +41 -4
- package/src/core/validation.js +35 -0
- package/src/core/vocabulary.js +7 -0
- package/src/grammar/aggregate.js +4 -18
- package/src/grammar/arcs.js +1 -386
- package/src/grammar/areaPaint.js +10 -0
- package/src/grammar/areaSeries.js +18 -10
- package/src/grammar/axisTextPlacement.js +1 -0
- package/src/grammar/bars/geometry.js +30 -3
- package/src/grammar/bars/policy.js +12 -1
- package/src/grammar/bin.js +2 -12
- package/src/grammar/bin2d.js +1 -6
- package/src/grammar/boxPlot.js +56 -9
- package/src/grammar/categoryOrder.js +1 -6
- package/src/grammar/colorSizeLegend.js +39 -0
- package/src/grammar/complete.js +15 -19
- package/src/grammar/computed.js +115 -26
- package/src/grammar/curveCommands.js +29 -16
- package/src/grammar/datasetSchema.js +13 -9
- package/src/grammar/displayLabels.js +36 -0
- package/src/grammar/ecdf.js +2 -9
- package/src/grammar/facets/dependencies.js +6 -2
- package/src/grammar/facets/guides.js +58 -30
- package/src/grammar/facets/index.js +2 -5
- package/src/grammar/facets/legendIntent.js +65 -0
- package/src/grammar/fold.js +2 -12
- package/src/grammar/gradientProfile.js +1 -6
- package/src/grammar/guideDash.js +1 -0
- package/src/grammar/impute.js +21 -48
- package/src/grammar/interval.js +2 -9
- package/src/grammar/legendBlocks.js +1 -0
- package/src/grammar/legendBorder.js +9 -0
- package/src/grammar/legendClip.js +19 -0
- package/src/grammar/legendCombinations.js +45 -0
- package/src/grammar/legendGradient.js +27 -0
- package/src/grammar/legendGroups.js +1 -0
- package/src/grammar/legendOpacity.js +6 -0
- package/src/grammar/legendTitleStyle.js +22 -0
- package/src/grammar/lineSeries.js +32 -17
- package/src/grammar/markLabels.js +5 -2
- package/src/grammar/normalize.js +4 -54
- package/src/grammar/numeric.js +1 -290
- package/src/grammar/parallelCoordinates.js +1 -6
- package/src/grammar/parseTime.js +41 -0
- package/src/grammar/pathCommands.js +11 -4
- package/src/grammar/pointShapes.js +16 -2
- package/src/grammar/polar.js +1 -184
- package/src/grammar/positionCompatibility.js +3 -3
- package/src/grammar/regression/derive.js +16 -2
- package/src/grammar/regression/models.js +142 -54
- package/src/grammar/regression/parameters.js +23 -4
- package/src/grammar/regression/statistics.js +64 -0
- package/src/grammar/roundedRect.js +42 -54
- package/src/grammar/scales/appearance.js +1 -206
- package/src/grammar/scales/color.js +1 -382
- package/src/grammar/scales/colorConsumers.js +5 -2
- package/src/grammar/scales/definition.js +1 -197
- package/src/grammar/scales/discretized.js +1 -195
- package/src/grammar/scales/size.js +1 -456
- package/src/grammar/scales/temporal.js +2 -13
- package/src/grammar/scales/transformed.js +1 -383
- package/src/grammar/scales/types.js +1 -1
- package/src/grammar/scales/validation.js +1 -66
- package/src/grammar/schemas/concreteGraphic.js +14 -0
- package/src/grammar/schemas/graphic.js +6 -0
- package/src/grammar/schemas/graphicBounds.js +31 -7
- package/src/grammar/schemas/semanticPath.js +19 -3
- package/src/grammar/stack.js +2 -10
- package/src/grammar/statisticalReference.js +1 -6
- package/src/grammar/summary.js +4 -27
- package/src/grammar/text.js +19 -0
- package/src/grammar/timeUnit.js +22 -11
- package/src/grammar/transformKeys.js +47 -0
- package/src/grammar/transformTopology.js +1 -0
- package/src/grammar/transforms.js +15 -2
- package/src/grammar/valueFormat.js +17 -5
- package/src/grammar/weightedStatistics.js +1 -6
- package/src/grammar/window.js +4 -58
- package/src/inspectionDescriptors.js +1 -1
- package/src/layout/canvas.js +1 -110
- package/src/layout/facets.js +1 -244
- package/src/layout/guideCollisions.js +9 -1
- package/src/layout/labels.js +1 -0
- package/src/layout/legend.js +13 -0
- package/src/layout/legendGroup.js +1 -0
- package/src/layout/legendItems.js +59 -15
- package/src/layout/legendLane.js +1 -441
- package/src/layout/legendText.js +1 -0
- package/src/layout/title.js +35 -13
- package/src/materialization/bars/aggregate.js +11 -5
- package/src/materialization/bars/histogram.js +4 -1
- package/src/materialization/bars/ranged.js +19 -6
- package/src/materialization/bars/resolve.js +22 -1
- package/src/materialization/compositionSnapshot.js +2 -7
- package/src/materialization/coordinateBounds.js +21 -0
- package/src/materialization/dependencies.js +4 -44
- package/src/materialization/facetGuides/edit.js +30 -0
- package/src/materialization/facetGuides/layout.js +1 -0
- package/src/materialization/facetGuides/owner.js +125 -0
- package/src/materialization/facetGuides/ownerLayout.js +71 -0
- package/src/materialization/facetGuides/placement.js +71 -14
- package/src/materialization/facetGuides/preparation.js +22 -7
- package/src/materialization/facetHeaders.js +1 -347
- package/src/materialization/facets.js +1 -185
- package/src/materialization/graphicHierarchy.js +5 -1
- package/src/materialization/graphicTranslation.js +73 -0
- package/src/materialization/guides/layout.js +1 -57
- package/src/materialization/guides/resources.js +1 -123
- package/src/materialization/layout.js +53 -0
- package/src/materialization/legendBorder.js +28 -0
- package/src/materialization/legendClip.js +76 -0
- package/src/materialization/legendGroups.js +1 -0
- package/src/materialization/legendText.js +1 -0
- package/src/materialization/legends.js +2 -2
- package/src/materialization/marks/capabilities.js +5 -6
- package/src/materialization/rect.js +1 -1
- package/src/materialization/scaleGuideDependencies.js +14 -15
- package/src/materialization/scales/map.js +6 -0
- package/src/materialization/scales/policies/arc.js +8 -7
- package/src/materialization/scales/policies/bar.js +19 -7
- package/src/materialization/scales/policies/series.js +2 -1
- package/src/materialization/scales/resolve.js +7 -3
- package/src/materialization/selection/items/arc.js +1 -1
- package/src/materialization/selection/items/bar.js +7 -6
- package/src/materialization/selection/items/path.js +7 -6
- package/src/materialization/selection/items/rect.js +2 -2
- package/src/materialization/text.js +13 -4
- package/src/materialization/textLines.js +15 -0
- package/src/materialization/typography.js +10 -2
- package/src/persistence/codec.js +37 -6
- package/src/persistence/validation.js +220 -0
- package/src/persistence.js +19 -6
- package/src/renderers/canvas/circle.js +6 -3
- package/src/renderers/canvas/fill.js +7 -1
- package/src/renderers/canvas/index.js +22 -11
- package/src/renderers/canvas/isolated.js +166 -0
- package/src/renderers/canvas/limits.js +3 -0
- package/src/renderers/canvas/line.js +1 -0
- package/src/renderers/canvas/path.js +1 -1
- package/src/renderers/canvas/rect.js +11 -8
- package/src/renderers/canvas/stroke.js +2 -1
- package/src/renderers/canvas/text.js +5 -3
- package/src/renderers/pdf.js +2 -2
- package/src/renderers/png.js +2 -2
- package/src/renderers/svg.js +14 -4
- package/src/selectors/axes.js +1 -0
- package/src/selectors/graphicCapacity.js +38 -0
- package/src/selectors/layers.js +19 -0
- package/src/theme/defaults.js +8 -2
- package/src/version.js +1 -1
- package/types/basic.d.ts +3 -0
- package/types/index.d.ts +12 -0
- package/types/program.d.ts +536 -129
|
@@ -1,6 +1,12 @@
|
|
|
1
|
+
import{validateLegendClip}from"../../../../grammar/legendClip.js";
|
|
2
|
+
import{hasLegendClipGraphics}from"../../../../materialization/legendClip.js";
|
|
3
|
+
import { normalizeColorSymbols, resolveColorSymbolsLayout, materializeColorSymbols } from "./colorSymbols.js";
|
|
4
|
+
import { alignLegendTitle, resolveLegendTitleText } from "../../../../layout/legendText.js";
|
|
5
|
+
import { intrinsicLegendConfig } from "../../../../materialization/legendGroups.js";
|
|
6
|
+
import { mapContinuousScaleValues, transformedTicks } from "../../../../grammar/scales/index.js";
|
|
1
7
|
import { action, closedAction } from "../../../../core/action.js";
|
|
2
8
|
import { isPlainObject } from "../../../../core/immutable.js";
|
|
3
|
-
import {
|
|
9
|
+
import { normalizeLegendGradient, DEFAULT_LEGEND_GRADIENT } from "../../../../grammar/legendGradient.js";
|
|
4
10
|
import { mapScaleConsumerValues } from "../../../../materialization/scales/map.js";
|
|
5
11
|
import { inverseLerp, interpolateNumber } from "../../../../grammar/numeric.js";
|
|
6
12
|
import { DEFAULT_COLORS } from "../../../../theme/defaults.js";
|
|
@@ -16,49 +22,61 @@ import {
|
|
|
16
22
|
resolveLegendBackgroundFromBounds,
|
|
17
23
|
resolveLegendTextBounds,
|
|
18
24
|
sampleContinuousValues,
|
|
19
|
-
styleContinuousText
|
|
20
|
-
validatePositive
|
|
25
|
+
styleContinuousText
|
|
21
26
|
} from "./common.js";
|
|
22
27
|
import { resolveLegendGraphicPlacement } from
|
|
23
28
|
"../../../../materialization/graphicHierarchy.js";
|
|
24
29
|
import { resolveEffectiveLegendBlockConfig } from "../blocks.js";
|
|
25
30
|
|
|
26
|
-
export const DEFAULT_GRADIENT_SIZE =
|
|
31
|
+
export const DEFAULT_GRADIENT_SIZE = DEFAULT_LEGEND_GRADIENT;
|
|
27
32
|
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
33
|
+
export function resolveGradientLayout(program, config, scale, label = "Gradient legend", stripStrokeWidth = 0) {
|
|
34
|
+
validateLegendClip("gradient",config);
|
|
35
|
+
if (config.representation === "symbols") return resolveColorSymbolsLayout(program, config, scale);
|
|
36
|
+
config = intrinsicLegendConfig(program, config);
|
|
31
37
|
const { plot, canvas } = resolveContinuousBounds(program);
|
|
32
|
-
const vertical =
|
|
38
|
+
const vertical = config.gradientDirection === undefined
|
|
39
|
+
? ["right", "left"].includes(config.position) : config.gradientDirection === "vertical";
|
|
40
|
+
const stripWidth = vertical ? config.gradient.thickness : config.gradient.length;
|
|
41
|
+
const stripHeight = vertical ? config.gradient.length : config.gradient.thickness;
|
|
33
42
|
const length = config.gradient.length;
|
|
34
43
|
const thickness = config.gradient.thickness;
|
|
44
|
+
const titleText = config.titleVisible === false ? { height: 0, extraHeight: 0 }
|
|
45
|
+
: resolveLegendTitleText(config.title, config.titleStyle, program.materializationConfigs.textMetrics);
|
|
35
46
|
const titleGap = config.blockGap ?? 12;
|
|
36
47
|
let x;
|
|
37
48
|
let y;
|
|
38
49
|
if (config.position === "right") {
|
|
39
50
|
x = plot.x + plot.width + config.offset;
|
|
40
|
-
y = plot.y + 46 + titleGap - 12;
|
|
51
|
+
y = plot.y + 46 + titleGap - 12 + titleText.extraHeight / 2;
|
|
41
52
|
} else if (config.position === "left") {
|
|
42
|
-
x = plot.x - config.offset -
|
|
43
|
-
y = plot.y + 46 + titleGap - 12;
|
|
53
|
+
x = plot.x - config.offset - stripWidth;
|
|
54
|
+
y = plot.y + 46 + titleGap - 12 + titleText.extraHeight / 2;
|
|
44
55
|
} else {
|
|
45
56
|
x = config.align === "left" ? plot.x
|
|
46
|
-
: config.align === "right" ? plot.x + plot.width -
|
|
47
|
-
: plot.x + (plot.width -
|
|
57
|
+
: config.align === "right" ? plot.x + plot.width - stripWidth
|
|
58
|
+
: plot.x + (plot.width - stripWidth) / 2;
|
|
48
59
|
y = config.position === "top"
|
|
49
|
-
? plot.y - config.offset -
|
|
60
|
+
? plot.y - config.offset - stripHeight - config.labels.offset -
|
|
50
61
|
config.labels.fontSize
|
|
51
62
|
: plot.y + plot.height + config.offset +
|
|
52
|
-
(config.titleVisible === false ? 0 :
|
|
63
|
+
(config.titleVisible === false ? 0 : titleText.height + titleGap);
|
|
53
64
|
}
|
|
54
|
-
|
|
55
|
-
? { x, y: plot.y + 20
|
|
65
|
+
let title = vertical
|
|
66
|
+
? { x, y: ["right", "left"].includes(config.position) ? plot.y + 20
|
|
67
|
+
: y - titleGap - titleText.height / 2, align: "left" }
|
|
56
68
|
: {
|
|
57
69
|
x: x + length / 2,
|
|
58
|
-
y: y - titleGap -
|
|
70
|
+
y: y - titleGap - titleText.height / 2,
|
|
59
71
|
align: "center"
|
|
60
72
|
};
|
|
61
|
-
const
|
|
73
|
+
const transformed = ["log", "pow", "sqrt", "symlog"].includes(scale.type);
|
|
74
|
+
const values = transformed
|
|
75
|
+
? transformedTicks(scale.type, scale.domain, config.count,
|
|
76
|
+
scale.type === "log" ? {base: scale.base}
|
|
77
|
+
: scale.type === "pow" ? {exponent: scale.exponent}
|
|
78
|
+
: scale.type === "symlog" ? {constant: scale.constant} : {})
|
|
79
|
+
: [...sampleContinuousValues(scale.domain, config.count)];
|
|
62
80
|
if (scale.midpoint !== undefined && !values.includes(scale.midpoint)) {
|
|
63
81
|
values.push(scale.midpoint);
|
|
64
82
|
values.sort((a, b) => scale.domain[1] > scale.domain[0] ? a - b : b - a);
|
|
@@ -69,17 +87,17 @@ export function resolveGradientLayout(program, config, scale, label = "Gradient
|
|
|
69
87
|
config.fieldType,
|
|
70
88
|
config.labels.format
|
|
71
89
|
);
|
|
72
|
-
const fractions = values
|
|
90
|
+
const fractions = transformed ? mapContinuousScaleValues(values, {...scale, range: [0, 1]})
|
|
91
|
+
: values.map((value, index) => scale.midpoint === undefined
|
|
73
92
|
? index / (values.length - 1)
|
|
74
93
|
: inverseLerp(value, ...scale.domain));
|
|
75
94
|
const labelOffset = config.labels.offset;
|
|
76
95
|
const labels = vertical
|
|
77
96
|
? fractions.map(fraction => ({
|
|
78
|
-
x: config.position === "
|
|
79
|
-
? x + thickness + labelOffset
|
|
80
|
-
: x - labelOffset,
|
|
97
|
+
x: config.position === "left"
|
|
98
|
+
? x - labelOffset : x + thickness + labelOffset,
|
|
81
99
|
y: y + length * (1 - fraction),
|
|
82
|
-
align: config.position === "
|
|
100
|
+
align: config.position === "left" ? "right" : "left"
|
|
83
101
|
}))
|
|
84
102
|
: fractions.map(fraction => ({
|
|
85
103
|
x: x + length * fraction,
|
|
@@ -88,9 +106,9 @@ export function resolveGradientLayout(program, config, scale, label = "Gradient
|
|
|
88
106
|
}));
|
|
89
107
|
const ticks = vertical
|
|
90
108
|
? labels.map(label => ({
|
|
91
|
-
x1: config.position === "
|
|
109
|
+
x1: config.position === "left" ? x : x + thickness,
|
|
92
110
|
y1: label.y,
|
|
93
|
-
x2: config.position === "
|
|
111
|
+
x2: config.position === "left" ? x - 6 : x + thickness + 6,
|
|
94
112
|
y2: label.y
|
|
95
113
|
}))
|
|
96
114
|
: labels.map(label => ({
|
|
@@ -114,11 +132,21 @@ export function resolveGradientLayout(program, config, scale, label = "Gradient
|
|
|
114
132
|
const labelBounds = labels.map((label, index) =>
|
|
115
133
|
resolveLegendTextBounds(label, texts[index], config.labels, program.materializationConfigs.textMetrics)
|
|
116
134
|
);
|
|
135
|
+
if (config.titlePosition === "bottom" && config.titleVisible !== false) {
|
|
136
|
+
const bottom = Math.max(stripBounds.bottom + stripStrokeWidth / 2,
|
|
137
|
+
...tickBounds.map(bounds => bounds.bottom), ...labelBounds.map(bounds => bounds.bottom));
|
|
138
|
+
title = { x: vertical ? x : x + length / 2,
|
|
139
|
+
y: bottom + titleGap + titleText.height / 2, align: vertical ? "left" : "center" };
|
|
140
|
+
}
|
|
141
|
+
if (config.titleVisible !== false) title = alignLegendTitle(title, config.title, config.titleStyle,
|
|
142
|
+
[{ left: stripBounds.left - stripStrokeWidth / 2, right: stripBounds.right + stripStrokeWidth / 2,
|
|
143
|
+
top: stripBounds.top - stripStrokeWidth / 2, bottom: stripBounds.bottom + stripStrokeWidth / 2 },
|
|
144
|
+
...tickBounds, ...labelBounds], program.materializationConfigs.textMetrics);
|
|
117
145
|
const titleBounds = config.titleVisible === false ? undefined : resolveLegendTextBounds(
|
|
118
146
|
title,
|
|
119
147
|
config.title,
|
|
120
148
|
config.titleStyle
|
|
121
|
-
, program.materializationConfigs.textMetrics);
|
|
149
|
+
, program.materializationConfigs.textMetrics, { hardBreaks: true });
|
|
122
150
|
const occupiedBounds = [stripBounds, ...tickBounds, ...labelBounds,
|
|
123
151
|
...(config.titleVisible === false ? [] : [titleBounds])];
|
|
124
152
|
assertLegendBoundsInsideCanvas(
|
|
@@ -173,14 +201,15 @@ export function materializeGradientLegend(program, resolved, appearance) {
|
|
|
173
201
|
const prefix = `${channel}Gradient`;
|
|
174
202
|
const { scale, encoding, config: currentConfig } = resolved;
|
|
175
203
|
const config = resolveEffectiveLegendBlockConfig(program, kind, currentConfig);
|
|
204
|
+
if (!stroke && config.representation === "symbols") return materializeColorSymbols(program, resolved, config);
|
|
176
205
|
const layout = resolveGradientLayout(program, config, scale,
|
|
177
|
-
stroke ? "Stroke gradient legend" : "Gradient legend");
|
|
206
|
+
stroke ? "Stroke gradient legend" : "Gradient legend", appearance?.strokeWidth ?? 0);
|
|
178
207
|
const stripCount = 60;
|
|
179
208
|
const stripSize = layout.length / stripCount;
|
|
180
209
|
const strips = Array.from({ length: stripCount }, (_, index) => {
|
|
181
210
|
const fraction = (index + 0.5) / stripCount;
|
|
182
211
|
const position = layout.vertical ? 1 - fraction : fraction;
|
|
183
|
-
const samplingScale = scale.midpoint === undefined ? { ...scale, domain: [0, 1] } : scale;
|
|
212
|
+
const samplingScale = scale.midpoint === undefined ? { ...scale, type: "sequential", domain: [0, 1] } : scale;
|
|
184
213
|
const value = scale.midpoint === undefined ? position : interpolateNumber(...scale.domain, position);
|
|
185
214
|
const [color] = mapScaleConsumerValues([value], samplingScale, channel);
|
|
186
215
|
return {
|
|
@@ -204,6 +233,9 @@ export function materializeGradientLegend(program, resolved, appearance) {
|
|
|
204
233
|
for (const property of ["x", "y", "width", "height", "fill", "stroke", "strokeWidth"]) {
|
|
205
234
|
next = next.editGraphics({ target: `${prefix}Strips`, property, value: strips.map(strip => strip[property]) });
|
|
206
235
|
}
|
|
236
|
+
if (config.gradient.opacity !== undefined) {
|
|
237
|
+
next = next.editGraphics({ target: `${prefix}Strips`, property: "opacity", value: config.gradient.opacity });
|
|
238
|
+
}
|
|
207
239
|
next = next.editGraphics({ target: `${prefix}Ticks`, property: "length", value: layout.ticks.length });
|
|
208
240
|
for (const property of ["x1", "y1", "x2", "y2"]) {
|
|
209
241
|
next = next.editGraphics({ target: `${prefix}Ticks`, property, value: layout.ticks.map(tick => tick[property]) });
|
|
@@ -225,6 +257,7 @@ export const rematerializeGradientLegend = /* @__PURE__ */ closedAction(
|
|
|
225
257
|
description: "Rematerialize a continuous color gradient legend."
|
|
226
258
|
}, [],
|
|
227
259
|
function (args = {}) {
|
|
260
|
+
if(hasLegendClipGraphics(this))return this.rematerializeLegend();
|
|
228
261
|
const stored = this.guideConfigs.legend?.gradient;
|
|
229
262
|
if (stored === undefined) {
|
|
230
263
|
throw new Error("Gradient legend requires stored configuration.");
|
|
@@ -235,7 +268,10 @@ export const rematerializeGradientLegend = /* @__PURE__ */ closedAction(
|
|
|
235
268
|
|
|
236
269
|
|
|
237
270
|
export function resolveGradientLegendCreation(program, args = {}, channel = "color") {
|
|
238
|
-
const
|
|
271
|
+
const { representation, ...options } = args;
|
|
272
|
+
if (representation !== undefined && !["gradient", "symbols"].includes(representation)) throw new Error("Legend representation must be gradient or symbols.");
|
|
273
|
+
if (channel !== "color" && representation !== undefined) throw new Error("Legend representation requires continuous color.");
|
|
274
|
+
const config = representation === "symbols" ? normalizeColorSymbols(options) : normalizeContinuousLegend(options, "gradient");
|
|
239
275
|
if (args.channels !== undefined && (
|
|
240
276
|
!Array.isArray(args.channels) ||
|
|
241
277
|
args.channels.length !== 1 ||
|
|
@@ -246,18 +282,7 @@ export function resolveGradientLegendCreation(program, args = {}, channel = "col
|
|
|
246
282
|
if (args.gradient !== undefined && !isPlainObject(args.gradient)) {
|
|
247
283
|
throw new TypeError("createLegend.gradient must be a plain object.");
|
|
248
284
|
}
|
|
249
|
-
|
|
250
|
-
args.gradient ?? {},
|
|
251
|
-
GRADIENT_OPTIONS,
|
|
252
|
-
"createLegend.gradient"
|
|
253
|
-
);
|
|
254
|
-
config.gradient = {
|
|
255
|
-
length: args.gradient?.length ?? DEFAULT_GRADIENT_SIZE.length,
|
|
256
|
-
thickness: args.gradient?.thickness ?? DEFAULT_GRADIENT_SIZE.thickness
|
|
257
|
-
};
|
|
258
|
-
config.titleVisible = true;
|
|
259
|
-
validatePositive(config.gradient.length, "Gradient length");
|
|
260
|
-
validatePositive(config.gradient.thickness, "Gradient thickness");
|
|
285
|
+
if (config.representation !== "symbols") config.gradient = normalizeLegendGradient(args.gradient);
|
|
261
286
|
const resolved = resolveGradientConfig(program, config, channel);
|
|
262
287
|
return resolved;
|
|
263
288
|
}
|
|
@@ -284,7 +309,9 @@ export function createGradientLegendFromConfig(program, config, channel = "color
|
|
|
284
309
|
...resolveLegendGraphicPlacement(next)
|
|
285
310
|
});
|
|
286
311
|
}
|
|
287
|
-
|
|
312
|
+
if (resolved.config.representation === "symbols") {
|
|
313
|
+
next = next.createGraphics({ id: `${prefix}Symbols`, type: "circle", length: 0, ...resolveLegendGraphicPlacement(next) });
|
|
314
|
+
} else next = next
|
|
288
315
|
.createGraphics({
|
|
289
316
|
id: `${prefix}Strips`,
|
|
290
317
|
type: "rect",
|
|
@@ -298,8 +325,8 @@ export function createGradientLegendFromConfig(program, config, channel = "color
|
|
|
298
325
|
type: "line",
|
|
299
326
|
length: 0,
|
|
300
327
|
...resolveLegendGraphicPlacement(next)
|
|
301
|
-
})
|
|
302
|
-
|
|
328
|
+
});
|
|
329
|
+
next = next.createGraphics({
|
|
303
330
|
id: `${prefix}Labels`,
|
|
304
331
|
type: "text",
|
|
305
332
|
length: 0,
|
|
@@ -323,7 +350,7 @@ export const createGradientLegend = /* @__PURE__ */ action(
|
|
|
323
350
|
function (args = {}) {
|
|
324
351
|
const resolved = resolveGradientLegendCreation(this, args);
|
|
325
352
|
resolveGradientLayout(this, resolved.config, resolved.scale);
|
|
326
|
-
if (this.
|
|
353
|
+
if (this.guideConfigs.legend?.gradient !== undefined) {
|
|
327
354
|
throw new Error(
|
|
328
355
|
"createGradientLegend requires a missing gradient legend."
|
|
329
356
|
);
|
|
@@ -1,3 +1,4 @@
|
|
|
1
|
+
import { intrinsicLegendConfig } from "../../../../materialization/legendGroups.js";
|
|
1
2
|
import { resolveLegendItemLayout } from "../../../../layout/legendItems.js";
|
|
2
3
|
import { action, closedAction } from "../../../../core/action.js";
|
|
3
4
|
import { isPlainObject } from "../../../../core/immutable.js";
|
|
@@ -13,6 +14,7 @@ import {
|
|
|
13
14
|
assertLegendBoundsInsideCanvas,
|
|
14
15
|
editGraphicProperties,
|
|
15
16
|
editLegendBackground,
|
|
17
|
+
normalizeInitialLegendTitle,
|
|
16
18
|
normalizeLegendBorder,
|
|
17
19
|
normalizeItemLegendLayout,
|
|
18
20
|
normalizeLegendTextOptions,
|
|
@@ -60,14 +62,11 @@ export function normalizeIntervalLegend(args) {
|
|
|
60
62
|
validatePositive(symbol.width, "Legend symbol width");
|
|
61
63
|
validatePositive(symbol.height, "Legend symbol height");
|
|
62
64
|
validateNonNegative(symbol.strokeWidth, "Legend symbol strokeWidth");
|
|
63
|
-
if (args.title !== undefined) validateNonEmptyString(args.title, "Legend title");
|
|
64
65
|
validateNonEmptyString(symbol.stroke, "Legend symbol stroke");
|
|
65
66
|
return {
|
|
66
67
|
target: args.target,
|
|
67
68
|
...layout,
|
|
68
|
-
|
|
69
|
-
inferredTitle: args.title === undefined,
|
|
70
|
-
titleVisible: true,
|
|
69
|
+
...normalizeInitialLegendTitle(args.title),
|
|
71
70
|
symbol,
|
|
72
71
|
labels: normalizeLegendTextOptions(args.labels, "createLegend.labels", {
|
|
73
72
|
offset: 8,
|
|
@@ -106,6 +105,7 @@ export function resolveIntervalConfig(program, stored, channel = "color") {
|
|
|
106
105
|
}
|
|
107
106
|
|
|
108
107
|
export function resolveIntervalLayout(program, config, scale, label = "Interval legend") {
|
|
108
|
+
config = intrinsicLegendConfig(program, config);
|
|
109
109
|
const { plot, canvas } = resolveContinuousBounds(program);
|
|
110
110
|
const labels = formatDiscretizedIntervals(scale.thresholds, config.labels.format);
|
|
111
111
|
const layout = resolveLegendItemLayout(plot, config, labels, config.symbol, undefined, program.materializationConfigs.textMetrics);
|
|
@@ -1,3 +1,7 @@
|
|
|
1
|
+
import{validateLegendClip}from"../../../../grammar/legendClip.js";
|
|
2
|
+
import{hasLegendClipGraphics,applyLegendClipGraphics}from"../../../../materialization/legendClip.js";
|
|
3
|
+
import { intrinsicLegendConfig } from "../../../../materialization/legendGroups.js";
|
|
4
|
+
import { alignLegendTitle, resolveLegendTitleText } from "../../../../layout/legendText.js";
|
|
1
5
|
import { editGraphicProperties } from "../../../primitives/graphicProperties.js";
|
|
2
6
|
import { action, closedAction } from "../../../../core/action.js";
|
|
3
7
|
import { isPlainObject } from "../../../../core/immutable.js";
|
|
@@ -23,6 +27,7 @@ import { resolveLegendGraphicPlacement } from
|
|
|
23
27
|
"../../../../materialization/graphicHierarchy.js";
|
|
24
28
|
import { resolveLegendSampleValues } from "../sampling.js";
|
|
25
29
|
import { resolveEffectiveLegendBlockConfig } from "../blocks.js";
|
|
30
|
+
import { legendLabelLineHeight } from "../../../../layout/legend.js";
|
|
26
31
|
|
|
27
32
|
const SYMBOL_OPTIONS = Object.freeze([
|
|
28
33
|
"type", "radius", "fill", "stroke", "strokeWidth"
|
|
@@ -85,6 +90,8 @@ function resolveOpacityConfig(program, config) {
|
|
|
85
90
|
}
|
|
86
91
|
|
|
87
92
|
function resolveOpacityLayout(program, config, scale) {
|
|
93
|
+
validateLegendClip("opacity",config);
|
|
94
|
+
config = intrinsicLegendConfig(program, config);
|
|
88
95
|
const { plot, canvas } = resolveContinuousBounds(program);
|
|
89
96
|
const vertical = ["right", "left"].includes(config.position);
|
|
90
97
|
const values = resolveLegendSampleValues(config, scale, "Opacity legend");
|
|
@@ -95,6 +102,9 @@ function resolveOpacityLayout(program, config, scale) {
|
|
|
95
102
|
config.labels.format
|
|
96
103
|
);
|
|
97
104
|
const symbolExtent = config.symbol.radius + (config.symbol.strokeWidth ?? 0) / 2;
|
|
105
|
+
const visibleExtent=Math.min(symbolExtent,config.clipHeight===undefined?Infinity:config.clipHeight/2);
|
|
106
|
+
const titleText = config.titleVisible === false ? { width: 0, height: 0 }
|
|
107
|
+
: resolveLegendTitleText(config.title, config.titleStyle, program.materializationConfigs.textMetrics);
|
|
98
108
|
const labelWidths = texts.map(text => measureTextWidth(text, config.labels, program.materializationConfigs.textMetrics));
|
|
99
109
|
let symbols;
|
|
100
110
|
let labels;
|
|
@@ -103,10 +113,10 @@ function resolveOpacityLayout(program, config, scale) {
|
|
|
103
113
|
const baseX = config.position === "right"
|
|
104
114
|
? plot.x + plot.width + config.offset
|
|
105
115
|
: plot.x - config.offset;
|
|
106
|
-
const itemHeight = Math.max(
|
|
116
|
+
const itemHeight = Math.max(visibleExtent * 2, legendLabelLineHeight(config.labels.fontSize));
|
|
107
117
|
const pitch = Math.max(config.itemGap, itemHeight);
|
|
108
118
|
const firstY = Math.max(plot.y + 46, config.titleVisible === false ? plot.y + 46
|
|
109
|
-
: plot.y + 20 +
|
|
119
|
+
: plot.y + 20 + titleText.height / 2 + 12 + itemHeight / 2);
|
|
110
120
|
const y = values.map((_, index) => firstY + index * pitch);
|
|
111
121
|
symbols = y.map(itemY => ({
|
|
112
122
|
x: config.position === "right" ? baseX + symbolExtent : baseX - symbolExtent,
|
|
@@ -125,7 +135,7 @@ function resolveOpacityLayout(program, config, scale) {
|
|
|
125
135
|
align: config.position === "right" ? "left" : "right"
|
|
126
136
|
};
|
|
127
137
|
} else if (config.titlePosition === "left") {
|
|
128
|
-
const titleWidth =
|
|
138
|
+
const titleWidth = titleText.width;
|
|
129
139
|
const titlePrefix = config.titleVisible === false ? 0 : titleWidth + 20;
|
|
130
140
|
const samplesWidth = labelWidths.reduce(
|
|
131
141
|
(sum, width) => sum + symbolExtent * 2 + config.labels.offset + width,
|
|
@@ -136,9 +146,9 @@ function resolveOpacityLayout(program, config, scale) {
|
|
|
136
146
|
: config.align === "right" ? plot.x + plot.width - width
|
|
137
147
|
: plot.x + (plot.width - width) / 2;
|
|
138
148
|
const height = Math.max(
|
|
139
|
-
|
|
149
|
+
visibleExtent * 2,
|
|
140
150
|
config.labels.fontSize,
|
|
141
|
-
|
|
151
|
+
titleText.height
|
|
142
152
|
);
|
|
143
153
|
const centerY = config.position === "top"
|
|
144
154
|
? plot.y - config.offset - height / 2
|
|
@@ -161,13 +171,13 @@ function resolveOpacityLayout(program, config, scale) {
|
|
|
161
171
|
const startX = config.align === "left" ? plot.x
|
|
162
172
|
: config.align === "right" ? plot.x + plot.width - width
|
|
163
173
|
: plot.x + (plot.width - width) / 2;
|
|
164
|
-
const titleHalf =
|
|
174
|
+
const titleHalf = titleText.height / 2;
|
|
165
175
|
const labelHalf = config.labels.fontSize / 2;
|
|
166
176
|
const y = config.position === "top"
|
|
167
177
|
? plot.y - config.offset - config.labels.fontSize -
|
|
168
|
-
config.labels.offset -
|
|
178
|
+
config.labels.offset - visibleExtent
|
|
169
179
|
: plot.y + plot.height + config.offset +
|
|
170
|
-
(config.titleVisible === false ? 0 :
|
|
180
|
+
(config.titleVisible === false ? 0 : titleText.height + 12) + visibleExtent;
|
|
171
181
|
const samplePitch = values.length === 1 ? 0 : width / (values.length - 1);
|
|
172
182
|
symbols = values.map((_, index) => ({
|
|
173
183
|
x: startX + index * samplePitch,
|
|
@@ -175,29 +185,31 @@ function resolveOpacityLayout(program, config, scale) {
|
|
|
175
185
|
}));
|
|
176
186
|
labels = symbols.map(symbol => ({
|
|
177
187
|
x: symbol.x,
|
|
178
|
-
y: symbol.y +
|
|
188
|
+
y: symbol.y + visibleExtent + config.labels.offset + labelHalf,
|
|
179
189
|
align: "center"
|
|
180
190
|
}));
|
|
181
191
|
title = {
|
|
182
192
|
x: startX + width / 2,
|
|
183
|
-
y: y -
|
|
193
|
+
y: y - visibleExtent - 12 - titleHalf,
|
|
184
194
|
align: "center"
|
|
185
195
|
};
|
|
186
196
|
}
|
|
187
|
-
const titleBounds = config.titleVisible === false ? undefined : resolveLegendTextBounds(
|
|
188
|
-
title,
|
|
189
|
-
config.title,
|
|
190
|
-
config.titleStyle
|
|
191
|
-
, program.materializationConfigs.textMetrics);
|
|
192
197
|
const labelBounds = labels.map((label, index) =>
|
|
193
198
|
resolveLegendTextBounds(label, texts[index], config.labels, program.materializationConfigs.textMetrics)
|
|
194
199
|
);
|
|
195
200
|
const symbolBounds = symbols.map(symbol => ({
|
|
196
201
|
left: symbol.x - symbolExtent,
|
|
197
202
|
right: symbol.x + symbolExtent,
|
|
198
|
-
top: symbol.y -
|
|
199
|
-
bottom: symbol.y +
|
|
203
|
+
top: symbol.y - visibleExtent,
|
|
204
|
+
bottom: symbol.y + visibleExtent
|
|
200
205
|
}));
|
|
206
|
+
if (config.titleVisible !== false) title = alignLegendTitle(title, config.title, config.titleStyle,
|
|
207
|
+
[...labelBounds, ...symbolBounds], program.materializationConfigs.textMetrics);
|
|
208
|
+
const titleBounds = config.titleVisible === false ? undefined : resolveLegendTextBounds(
|
|
209
|
+
title,
|
|
210
|
+
config.title,
|
|
211
|
+
config.titleStyle
|
|
212
|
+
, program.materializationConfigs.textMetrics, { hardBreaks: true });
|
|
201
213
|
const occupiedBounds = [...(config.titleVisible === false ? [] : [titleBounds]), ...labelBounds, ...symbolBounds];
|
|
202
214
|
assertLegendBoundsInsideCanvas(
|
|
203
215
|
occupiedBounds,
|
|
@@ -219,6 +231,7 @@ export const rematerializeOpacityLegend = /* @__PURE__ */ closedAction(
|
|
|
219
231
|
description: "Rematerialize a field-opacity sample legend."
|
|
220
232
|
}, [],
|
|
221
233
|
function (args = {}) {
|
|
234
|
+
if(hasLegendClipGraphics(this))return this.rematerializeLegend();
|
|
222
235
|
const stored = this.guideConfigs.legend?.opacity;
|
|
223
236
|
if (stored === undefined) {
|
|
224
237
|
throw new Error("Opacity legend requires stored configuration.");
|
|
@@ -278,18 +291,18 @@ export const rematerializeOpacityLegend = /* @__PURE__ */ closedAction(
|
|
|
278
291
|
config.labels,
|
|
279
292
|
{ align: layout.labels[0].align }
|
|
280
293
|
);
|
|
281
|
-
if (config.titleVisible === false) return next;
|
|
294
|
+
if (config.titleVisible === false) return applyLegendClipGraphics(next);
|
|
282
295
|
next = editGraphicProperties(next, "opacityLegendTitle", {
|
|
283
296
|
x: layout.title.x,
|
|
284
297
|
y: layout.title.y,
|
|
285
298
|
text: config.title
|
|
286
299
|
});
|
|
287
|
-
return styleContinuousText(
|
|
300
|
+
return applyLegendClipGraphics(styleContinuousText(
|
|
288
301
|
next,
|
|
289
302
|
"opacityLegendTitle",
|
|
290
303
|
config.titleStyle,
|
|
291
304
|
{ align: layout.title.align }
|
|
292
|
-
);
|
|
305
|
+
));
|
|
293
306
|
}
|
|
294
307
|
);
|
|
295
308
|
|
|
@@ -304,7 +317,6 @@ export function resolveOpacityLegendCreation(program, args = {}) {
|
|
|
304
317
|
throw new Error('Opacity legend requires channels: ["opacity"].');
|
|
305
318
|
}
|
|
306
319
|
config.symbol = normalizeOpacitySymbol(args.symbol);
|
|
307
|
-
config.titleVisible = true;
|
|
308
320
|
const resolved = resolveOpacityConfig(program, config);
|
|
309
321
|
return resolved;
|
|
310
322
|
}
|
|
@@ -1,3 +1,4 @@
|
|
|
1
|
+
import {resolveColorSizeConfig} from "./colorSize.js";
|
|
1
2
|
import { resolveCategoricalLegendConfig } from "./categorical/actions.js";
|
|
2
3
|
import { resolveGradientLegendCreation } from "./continuous/gradient.js";
|
|
3
4
|
import { resolveOpacityLegendCreation } from "./continuous/opacity.js";
|
|
@@ -11,6 +12,7 @@ import {
|
|
|
11
12
|
|
|
12
13
|
export function resolveLegendStepConfig(program, step) {
|
|
13
14
|
switch (step.op) {
|
|
15
|
+
case "createColorSizeLegend": return {kind:"colorSize",config:resolveColorSizeConfig(program,step.args)};
|
|
14
16
|
case "createCategoricalLegend": {
|
|
15
17
|
const config = resolveCategoricalLegendConfig(program, step.args);
|
|
16
18
|
return { kind: config.kind, config };
|