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
|
@@ -9,7 +9,7 @@ import {
|
|
|
9
9
|
validateNonNegativeFinite,
|
|
10
10
|
validatePositiveFinite
|
|
11
11
|
} from "../../../core/validation.js";
|
|
12
|
-
import {
|
|
12
|
+
import { resolveGuideCoordinateBounds } from "../../../materialization/coordinateBounds.js";
|
|
13
13
|
import {
|
|
14
14
|
isTransformedScaleType,
|
|
15
15
|
mapContinuousScaleValues,
|
|
@@ -38,11 +38,15 @@ import {
|
|
|
38
38
|
import { resolveConcreteGraphicBounds } from
|
|
39
39
|
"../../../grammar/schemas/graphicBounds.js";
|
|
40
40
|
import { wrapText } from "../../../layout/text.js";
|
|
41
|
+
import {
|
|
42
|
+
normalizeDisplayLabelMap,
|
|
43
|
+
resolveDisplayLabel
|
|
44
|
+
} from "../../../grammar/displayLabels.js";
|
|
41
45
|
|
|
42
46
|
const OPTIONS = [
|
|
43
47
|
"scale", "position", "count", "values", "offset", "format", "color",
|
|
44
48
|
"fontSize", "fontFamily", "fontWeight", "rotation", "maxWidth", "wrap",
|
|
45
|
-
"lineHeight", "overlap"
|
|
49
|
+
"lineHeight", "overlap", "labelMap"
|
|
46
50
|
];
|
|
47
51
|
|
|
48
52
|
const DEFAULTS = {
|
|
@@ -136,6 +140,24 @@ function validateConfig(channel, config) {
|
|
|
136
140
|
}
|
|
137
141
|
}
|
|
138
142
|
|
|
143
|
+
function normalizeAxisLabelMap(program, config, args, operation) {
|
|
144
|
+
if (!Object.hasOwn(args, "labelMap")) return config;
|
|
145
|
+
const scale = program.resolvedScales[config.scale];
|
|
146
|
+
if (!["ordinal", "band", "point"].includes(scale?.type)) {
|
|
147
|
+
throw new Error(`${operation} labelMap requires a categorical scale.`);
|
|
148
|
+
}
|
|
149
|
+
const next = { ...config };
|
|
150
|
+
if (args.labelMap === "auto") {
|
|
151
|
+
delete next.labelMap;
|
|
152
|
+
} else {
|
|
153
|
+
next.labelMap = normalizeDisplayLabelMap(
|
|
154
|
+
args.labelMap,
|
|
155
|
+
`${operation} labelMap`
|
|
156
|
+
);
|
|
157
|
+
}
|
|
158
|
+
return next;
|
|
159
|
+
}
|
|
160
|
+
|
|
139
161
|
function assertTickCompatibility(ticks, config, operation) {
|
|
140
162
|
if (!ticks) return;
|
|
141
163
|
if (ticks.scale !== config.scale || ticks.mode !== config.mode) throw new Error(`${operation} conflicts with axis ticks.`);
|
|
@@ -143,7 +165,7 @@ function assertTickCompatibility(ticks, config, operation) {
|
|
|
143
165
|
if (config.mode === "values" && !sameOrderedValues(ticks.values, config.values)) throw new Error(`${operation} conflicts with axis ticks.`);
|
|
144
166
|
}
|
|
145
167
|
|
|
146
|
-
function expandWrappedLabels(resolved, text, config, channel) {
|
|
168
|
+
function expandWrappedLabels(resolved, text, config, channel, profile) {
|
|
147
169
|
if (config.maxWidth === undefined) {
|
|
148
170
|
return {
|
|
149
171
|
...resolved,
|
|
@@ -162,7 +184,7 @@ function expandWrappedLabels(resolved, text, config, channel) {
|
|
|
162
184
|
const lines = wrapText(text[index], {
|
|
163
185
|
maxWidth: config.maxWidth,
|
|
164
186
|
mode: config.wrap,
|
|
165
|
-
style
|
|
187
|
+
style, profile
|
|
166
188
|
});
|
|
167
189
|
validateGeneratedItemLimit(
|
|
168
190
|
expanded.text.length + lines.length,
|
|
@@ -198,8 +220,15 @@ function unionLabelBounds(records) {
|
|
|
198
220
|
|
|
199
221
|
function resolve(program, channel, config) {
|
|
200
222
|
const scale = program.resolvedScales[config.scale];
|
|
201
|
-
const bounds =
|
|
223
|
+
const bounds = resolveGuideCoordinateBounds(program, {
|
|
224
|
+
coordinate: program.semanticSpec.guides.axis?.[channel]?.coordinate,
|
|
225
|
+
scale: config.scale,
|
|
226
|
+
channel
|
|
227
|
+
});
|
|
202
228
|
const discrete = ["ordinal", "band", "point"].includes(scale?.type);
|
|
229
|
+
if (config.labelMap !== undefined && !discrete) {
|
|
230
|
+
throw new Error("Axis labelMap requires a categorical scale.");
|
|
231
|
+
}
|
|
203
232
|
if ((
|
|
204
233
|
!["linear", "time", "ordinal", "band", "point"].includes(scale?.type) &&
|
|
205
234
|
!isTransformedScaleType(scale?.type)
|
|
@@ -217,9 +246,7 @@ function resolve(program, channel, config) {
|
|
|
217
246
|
const positions = discrete
|
|
218
247
|
? mapOrdinalPositionValues(values, scale)
|
|
219
248
|
: mapContinuousScaleValues(values, scale);
|
|
220
|
-
const
|
|
221
|
-
? formatTimeTicks(values, scale.domain)
|
|
222
|
-
: values.map(value => formatAxisValue(
|
|
249
|
+
const fallback = value => formatAxisValue(
|
|
223
250
|
value,
|
|
224
251
|
scale.type,
|
|
225
252
|
config.format,
|
|
@@ -228,7 +255,12 @@ function resolve(program, channel, config) {
|
|
|
228
255
|
: isTransformedScaleType(scale.type)
|
|
229
256
|
? formatTransformedTick(scale.type, item)
|
|
230
257
|
: String(item)
|
|
231
|
-
)
|
|
258
|
+
);
|
|
259
|
+
const text = discrete
|
|
260
|
+
? values.map(value => resolveDisplayLabel(value, config.labelMap, fallback))
|
|
261
|
+
: scale.type === "time" && config.format === "auto"
|
|
262
|
+
? formatTimeTicks(values, scale.domain)
|
|
263
|
+
: values.map(fallback);
|
|
232
264
|
const geometry = {
|
|
233
265
|
values,
|
|
234
266
|
...resolveAxisLabelGeometry({
|
|
@@ -239,7 +271,7 @@ function resolve(program, channel, config) {
|
|
|
239
271
|
offset: config.offset
|
|
240
272
|
})
|
|
241
273
|
};
|
|
242
|
-
const resolved = expandWrappedLabels(geometry, text, config, channel);
|
|
274
|
+
const resolved = expandWrappedLabels(geometry, text, config, channel, program.materializationConfigs.textMetrics);
|
|
243
275
|
const canvas = findCanvasGraphic(program)?.properties;
|
|
244
276
|
const labelBounds = resolved.text.map((value, index) => resolveTextBounds({
|
|
245
277
|
x: Array.isArray(resolved.x) ? resolved.x[index] : resolved.x,
|
|
@@ -251,7 +283,7 @@ function resolve(program, channel, config) {
|
|
|
251
283
|
textAlign: resolved.textAlign,
|
|
252
284
|
textBaseline: resolved.textBaseline,
|
|
253
285
|
rotation: config.rotation
|
|
254
|
-
}));
|
|
286
|
+
}, program.materializationConfigs.textMetrics));
|
|
255
287
|
const groupedBounds = unionLabelBounds(labelBounds.map((bounds, index) => ({
|
|
256
288
|
bounds,
|
|
257
289
|
group: resolved.groups[index]
|
|
@@ -267,7 +299,7 @@ function resolve(program, channel, config) {
|
|
|
267
299
|
throw new Error(`The ${channel}-axis labels overlap each other.`);
|
|
268
300
|
}
|
|
269
301
|
const title = program.graphicSpec.objects[`${channel}AxisTitle`]
|
|
270
|
-
? resolveConcreteGraphicBounds(program.graphicSpec, `${channel}AxisTitle
|
|
302
|
+
? resolveConcreteGraphicBounds(program.graphicSpec, `${channel}AxisTitle`, program.materializationConfigs.textMetrics)
|
|
271
303
|
: undefined;
|
|
272
304
|
if (title &&
|
|
273
305
|
program.guideConfigs.axis?.[channel]?.title?.inferredOffset !== true &&
|
|
@@ -294,13 +326,14 @@ function makeEdit(channel) {
|
|
|
294
326
|
const mode = Object.hasOwn(args, "values") || inferredValues !== undefined
|
|
295
327
|
? "values"
|
|
296
328
|
: Object.hasOwn(args, "count") ? "count" : previous.mode;
|
|
297
|
-
|
|
329
|
+
let config = normalizeLabelLayout({
|
|
298
330
|
...previous,
|
|
299
331
|
...args,
|
|
300
332
|
...(inferredValues === undefined ? {} : { values: inferredValues }),
|
|
301
333
|
...(explicitMode ? { inferredValues: false } : {}),
|
|
302
334
|
mode
|
|
303
335
|
}, args, op);
|
|
336
|
+
config = normalizeAxisLabelMap(this, config, args, op);
|
|
304
337
|
if (mode === "values") delete config.count; else delete config.values;
|
|
305
338
|
validateConfig(channel, config);
|
|
306
339
|
assertTickCompatibility(this.guideConfigs.axis?.[channel]?.ticks, config, op);
|
|
@@ -333,8 +366,8 @@ function makeEdit(channel) {
|
|
|
333
366
|
}));
|
|
334
367
|
}
|
|
335
368
|
|
|
336
|
-
const editXAxisLabels = makeEdit("x");
|
|
337
|
-
const editYAxisLabels = makeEdit("y");
|
|
369
|
+
const editXAxisLabels = /* @__PURE__ */ makeEdit("x");
|
|
370
|
+
const editYAxisLabels = /* @__PURE__ */ makeEdit("y");
|
|
338
371
|
|
|
339
372
|
function makeCreate(channel) {
|
|
340
373
|
const op = channel === "x" ? "createXAxisLabels" : "createYAxisLabels";
|
|
@@ -349,8 +382,15 @@ function makeCreate(channel) {
|
|
|
349
382
|
const ticks = this.guideConfigs.axis?.[channel]?.ticks;
|
|
350
383
|
const hasValues = Object.hasOwn(args, "values");
|
|
351
384
|
const hasCount = Object.hasOwn(args, "count");
|
|
352
|
-
const
|
|
353
|
-
const
|
|
385
|
+
const resolvedScale = this.resolvedScales[scale];
|
|
386
|
+
const inferredDiscreteValues = !hasValues && !hasCount && ticks === undefined &&
|
|
387
|
+
["ordinal", "band", "point"].includes(resolvedScale?.type)
|
|
388
|
+
? resolvedScale.domain
|
|
389
|
+
: undefined;
|
|
390
|
+
const mode = hasValues || inferredDiscreteValues !== undefined
|
|
391
|
+
? "values"
|
|
392
|
+
: hasCount ? "count" : ticks?.mode ?? "count";
|
|
393
|
+
let config = normalizeLabelLayout({
|
|
354
394
|
scale,
|
|
355
395
|
position: defaultAxisPosition(channel),
|
|
356
396
|
offset: channel === "x" ? 18 : 12,
|
|
@@ -362,10 +402,16 @@ function makeCreate(channel) {
|
|
|
362
402
|
rotation: DEFAULTS.rotation,
|
|
363
403
|
overlap: DEFAULTS.overlap,
|
|
364
404
|
...args,
|
|
365
|
-
inferredValues: !hasValues && !hasCount &&
|
|
405
|
+
inferredValues: !hasValues && !hasCount &&
|
|
406
|
+
(ticks?.inferredValues === true || inferredDiscreteValues !== undefined),
|
|
366
407
|
mode
|
|
367
408
|
}, args, op);
|
|
368
|
-
|
|
409
|
+
config = normalizeAxisLabelMap(this, config, args, op);
|
|
410
|
+
if (mode === "values") {
|
|
411
|
+
config.values ??= ticks?.values ?? inferredDiscreteValues;
|
|
412
|
+
} else {
|
|
413
|
+
config.count ??= ticks?.count ?? DEFAULTS.count;
|
|
414
|
+
}
|
|
369
415
|
validateConfig(channel, config);
|
|
370
416
|
assertTickCompatibility(ticks, config, op);
|
|
371
417
|
resolve(this, channel, config);
|
|
@@ -380,8 +426,8 @@ function makeCreate(channel) {
|
|
|
380
426
|
}));
|
|
381
427
|
}
|
|
382
428
|
|
|
383
|
-
const createXAxisLabels = makeCreate("x");
|
|
384
|
-
const createYAxisLabels = makeCreate("y");
|
|
429
|
+
const createXAxisLabels = /* @__PURE__ */ makeCreate("x");
|
|
430
|
+
const createYAxisLabels = /* @__PURE__ */ makeCreate("y");
|
|
385
431
|
|
|
386
432
|
export function registerAxisLabelActions(Class) {
|
|
387
433
|
Class.prototype.editXAxisLabels = editXAxisLabels;
|
|
@@ -1,3 +1,4 @@
|
|
|
1
|
+
import { editGraphicProperties } from "../../primitives/graphicProperties.js";
|
|
1
2
|
import { isSourceOwnedText } from "../../../grammar/text.js";
|
|
2
3
|
import { withGuideLayoutValidation } from "../../../materialization/guides/layout.js";
|
|
3
4
|
import { action } from "../../../core/action.js";
|
|
@@ -7,7 +8,7 @@ import {
|
|
|
7
8
|
validateNonEmptyString,
|
|
8
9
|
validateNonNegativeFinite
|
|
9
10
|
} from "../../../core/validation.js";
|
|
10
|
-
import {
|
|
11
|
+
import { resolveGuideCoordinateBounds } from "../../../materialization/coordinateBounds.js";
|
|
11
12
|
import { DEFAULT_COLORS } from "../../../theme/defaults.js";
|
|
12
13
|
import {
|
|
13
14
|
defaultAxisPosition,
|
|
@@ -53,7 +54,11 @@ function resolveGeometry(program, channel, scaleId, position) {
|
|
|
53
54
|
|
|
54
55
|
const resolvedScale = program.resolvedScales[scaleId];
|
|
55
56
|
const range = resolvedScale?.range;
|
|
56
|
-
const bounds =
|
|
57
|
+
const bounds = resolveGuideCoordinateBounds(program, {
|
|
58
|
+
coordinate: program.semanticSpec.guides.axis?.[channel]?.coordinate,
|
|
59
|
+
scale: scaleId,
|
|
60
|
+
channel
|
|
61
|
+
});
|
|
57
62
|
|
|
58
63
|
if (!Array.isArray(range) || range.length !== 2 || !range.every(Number.isFinite)) {
|
|
59
64
|
throw new Error(`Axis line requires a resolved numeric scale "${scaleId}".`);
|
|
@@ -115,15 +120,16 @@ function createEditAxisLine(channel) {
|
|
|
115
120
|
next = next.editGraphics({ target: graphic, property, value: geometry[property] });
|
|
116
121
|
}
|
|
117
122
|
|
|
118
|
-
return next
|
|
119
|
-
|
|
120
|
-
|
|
123
|
+
return editGraphicProperties(next, graphic, {
|
|
124
|
+
stroke: color,
|
|
125
|
+
strokeWidth: lineWidth
|
|
126
|
+
});
|
|
121
127
|
})
|
|
122
128
|
);
|
|
123
129
|
}
|
|
124
130
|
|
|
125
|
-
const editXAxisLine = createEditAxisLine("x");
|
|
126
|
-
const editYAxisLine = createEditAxisLine("y");
|
|
131
|
+
const editXAxisLine = /* @__PURE__ */ createEditAxisLine("x");
|
|
132
|
+
const editYAxisLine = /* @__PURE__ */ createEditAxisLine("y");
|
|
127
133
|
|
|
128
134
|
function createAxisLine(channel) {
|
|
129
135
|
const operation = channel === "x" ? "createXAxisLine" : "createYAxisLine";
|
|
@@ -160,8 +166,8 @@ function createAxisLine(channel) {
|
|
|
160
166
|
);
|
|
161
167
|
}
|
|
162
168
|
|
|
163
|
-
const createXAxisLine = createAxisLine("x");
|
|
164
|
-
const createYAxisLine = createAxisLine("y");
|
|
169
|
+
const createXAxisLine = /* @__PURE__ */ createAxisLine("x");
|
|
170
|
+
const createYAxisLine = /* @__PURE__ */ createAxisLine("y");
|
|
165
171
|
|
|
166
172
|
export function registerAxisLineActions(ProgramClass) {
|
|
167
173
|
ProgramClass.prototype.editXAxisLine = editXAxisLine;
|
|
@@ -1,5 +1,5 @@
|
|
|
1
|
-
import { action } from "../../../../core/action.js";
|
|
2
|
-
import { validateNonEmptyString
|
|
1
|
+
import { action, closedAction } from "../../../../core/action.js";
|
|
2
|
+
import { validateNonEmptyString } from "../../../../core/validation.js";
|
|
3
3
|
import { requireParallelAxisLayer, resolveParallelAxisTarget } from "./resolve.js";
|
|
4
4
|
import {
|
|
5
5
|
defaultParallelAxis, hasParallelAxisParts, PARALLEL_AXIS_GRAPHICS,
|
|
@@ -45,10 +45,10 @@ function withTitle(program, args, create) {
|
|
|
45
45
|
...(titles.length === 0 ? { remove: true } : { value: titles }) });
|
|
46
46
|
}
|
|
47
47
|
|
|
48
|
-
const createParallelAxes =
|
|
48
|
+
const createParallelAxes = /* @__PURE__ */ closedAction({
|
|
49
49
|
op: "createParallelAxes", description: "Create axes for every encoded Parallel dimension."
|
|
50
|
-
}, function (args = {}) {
|
|
51
|
-
|
|
50
|
+
}, ["target", "coordinate"], function (args = {}) {
|
|
51
|
+
|
|
52
52
|
const resolved = owner(this, args, "createParallelAxes");
|
|
53
53
|
if (resolved.stored !== undefined || this.guideConfigs.axis?.parallel !== undefined ||
|
|
54
54
|
Object.values(PARALLEL_AXIS_GRAPHICS).some(id => this.graphicSpec.objects[id] !== undefined)) {
|
|
@@ -76,13 +76,13 @@ function makeAxisAction(create) {
|
|
|
76
76
|
});
|
|
77
77
|
}
|
|
78
78
|
|
|
79
|
-
const createParallelAxis = makeAxisAction(true);
|
|
80
|
-
const editParallelAxis = makeAxisAction(false);
|
|
79
|
+
const createParallelAxis = /* @__PURE__ */ makeAxisAction(true);
|
|
80
|
+
const editParallelAxis = /* @__PURE__ */ makeAxisAction(false);
|
|
81
81
|
|
|
82
|
-
const removeParallelAxis =
|
|
82
|
+
const removeParallelAxis = /* @__PURE__ */ closedAction({
|
|
83
83
|
op: "removeParallelAxis", description: "Remove every component of one Parallel field axis."
|
|
84
|
-
}, function (args = {}) {
|
|
85
|
-
|
|
84
|
+
}, ["field", "target"], function (args = {}) {
|
|
85
|
+
|
|
86
86
|
validateNonEmptyString(args.field, "Parallel axis field");
|
|
87
87
|
const resolved = owner(this, args, "removeParallelAxis", true);
|
|
88
88
|
const config = resolveParallelAxisConfigs(this, resolved.dimensions).dimensions.find(dimension => dimension.field === args.field);
|
|
@@ -91,10 +91,10 @@ const removeParallelAxis = action({
|
|
|
91
91
|
...Object.fromEntries(PARALLEL_AXIS_PARTS.filter(part => config[part] !== undefined).map(part => [part, false])) });
|
|
92
92
|
});
|
|
93
93
|
|
|
94
|
-
const removeParallelAxes =
|
|
94
|
+
const removeParallelAxes = /* @__PURE__ */ closedAction({
|
|
95
95
|
op: "removeParallelAxes", description: "Remove all Parallel axis semantics, recipes and graphics."
|
|
96
|
-
}, function (args = {}) {
|
|
97
|
-
|
|
96
|
+
}, ["target", "coordinate"], function (args = {}) {
|
|
97
|
+
|
|
98
98
|
const stored = this.semanticSpec.guides.axis?.parallel;
|
|
99
99
|
if (stored === undefined) throw new Error("removeParallelAxes requires existing Parallel axes.");
|
|
100
100
|
if (args.target !== undefined && args.target !== stored.target ||
|
|
@@ -6,7 +6,7 @@ import {
|
|
|
6
6
|
transformedTicks
|
|
7
7
|
} from "../../../../grammar/scales/index.js";
|
|
8
8
|
import { niceTicks } from "../../../../grammar/ticks.js";
|
|
9
|
-
import {
|
|
9
|
+
import { resolveCoordinateBounds } from "../../../../materialization/coordinateBounds.js";
|
|
10
10
|
import { findCoordinate } from "../../../../selectors/coordinates.js";
|
|
11
11
|
import { findLayer } from "../../../../selectors/layers.js";
|
|
12
12
|
import { formatAxisValue } from "../policy.js";
|
|
@@ -85,7 +85,11 @@ function componentValues(program, dimension, config) {
|
|
|
85
85
|
}
|
|
86
86
|
|
|
87
87
|
export function resolveStyledParallelAxes(program, dimensions) {
|
|
88
|
-
const
|
|
88
|
+
const stored = program.guideConfigs.axis?.parallel?.axes;
|
|
89
|
+
const layer = stored === undefined
|
|
90
|
+
? undefined
|
|
91
|
+
: findLayer(program, stored.target);
|
|
92
|
+
const bounds = resolveCoordinateBounds(program, layer?.coordinate);
|
|
89
93
|
const step = bounds.width / (dimensions.length - 1);
|
|
90
94
|
const configs = resolveParallelAxisConfigs(program, dimensions);
|
|
91
95
|
const titles = program.semanticSpec.guides.axis?.parallel?.titles ?? [];
|
|
@@ -1,5 +1,5 @@
|
|
|
1
|
-
import {
|
|
2
|
-
import { validateGeneratedItemLimit
|
|
1
|
+
import { closedAction } from "../../../core/action.js";
|
|
2
|
+
import { validateGeneratedItemLimit } from "../../../core/validation.js";
|
|
3
3
|
import { resolvePlotGraphicPlacement } from "../../../materialization/graphicHierarchy.js";
|
|
4
4
|
import { requireParallelAxisLayer, resolveParallelAxisTarget, resolveStyledParallelAxes } from "./parallel/resolve.js";
|
|
5
5
|
import { PARALLEL_AXIS_GRAPHICS, PARALLEL_AXIS_PARTS, hasParallelAxisParts } from "./parallel/policy.js";
|
|
@@ -47,11 +47,11 @@ function collectionProperties(part, axes, bounds) {
|
|
|
47
47
|
};
|
|
48
48
|
}
|
|
49
49
|
|
|
50
|
-
export const rematerializeParallelAxes =
|
|
50
|
+
export const rematerializeParallelAxes = /* @__PURE__ */ closedAction({
|
|
51
51
|
op: "rematerializeParallelAxes",
|
|
52
52
|
description: "Recompute concrete Parallel dimension axes."
|
|
53
|
-
}, function (args = {}) {
|
|
54
|
-
|
|
53
|
+
}, ["target"], function (args = {}) {
|
|
54
|
+
|
|
55
55
|
const stored = this.semanticSpec.guides.axis?.parallel;
|
|
56
56
|
if (stored === undefined) throw new Error("rematerializeParallelAxes requires existing Parallel axes.");
|
|
57
57
|
const target = resolveParallelAxisTarget(this, args.target ?? stored.target);
|
|
@@ -54,7 +54,7 @@ function makeRemoveAxis(channel) {
|
|
|
54
54
|
);
|
|
55
55
|
}
|
|
56
56
|
|
|
57
|
-
export const removeXAxis = makeRemoveAxis("x");
|
|
58
|
-
export const removeYAxis = makeRemoveAxis("y");
|
|
59
|
-
export const removeThetaAxis = makeRemoveAxis("theta");
|
|
60
|
-
export const removeRadialAxis = makeRemoveAxis("radius");
|
|
57
|
+
export const removeXAxis = /* @__PURE__ */ makeRemoveAxis("x");
|
|
58
|
+
export const removeYAxis = /* @__PURE__ */ makeRemoveAxis("y");
|
|
59
|
+
export const removeThetaAxis = /* @__PURE__ */ makeRemoveAxis("theta");
|
|
60
|
+
export const removeRadialAxis = /* @__PURE__ */ makeRemoveAxis("radius");
|
|
@@ -30,7 +30,8 @@ const LABEL_OPTIONS = Object.freeze([
|
|
|
30
30
|
"maxWidth",
|
|
31
31
|
"wrap",
|
|
32
32
|
"lineHeight",
|
|
33
|
-
"overlap"
|
|
33
|
+
"overlap",
|
|
34
|
+
"labelMap"
|
|
34
35
|
]);
|
|
35
36
|
const SHARED_CREATE = Object.freeze(["scale", "position", "count", "values"]);
|
|
36
37
|
const SHARED_EDIT = Object.freeze(["position", "count", "values"]);
|
|
@@ -144,10 +145,10 @@ function makeEdit(channel) {
|
|
|
144
145
|
);
|
|
145
146
|
}
|
|
146
147
|
|
|
147
|
-
const createXAxisTicksAndLabels = makeCreate("x");
|
|
148
|
-
const createYAxisTicksAndLabels = makeCreate("y");
|
|
149
|
-
const editXAxisTicksAndLabels = makeEdit("x");
|
|
150
|
-
const editYAxisTicksAndLabels = makeEdit("y");
|
|
148
|
+
const createXAxisTicksAndLabels = /* @__PURE__ */ makeCreate("x");
|
|
149
|
+
const createYAxisTicksAndLabels = /* @__PURE__ */ makeCreate("y");
|
|
150
|
+
const editXAxisTicksAndLabels = /* @__PURE__ */ makeEdit("x");
|
|
151
|
+
const editYAxisTicksAndLabels = /* @__PURE__ */ makeEdit("y");
|
|
151
152
|
|
|
152
153
|
export function registerAxisTickGroupActions(Class) {
|
|
153
154
|
Class.prototype.createXAxisTicksAndLabels = createXAxisTicksAndLabels;
|
|
@@ -1,4 +1,7 @@
|
|
|
1
|
+
import { editGraphicProperties } from "../../primitives/graphicProperties.js";
|
|
1
2
|
import { withGuideLayoutValidation } from "../../../materialization/guides/layout.js";
|
|
3
|
+
import { applyMaterializationPlan } from "../../../materialization/planner.js";
|
|
4
|
+
import { planAxisTickGridRematerialization } from "../../../materialization/scaleGuideDependencies.js";
|
|
2
5
|
import { action } from "../../../core/action.js";
|
|
3
6
|
import { validateUserId } from "../../../core/identifiers.js";
|
|
4
7
|
import {
|
|
@@ -7,7 +10,7 @@ import {
|
|
|
7
10
|
validateNonNegativeFinite,
|
|
8
11
|
validateOptionObject
|
|
9
12
|
} from "../../../core/validation.js";
|
|
10
|
-
import {
|
|
13
|
+
import { resolveGuideCoordinateBounds } from "../../../materialization/coordinateBounds.js";
|
|
11
14
|
import {
|
|
12
15
|
isTransformedScaleType,
|
|
13
16
|
mapContinuousScaleValues,
|
|
@@ -69,7 +72,11 @@ function validateConfig(channel, config) {
|
|
|
69
72
|
|
|
70
73
|
function geometry(program, channel, config) {
|
|
71
74
|
const scale = program.resolvedScales[config.scale];
|
|
72
|
-
const bounds =
|
|
75
|
+
const bounds = resolveGuideCoordinateBounds(program, {
|
|
76
|
+
coordinate: program.semanticSpec.guides.axis?.[channel]?.coordinate,
|
|
77
|
+
scale: config.scale,
|
|
78
|
+
channel
|
|
79
|
+
});
|
|
73
80
|
const discrete = ["ordinal", "band", "point"].includes(scale?.type);
|
|
74
81
|
if ((
|
|
75
82
|
!["linear", "time", "ordinal", "band", "point"].includes(scale?.type) &&
|
|
@@ -157,11 +164,16 @@ function makeEdit(channel) {
|
|
|
157
164
|
const resolved = geometry(this, channel, config);
|
|
158
165
|
let next = this._withGuideConfig(channel, config).editGraphics({ target: id, property: "length", value: resolved.values.length });
|
|
159
166
|
for (const property of ["x1", "y1", "x2", "y2"]) next = next.editGraphics({ target: id, property, value: resolved[property] });
|
|
160
|
-
|
|
167
|
+
next = editGraphicProperties(next, id, {
|
|
168
|
+
stroke: config.color,
|
|
169
|
+
strokeWidth: config.lineWidth
|
|
170
|
+
});
|
|
171
|
+
// Structural dependency plans own grids during a scale/role handoff.
|
|
172
|
+
return explicitMode ? applyMaterializationPlan(next, planAxisTickGridRematerialization(next, channel)) : next;
|
|
161
173
|
}));
|
|
162
174
|
}
|
|
163
175
|
|
|
164
|
-
const editXAxisTicks = makeEdit("x"), editYAxisTicks = makeEdit("y");
|
|
176
|
+
const editXAxisTicks = /* @__PURE__ */ makeEdit("x"), editYAxisTicks = /* @__PURE__ */ makeEdit("y");
|
|
165
177
|
|
|
166
178
|
function makeCreate(channel) {
|
|
167
179
|
const op = channel === "x" ? "createXAxisTicks" : "createYAxisTicks";
|
|
@@ -185,7 +197,7 @@ function makeCreate(channel) {
|
|
|
185
197
|
const config = { scale, position: defaultAxisPosition(channel), length: DEFAULTS.length, color: DEFAULTS.color, lineWidth: DEFAULTS.lineWidth, ...options, inferredValues: inferredValues !== undefined, mode: Object.hasOwn(options, "values") ? "values" : "count" };
|
|
186
198
|
if (config.mode === "values") delete config.count; else config.count ??= DEFAULTS.count;
|
|
187
199
|
validateConfig(channel, config); geometry(this, channel, config);
|
|
188
|
-
|
|
200
|
+
const next = this.editSemantic({ property: `guide.axis.${channel}.scale`, value: scale })
|
|
189
201
|
.createGraphics({
|
|
190
202
|
id,
|
|
191
203
|
type: "line",
|
|
@@ -193,10 +205,11 @@ function makeCreate(channel) {
|
|
|
193
205
|
...resolvePlotGraphicPlacement(this)
|
|
194
206
|
})
|
|
195
207
|
._withGuideConfig(channel, config)[edit]();
|
|
208
|
+
return applyMaterializationPlan(next, planAxisTickGridRematerialization(next, channel));
|
|
196
209
|
}));
|
|
197
210
|
}
|
|
198
211
|
|
|
199
|
-
const createXAxisTicks = makeCreate("x"), createYAxisTicks = makeCreate("y");
|
|
212
|
+
const createXAxisTicks = /* @__PURE__ */ makeCreate("x"), createYAxisTicks = /* @__PURE__ */ makeCreate("y");
|
|
200
213
|
export function registerAxisTickActions(Class) {
|
|
201
214
|
Class.prototype.editXAxisTicks = editXAxisTicks; Class.prototype.editYAxisTicks = editYAxisTicks;
|
|
202
215
|
Class.prototype.createXAxisTicks = createXAxisTicks; Class.prototype.createYAxisTicks = createYAxisTicks;
|
|
@@ -7,7 +7,7 @@ import {
|
|
|
7
7
|
validateNonEmptyString,
|
|
8
8
|
validateNonNegativeFinite
|
|
9
9
|
} from "../../../core/validation.js";
|
|
10
|
-
import {
|
|
10
|
+
import { resolveGuideCoordinateBounds } from "../../../materialization/coordinateBounds.js";
|
|
11
11
|
import {
|
|
12
12
|
isTransformedScaleType,
|
|
13
13
|
mapContinuousScaleValues,
|
|
@@ -36,7 +36,7 @@ import { resolveConcreteGraphicBounds } from
|
|
|
36
36
|
import { validateAxisTextStyle } from "./labels.js";
|
|
37
37
|
import { resolveRotation } from "../../../grammar/rotation.js";
|
|
38
38
|
|
|
39
|
-
function titleBounds(geometry, config, text) {
|
|
39
|
+
function titleBounds(geometry, config, text, profile) {
|
|
40
40
|
return resolveTextBounds({
|
|
41
41
|
...geometry,
|
|
42
42
|
text,
|
|
@@ -46,14 +46,18 @@ function titleBounds(geometry, config, text) {
|
|
|
46
46
|
textAlign: "center",
|
|
47
47
|
textBaseline: "middle",
|
|
48
48
|
rotation: config.rotation
|
|
49
|
-
});
|
|
49
|
+
}, profile);
|
|
50
50
|
}
|
|
51
51
|
|
|
52
52
|
function inferredTitleOffset(program, channel, config) {
|
|
53
|
-
const plot =
|
|
53
|
+
const plot = resolveGuideCoordinateBounds(program, {
|
|
54
|
+
coordinate: program.semanticSpec.guides.axis?.[channel]?.coordinate,
|
|
55
|
+
scale: config.scale,
|
|
56
|
+
channel
|
|
57
|
+
});
|
|
54
58
|
const canvas = findCanvasGraphic(program)?.properties;
|
|
55
59
|
const labels = program.graphicSpec.objects[`${channel}AxisLabels`]
|
|
56
|
-
? resolveConcreteGraphicBounds(program.graphicSpec, `${channel}AxisLabels
|
|
60
|
+
? resolveConcreteGraphicBounds(program.graphicSpec, `${channel}AxisLabels`, program.materializationConfigs.textMetrics)
|
|
57
61
|
: undefined;
|
|
58
62
|
const preferred = channel === "x" ? 42 : 52;
|
|
59
63
|
if (!plot || !canvas || !labels) return preferred;
|
|
@@ -67,7 +71,7 @@ function inferredTitleOffset(program, channel, config) {
|
|
|
67
71
|
position: config.position,
|
|
68
72
|
along: 0,
|
|
69
73
|
offset: preferred
|
|
70
|
-
}), config, program.semanticSpec.guides.axis?.[channel]?.title ?? "");
|
|
74
|
+
}), config, program.semanticSpec.guides.axis?.[channel]?.title ?? "", program.materializationConfigs.textMetrics);
|
|
71
75
|
const needed = positive
|
|
72
76
|
? labels[far] + 4 - bounds[near]
|
|
73
77
|
: bounds[far] - labels[near] + 4;
|
|
@@ -151,7 +155,11 @@ export function inferAxisTitleText(program, channel, scaleId) {
|
|
|
151
155
|
|
|
152
156
|
function resolveGeometry(program, channel, config) {
|
|
153
157
|
const scale = program.resolvedScales[config.scale];
|
|
154
|
-
const bounds =
|
|
158
|
+
const bounds = resolveGuideCoordinateBounds(program, {
|
|
159
|
+
coordinate: program.semanticSpec.guides.axis?.[channel]?.coordinate,
|
|
160
|
+
scale: config.scale,
|
|
161
|
+
channel
|
|
162
|
+
});
|
|
155
163
|
const discrete = ["ordinal", "band", "point"].includes(scale?.type);
|
|
156
164
|
if ((
|
|
157
165
|
!["linear", "time", "ordinal", "band", "point"].includes(scale?.type) &&
|
|
@@ -183,13 +191,13 @@ function resolveGeometry(program, channel, config) {
|
|
|
183
191
|
geometry,
|
|
184
192
|
config,
|
|
185
193
|
program.semanticSpec.guides.axis?.[channel]?.title ?? ""
|
|
186
|
-
);
|
|
194
|
+
, program.materializationConfigs.textMetrics);
|
|
187
195
|
const canvas = findCanvasGraphic(program)?.properties;
|
|
188
196
|
if (!canvas || !textBoundsFitCanvas(resolvedBounds, canvas)) {
|
|
189
197
|
throw new Error(`The ${channel}-axis title does not fit the Canvas margin.`);
|
|
190
198
|
}
|
|
191
199
|
const labelsBounds = program.graphicSpec.objects[`${channel}AxisLabels`]
|
|
192
|
-
? resolveConcreteGraphicBounds(program.graphicSpec, `${channel}AxisLabels
|
|
200
|
+
? resolveConcreteGraphicBounds(program.graphicSpec, `${channel}AxisLabels`, program.materializationConfigs.textMetrics)
|
|
193
201
|
: undefined;
|
|
194
202
|
if (labelsBounds && textBoundsIntersect(resolvedBounds, labelsBounds)) {
|
|
195
203
|
throw new Error(`The ${channel}-axis title overlaps the axis labels.`);
|
|
@@ -261,8 +269,8 @@ function makeEdit(channel) {
|
|
|
261
269
|
}));
|
|
262
270
|
}
|
|
263
271
|
|
|
264
|
-
const editXAxisTitle = makeEdit("x");
|
|
265
|
-
const editYAxisTitle = makeEdit("y");
|
|
272
|
+
const editXAxisTitle = /* @__PURE__ */ makeEdit("x");
|
|
273
|
+
const editYAxisTitle = /* @__PURE__ */ makeEdit("y");
|
|
266
274
|
|
|
267
275
|
function makeCreate(channel) {
|
|
268
276
|
const operation = names(channel);
|
|
@@ -319,8 +327,8 @@ function makeCreate(channel) {
|
|
|
319
327
|
}));
|
|
320
328
|
}
|
|
321
329
|
|
|
322
|
-
const createXAxisTitle = makeCreate("x");
|
|
323
|
-
const createYAxisTitle = makeCreate("y");
|
|
330
|
+
const createXAxisTitle = /* @__PURE__ */ makeCreate("x");
|
|
331
|
+
const createYAxisTitle = /* @__PURE__ */ makeCreate("y");
|
|
324
332
|
|
|
325
333
|
export function registerAxisTitleActions(Class) {
|
|
326
334
|
Class.prototype.createXAxisTitle = createXAxisTitle;
|