ggaction 0.0.16 → 0.0.18
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 +66 -0
- package/README.md +3 -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 +10 -4
- 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 +16 -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 +4 -4
- 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/bin.js +1 -1
- package/src/actions/data/box.js +2 -1
- package/src/actions/data/create.js +18 -5
- package/src/actions/data/density.js +1 -1
- package/src/actions/data/derived.js +15 -1
- package/src/actions/data/edit.js +20 -7
- package/src/actions/data/filter.js +15 -4
- package/src/actions/data/index.js +3 -0
- package/src/actions/data/interval.js +2 -0
- package/src/actions/data/regression.js +6 -2
- package/src/actions/data/revise.js +37 -5
- package/src/actions/data/shared.js +33 -4
- package/src/actions/data/sort.js +21 -0
- package/src/actions/data/stack.js +3 -1
- package/src/actions/data/summary.js +1 -1
- package/src/actions/encodings/angle.js +4 -1
- package/src/actions/encodings/appearance.js +43 -31
- package/src/actions/encodings/barWidth.js +36 -11
- package/src/actions/encodings/channels.js +0 -1
- package/src/actions/encodings/color/continuous.js +5 -2
- package/src/actions/encodings/color/index.js +5 -2
- package/src/actions/encodings/color/policy.js +10 -3
- package/src/actions/encodings/density/resolve.js +1 -6
- package/src/actions/encodings/offset.js +4 -1
- 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 +9 -3
- package/src/actions/encodings/ranged.js +23 -1
- package/src/actions/encodings/remove.js +3 -2
- package/src/actions/encodings/ruleAppearance.js +4 -1
- package/src/actions/encodings/seriesLayout.js +1 -0
- package/src/actions/encodings/stroke.js +4 -1
- package/src/actions/encodings/strokeDash.js +6 -1
- package/src/actions/encodings/text.js +12 -4
- package/src/actions/errorBands/create.js +2 -2
- package/src/actions/errorBands/edit.js +2 -1
- package/src/actions/facets/actions.js +158 -240
- package/src/actions/gradientPlots/resolve.js +2 -17
- package/src/actions/guides/applicability.js +1 -1
- package/src/actions/guides/axes/axis.js +16 -4
- package/src/actions/guides/axes/edit.js +4 -4
- package/src/actions/guides/axes/labels.js +120 -46
- package/src/actions/guides/axes/lines.js +6 -5
- 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 +3 -2
- package/src/actions/guides/axes/tickGroups.js +5 -2
- package/src/actions/guides/axes/ticks.js +6 -3
- package/src/actions/guides/axes/titles.js +71 -26
- package/src/actions/guides/basic.js +2 -0
- package/src/actions/guides/facadeLegend.js +10 -2
- package/src/actions/guides/grids/grid.js +7 -1
- package/src/actions/guides/grids/resolve.js +59 -12
- package/src/actions/guides/legends/blocks.js +3 -1
- package/src/actions/guides/legends/categorical/actions.js +70 -17
- package/src/actions/guides/legends/categorical/components.js +12 -8
- package/src/actions/guides/legends/categorical/index.js +6 -0
- package/src/actions/guides/legends/categorical/layout.js +37 -8
- package/src/actions/guides/legends/categorical/options.js +31 -20
- package/src/actions/guides/legends/categorical/resolve.js +2 -2
- package/src/actions/guides/legends/categorical/symbols.js +18 -12
- package/src/actions/guides/legends/categorical/validation.js +1 -6
- 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 +47 -34
- package/src/actions/guides/legends/continuous/interval.js +4 -4
- package/src/actions/guides/legends/continuous/opacity.js +19 -12
- package/src/actions/guides/legends/edit.js +1 -604
- package/src/actions/guides/legends/focused.js +2 -2
- package/src/actions/guides/legends/group.js +1 -0
- package/src/actions/guides/legends/lane.js +1 -516
- package/src/actions/guides/legends/remove.js +3 -0
- package/src/actions/guides/legends/sampling.js +1 -1
- package/src/actions/guides/legends/size.js +51 -43
- package/src/actions/guides/legends/strokeWidth.js +11 -29
- package/src/actions/guides/legends/target.js +3 -3
- package/src/actions/guides/legends/transition.js +21 -7
- 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/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 +17 -4
- package/src/actions/marks/bar/edit.js +18 -7
- package/src/actions/marks/bar/materialize.js +9 -6
- package/src/actions/marks/line/actions.js +11 -4
- package/src/actions/marks/line/materialize.js +9 -5
- package/src/actions/marks/point/create.js +8 -1
- package/src/actions/marks/point/edit.js +13 -6
- package/src/actions/marks/point/materialize.js +4 -2
- package/src/actions/marks/rect/actions.js +26 -11
- package/src/actions/marks/remove.js +2 -0
- package/src/actions/marks/rule/actions.js +31 -12
- package/src/actions/marks/text/actions.js +42 -11
- package/src/actions/marks/text/layout.js +3 -0
- package/src/actions/marks/tick/actions.js +23 -8
- package/src/actions/primitives/semanticAction.js +37 -3
- package/src/actions/primitives/semanticValidation/dataset.js +13 -1
- package/src/actions/primitives/semanticValidation/layer.js +26 -2
- package/src/actions/primitives/semanticValidation/scale.js +6 -0
- package/src/actions/regression/create.js +26 -5
- package/src/actions/regression/edit.js +50 -15
- package/src/actions/regression/follow.js +22 -0
- package/src/actions/regression/resolve.js +2 -6
- package/src/actions/scales/channels.js +20 -15
- package/src/actions/scales/consumers/common.js +2 -1
- package/src/actions/scales/consumers/families.js +16 -5
- package/src/actions/scales/create.js +10 -4
- package/src/actions/scales/definitions.js +1 -425
- package/src/actions/scales/edit.js +3 -3
- package/src/actions/scales/editPolicy.js +9 -3
- package/src/actions/scales/materialize.js +1 -1
- package/src/actions/scales/parallel.js +1 -1
- package/src/actions/scales/patch.js +1 -1
- package/src/actions/scales/preview.js +49 -2
- package/src/actions/scales/quantitativeColor.js +3 -3
- package/src/actions/selection/actions.js +1 -13
- package/src/actions/theme/reconcile.js +83 -27
- 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/action.js +3 -2
- package/src/core/compositionState.js +4 -1
- package/src/core/font.js +9 -2
- package/src/core/optionRequirements.js +1 -0
- package/src/core/programState.js +5 -1
- package/src/core/resourceReferences.js +3 -0
- package/src/core/textMetricProfile.js +3 -2
- package/src/core/textMetrics.js +41 -4
- package/src/core/validation.js +26 -0
- package/src/core/vocabulary.js +4 -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/bars/geometry.js +30 -3
- package/src/grammar/bars/policy.js +12 -1
- package/src/grammar/bin.js +41 -22
- package/src/grammar/bin2d.js +1 -6
- package/src/grammar/boxPlot.js +56 -9
- package/src/grammar/categoryOrder.js +1 -6
- package/src/grammar/complete.js +15 -19
- package/src/grammar/computed.js +92 -25
- package/src/grammar/curveCommands.js +29 -16
- package/src/grammar/datasetSchema.js +382 -0
- package/src/grammar/density.js +53 -5
- package/src/grammar/displayLabels.js +28 -0
- package/src/grammar/ecdf.js +2 -9
- package/src/grammar/facets/dependencies.js +6 -2
- package/src/grammar/facets/guides.js +5 -0
- package/src/grammar/facets/index.js +2 -5
- package/src/grammar/filter.js +133 -39
- package/src/grammar/fold.js +2 -12
- package/src/grammar/gradientProfile.js +1 -6
- package/src/grammar/impute.js +21 -48
- package/src/grammar/interval.js +34 -10
- package/src/grammar/itemMissing.js +59 -0
- package/src/grammar/legendGradient.js +18 -0
- package/src/grammar/legendGroups.js +1 -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/polar.js +1 -184
- package/src/grammar/positionCompatibility.js +3 -3
- package/src/grammar/regression/derive.js +63 -16
- package/src/grammar/regression/index.js +1 -0
- package/src/grammar/regression/models.js +116 -59
- package/src/grammar/regression/parameters.js +69 -6
- 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 -190
- 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 +11 -0
- package/src/grammar/schemas/graphic.js +3 -0
- package/src/grammar/schemas/semanticPath.js +5 -3
- package/src/grammar/sort.js +88 -0
- package/src/grammar/stack.js +2 -10
- package/src/grammar/statisticalReference.js +1 -6
- package/src/grammar/summary.js +120 -45
- package/src/grammar/text.js +19 -0
- package/src/grammar/timeUnit.js +16 -7
- package/src/grammar/transformKeys.js +47 -0
- package/src/grammar/transformTopology.js +1 -0
- package/src/grammar/transforms.js +25 -12
- package/src/grammar/valueFormat.js +17 -5
- package/src/grammar/weightedStatistics.js +1 -6
- package/src/grammar/window.js +4 -58
- package/src/inspection.js +495 -0
- package/src/inspectionDescriptors.js +3 -0
- package/src/layout/canvas.js +1 -110
- package/src/layout/facets.js +1 -244
- 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 +26 -3
- package/src/materialization/coordinateBounds.js +8 -0
- package/src/materialization/dependencies.js +4 -44
- package/src/materialization/facetGuides/layout.js +1 -0
- package/src/materialization/facetGuides/placement.js +19 -8
- package/src/materialization/facetGuides/preparation.js +15 -7
- package/src/materialization/facetHeaders.js +1 -347
- package/src/materialization/facets.js +1 -185
- package/src/materialization/graphicHierarchy.js +1 -1
- 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/legendGroups.js +1 -0
- package/src/materialization/legendText.js +1 -0
- package/src/materialization/legends.js +1 -1
- package/src/materialization/marks/capabilities.js +5 -6
- package/src/materialization/rect.js +1 -1
- package/src/materialization/revisionIdentity.js +19 -0
- package/src/materialization/scaleGuideDependencies.js +1 -1
- package/src/materialization/scales/map.js +3 -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 +72 -7
- 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 +17 -6
- package/src/materialization/textLines.js +15 -0
- package/src/persistence/codec.js +37 -6
- package/src/persistence/validation.js +47 -0
- package/src/persistence.js +94 -8
- package/src/renderers/canvas/circle.js +6 -3
- package/src/renderers/canvas/fill.js +7 -1
- package/src/renderers/canvas/index.js +2 -1
- 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/svg.js +4 -1
- 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 +1 -0
- package/types/index.d.ts +7 -0
- package/types/inspection.d.ts +17 -0
- package/types/program.d.ts +494 -112
|
@@ -1,28 +1,30 @@
|
|
|
1
|
+
import { intrinsicLegendConfig, legendGroup } from "../../../materialization/legendGroups.js";
|
|
2
|
+
import { formatVisibleText } from "../../../core/textMetrics.js";
|
|
1
3
|
import { action, closedAction } from "../../../core/action.js";
|
|
2
4
|
import {
|
|
3
|
-
validateNonEmptyString,
|
|
4
5
|
validateKeys
|
|
5
6
|
} from "../../../core/validation.js";
|
|
6
7
|
import {
|
|
7
8
|
formatDiscretizedIntervals,
|
|
8
9
|
isDiscreteSizeScaleType,
|
|
10
|
+
isEnumeratedSizeScaleType,
|
|
9
11
|
isSizeScaleType,
|
|
10
12
|
mapSizeValues
|
|
11
13
|
} from "../../../grammar/scales/index.js";
|
|
12
14
|
import { resolveLegendItemLayout } from "../../../layout/legendItems.js";
|
|
13
|
-
import { DEFAULT_COLORS
|
|
15
|
+
import { DEFAULT_COLORS } from
|
|
14
16
|
"../../../theme/defaults.js";
|
|
15
17
|
import { findLayer } from "../../../selectors/layers.js";
|
|
16
18
|
import { resolveLegendGraphicPlacement } from
|
|
17
19
|
"../../../materialization/graphicHierarchy.js";
|
|
18
20
|
import {
|
|
21
|
+
ITEM_LEGEND_LABELS as SIZE_LEGEND_LABELS,
|
|
22
|
+
ITEM_LEGEND_TITLE_STYLE as SIZE_LEGEND_TITLE_STYLE,
|
|
23
|
+
normalizeItemLegendConfig,
|
|
24
|
+
ITEM_LEGEND_OPTIONS as SIZE_OPTIONS,
|
|
19
25
|
assertLegendBoundsInsideCanvas,
|
|
20
26
|
materializeItemLegend,
|
|
21
27
|
createItemLegendGraphics,
|
|
22
|
-
normalizeItemLegendLayout,
|
|
23
|
-
normalizeLegendBorder,
|
|
24
|
-
normalizeLegendTextOptions,
|
|
25
|
-
normalizeLegendTitleOptions,
|
|
26
28
|
resolveContinuousBounds,
|
|
27
29
|
resolveLegendBackgroundFromBounds,
|
|
28
30
|
formatContinuousValues,
|
|
@@ -35,23 +37,11 @@ import {
|
|
|
35
37
|
resolveLegendSampleValues
|
|
36
38
|
} from "./sampling.js";
|
|
37
39
|
import { resolveEffectiveLegendBlockConfig } from "./blocks.js";
|
|
40
|
+
import { normalizeLegendOverflow } from "./categorical/options.js";
|
|
38
41
|
|
|
39
|
-
const SIZE_OPTIONS = Object.freeze(["target", "count", "values", "position", "layout", "align",
|
|
40
|
-
"direction", "columns", "titlePosition", "offset", "itemGap", "title", "labels", "titleStyle", "border"]);
|
|
41
42
|
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
color: DEFAULT_COLORS.text,
|
|
45
|
-
fontSize: 12,
|
|
46
|
-
fontFamily: DEFAULT_FONT_FAMILY,
|
|
47
|
-
fontWeight: "normal"
|
|
48
|
-
});
|
|
49
|
-
export const SIZE_LEGEND_TITLE_STYLE = Object.freeze({
|
|
50
|
-
color: DEFAULT_COLORS.strongText,
|
|
51
|
-
fontSize: 13,
|
|
52
|
-
fontFamily: DEFAULT_FONT_FAMILY,
|
|
53
|
-
fontWeight: 600
|
|
54
|
-
});
|
|
43
|
+
|
|
44
|
+
export { SIZE_LEGEND_LABELS, SIZE_LEGEND_TITLE_STYLE };
|
|
55
45
|
|
|
56
46
|
export function isSizeLegendPoint(layer) {
|
|
57
47
|
return layer?.mark?.type === "point" &&
|
|
@@ -79,6 +69,7 @@ function requireScale(program, id) {
|
|
|
79
69
|
}
|
|
80
70
|
|
|
81
71
|
export function resolveSizeLegendLayout(program, config) {
|
|
72
|
+
config = intrinsicLegendConfig(program, config);
|
|
82
73
|
const scale = requireScale(program, config.scale);
|
|
83
74
|
const categorical = [
|
|
84
75
|
program.guideConfigs.legend?.series,
|
|
@@ -96,23 +87,38 @@ export function resolveSizeLegendLayout(program, config) {
|
|
|
96
87
|
});
|
|
97
88
|
const labels = effective.labels;
|
|
98
89
|
const titleStyle = effective.titleStyle;
|
|
99
|
-
|
|
100
|
-
|
|
90
|
+
// Group ownership replaces placement inheritance, never shared typography.
|
|
91
|
+
const placementCategorical = legendGroup(program, config.target) === undefined &&
|
|
92
|
+
(config.inheritPosition !== false || categorical?.position === config.position)
|
|
93
|
+
? categorical : undefined;
|
|
94
|
+
const position = placementCategorical?.position ?? config.position;
|
|
95
|
+
if (placementCategorical?.layout === "legacy-bottom") {
|
|
101
96
|
throw new Error('Combined size legends require layout "edge".');
|
|
102
97
|
}
|
|
103
|
-
const horizontal =
|
|
98
|
+
const horizontal = placementCategorical !== undefined && ["top", "bottom"].includes(position);
|
|
104
99
|
const geometry = horizontal ? {
|
|
105
100
|
position, align: categorical.align, direction: categorical.direction,
|
|
106
101
|
columns: categorical.columns, titlePosition: categorical.titlePosition,
|
|
107
102
|
offset: categorical.offset, itemGap: effective.blockGap ?? categorical.itemGap
|
|
108
103
|
} : { position };
|
|
104
|
+
const ordinalSize = scale.type === "ordinal";
|
|
105
|
+
if (ordinalSize && config.labels.format !== undefined && config.labels.format !== "auto") {
|
|
106
|
+
throw new Error("Categorical size legends retain original category labels.");
|
|
107
|
+
}
|
|
109
108
|
const discrete = isDiscreteSizeScaleType(scale.type);
|
|
110
|
-
if (discrete && readLegendSampling(config).mode === "values") {
|
|
109
|
+
if ((discrete || ordinalSize) && readLegendSampling(config).mode === "values") {
|
|
111
110
|
throw new Error("Discrete size legends do not support exact values.");
|
|
112
111
|
}
|
|
113
|
-
const
|
|
112
|
+
const allValues = discrete
|
|
114
113
|
? undefined
|
|
115
|
-
: resolveLegendSampleValues(effective, scale, "Size legend");
|
|
114
|
+
: ordinalSize ? scale.domain : resolveLegendSampleValues(effective, scale, "Size legend");
|
|
115
|
+
const hiddenCount = ordinalSize && effective.overflow &&
|
|
116
|
+
allValues.length > effective.overflow.maxItems
|
|
117
|
+
? allValues.length - effective.overflow.maxItems
|
|
118
|
+
: 0;
|
|
119
|
+
const values = hiddenCount > 0
|
|
120
|
+
? allValues.slice(0, effective.overflow.maxItems)
|
|
121
|
+
: allValues;
|
|
116
122
|
const areas = discrete
|
|
117
123
|
? scale.range
|
|
118
124
|
: mapSizeValues(values, scale);
|
|
@@ -120,14 +126,15 @@ export function resolveSizeLegendLayout(program, config) {
|
|
|
120
126
|
const radius = Math.max(...radii);
|
|
121
127
|
const width = Math.max(32, radius * 2);
|
|
122
128
|
const { plot, canvas } = resolveContinuousBounds(program);
|
|
123
|
-
const
|
|
129
|
+
const itemText = discrete
|
|
124
130
|
? formatDiscretizedIntervals(scale.thresholds, config.labels.format)
|
|
125
|
-
: formatContinuousValues(
|
|
131
|
+
: ordinalSize ? values.map(formatVisibleText) : formatContinuousValues(
|
|
126
132
|
values,
|
|
127
133
|
scale.domain,
|
|
128
134
|
"quantitative",
|
|
129
135
|
config.labels.format
|
|
130
136
|
);
|
|
137
|
+
const text = hiddenCount > 0 ? [...itemText, `…${hiddenCount} entries`] : itemText;
|
|
131
138
|
const symbolStroke = effective.blockSymbol?.strokeWidth ?? 0;
|
|
132
139
|
const symbolExtent = symbolStroke / 2;
|
|
133
140
|
const sampleWidth = width + symbolStroke;
|
|
@@ -142,14 +149,15 @@ export function resolveSizeLegendLayout(program, config) {
|
|
|
142
149
|
}, undefined, program.materializationConfigs.textMetrics);
|
|
143
150
|
assertLegendBoundsInsideCanvas(layout.bounds, canvas, "Size legend layout", { ...effective, ...geometry });
|
|
144
151
|
const background = resolveLegendBackgroundFromBounds(layout.bounds, effective.border, canvas, "Size legend", { ...effective, ...geometry });
|
|
145
|
-
return { ...layout, symbolX: layout.symbolX.map(x => x + sampleWidth / 2),
|
|
152
|
+
return { ...layout, symbolX: layout.symbolX.slice(0, radii.length).map(x => x + sampleWidth / 2),
|
|
153
|
+
symbolY: layout.itemY.slice(0, radii.length), radii, text,
|
|
146
154
|
labels, titleStyle, background, config: effective };
|
|
147
155
|
}
|
|
148
156
|
|
|
149
157
|
export const rematerializeSizeLegend = /* @__PURE__ */ closedAction(
|
|
150
158
|
{
|
|
151
159
|
op: "rematerializeSizeLegend",
|
|
152
|
-
description: "Rematerialize a
|
|
160
|
+
description: "Rematerialize a point-size legend."
|
|
153
161
|
}, [],
|
|
154
162
|
function (args = {}) {
|
|
155
163
|
const config = this.guideConfigs.legend?.size;
|
|
@@ -171,13 +179,14 @@ export const rematerializeSizeLegend = /* @__PURE__ */ closedAction(
|
|
|
171
179
|
return materializeItemLegend(this, "size", currentConfig, layout, {
|
|
172
180
|
text: layout.text, labels: layout.labels, titleStyle: layout.titleStyle,
|
|
173
181
|
symbols: {
|
|
174
|
-
x: layout.symbolX, y: layout.
|
|
182
|
+
x: layout.symbolX, y: layout.symbolY, radius: layout.radii,
|
|
175
183
|
fill: layout.config.blockSymbol?.fill ?? DEFAULT_COLORS.sizeSymbol,
|
|
176
184
|
opacity: layout.config.blockSymbol?.opacity ?? 0.7
|
|
177
185
|
},
|
|
178
186
|
optional: {
|
|
179
187
|
stroke: layout.config.blockSymbol?.stroke,
|
|
180
|
-
strokeWidth: layout.config.blockSymbol?.strokeWidth
|
|
188
|
+
strokeWidth: layout.config.blockSymbol?.strokeWidth ??
|
|
189
|
+
(layout.config.blockSymbol?.stroke === undefined ? undefined : 0)
|
|
181
190
|
}
|
|
182
191
|
});
|
|
183
192
|
}
|
|
@@ -186,14 +195,16 @@ export const rematerializeSizeLegend = /* @__PURE__ */ closedAction(
|
|
|
186
195
|
|
|
187
196
|
export function resolveSizeLegendConfig(program, args = {}) {
|
|
188
197
|
validateKeys(args, [...SIZE_OPTIONS, "inheritAppearance"], "createSizeLegend");
|
|
189
|
-
if (args.title !== undefined) validateNonEmptyString(args.title, "Legend title");
|
|
190
198
|
const layer = resolveSizeLegendPoint(program, args.target);
|
|
191
199
|
const encoding = layer.encoding?.size;
|
|
192
200
|
if (encoding?.scale === undefined) {
|
|
193
201
|
throw new Error(`Point mark "${layer.id}" requires a size encoding.`);
|
|
194
202
|
}
|
|
195
203
|
const scale = requireScale(program, encoding.scale);
|
|
196
|
-
const discrete =
|
|
204
|
+
const discrete = isEnumeratedSizeScaleType(scale.type);
|
|
205
|
+
if (args.overflow !== undefined && scale.type !== "ordinal") {
|
|
206
|
+
throw new Error("Size legend overflow requires an ordinal scale.");
|
|
207
|
+
}
|
|
197
208
|
if (discrete && (Object.hasOwn(args, "count") || Object.hasOwn(args, "values"))) {
|
|
198
209
|
throw new Error("Discrete size legends do not support count or exact values.");
|
|
199
210
|
}
|
|
@@ -201,20 +212,17 @@ export function resolveSizeLegendConfig(program, args = {}) {
|
|
|
201
212
|
operation: "create",
|
|
202
213
|
label: "Size legend"
|
|
203
214
|
});
|
|
204
|
-
const count = discrete ? scale.range.length : undefined;
|
|
215
|
+
const count = discrete ? (scale.type === "ordinal" ? scale.domain.length : scale.range.length) : undefined;
|
|
205
216
|
return {
|
|
206
217
|
target: layer.id,
|
|
207
218
|
scale: encoding.scale,
|
|
208
|
-
...
|
|
209
|
-
|
|
210
|
-
inferredTitle: args.title === undefined,
|
|
219
|
+
...normalizeItemLegendConfig(args, encoding, 40),
|
|
220
|
+
...(args.overflow === undefined ? {} : { overflow: normalizeLegendOverflow(args.overflow) }),
|
|
211
221
|
domain: scale.domain,
|
|
212
222
|
...(discrete ? { count } : { sampling }),
|
|
213
223
|
inheritAppearance: args.inheritAppearance === true,
|
|
214
|
-
|
|
215
|
-
|
|
216
|
-
border: normalizeLegendBorder(args.border),
|
|
217
|
-
titleVisible: true
|
|
224
|
+
inheritPosition: args.position === undefined,
|
|
225
|
+
|
|
218
226
|
};
|
|
219
227
|
}
|
|
220
228
|
|
|
@@ -1,6 +1,6 @@
|
|
|
1
|
+
import { intrinsicLegendConfig } from "../../../materialization/legendGroups.js";
|
|
1
2
|
import { action, closedAction } from "../../../core/action.js";
|
|
2
3
|
import {
|
|
3
|
-
validateNonEmptyString,
|
|
4
4
|
validateKeys
|
|
5
5
|
} from "../../../core/validation.js";
|
|
6
6
|
import { mapContinuousScaleValues } from "../../../grammar/scales/index.js";
|
|
@@ -8,16 +8,16 @@ import { resolveLegendItemLayout } from "../../../layout/legendItems.js";
|
|
|
8
8
|
import { resolveLegendGraphicPlacement } from
|
|
9
9
|
"../../../materialization/graphicHierarchy.js";
|
|
10
10
|
import { findLayer } from "../../../selectors/layers.js";
|
|
11
|
-
import { DEFAULT_COLORS
|
|
11
|
+
import { DEFAULT_COLORS } from
|
|
12
12
|
"../../../theme/defaults.js";
|
|
13
13
|
import {
|
|
14
|
+
ITEM_LEGEND_LABELS as STROKE_WIDTH_LEGEND_LABELS,
|
|
15
|
+
ITEM_LEGEND_TITLE_STYLE as STROKE_WIDTH_LEGEND_TITLE_STYLE,
|
|
16
|
+
normalizeItemLegendConfig,
|
|
17
|
+
ITEM_LEGEND_OPTIONS as OPTIONS,
|
|
14
18
|
assertLegendBoundsInsideCanvas,
|
|
15
19
|
materializeItemLegend,
|
|
16
20
|
createItemLegendGraphics,
|
|
17
|
-
normalizeItemLegendLayout,
|
|
18
|
-
normalizeLegendBorder,
|
|
19
|
-
normalizeLegendTextOptions,
|
|
20
|
-
normalizeLegendTitleOptions,
|
|
21
21
|
resolveContinuousBounds,
|
|
22
22
|
resolveLegendBackgroundFromBounds,
|
|
23
23
|
formatContinuousValues,
|
|
@@ -29,29 +29,16 @@ import {
|
|
|
29
29
|
} from "./sampling.js";
|
|
30
30
|
import { resolveEffectiveLegendBlockConfig } from "./blocks.js";
|
|
31
31
|
|
|
32
|
-
const OPTIONS = Object.freeze(["target", "count", "values", "position", "layout", "align",
|
|
33
|
-
"direction", "columns", "titlePosition", "offset", "itemGap", "title", "labels", "titleStyle", "border"]);
|
|
34
32
|
|
|
35
|
-
export const STROKE_WIDTH_LEGEND_LABELS = Object.freeze({
|
|
36
|
-
offset: 12,
|
|
37
|
-
color: DEFAULT_COLORS.text,
|
|
38
|
-
fontSize: 12,
|
|
39
|
-
fontFamily: DEFAULT_FONT_FAMILY,
|
|
40
|
-
fontWeight: "normal"
|
|
41
|
-
});
|
|
42
33
|
|
|
43
|
-
export
|
|
44
|
-
color: DEFAULT_COLORS.strongText,
|
|
45
|
-
fontSize: 13,
|
|
46
|
-
fontFamily: DEFAULT_FONT_FAMILY,
|
|
47
|
-
fontWeight: 600
|
|
48
|
-
});
|
|
34
|
+
export { STROKE_WIDTH_LEGEND_LABELS, STROKE_WIDTH_LEGEND_TITLE_STYLE };
|
|
49
35
|
|
|
50
36
|
export function isStrokeWidthLegendLayer(layer) {
|
|
51
37
|
return ["line", "rule"].includes(layer?.mark?.type) &&
|
|
52
38
|
layer.encoding?.strokeWidth?.scale !== undefined;
|
|
53
39
|
}
|
|
54
40
|
|
|
41
|
+
|
|
55
42
|
function resolveLayer(program, requested) {
|
|
56
43
|
const layer = selectLegendLayer(
|
|
57
44
|
program,
|
|
@@ -77,6 +64,7 @@ function requireScale(program, id) {
|
|
|
77
64
|
}
|
|
78
65
|
|
|
79
66
|
export function resolveStrokeWidthLegendLayout(program, config) {
|
|
67
|
+
config = intrinsicLegendConfig(program, config);
|
|
80
68
|
const effective = resolveEffectiveLegendBlockConfig(program, "strokeWidth", config);
|
|
81
69
|
const scale = requireScale(program, config.scale);
|
|
82
70
|
const { plot, canvas } = resolveContinuousBounds(program);
|
|
@@ -134,7 +122,6 @@ export const rematerializeStrokeWidthLegend = /* @__PURE__ */ closedAction(
|
|
|
134
122
|
|
|
135
123
|
export function resolveStrokeWidthLegendConfig(program, args = {}) {
|
|
136
124
|
validateKeys(args, OPTIONS, "createStrokeWidthLegend");
|
|
137
|
-
if (args.title !== undefined) validateNonEmptyString(args.title, "Legend title");
|
|
138
125
|
const layer = resolveLayer(program, args.target);
|
|
139
126
|
const encoding = layer.encoding.strokeWidth;
|
|
140
127
|
requireScale(program, encoding.scale);
|
|
@@ -145,14 +132,9 @@ export function resolveStrokeWidthLegendConfig(program, args = {}) {
|
|
|
145
132
|
return {
|
|
146
133
|
target: layer.id,
|
|
147
134
|
scale: encoding.scale,
|
|
148
|
-
...
|
|
149
|
-
title: args.title ?? encoding.field,
|
|
150
|
-
inferredTitle: args.title === undefined,
|
|
135
|
+
...normalizeItemLegendConfig(args, encoding, 32),
|
|
151
136
|
sampling,
|
|
152
|
-
|
|
153
|
-
titleStyle: normalizeLegendTitleOptions(args.titleStyle, "createLegend.titleStyle", STROKE_WIDTH_LEGEND_TITLE_STYLE),
|
|
154
|
-
border: normalizeLegendBorder(args.border),
|
|
155
|
-
titleVisible: true
|
|
137
|
+
|
|
156
138
|
};
|
|
157
139
|
}
|
|
158
140
|
|
|
@@ -3,7 +3,7 @@ import {
|
|
|
3
3
|
LEGEND_CHANNELS,
|
|
4
4
|
LEGEND_CONFIG_KINDS
|
|
5
5
|
} from "../../../core/vocabulary.js";
|
|
6
|
-
import {
|
|
6
|
+
import { isEnumeratedSizeScaleType } from "../../../grammar/scales/index.js";
|
|
7
7
|
|
|
8
8
|
export function validateLegendChannels(channels, operation) {
|
|
9
9
|
if (!Array.isArray(channels)) throw new TypeError(`${operation} channels must be an array.`);
|
|
@@ -88,10 +88,10 @@ export function describeLegendBlock(program, kind, config) {
|
|
|
88
88
|
const family = CATEGORICAL_KINDS.includes(kind)
|
|
89
89
|
? "categorical"
|
|
90
90
|
: kind === "size"
|
|
91
|
-
?
|
|
91
|
+
? isEnumeratedSizeScaleType(program.resolvedScales[scaleIds[0]].type)
|
|
92
92
|
? "discrete-size"
|
|
93
93
|
: "sampled"
|
|
94
|
-
: ["opacity", "strokeWidth"].includes(kind)
|
|
94
|
+
: ["opacity", "strokeWidth"].includes(kind) || kind === "gradient" && config.representation === "symbols"
|
|
95
95
|
? "sampled"
|
|
96
96
|
: ["gradient", "strokeGradient"].includes(kind)
|
|
97
97
|
? "gradient"
|
|
@@ -1,3 +1,5 @@
|
|
|
1
|
+
import { legendResourcePolicy } from "../../../materialization/guides/resources.js";
|
|
2
|
+
import { isContinuousColorScaleType } from "../../../grammar/scales/types.js";
|
|
1
3
|
import { isDiscretizedColorScaleType } from "../../../grammar/scales/types.js";
|
|
2
4
|
import { normalizeContinuousLegend } from "./continuous/common.js";
|
|
3
5
|
import { DEFAULT_GRADIENT_SIZE } from "./continuous/gradient.js";
|
|
@@ -8,8 +10,9 @@ import {
|
|
|
8
10
|
resolveLegendBlock
|
|
9
11
|
} from "./target.js";
|
|
10
12
|
import { validateLegendBlockOverride } from "./blocks.js";
|
|
13
|
+
import { DEFAULT_VERTICAL_LEGEND_ITEM_GAP } from "../../../theme/defaults.js";
|
|
11
14
|
|
|
12
|
-
const family = (channel, type) => type
|
|
15
|
+
const family = (channel, type) => isContinuousColorScaleType(type)
|
|
13
16
|
? channel === "stroke" ? "strokeGradient" : "gradient"
|
|
14
17
|
: isDiscretizedColorScaleType(type)
|
|
15
18
|
? channel === "stroke" ? "strokeInterval" : "interval"
|
|
@@ -21,7 +24,7 @@ const same = (a, b) => JSON.stringify(a) === JSON.stringify(b);
|
|
|
21
24
|
function categoricalFamilyCustom(program, kind, stored) {
|
|
22
25
|
const side = ["left", "right"].includes(stored.position);
|
|
23
26
|
const direction = side ? "vertical" : "horizontal";
|
|
24
|
-
const itemGap = side ?
|
|
27
|
+
const itemGap = side ? DEFAULT_VERTICAL_LEGEND_ITEM_GAP : stored.position === "top" ? 24 : 20;
|
|
25
28
|
const order = program.semanticSpec.guides.legend?.[kind]?.order;
|
|
26
29
|
return stored.inferredSymbol !== true ||
|
|
27
30
|
stored.direction !== direction ||
|
|
@@ -40,7 +43,9 @@ function planChannelLegendTransition(program, scale, nextType, channel) {
|
|
|
40
43
|
if (overrideKeys.some(key => key !== oldDescriptor.key)) {
|
|
41
44
|
throw new Error(`${channel} legend transition found stale legend block overrides.`);
|
|
42
45
|
}
|
|
43
|
-
const
|
|
46
|
+
const storedOverride = stored.blockOverrides?.[oldDescriptor.key];
|
|
47
|
+
const { symbol: _sampleSymbol, labelMap: _sampleMap, gap: _sampleGap, ...commonOverride } = storedOverride ?? {};
|
|
48
|
+
const blockOverride = stored.representation === "symbols" && storedOverride !== undefined ? commonOverride : storedOverride;
|
|
44
49
|
const side = ["left", "right"].includes(stored.position);
|
|
45
50
|
const categorical = ["color", "stroke"].includes(from);
|
|
46
51
|
const gradientFamily = from.toLowerCase().endsWith("gradient");
|
|
@@ -49,10 +54,11 @@ function planChannelLegendTransition(program, scale, nextType, channel) {
|
|
|
49
54
|
const comparableSymbol = channel === "stroke" && stored.inferredStrokeWidth === true
|
|
50
55
|
? { ...stored.symbol, strokeWidth: defaults.symbol?.strokeWidth }
|
|
51
56
|
: stored.symbol;
|
|
52
|
-
const
|
|
57
|
+
const sampledColor = from === "gradient" && stored.representation === "symbols";
|
|
58
|
+
const custom = sampledColor ? false : categorical
|
|
53
59
|
? categoricalFamilyCustom(program, from, stored)
|
|
54
60
|
: gradientFamily
|
|
55
|
-
? stored.count !== defaults.count || !same(stored.gradient, DEFAULT_GRADIENT_SIZE) || stored.itemGap !== defaults.itemGap
|
|
61
|
+
? stored.count !== defaults.count || !same({ ...stored.gradient, opacity: stored.gradient?.opacity ?? 1 }, { ...DEFAULT_GRADIENT_SIZE, opacity: 1 }) || stored.itemGap !== defaults.itemGap
|
|
56
62
|
: !same(comparableSymbol, defaults.symbol) || stored.itemGap !== defaults.itemGap ||
|
|
57
63
|
stored.direction !== defaults.direction || (stored.columns !== undefined && !(side && stored.columns === 1));
|
|
58
64
|
if (custom) {
|
|
@@ -70,7 +76,7 @@ function planChannelLegendTransition(program, scale, nextType, channel) {
|
|
|
70
76
|
const args = {
|
|
71
77
|
target: stored.target, channels: [channel], position: stored.position,
|
|
72
78
|
labels: stored.labels, titleStyle: stored.titleStyle, border: stored.border,
|
|
73
|
-
align: stored.align, offset: stored.offset, titlePosition: stored.titlePosition,
|
|
79
|
+
align: stored.align, offset: stored.offset, titlePosition: sampledColor ? "top" : stored.titlePosition,
|
|
74
80
|
...(stored.inferredTitle ? {} : { title: stored.title })
|
|
75
81
|
};
|
|
76
82
|
try {
|
|
@@ -83,7 +89,7 @@ function planChannelLegendTransition(program, scale, nextType, channel) {
|
|
|
83
89
|
} catch (error) {
|
|
84
90
|
throw new Error(`${channel} legend transition has incompatible layout or style: ${error.message}`);
|
|
85
91
|
}
|
|
86
|
-
return { args, channel, titleVisible: stored.titleVisible !== false, blockOverride };
|
|
92
|
+
return { args, channel, titleVisible: stored.titleVisible !== false, inferredOffset: stored.inferredOffset, blockOverride };
|
|
87
93
|
}
|
|
88
94
|
|
|
89
95
|
export function planColorLegendTransitions(program, scale, nextType) {
|
|
@@ -95,6 +101,11 @@ export function planColorLegendTransitions(program, scale, nextType) {
|
|
|
95
101
|
|
|
96
102
|
export function applyColorLegendTransition(program, plan) {
|
|
97
103
|
let next = program.createLegend(plan.args);
|
|
104
|
+
for (const [kind, config] of Object.entries(next.guideConfigs.legend ?? {})) {
|
|
105
|
+
if (config.target === plan.args.target && legendResourcePolicy(kind).semanticKind === plan.channel) {
|
|
106
|
+
next = next._withLegendConfig(kind, { ...config, inferredOffset: plan.inferredOffset === true });
|
|
107
|
+
}
|
|
108
|
+
}
|
|
98
109
|
if (!plan.titleVisible) {
|
|
99
110
|
next = next.editLegend({ target: plan.args.target, title: false });
|
|
100
111
|
}
|
|
@@ -160,6 +171,9 @@ export function planLegendBlockTransitions(program, target, plans) {
|
|
|
160
171
|
let override;
|
|
161
172
|
if (incoming.length === 1 && incoming[0].key === descriptor.key) {
|
|
162
173
|
override = incoming[0].config.blockOverrides?.[incoming[0].key];
|
|
174
|
+
if (incoming[0].config.representation === "symbols" && descriptor.kind === "gradient" && descriptor.config.representation !== "symbols" && override !== undefined) {
|
|
175
|
+
const { symbol: _symbol, labelMap: _labelMap, ...common } = override; override = common;
|
|
176
|
+
}
|
|
163
177
|
} else if (incoming.length === 1) {
|
|
164
178
|
const old = incoming[0];
|
|
165
179
|
override = old.config.blockOverrides?.[old.key];
|
|
@@ -1,3 +1,4 @@
|
|
|
1
|
+
import { axisThemeTypography } from "../../../theme/state.js";
|
|
1
2
|
import { action } from "../../../../core/action.js";
|
|
2
3
|
import { validateNonNegativeFinite } from "../../../../core/validation.js";
|
|
3
4
|
import {
|
|
@@ -99,6 +100,7 @@ function resolveLabelConfig(program, kind, args, resources, previous) {
|
|
|
99
100
|
} else {
|
|
100
101
|
mode = normalizePolarTickMode(program, resources.scale, {}, count);
|
|
101
102
|
}
|
|
103
|
+
const typography = axisThemeTypography(program.materializationConfigs.theme, "labels");
|
|
102
104
|
const config = {
|
|
103
105
|
...(previous ?? {}),
|
|
104
106
|
scale: resources.scale,
|
|
@@ -110,9 +112,9 @@ function resolveLabelConfig(program, kind, args, resources, previous) {
|
|
|
110
112
|
format: args.format ?? previous?.format ??
|
|
111
113
|
POLAR_AXIS_DEFAULTS.labels.format,
|
|
112
114
|
color: args.color ?? previous?.color ?? POLAR_AXIS_DEFAULTS.labels.color,
|
|
113
|
-
fontSize: args.fontSize ?? previous?.fontSize ??
|
|
115
|
+
fontSize: args.fontSize ?? previous?.fontSize ?? typography.fontSize ??
|
|
114
116
|
POLAR_AXIS_DEFAULTS.labels.fontSize,
|
|
115
|
-
fontFamily: args.fontFamily ?? previous?.fontFamily ??
|
|
117
|
+
fontFamily: args.fontFamily ?? previous?.fontFamily ?? typography.fontFamily ??
|
|
116
118
|
POLAR_AXIS_DEFAULTS.labels.fontFamily,
|
|
117
119
|
fontWeight: args.fontWeight ?? previous?.fontWeight ??
|
|
118
120
|
POLAR_AXIS_DEFAULTS.labels.fontWeight
|
|
@@ -1,3 +1,4 @@
|
|
|
1
|
+
import { axisThemeTypography } from "../../../theme/state.js";
|
|
1
2
|
import { action } from "../../../../core/action.js";
|
|
2
3
|
import {
|
|
3
4
|
validateNonEmptyString,
|
|
@@ -55,7 +56,8 @@ function validateTitleGeometry(program, kind, config, geometry, text) {
|
|
|
55
56
|
}, program.materializationConfigs.textMetrics);
|
|
56
57
|
}
|
|
57
58
|
|
|
58
|
-
function resolveTitleConfig(kind, args, resources, previous) {
|
|
59
|
+
function resolveTitleConfig(program, kind, args, resources, previous) {
|
|
60
|
+
const typography = axisThemeTypography(program.materializationConfigs.theme, "title");
|
|
59
61
|
const config = {
|
|
60
62
|
...(previous ?? {}),
|
|
61
63
|
scale: resources.scale,
|
|
@@ -65,9 +67,9 @@ function resolveTitleConfig(kind, args, resources, previous) {
|
|
|
65
67
|
? POLAR_AXIS_DEFAULTS.title.thetaOffset
|
|
66
68
|
: POLAR_AXIS_DEFAULTS.title.radiusOffset),
|
|
67
69
|
color: args.color ?? previous?.color ?? POLAR_AXIS_DEFAULTS.title.color,
|
|
68
|
-
fontSize: args.fontSize ?? previous?.fontSize ??
|
|
70
|
+
fontSize: args.fontSize ?? previous?.fontSize ?? typography.fontSize ??
|
|
69
71
|
POLAR_AXIS_DEFAULTS.title.fontSize,
|
|
70
|
-
fontFamily: args.fontFamily ?? previous?.fontFamily ??
|
|
72
|
+
fontFamily: args.fontFamily ?? previous?.fontFamily ?? typography.fontFamily ??
|
|
71
73
|
POLAR_AXIS_DEFAULTS.title.fontFamily,
|
|
72
74
|
fontWeight: args.fontWeight ?? previous?.fontWeight ??
|
|
73
75
|
POLAR_AXIS_DEFAULTS.title.fontWeight
|
|
@@ -106,7 +108,7 @@ function makeEditTitle(kind) {
|
|
|
106
108
|
scale: previous.scale,
|
|
107
109
|
coordinate: previous.coordinate
|
|
108
110
|
};
|
|
109
|
-
const config = resolveTitleConfig(kind, args, resources, previous);
|
|
111
|
+
const config = resolveTitleConfig(this, kind, args, resources, previous);
|
|
110
112
|
const text = Object.hasOwn(args, "text")
|
|
111
113
|
? validateNonEmptyString(args.text, "Polar axis title text")
|
|
112
114
|
: config.inferredText
|
|
@@ -150,7 +152,7 @@ function makeCreateTitle(kind) {
|
|
|
150
152
|
}
|
|
151
153
|
const resources = componentResources(this, kind, args, operation.create);
|
|
152
154
|
const angle = resolveAngle(this, kind, args);
|
|
153
|
-
const config = resolveTitleConfig(kind, args, resources);
|
|
155
|
+
const config = resolveTitleConfig(this, kind, args, resources);
|
|
154
156
|
const text = validateNonEmptyString(
|
|
155
157
|
args.text ?? inferAxisTitleText(this, names.channel, resources.scale),
|
|
156
158
|
"Polar axis title text"
|
|
@@ -1,9 +1,9 @@
|
|
|
1
1
|
import { validateUserId } from "../../../core/identifiers.js";
|
|
2
2
|
import {
|
|
3
3
|
validateGeneratedItemLimit,
|
|
4
|
+
validateTextStyle,
|
|
4
5
|
validateNonEmptyString,
|
|
5
|
-
validateNonNegativeFinite
|
|
6
|
-
validatePositiveFinite
|
|
6
|
+
validateNonNegativeFinite
|
|
7
7
|
} from "../../../core/validation.js";
|
|
8
8
|
import {
|
|
9
9
|
formatTransformedTick,
|
|
@@ -15,7 +15,7 @@ import { formatTimeTick, formatTimeTicks } from "../../../grammar/ticks.js";
|
|
|
15
15
|
import { resolveCoordinatePolarFrame } from
|
|
16
16
|
"../../../materialization/coordinateBounds.js";
|
|
17
17
|
import { findCoordinate } from "../../../selectors/coordinates.js";
|
|
18
|
-
import { DEFAULT_COLORS, DEFAULT_FONT_FAMILY } from
|
|
18
|
+
import { AXIS_LABEL_FONT_SIZES, AXIS_TITLE_FONT_SIZE, DEFAULT_COLORS, DEFAULT_FONT_FAMILY } from
|
|
19
19
|
"../../../theme/defaults.js";
|
|
20
20
|
import {
|
|
21
21
|
findGraphicParent,
|
|
@@ -41,7 +41,7 @@ export const POLAR_AXIS_DEFAULTS = Object.freeze({
|
|
|
41
41
|
radiusOffset: 10,
|
|
42
42
|
format: "auto",
|
|
43
43
|
color: DEFAULT_COLORS.text,
|
|
44
|
-
fontSize:
|
|
44
|
+
fontSize: AXIS_LABEL_FONT_SIZES.polar,
|
|
45
45
|
fontFamily: DEFAULT_FONT_FAMILY,
|
|
46
46
|
fontWeight: "normal"
|
|
47
47
|
}),
|
|
@@ -49,7 +49,7 @@ export const POLAR_AXIS_DEFAULTS = Object.freeze({
|
|
|
49
49
|
thetaOffset: 42,
|
|
50
50
|
radiusOffset: 8,
|
|
51
51
|
color: DEFAULT_COLORS.strongText,
|
|
52
|
-
fontSize:
|
|
52
|
+
fontSize: AXIS_TITLE_FONT_SIZE,
|
|
53
53
|
fontFamily: DEFAULT_FONT_FAMILY,
|
|
54
54
|
fontWeight: 600
|
|
55
55
|
})
|
|
@@ -264,15 +264,7 @@ export function validatePolarLineStyle(config, label) {
|
|
|
264
264
|
validateNonNegativeFinite(config.lineWidth, `${label} lineWidth`);
|
|
265
265
|
}
|
|
266
266
|
|
|
267
|
-
export
|
|
268
|
-
validateNonEmptyString(config.color, `${label} color`);
|
|
269
|
-
validatePositiveFinite(config.fontSize, `${label} fontSize`);
|
|
270
|
-
validateNonEmptyString(config.fontFamily, `${label} fontFamily`);
|
|
271
|
-
if (typeof config.fontWeight !== "string" &&
|
|
272
|
-
!Number.isFinite(config.fontWeight)) {
|
|
273
|
-
throw new TypeError(`${label} fontWeight must be a string or number.`);
|
|
274
|
-
}
|
|
275
|
-
}
|
|
267
|
+
export { validateTextStyle as validatePolarTextStyle };
|
|
276
268
|
|
|
277
269
|
export function validatePolarLabelFormat(format) {
|
|
278
270
|
return validateAxisFormat(format);
|
package/src/actions/index.js
CHANGED
|
@@ -1,27 +1,27 @@
|
|
|
1
|
-
import { registerTextMetricActions } from "./textMetrics/index.js";
|
|
2
1
|
import { registerPrimitiveActions } from "./primitives/index.js";
|
|
3
|
-
import {
|
|
4
|
-
import { registerDataActions } from "./data/index.js";
|
|
5
|
-
import { registerCategoryOrderActions } from "./categoryOrder/index.js";
|
|
6
|
-
import { registerEncodingActions } from "./encodings/index.js";
|
|
7
|
-
import { registerScaleActions } from "./scales/index.js";
|
|
8
|
-
import { registerMarkActions } from "./marks/index.js";
|
|
2
|
+
import { registerCanvasActions } from "./canvas/index.js";
|
|
9
3
|
import { registerBasicCoordinateActions } from "./coordinates/actions.js";
|
|
10
4
|
import { registerCoordinateEditActions } from "./coordinates/edit.js";
|
|
11
|
-
import {
|
|
12
|
-
import {
|
|
13
|
-
import {
|
|
14
|
-
import {
|
|
5
|
+
import { registerDataActions } from "./data/index.js";
|
|
6
|
+
import { registerMarkActions } from "./marks/index.js";
|
|
7
|
+
import { registerScaleActions } from "./scales/index.js";
|
|
8
|
+
import { registerEncodingActions } from "./encodings/index.js";
|
|
15
9
|
import { registerGuideActions } from "./guides/index.js";
|
|
16
|
-
import {
|
|
17
|
-
import { registerBoxPlotActions } from "./boxPlots/index.js";
|
|
18
|
-
import { registerErrorBarActions } from "./errorBars/index.js";
|
|
10
|
+
import { registerTitleActions } from "./titles/index.js";
|
|
19
11
|
import { registerRegressionActions } from "./regression/index.js";
|
|
20
|
-
import {
|
|
12
|
+
import { registerErrorBarActions } from "./errorBars/index.js";
|
|
21
13
|
import { registerErrorBandActions } from "./errorBands/index.js";
|
|
14
|
+
import { registerBoxPlotActions } from "./boxPlots/index.js";
|
|
15
|
+
import { registerGradientPlotActions } from "./gradientPlots/index.js";
|
|
16
|
+
import { registerViolinPlotActions } from "./violinPlots/index.js";
|
|
22
17
|
import { registerChartActions } from "./charts/index.js";
|
|
23
|
-
import {
|
|
18
|
+
import { registerCategoryOrderActions } from "./categoryOrder/index.js";
|
|
19
|
+
import { registerSelectionActions } from "./selection/index.js";
|
|
24
20
|
import { registerResourceActions } from "./resources/index.js";
|
|
21
|
+
import { registerTextMetricActions } from "./textMetrics/index.js";
|
|
22
|
+
import { registerCompositionActions } from "./composition/index.js";
|
|
23
|
+
import { registerFacetActions } from "./facets/index.js";
|
|
24
|
+
import { registerThemeActions } from "./theme/index.js";
|
|
25
25
|
import {
|
|
26
26
|
applyCompositionTheme,
|
|
27
27
|
removeCompositionTheme
|
|
@@ -1,3 +1,4 @@
|
|
|
1
|
+
import { normalizeArcInnerRadius } from "../../../grammar/arcs.js";
|
|
1
2
|
import { action } from "../../../core/action.js";
|
|
2
3
|
import { validateUserId } from "../../../core/identifiers.js";
|
|
3
4
|
import {
|
|
@@ -49,14 +50,6 @@ const CREATE_OPTIONS = Object.freeze(["id", "data", ...ARC_OPTIONS]);
|
|
|
49
50
|
const EDIT_OPTIONS = Object.freeze(["target", ...ARC_OPTIONS]);
|
|
50
51
|
const REMATERIALIZE_OPTIONS = Object.freeze(["id", "scales"]);
|
|
51
52
|
|
|
52
|
-
function validateInnerRadius(value) {
|
|
53
|
-
if (!Number.isFinite(value) || value < 0 || value >= 1) {
|
|
54
|
-
throw new RangeError(
|
|
55
|
-
"Arc innerRadius must be from 0 (inclusive) to 1 (exclusive)."
|
|
56
|
-
);
|
|
57
|
-
}
|
|
58
|
-
return value;
|
|
59
|
-
}
|
|
60
53
|
|
|
61
54
|
function normalizeConfig(
|
|
62
55
|
args,
|
|
@@ -67,7 +60,7 @@ function normalizeConfig(
|
|
|
67
60
|
...previous,
|
|
68
61
|
...strokeDetails,
|
|
69
62
|
...(Object.hasOwn(args, "innerRadius")
|
|
70
|
-
? { innerRadius:
|
|
63
|
+
? { innerRadius: normalizeArcInnerRadius(args.innerRadius), innerRadiusExplicit: true }
|
|
71
64
|
: {}),
|
|
72
65
|
...(Object.hasOwn(args, "padAngle")
|
|
73
66
|
? { padAngle: validateNonNegativeFinite(args.padAngle, "Arc padAngle") }
|
|
@@ -204,7 +197,7 @@ const rematerializeArcMark = /* @__PURE__ */ action(
|
|
|
204
197
|
? {}
|
|
205
198
|
: { radiusScale: resolved.resolvedScales[radiusScaleId] }),
|
|
206
199
|
frame,
|
|
207
|
-
|
|
200
|
+
innerRadius: config.innerRadius ?? 0
|
|
208
201
|
});
|
|
209
202
|
const commands = derived.sectors.map(sector => buildAnnularSectorCommands({
|
|
210
203
|
frame,
|