ggaction 0.0.17 → 0.0.19
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/CHANGELOG.md +96 -0
- package/README.md +6 -2
- package/knowledge/action-card.schema.json +1 -1
- package/knowledge/action-cards.json +1 -1
- package/knowledge/intent-taxonomy.json +1 -1
- package/knowledge/mcp-resources.json +1 -1
- package/knowledge/task-resolver.js +1 -1
- package/package.json +3 -3
- package/src/BasicChartProgram.js +1 -1
- package/src/accessibility.js +3 -2
- package/src/actions/boxPlots/create.js +14 -4
- package/src/actions/boxPlots/edit.js +39 -33
- package/src/actions/boxPlots/materialize.js +7 -3
- package/src/actions/boxPlots/options.js +37 -11
- package/src/actions/canvas/actions.js +70 -95
- package/src/actions/canvas/fitting.js +20 -1
- package/src/actions/canvas/index.js +3 -0
- package/src/actions/canvas/plotBorder.js +28 -0
- package/src/actions/charts/area.js +2 -2
- package/src/actions/charts/bar.js +34 -7
- package/src/actions/charts/ecdf.js +4 -18
- package/src/actions/charts/endpoints.js +4 -18
- package/src/actions/charts/heatmap.js +8 -7
- package/src/actions/charts/index.js +2 -0
- package/src/actions/charts/interval-regression.js +2 -2
- package/src/actions/charts/line.js +1 -1
- package/src/actions/charts/pie.js +3 -47
- package/src/actions/charts/radial.js +34 -12
- package/src/actions/charts/scatter.js +16 -2
- package/src/actions/charts/shared.js +2 -2
- package/src/actions/charts/text.js +35 -0
- package/src/actions/composition/actions.js +6 -2
- package/src/actions/data/box.js +2 -1
- package/src/actions/data/derived.js +11 -1
- package/src/actions/data/edit.js +3 -1
- package/src/actions/data/index.js +4 -0
- package/src/actions/data/regression.js +25 -16
- package/src/actions/data/regressionStatistics.js +73 -0
- package/src/actions/data/shared.js +8 -4
- package/src/actions/data/stack.js +3 -1
- package/src/actions/distributions/revision.js +24 -18
- package/src/actions/encodings/appearance.js +37 -29
- package/src/actions/encodings/barWidth.js +36 -11
- package/src/actions/encodings/channels.js +0 -1
- package/src/actions/encodings/color/continuous.js +1 -1
- package/src/actions/encodings/color/index.js +1 -1
- package/src/actions/encodings/color/policy.js +10 -3
- package/src/actions/encodings/density/resolve.js +1 -6
- package/src/actions/encodings/position/policies/arc.js +12 -10
- package/src/actions/encodings/position/policies/area.js +3 -3
- package/src/actions/encodings/position/policies/bar.js +15 -6
- package/src/actions/encodings/position/policies/line.js +17 -6
- package/src/actions/encodings/position/resolve.js +3 -2
- package/src/actions/encodings/ranged.js +17 -0
- package/src/actions/encodings/remove.js +14 -8
- package/src/actions/encodings/seriesLayout.js +1 -0
- package/src/actions/encodings/shared.js +26 -24
- package/src/actions/encodings/text.js +6 -3
- package/src/actions/errorBands/create.js +2 -2
- package/src/actions/errorBands/edit.js +2 -1
- package/src/actions/facets/actions.js +176 -247
- package/src/actions/facets/guides.js +2 -1
- package/src/actions/gradientPlots/resolve.js +2 -17
- package/src/actions/guides/applicability.js +1 -1
- package/src/actions/guides/axes/axes.js +30 -11
- package/src/actions/guides/axes/axis.js +72 -10
- package/src/actions/guides/axes/components.js +13 -13
- package/src/actions/guides/axes/edit.js +36 -24
- package/src/actions/guides/axes/labels.js +155 -71
- package/src/actions/guides/axes/lines.js +27 -24
- package/src/actions/guides/axes/parallel/lifecycle.js +1 -1
- package/src/actions/guides/axes/parallel/policy.js +8 -7
- package/src/actions/guides/axes/remove.js +13 -8
- package/src/actions/guides/axes/tickGroups.js +11 -7
- package/src/actions/guides/axes/ticks.js +36 -24
- package/src/actions/guides/axes/titles.js +107 -69
- package/src/actions/guides/basic.js +2 -0
- package/src/actions/guides/facadeAxes.js +33 -24
- package/src/actions/guides/facadeLegend.js +12 -4
- package/src/actions/guides/grids/grid.js +8 -2
- package/src/actions/guides/grids/resolve.js +102 -58
- package/src/actions/guides/legends/blocks.js +46 -20
- package/src/actions/guides/legends/categorical/actions.js +95 -19
- package/src/actions/guides/legends/categorical/components.js +15 -18
- package/src/actions/guides/legends/categorical/index.js +8 -0
- package/src/actions/guides/legends/categorical/layout.js +45 -20
- package/src/actions/guides/legends/categorical/options.js +39 -22
- package/src/actions/guides/legends/categorical/recipes.js +7 -3
- package/src/actions/guides/legends/categorical/resolve.js +11 -4
- package/src/actions/guides/legends/categorical/symbols.js +38 -18
- package/src/actions/guides/legends/categorical/validation.js +1 -6
- package/src/actions/guides/legends/colorSize.js +110 -0
- package/src/actions/guides/legends/combine.js +37 -0
- package/src/actions/guides/legends/continuous/colorSymbols.js +1 -0
- package/src/actions/guides/legends/continuous/common.js +1 -447
- package/src/actions/guides/legends/continuous/gradient.js +73 -46
- package/src/actions/guides/legends/continuous/interval.js +4 -4
- package/src/actions/guides/legends/continuous/opacity.js +33 -21
- package/src/actions/guides/legends/creation.js +2 -0
- package/src/actions/guides/legends/edit.js +1 -604
- package/src/actions/guides/legends/focused.js +8 -7
- package/src/actions/guides/legends/group.js +1 -0
- package/src/actions/guides/legends/lane.js +1 -516
- package/src/actions/guides/legends/lifecycle.js +2 -1
- package/src/actions/guides/legends/remove.js +9 -3
- package/src/actions/guides/legends/sampling.js +1 -1
- package/src/actions/guides/legends/size.js +65 -47
- package/src/actions/guides/legends/strokeWidth.js +13 -29
- package/src/actions/guides/legends/target.js +2 -79
- package/src/actions/guides/legends/transition.js +44 -11
- package/src/actions/guides/polar/axes/labels.js +4 -2
- package/src/actions/guides/polar/axes/titles.js +7 -5
- package/src/actions/guides/polar/resolve.js +6 -14
- package/src/actions/guides/tickValues.js +8 -5
- package/src/actions/index.js +16 -16
- package/src/actions/marks/arc/actions.js +3 -10
- package/src/actions/marks/area/actions.js +8 -5
- package/src/actions/marks/area/materialize.js +8 -9
- package/src/actions/marks/bar/create.js +10 -4
- package/src/actions/marks/bar/edit.js +29 -14
- package/src/actions/marks/bar/materialize.js +15 -7
- package/src/actions/marks/line/actions.js +11 -4
- package/src/actions/marks/line/materialize.js +9 -5
- package/src/actions/marks/point/edit.js +1 -1
- package/src/actions/marks/point/materialize.js +5 -1
- package/src/actions/marks/rect/actions.js +3 -3
- package/src/actions/marks/remove.js +12 -10
- package/src/actions/marks/rule/actions.js +7 -4
- package/src/actions/marks/text/actions.js +17 -5
- package/src/actions/marks/text/layout.js +3 -0
- package/src/actions/primitives/createGraphics.js +3 -2
- package/src/actions/primitives/editGraphics.js +15 -11
- package/src/actions/primitives/graphicProperties.js +1 -6
- package/src/actions/primitives/semanticAction.js +27 -1
- package/src/actions/primitives/semanticValidation/guide.js +11 -1
- package/src/actions/primitives/semanticValidation/layer.js +8 -0
- package/src/actions/regression/create.js +1 -1
- package/src/actions/regression/edit.js +18 -6
- package/src/actions/regression/resolve.js +2 -6
- package/src/actions/scales/channels.js +9 -4
- package/src/actions/scales/consumers/families.js +16 -5
- package/src/actions/scales/create.js +10 -5
- package/src/actions/scales/definitions.js +1 -425
- package/src/actions/scales/edit.js +3 -3
- package/src/actions/scales/editPolicy.js +12 -3
- package/src/actions/scales/materialize.js +1 -1
- package/src/actions/scales/patch.js +1 -1
- package/src/actions/scales/preview.js +21 -1
- package/src/actions/scales/quantitativeColor.js +8 -3
- package/src/actions/selection/actions.js +1 -13
- package/src/actions/theme/reconcile.js +126 -45
- package/src/actions/theme/state.js +12 -0
- package/src/actions/titles/actions.js +5 -18
- package/src/actions/titles/resolve.js +41 -19
- package/src/actions/violinPlots/edit.js +3 -20
- package/src/core/compositionState.js +6 -3
- package/src/core/font.js +9 -2
- package/src/core/graphicProperties.js +1 -0
- package/src/core/optionRequirements.js +1 -0
- package/src/core/programState.js +4 -0
- package/src/core/resourceReferences.js +5 -2
- package/src/core/textMetricProfile.js +3 -2
- package/src/core/textMetrics.js +41 -4
- package/src/core/validation.js +35 -0
- package/src/core/vocabulary.js +7 -0
- package/src/grammar/aggregate.js +4 -18
- package/src/grammar/arcs.js +1 -386
- package/src/grammar/areaPaint.js +10 -0
- package/src/grammar/areaSeries.js +18 -10
- package/src/grammar/axisTextPlacement.js +1 -0
- package/src/grammar/bars/geometry.js +30 -3
- package/src/grammar/bars/policy.js +12 -1
- package/src/grammar/bin.js +2 -12
- package/src/grammar/bin2d.js +1 -6
- package/src/grammar/boxPlot.js +56 -9
- package/src/grammar/categoryOrder.js +1 -6
- package/src/grammar/colorSizeLegend.js +39 -0
- package/src/grammar/complete.js +15 -19
- package/src/grammar/computed.js +115 -26
- package/src/grammar/curveCommands.js +29 -16
- package/src/grammar/datasetSchema.js +13 -9
- package/src/grammar/displayLabels.js +36 -0
- package/src/grammar/ecdf.js +2 -9
- package/src/grammar/facets/dependencies.js +6 -2
- package/src/grammar/facets/guides.js +58 -30
- package/src/grammar/facets/index.js +2 -5
- package/src/grammar/facets/legendIntent.js +65 -0
- package/src/grammar/fold.js +2 -12
- package/src/grammar/gradientProfile.js +1 -6
- package/src/grammar/guideDash.js +1 -0
- package/src/grammar/impute.js +21 -48
- package/src/grammar/interval.js +2 -9
- package/src/grammar/legendBlocks.js +1 -0
- package/src/grammar/legendBorder.js +9 -0
- package/src/grammar/legendClip.js +19 -0
- package/src/grammar/legendCombinations.js +45 -0
- package/src/grammar/legendGradient.js +27 -0
- package/src/grammar/legendGroups.js +1 -0
- package/src/grammar/legendOpacity.js +6 -0
- package/src/grammar/legendTitleStyle.js +22 -0
- package/src/grammar/lineSeries.js +32 -17
- package/src/grammar/markLabels.js +5 -2
- package/src/grammar/normalize.js +4 -54
- package/src/grammar/numeric.js +1 -290
- package/src/grammar/parallelCoordinates.js +1 -6
- package/src/grammar/parseTime.js +41 -0
- package/src/grammar/pathCommands.js +11 -4
- package/src/grammar/pointShapes.js +16 -2
- package/src/grammar/polar.js +1 -184
- package/src/grammar/positionCompatibility.js +3 -3
- package/src/grammar/regression/derive.js +16 -2
- package/src/grammar/regression/models.js +142 -54
- package/src/grammar/regression/parameters.js +23 -4
- package/src/grammar/regression/statistics.js +64 -0
- package/src/grammar/roundedRect.js +42 -54
- package/src/grammar/scales/appearance.js +1 -206
- package/src/grammar/scales/color.js +1 -382
- package/src/grammar/scales/colorConsumers.js +5 -2
- package/src/grammar/scales/definition.js +1 -197
- package/src/grammar/scales/discretized.js +1 -195
- package/src/grammar/scales/size.js +1 -456
- package/src/grammar/scales/temporal.js +2 -13
- package/src/grammar/scales/transformed.js +1 -383
- package/src/grammar/scales/types.js +1 -1
- package/src/grammar/scales/validation.js +1 -66
- package/src/grammar/schemas/concreteGraphic.js +14 -0
- package/src/grammar/schemas/graphic.js +6 -0
- package/src/grammar/schemas/graphicBounds.js +31 -7
- package/src/grammar/schemas/semanticPath.js +19 -3
- package/src/grammar/stack.js +2 -10
- package/src/grammar/statisticalReference.js +1 -6
- package/src/grammar/summary.js +4 -27
- package/src/grammar/text.js +19 -0
- package/src/grammar/timeUnit.js +22 -11
- package/src/grammar/transformKeys.js +47 -0
- package/src/grammar/transformTopology.js +1 -0
- package/src/grammar/transforms.js +15 -2
- package/src/grammar/valueFormat.js +17 -5
- package/src/grammar/weightedStatistics.js +1 -6
- package/src/grammar/window.js +4 -58
- package/src/inspectionDescriptors.js +1 -1
- package/src/layout/canvas.js +1 -110
- package/src/layout/facets.js +1 -244
- package/src/layout/guideCollisions.js +9 -1
- package/src/layout/labels.js +1 -0
- package/src/layout/legend.js +13 -0
- package/src/layout/legendGroup.js +1 -0
- package/src/layout/legendItems.js +59 -15
- package/src/layout/legendLane.js +1 -441
- package/src/layout/legendText.js +1 -0
- package/src/layout/title.js +35 -13
- package/src/materialization/bars/aggregate.js +11 -5
- package/src/materialization/bars/histogram.js +4 -1
- package/src/materialization/bars/ranged.js +19 -6
- package/src/materialization/bars/resolve.js +22 -1
- package/src/materialization/compositionSnapshot.js +2 -7
- package/src/materialization/coordinateBounds.js +21 -0
- package/src/materialization/dependencies.js +4 -44
- package/src/materialization/facetGuides/edit.js +30 -0
- package/src/materialization/facetGuides/layout.js +1 -0
- package/src/materialization/facetGuides/owner.js +125 -0
- package/src/materialization/facetGuides/ownerLayout.js +71 -0
- package/src/materialization/facetGuides/placement.js +71 -14
- package/src/materialization/facetGuides/preparation.js +22 -7
- package/src/materialization/facetHeaders.js +1 -347
- package/src/materialization/facets.js +1 -185
- package/src/materialization/graphicHierarchy.js +5 -1
- package/src/materialization/graphicTranslation.js +73 -0
- package/src/materialization/guides/layout.js +1 -57
- package/src/materialization/guides/resources.js +1 -123
- package/src/materialization/layout.js +53 -0
- package/src/materialization/legendBorder.js +28 -0
- package/src/materialization/legendClip.js +76 -0
- package/src/materialization/legendGroups.js +1 -0
- package/src/materialization/legendText.js +1 -0
- package/src/materialization/legends.js +2 -2
- package/src/materialization/marks/capabilities.js +5 -6
- package/src/materialization/rect.js +1 -1
- package/src/materialization/scaleGuideDependencies.js +14 -15
- package/src/materialization/scales/map.js +6 -0
- package/src/materialization/scales/policies/arc.js +8 -7
- package/src/materialization/scales/policies/bar.js +19 -7
- package/src/materialization/scales/policies/series.js +2 -1
- package/src/materialization/scales/resolve.js +7 -3
- package/src/materialization/selection/items/arc.js +1 -1
- package/src/materialization/selection/items/bar.js +7 -6
- package/src/materialization/selection/items/path.js +7 -6
- package/src/materialization/selection/items/rect.js +2 -2
- package/src/materialization/text.js +13 -4
- package/src/materialization/textLines.js +15 -0
- package/src/materialization/typography.js +10 -2
- package/src/persistence/codec.js +37 -6
- package/src/persistence/validation.js +220 -0
- package/src/persistence.js +19 -6
- package/src/renderers/canvas/circle.js +6 -3
- package/src/renderers/canvas/fill.js +7 -1
- package/src/renderers/canvas/index.js +22 -11
- package/src/renderers/canvas/isolated.js +166 -0
- package/src/renderers/canvas/limits.js +3 -0
- package/src/renderers/canvas/line.js +1 -0
- package/src/renderers/canvas/path.js +1 -1
- package/src/renderers/canvas/rect.js +11 -8
- package/src/renderers/canvas/stroke.js +2 -1
- package/src/renderers/canvas/text.js +5 -3
- package/src/renderers/pdf.js +2 -2
- package/src/renderers/png.js +2 -2
- package/src/renderers/svg.js +14 -4
- package/src/selectors/axes.js +1 -0
- package/src/selectors/graphicCapacity.js +38 -0
- package/src/selectors/layers.js +19 -0
- package/src/theme/defaults.js +8 -2
- package/src/version.js +1 -1
- package/types/basic.d.ts +3 -0
- package/types/index.d.ts +12 -0
- package/types/program.d.ts +536 -129
|
@@ -1,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);
|
|
@@ -1,3 +1,4 @@
|
|
|
1
|
+
import { cartesianAxisOwners } from "../../selectors/axes.js";
|
|
1
2
|
import { resolveHistogramBins } from "../../grammar/histogram.js";
|
|
2
3
|
import {
|
|
3
4
|
isTransformedScaleType,
|
|
@@ -61,12 +62,14 @@ export function valuesFromTickConfig(program, config) {
|
|
|
61
62
|
}
|
|
62
63
|
|
|
63
64
|
export function inferGridTickConfig(program, channel, scaleId) {
|
|
64
|
-
const
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
|
|
65
|
+
const axes = cartesianAxisOwners(program).filter(owner => owner.channel === channel &&
|
|
66
|
+
owner.config?.ticks?.scale === scaleId).map(owner => owner.config.ticks);
|
|
67
|
+
const policies = axes.map(axis => axis.mode === "values"
|
|
68
|
+
? { mode: "values", values: axis.values } : { mode: "count", count: axis.count });
|
|
69
|
+
if (new Set(policies.map(policy => JSON.stringify(policy))).size > 1) {
|
|
70
|
+
throw new Error("Grid values require explicit count or values when bound axis tick policies differ.");
|
|
69
71
|
}
|
|
72
|
+
if (policies.length > 0) return policies[0];
|
|
70
73
|
|
|
71
74
|
const boundaries = inferHistogramBoundaries(program, channel, scaleId);
|
|
72
75
|
const scale = program.resolvedScales[scaleId];
|
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,
|
|
@@ -1,3 +1,5 @@
|
|
|
1
|
+
import { validateFillPaint } from "../../../grammar/paint.js";
|
|
2
|
+
import { validateAreaPaintConfig } from "../../../grammar/areaPaint.js";
|
|
1
3
|
import { validateAreaMissing } from "../../../grammar/areaEndpoints.js";
|
|
2
4
|
import { action } from "../../../core/action.js";
|
|
3
5
|
import { validateUserId } from "../../../core/identifiers.js";
|
|
@@ -81,7 +83,7 @@ const createAreaMark = /* @__PURE__ */ action(
|
|
|
81
83
|
if (missing === "break" && ["density", "horizon"].some(type => findUpstreamTransform(this, findDataset(this, data), type))) {
|
|
82
84
|
throw new Error("Area missing:break does not reinterpret density or horizon data.");
|
|
83
85
|
}
|
|
84
|
-
const fill =
|
|
86
|
+
const fill = validateFillPaint(args.fill ?? DEFAULT_COLORS.mark, "Area fill");
|
|
85
87
|
const opacity = validateUnitInterval(args.opacity ?? 0.2, "Area opacity");
|
|
86
88
|
const curve = validateCurveInterpolation(args.curve ?? "linear");
|
|
87
89
|
const { stroke, strokeWidth } = validateAreaCreateOutline(args);
|
|
@@ -127,14 +129,14 @@ const configureAreaStrokeFromFill = /* @__PURE__ */ action(
|
|
|
127
129
|
}
|
|
128
130
|
const { stroke: _stroke, ...config } = this.markConfigs[id] ?? {};
|
|
129
131
|
void _stroke;
|
|
130
|
-
return this._withMarkConfig(id, {
|
|
132
|
+
return this._withMarkConfig(id, validateAreaPaintConfig({
|
|
131
133
|
...config,
|
|
132
134
|
strokeFromFill: true,
|
|
133
135
|
strokeWidth: validateNonNegativeFinite(
|
|
134
136
|
args.strokeWidth ?? 1,
|
|
135
137
|
"Area strokeWidth"
|
|
136
138
|
)
|
|
137
|
-
});
|
|
139
|
+
}));
|
|
138
140
|
}
|
|
139
141
|
);
|
|
140
142
|
|
|
@@ -199,7 +201,7 @@ const rematerializeAreaMark = /* @__PURE__ */ action(
|
|
|
199
201
|
if (args.scales !== false && strokeEncoding?.scale !== undefined) {
|
|
200
202
|
resolved = resolved.rematerializeScale({ id: strokeEncoding.scale });
|
|
201
203
|
}
|
|
202
|
-
const config = this.markConfigs[id];
|
|
204
|
+
const config = validateAreaPaintConfig(this.markConfigs[id]);
|
|
203
205
|
const { paths, fills, strokes } = resolveAreaMaterialization({
|
|
204
206
|
rows: dataset.values,
|
|
205
207
|
layer,
|
|
@@ -273,7 +275,7 @@ const editAreaMark = /* @__PURE__ */ action(
|
|
|
273
275
|
let config = { ...this.markConfigs[layer.id] };
|
|
274
276
|
Object.assign(config, strokeDetails);
|
|
275
277
|
if (Object.hasOwn(args, "fill")) {
|
|
276
|
-
config.fill =
|
|
278
|
+
config.fill = validateFillPaint(args.fill, "Area fill");
|
|
277
279
|
if (config.errorBand !== undefined) config.errorBand = { ...config.errorBand, fill: config.fill };
|
|
278
280
|
}
|
|
279
281
|
if (Object.hasOwn(args, "opacity")) {
|
|
@@ -314,6 +316,7 @@ const editAreaMark = /* @__PURE__ */ action(
|
|
|
314
316
|
);
|
|
315
317
|
}
|
|
316
318
|
|
|
319
|
+
validateAreaPaintConfig(config);
|
|
317
320
|
let next = this._withMarkConfig(layer.id, config);
|
|
318
321
|
if (Object.hasOwn(args, "missing")) {
|
|
319
322
|
const missing = validateAreaMissing(args.missing);
|
|
@@ -6,6 +6,7 @@ import {
|
|
|
6
6
|
} from "../../../grammar/areaSeries.js";
|
|
7
7
|
import {
|
|
8
8
|
mapContinuousScaleValues,
|
|
9
|
+
mapOrdinalPositionValues,
|
|
9
10
|
mapOrdinalValues
|
|
10
11
|
} from "../../../grammar/scales/index.js";
|
|
11
12
|
import { mapScaleConsumerValues } from
|
|
@@ -37,9 +38,8 @@ function resolveAreaPaths({
|
|
|
37
38
|
}
|
|
38
39
|
return derived.series.map(series => {
|
|
39
40
|
if (densityTransform === undefined && derived.orientation === "horizontal") {
|
|
40
|
-
const y = mapContinuousScaleValues(
|
|
41
|
-
series.values.map(value => value.y),
|
|
42
|
-
yScale
|
|
41
|
+
const y = (["point", "band"].includes(yScale.type) ? mapOrdinalPositionValues : mapContinuousScaleValues)(
|
|
42
|
+
series.values.map(value => value.y), yScale
|
|
43
43
|
);
|
|
44
44
|
const lower = mapContinuousScaleValues(
|
|
45
45
|
series.values.map(value => value.x),
|
|
@@ -57,9 +57,8 @@ function resolveAreaPaths({
|
|
|
57
57
|
);
|
|
58
58
|
}
|
|
59
59
|
if (densityTransform !== undefined && derived.mode === "x-density") {
|
|
60
|
-
const y = mapContinuousScaleValues(
|
|
61
|
-
series.values.map(value => value.y),
|
|
62
|
-
yScale
|
|
60
|
+
const y = (["point", "band"].includes(yScale.type) ? mapOrdinalPositionValues : mapContinuousScaleValues)(
|
|
61
|
+
series.values.map(value => value.y), yScale
|
|
63
62
|
);
|
|
64
63
|
const upper = mapContinuousScaleValues(
|
|
65
64
|
series.values.map(value => value.x),
|
|
@@ -80,7 +79,7 @@ function resolveAreaPaths({
|
|
|
80
79
|
{ independentAxis: "y" }
|
|
81
80
|
);
|
|
82
81
|
}
|
|
83
|
-
const x = mapContinuousScaleValues(
|
|
82
|
+
const x = (["point", "band"].includes(xScale.type) ? mapOrdinalPositionValues : mapContinuousScaleValues)(
|
|
84
83
|
series.values.map(value => value.x),
|
|
85
84
|
xScale
|
|
86
85
|
);
|
|
@@ -134,8 +133,8 @@ export function resolveAreaMaterialization({
|
|
|
134
133
|
layer.encoding?.y?.stack === "center";
|
|
135
134
|
const rawDerived = densityTransform === undefined
|
|
136
135
|
? centered
|
|
137
|
-
? deriveCenteredAreaSeries(rows, layer)
|
|
138
|
-
: deriveAreaSeries(rows, layer)
|
|
136
|
+
? deriveCenteredAreaSeries(rows, layer, { xDomain: xScale.domain })
|
|
137
|
+
: deriveAreaSeries(rows, layer, { xDomain: xScale.domain, yDomain: yScale.domain })
|
|
139
138
|
: deriveDensityAreaSeries(rows, layer, densityTransform);
|
|
140
139
|
const colorEncoding = layer.encoding?.color;
|
|
141
140
|
const layout = layer.layout?.mode ?? colorEncoding?.layout ?? "overlay";
|
|
@@ -10,15 +10,15 @@ import {
|
|
|
10
10
|
} from "../shared.js";
|
|
11
11
|
import { resolveMarkGraphicPlacement } from
|
|
12
12
|
"../../../materialization/graphicHierarchy.js";
|
|
13
|
-
import { requestedRectStyleDetails } from
|
|
13
|
+
import { requestedRectStyleDetails, RECT_RADIUS_PROPERTIES } from
|
|
14
14
|
"../../../grammar/roundedRect.js";
|
|
15
15
|
import { STROKE_STYLE_PROPERTIES } from
|
|
16
16
|
"../../../grammar/strokeStyle.js";
|
|
17
17
|
import { validateItemMissing } from "../../../grammar/itemMissing.js";
|
|
18
18
|
|
|
19
19
|
const CREATE_OPTIONS = Object.freeze([
|
|
20
|
-
"id", "data", "missing", "fill", "opacity", "stroke", "strokeWidth",
|
|
21
|
-
|
|
20
|
+
"id", "data", "orientation", "missing", "fill", "opacity", "stroke", "strokeWidth",
|
|
21
|
+
...RECT_RADIUS_PROPERTIES, ...STROKE_STYLE_PROPERTIES
|
|
22
22
|
]);
|
|
23
23
|
|
|
24
24
|
export const createBarMark = /* @__PURE__ */ action(
|
|
@@ -29,6 +29,9 @@ export const createBarMark = /* @__PURE__ */ action(
|
|
|
29
29
|
function (args = {}) {
|
|
30
30
|
validateMarkOptions(args, CREATE_OPTIONS, "createBarMark");
|
|
31
31
|
requestedRectStyleDetails(args, "createBarMark");
|
|
32
|
+
if (args.orientation !== undefined && !["vertical", "horizontal"].includes(args.orientation)) {
|
|
33
|
+
throw new Error("Bar orientation must be vertical or horizontal.");
|
|
34
|
+
}
|
|
32
35
|
const id = resolveMarkId(this, args.id, {
|
|
33
36
|
defaultId: "bar",
|
|
34
37
|
label: "Bar mark id",
|
|
@@ -59,6 +62,9 @@ export const createBarMark = /* @__PURE__ */ action(
|
|
|
59
62
|
value: validateItemMissing(args.missing, "Bar missing")
|
|
60
63
|
});
|
|
61
64
|
}
|
|
65
|
+
if (args.orientation !== undefined) {
|
|
66
|
+
created = created.editSemantic({ property: `layer[${id}].mark.orientation`, value: args.orientation });
|
|
67
|
+
}
|
|
62
68
|
created = applyLayeredMarkInheritance(created, id, inherited);
|
|
63
69
|
created = created
|
|
64
70
|
.createGraphics({
|
|
@@ -70,7 +76,7 @@ export const createBarMark = /* @__PURE__ */ action(
|
|
|
70
76
|
created = materializeInheritedMark(created, id);
|
|
71
77
|
const appearance = Object.fromEntries(
|
|
72
78
|
[
|
|
73
|
-
"fill", "opacity", "stroke", "strokeWidth",
|
|
79
|
+
"fill", "opacity", "stroke", "strokeWidth", ...RECT_RADIUS_PROPERTIES,
|
|
74
80
|
...STROKE_STYLE_PROPERTIES
|
|
75
81
|
]
|
|
76
82
|
.filter(property => Object.hasOwn(args, property))
|
|
@@ -9,28 +9,29 @@ import { canMaterializeBar } from "../../../materialization/marks/index.js";
|
|
|
9
9
|
import { DEFAULT_BAR_STROKE_WIDTH } from "../../../materialization/bars/resolve.js";
|
|
10
10
|
import { resolveEligibleLayer } from "../../../selectors/layers.js";
|
|
11
11
|
import { validateMarkOptions } from "../shared.js";
|
|
12
|
-
import { requestedRectStyleDetails } from
|
|
12
|
+
import { requestedRectStyleDetails, RECT_RADIUS_PROPERTIES } from
|
|
13
13
|
"../../../grammar/roundedRect.js";
|
|
14
14
|
import { STROKE_STYLE_PROPERTIES } from
|
|
15
15
|
"../../../grammar/strokeStyle.js";
|
|
16
16
|
import { rematerializeExistingLegend } from "../../encodings/shared.js";
|
|
17
|
+
import { validateFillPaint } from "../../../grammar/paint.js";
|
|
17
18
|
import { validateItemMissing } from "../../../grammar/itemMissing.js";
|
|
18
19
|
|
|
19
20
|
const EDIT_OPTIONS = Object.freeze([
|
|
20
|
-
"target", "missing", "fill", "opacity", "stroke", "strokeWidth",
|
|
21
|
+
"target", "missing", "blend", "fill", "opacity", "stroke", "strokeWidth", ...RECT_RADIUS_PROPERTIES,
|
|
21
22
|
...STROKE_STYLE_PROPERTIES
|
|
22
23
|
]);
|
|
23
24
|
|
|
24
25
|
export const editBarMark = /* @__PURE__ */ action(
|
|
25
26
|
{
|
|
26
27
|
op: "editBarMark",
|
|
27
|
-
description: "Edit whole-bar fill, opacity, and
|
|
28
|
+
description: "Edit whole-bar fill, opacity, outline, and compositing appearance."
|
|
28
29
|
},
|
|
29
30
|
function (args = {}) {
|
|
30
31
|
validateMarkOptions(args, EDIT_OPTIONS, "editBarMark");
|
|
31
32
|
const styleDetails = requestedRectStyleDetails(args, "editBarMark");
|
|
32
33
|
const changes = [
|
|
33
|
-
"missing", "fill", "opacity", "stroke", "strokeWidth",
|
|
34
|
+
"missing", "blend", "fill", "opacity", "stroke", "strokeWidth", ...RECT_RADIUS_PROPERTIES,
|
|
34
35
|
...STROKE_STYLE_PROPERTIES
|
|
35
36
|
];
|
|
36
37
|
if (!changes.some(key => Object.hasOwn(args, key))) {
|
|
@@ -56,23 +57,25 @@ export const editBarMark = /* @__PURE__ */ action(
|
|
|
56
57
|
"editBarMark stroke conflicts with a field encoding; use encodeStroke with value to replace it."
|
|
57
58
|
);
|
|
58
59
|
}
|
|
60
|
+
if (Object.hasOwn(args, "opacity") && layer.encoding?.opacity !== undefined) {
|
|
61
|
+
throw new Error("editBarMark opacity conflicts with a field encoding; use encodeOpacity with value to replace it.");
|
|
62
|
+
}
|
|
59
63
|
if (args.stroke === false && Object.hasOwn(args, "strokeWidth")) {
|
|
60
64
|
throw new Error(
|
|
61
65
|
"editBarMark cannot set strokeWidth while removing stroke."
|
|
62
66
|
);
|
|
63
67
|
}
|
|
64
68
|
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
|
|
69
|
-
|
|
70
|
-
|
|
71
|
-
const config = { ...semantic.markConfigs[layer.id] };
|
|
69
|
+
if (Object.hasOwn(args, "blend") && !["normal", "difference"].includes(args.blend)) {
|
|
70
|
+
throw new Error("Bar blend must be normal or difference.");
|
|
71
|
+
}
|
|
72
|
+
const missing = Object.hasOwn(args, "missing")
|
|
73
|
+
? validateItemMissing(args.missing, "Bar missing") : undefined;
|
|
74
|
+
const config = { ...this.markConfigs[layer.id] };
|
|
72
75
|
const appearance = { ...config.barAppearance };
|
|
73
76
|
Object.assign(appearance, styleDetails);
|
|
74
77
|
if (Object.hasOwn(args, "fill")) {
|
|
75
|
-
appearance.fill =
|
|
78
|
+
appearance.fill = validateFillPaint(args.fill, "Bar fill");
|
|
76
79
|
}
|
|
77
80
|
if (Object.hasOwn(args, "opacity")) {
|
|
78
81
|
appearance.opacity = validateUnitInterval(args.opacity, "Bar opacity");
|
|
@@ -102,10 +105,22 @@ export const editBarMark = /* @__PURE__ */ action(
|
|
|
102
105
|
);
|
|
103
106
|
}
|
|
104
107
|
|
|
105
|
-
|
|
108
|
+
let semantic = missing === undefined ? this : this.editSemantic({
|
|
109
|
+
property: `layer[${layer.id}].mark.missing`, value: missing
|
|
110
|
+
});
|
|
111
|
+
if (Object.hasOwn(args, "blend")) {
|
|
112
|
+
if (args.blend === "difference") {
|
|
113
|
+
semantic = semantic.editSemantic({property: `layer[${layer.id}].mark.blend`, value: "difference"});
|
|
114
|
+
} else if (layer.mark.blend !== undefined) {
|
|
115
|
+
semantic = semantic.editSemantic({property: `layer[${layer.id}].mark.blend`, remove: true});
|
|
116
|
+
}
|
|
117
|
+
}
|
|
118
|
+
const editsAppearance = changes.some(key => key !== "missing" && key !== "blend" &&
|
|
119
|
+
Object.hasOwn(args, key));
|
|
120
|
+
const next = editsAppearance ? semantic._withMarkConfig(layer.id, {
|
|
106
121
|
...config,
|
|
107
122
|
barAppearance: appearance
|
|
108
|
-
});
|
|
123
|
+
}) : semantic;
|
|
109
124
|
const materialized = canMaterializeBar(next, layer)
|
|
110
125
|
? next.rematerializeBarMark({ id: layer.id })
|
|
111
126
|
: next;
|
|
@@ -1,3 +1,4 @@
|
|
|
1
|
+
import { findLayer } from "../../../selectors/layers.js";
|
|
1
2
|
import { editGraphicProperties } from "../../primitives/graphicProperties.js";
|
|
2
3
|
import { action } from "../../../core/action.js";
|
|
3
4
|
import { validateUserId } from "../../../core/identifiers.js";
|
|
@@ -13,19 +14,21 @@ import {
|
|
|
13
14
|
import { rematerializeHighlightBaseline } from "../lifecycle.js";
|
|
14
15
|
import { offsetCategoryRectangles } from
|
|
15
16
|
"../../../materialization/categorySlotOffset.js";
|
|
16
|
-
import { materializeRectItem } from "../../../grammar/roundedRect.js";
|
|
17
|
-
import { STROKE_STYLE_PROPERTIES } from
|
|
18
|
-
"../../../grammar/strokeStyle.js";
|
|
17
|
+
import { materializeRectItem, RECT_STYLE_PROPERTIES } from "../../../grammar/roundedRect.js";
|
|
19
18
|
import { replaceGraphicItems } from "../../primitives/editGraphics.js";
|
|
20
19
|
|
|
21
20
|
const REMATERIALIZE_OPTIONS = Object.freeze(["id", "scales"]);
|
|
22
21
|
|
|
23
22
|
function editRectangles(program, id, rectangles) {
|
|
24
23
|
const appearance = program.markConfigs[id]?.barAppearance ?? {};
|
|
25
|
-
const
|
|
24
|
+
const blend = findLayer(program, id)?.mark?.blend;
|
|
25
|
+
if (blend !== undefined) rectangles = rectangles.map(rect => ({...rect, blend}));
|
|
26
|
+
const hasShapeStyle = RECT_STYLE_PROPERTIES
|
|
26
27
|
.some(property => Object.hasOwn(appearance, property));
|
|
27
|
-
|
|
28
|
-
|
|
28
|
+
const previousBlend = program.graphicSpec.objects[id]?.items?.some(item =>
|
|
29
|
+
item.properties?.blend !== undefined);
|
|
30
|
+
if (hasShapeStyle || blend !== undefined || previousBlend) {
|
|
31
|
+
const radius = appearance;
|
|
29
32
|
return replaceGraphicItems(
|
|
30
33
|
program,
|
|
31
34
|
id,
|
|
@@ -92,6 +95,11 @@ export const rematerializeBarMark = /* @__PURE__ */ action(
|
|
|
92
95
|
resolved = resolved.rematerializeScale({ id: strokeScaleId });
|
|
93
96
|
}
|
|
94
97
|
|
|
98
|
+
const opacityScaleId = required.layer.encoding?.opacity?.scale;
|
|
99
|
+
if (opacityScaleId !== undefined && args.scales !== false) {
|
|
100
|
+
resolved = resolved.rematerializeScale({ id: opacityScaleId });
|
|
101
|
+
}
|
|
102
|
+
|
|
95
103
|
if (required.materialization === "aggregate") {
|
|
96
104
|
const offsetChannel = resolveBarOffsetChannel(required.layer);
|
|
97
105
|
const offsetScaleId = required.layer.encoding?.[offsetChannel]?.scale;
|
|
@@ -104,7 +112,7 @@ export const rematerializeBarMark = /* @__PURE__ */ action(
|
|
|
104
112
|
));
|
|
105
113
|
}
|
|
106
114
|
|
|
107
|
-
if (
|
|
115
|
+
if ([BAR_GRAINS.ranged, BAR_GRAINS.centered].includes(required.materialization)) {
|
|
108
116
|
const width = resolved.markConfigs[id]?.barWidth;
|
|
109
117
|
return editRectangles(resolved, id, offsetCategoryRectangles(
|
|
110
118
|
resolved, required.layer, deriveRangedRectangles(required, resolved, width)
|
|
@@ -18,7 +18,7 @@ import {
|
|
|
18
18
|
import { DEFAULT_COLORS } from "../../../theme/defaults.js";
|
|
19
19
|
import { findDataset } from "../../../selectors/datasets.js";
|
|
20
20
|
import { findLayer, resolveEligibleLayer } from "../../../selectors/layers.js";
|
|
21
|
-
import { validateCurveInterpolation } from "../../../grammar/curveCommands.js";
|
|
21
|
+
import { validateCurveInterpolation, validateCardinalTension } from "../../../grammar/curveCommands.js";
|
|
22
22
|
import {
|
|
23
23
|
resolveCoordinateBounds,
|
|
24
24
|
resolveCoordinatePolarFrame
|
|
@@ -43,11 +43,11 @@ import {
|
|
|
43
43
|
const DEFAULT_LINE_STROKE = DEFAULT_COLORS.mark;
|
|
44
44
|
const DEFAULT_LINE_WIDTH = 2;
|
|
45
45
|
const CREATE_OPTIONS = Object.freeze([
|
|
46
|
-
"id", "data", "stroke", "strokeWidth", "opacity", "curve", "closed",
|
|
46
|
+
"id", "data", "stroke", "strokeWidth", "opacity", "curve", "tension", "closed",
|
|
47
47
|
...STROKE_STYLE_PROPERTIES
|
|
48
48
|
]);
|
|
49
49
|
const EDIT_OPTIONS = Object.freeze([
|
|
50
|
-
"target", "stroke", "strokeWidth", "opacity", "curve", "closed",
|
|
50
|
+
"target", "stroke", "strokeWidth", "opacity", "curve", "tension", "closed",
|
|
51
51
|
...STROKE_STYLE_PROPERTIES
|
|
52
52
|
]);
|
|
53
53
|
const REMATERIALIZE_OPTIONS = Object.freeze(["id", "scales"]);
|
|
@@ -118,6 +118,7 @@ const createLineMark = /* @__PURE__ */ action(
|
|
|
118
118
|
"Line strokeWidth"
|
|
119
119
|
);
|
|
120
120
|
const curve = validateCurveInterpolation(args.curve ?? "linear");
|
|
121
|
+
validateCardinalTension(args.tension, curve);
|
|
121
122
|
const closed = Object.hasOwn(args, "closed")
|
|
122
123
|
? validateClosed(args.closed)
|
|
123
124
|
: false;
|
|
@@ -151,6 +152,7 @@ const createLineMark = /* @__PURE__ */ action(
|
|
|
151
152
|
{
|
|
152
153
|
...(Object.hasOwn(args, "strokeWidth") ? { strokeWidth } : {}),
|
|
153
154
|
...(Object.hasOwn(args, "curve") ? { curve } : {}),
|
|
155
|
+
...(args.tension === undefined ? {} : { tension: args.tension }),
|
|
154
156
|
...(Object.hasOwn(args, "closed") ? { closed } : {}),
|
|
155
157
|
...strokeDetails
|
|
156
158
|
}
|
|
@@ -277,7 +279,7 @@ const editLineMark = /* @__PURE__ */ action(
|
|
|
277
279
|
validateMarkOptions(args, EDIT_OPTIONS, "editLineMark");
|
|
278
280
|
const strokeDetails = requestedStrokeDetails(args, "editLineMark");
|
|
279
281
|
if (!EDIT_OPTIONS.slice(1).some(key => Object.hasOwn(args, key))) {
|
|
280
|
-
throw new Error("editLineMark requires stroke, strokeWidth, opacity, curve, or closed.");
|
|
282
|
+
throw new Error("editLineMark requires stroke, strokeWidth, opacity, curve, tension, or closed.");
|
|
281
283
|
}
|
|
282
284
|
const target = Object.hasOwn(args, "target")
|
|
283
285
|
? validateUserId(args.target, "Line mark id")
|
|
@@ -315,6 +317,11 @@ const editLineMark = /* @__PURE__ */ action(
|
|
|
315
317
|
})) {
|
|
316
318
|
if (Object.hasOwn(args, key)) config[key] = validate(args[key], `Line ${key}`);
|
|
317
319
|
}
|
|
320
|
+
if (args.curve !== undefined && args.curve !== "cardinal" && args.tension === undefined) {
|
|
321
|
+
delete config.tension;
|
|
322
|
+
}
|
|
323
|
+
if (Object.hasOwn(args, "tension")) config.tension = args.tension;
|
|
324
|
+
validateCardinalTension(config.tension, config.curve ?? "linear");
|
|
318
325
|
validatePolarLineConfig(layer, config);
|
|
319
326
|
const next = this._withMarkConfig(layer.id, config);
|
|
320
327
|
const materialized = canMaterializeLine(next, layer)
|
|
@@ -3,6 +3,7 @@ import {
|
|
|
3
3
|
} from "../../../grammar/lineSeries.js";
|
|
4
4
|
import {
|
|
5
5
|
mapContinuousScaleValues,
|
|
6
|
+
mapOrdinalPositionValues,
|
|
6
7
|
normalizeStrokeDashPattern
|
|
7
8
|
} from "../../../grammar/scales/index.js";
|
|
8
9
|
import { buildCurvePathCommands } from
|
|
@@ -97,9 +98,7 @@ export function resolvePositionedLineMaterialization({
|
|
|
97
98
|
const radiusScaleId = layer.encoding?.radius?.scale;
|
|
98
99
|
const lineOptions = polar
|
|
99
100
|
? { thetaDomain: resolvedScales[thetaScaleId].domain }
|
|
100
|
-
:
|
|
101
|
-
? undefined
|
|
102
|
-
: { xBinBoundaries };
|
|
101
|
+
: { xBinBoundaries, xDomain: resolvedScales[xScaleId].domain };
|
|
103
102
|
const derived = deriveLineSeries(rows, layer, lineOptions);
|
|
104
103
|
const commands = polar
|
|
105
104
|
? derived.series.map(series => buildPolarLinePathCommands({
|
|
@@ -111,7 +110,9 @@ export function resolvePositionedLineMaterialization({
|
|
|
111
110
|
closed: config.closed ?? false
|
|
112
111
|
}))
|
|
113
112
|
: derived.series.map(series => {
|
|
114
|
-
const
|
|
113
|
+
const mapX = ["nominal", "ordinal"].includes(layer.encoding.x.fieldType)
|
|
114
|
+
? mapOrdinalPositionValues : mapContinuousScaleValues;
|
|
115
|
+
const x = mapX(
|
|
115
116
|
series.values.map(value => value.x),
|
|
116
117
|
resolvedScales[xScaleId]
|
|
117
118
|
);
|
|
@@ -119,9 +120,12 @@ export function resolvePositionedLineMaterialization({
|
|
|
119
120
|
series.values.map(value => value.y),
|
|
120
121
|
resolvedScales[yScaleId]
|
|
121
122
|
);
|
|
123
|
+
// A raw singleton retains its data position and series identity, but
|
|
124
|
+
// contributes no segment. Do not fabricate another observation.
|
|
125
|
+
if (series.values.length === 1) return [{ op: "M", x: x[0], y: y[0] }];
|
|
122
126
|
return buildCurvePathCommands(
|
|
123
127
|
series.values.map((_, index) => ({ x: x[index], y: y[index] })),
|
|
124
|
-
config.curve ?? "linear"
|
|
128
|
+
config.curve ?? "linear", config.tension
|
|
125
129
|
);
|
|
126
130
|
});
|
|
127
131
|
const appearance = appearanceMapper(layer, resolvedScales,
|
|
@@ -96,7 +96,7 @@ export const editPointMark = /* @__PURE__ */ action(
|
|
|
96
96
|
}
|
|
97
97
|
}
|
|
98
98
|
if (Object.hasOwn(args, "strokeWidth")) {
|
|
99
|
-
if (typeof config.stroke !== "string") {
|
|
99
|
+
if (typeof config.stroke !== "string" && layer.encoding?.stroke?.field === undefined) {
|
|
100
100
|
throw new Error("Point strokeWidth requires an active stroke.");
|
|
101
101
|
}
|
|
102
102
|
config.strokeWidth = validateNonNegativeFinite(
|
|
@@ -1,3 +1,4 @@
|
|
|
1
|
+
import { validateGraphicItemLimit } from "../../../core/validation.js";
|
|
1
2
|
import { editGraphicProperties } from "../../primitives/graphicProperties.js";
|
|
2
3
|
import { action } from "../../../core/action.js";
|
|
3
4
|
import { validateUserId } from "../../../core/identifiers.js";
|
|
@@ -29,6 +30,8 @@ import {
|
|
|
29
30
|
} from "../../../theme/defaults.js";
|
|
30
31
|
import { findDataset } from "../../../selectors/datasets.js";
|
|
31
32
|
import { findLayer } from "../../../selectors/layers.js";
|
|
33
|
+
import { resolveGraphicItemCapacity } from "../../../selectors/graphicCapacity.js";
|
|
34
|
+
import { getMarkGraphicTypes } from "../../../core/vocabulary.js";
|
|
32
35
|
import { canMaterializePoint } from "../../../materialization/marks/capabilities.js";
|
|
33
36
|
import { rematerializeHighlightBaseline } from "../lifecycle.js";
|
|
34
37
|
import {
|
|
@@ -335,13 +338,14 @@ export const rematerializePointMark = /* @__PURE__ */ action(
|
|
|
335
338
|
if (layer?.mark?.type !== "point") {
|
|
336
339
|
throw new Error(`Unknown point mark "${id}".`);
|
|
337
340
|
}
|
|
338
|
-
if (!
|
|
341
|
+
if (!getMarkGraphicTypes("point").includes(graphic?.type)) {
|
|
339
342
|
throw new Error(`Point mark "${id}" requires point graphics.`);
|
|
340
343
|
}
|
|
341
344
|
const sourceDataset = findDataset(resolved, layer.data);
|
|
342
345
|
if (sourceDataset === undefined) {
|
|
343
346
|
throw new Error(`Point mark "${id}" requires an existing dataset.`);
|
|
344
347
|
}
|
|
348
|
+
validateGraphicItemLimit(sourceDataset.values.length, resolveGraphicItemCapacity(resolved, { id, label: "Point mark item count" }));
|
|
345
349
|
const dataset = applyItemMissingPolicy(layer, sourceDataset);
|
|
346
350
|
|
|
347
351
|
if (graphic.items.length === 0 && !canMaterializePoint(resolved, layer)) {
|
|
@@ -25,7 +25,7 @@ import { resolveMarkGraphicPlacement } from
|
|
|
25
25
|
import { rematerializeExistingLegend } from "../../encodings/shared.js";
|
|
26
26
|
import { rematerializeHighlightBaseline } from "../lifecycle.js";
|
|
27
27
|
import {
|
|
28
|
-
requestedRectStyleDetails
|
|
28
|
+
requestedRectStyleDetails, hasRectRadius, RECT_RADIUS_PROPERTIES
|
|
29
29
|
} from "../../../grammar/roundedRect.js";
|
|
30
30
|
import { STROKE_STYLE_PROPERTIES } from
|
|
31
31
|
"../../../grammar/strokeStyle.js";
|
|
@@ -33,7 +33,7 @@ import { applyItemMissingPolicy, validateItemMissing } from
|
|
|
33
33
|
"../../../grammar/itemMissing.js";
|
|
34
34
|
|
|
35
35
|
const STYLE_OPTIONS = Object.freeze([
|
|
36
|
-
"fill", "opacity", "stroke", "strokeWidth",
|
|
36
|
+
"fill", "opacity", "stroke", "strokeWidth", ...RECT_RADIUS_PROPERTIES,
|
|
37
37
|
...STROKE_STYLE_PROPERTIES
|
|
38
38
|
]);
|
|
39
39
|
const CREATE_OPTIONS = Object.freeze(["id", "data", "missing", ...STYLE_OPTIONS]);
|
|
@@ -117,7 +117,7 @@ const rematerializeRectMark = /* @__PURE__ */ action(
|
|
|
117
117
|
const graphic = this.graphicSpec.objects[id];
|
|
118
118
|
if (layer?.mark?.type !== "rect") throw new Error(`Unknown rect mark "${id}".`);
|
|
119
119
|
const roundedCollection = graphic?.type === "collection" &&
|
|
120
|
-
|
|
120
|
+
hasRectRadius(this.markConfigs[id]) &&
|
|
121
121
|
graphic.items?.every(item => ["rect", "path"].includes(item.type));
|
|
122
122
|
if (
|
|
123
123
|
(graphic?.type !== "rect" && !roundedCollection) ||
|