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
|
@@ -5,17 +5,17 @@ import {
|
|
|
5
5
|
import { derivedCreator, derivedMaterializer } from "./shared.js";
|
|
6
6
|
|
|
7
7
|
const OPTIONS = Object.freeze([
|
|
8
|
-
"id", "source", "partitionBy", "sortBy", "operations"
|
|
8
|
+
"id", "source", "partitionBy", "sortBy", "operations", "temporalUnit"
|
|
9
9
|
]);
|
|
10
10
|
|
|
11
|
-
export const materializeWindowData = derivedMaterializer(
|
|
11
|
+
export const materializeWindowData = /* @__PURE__ */ derivedMaterializer(
|
|
12
12
|
"materializeWindowData",
|
|
13
13
|
"Materialize one immutable window-derived dataset.",
|
|
14
14
|
"window",
|
|
15
15
|
deriveWindowRows
|
|
16
16
|
);
|
|
17
17
|
|
|
18
|
-
export const createWindowData = derivedCreator(
|
|
18
|
+
export const createWindowData = /* @__PURE__ */ derivedCreator(
|
|
19
19
|
"createWindowData",
|
|
20
20
|
"Create immutable partitioned window values.",
|
|
21
21
|
OPTIONS,
|
|
@@ -14,7 +14,7 @@ function rematerialize(program, layer, target) {
|
|
|
14
14
|
: program.rematerializePointMark({ id: target });
|
|
15
15
|
}
|
|
16
16
|
|
|
17
|
-
export const encodeAngle = action(
|
|
17
|
+
export const encodeAngle = /* @__PURE__ */ action(
|
|
18
18
|
{
|
|
19
19
|
op: "encodeAngle",
|
|
20
20
|
description: "Assign direct clockwise degree rotation to point or Tick glyphs."
|
|
@@ -79,7 +79,7 @@ function encodeAppearanceField(program, channel, args, operation) {
|
|
|
79
79
|
return rematerializeEncoding(next, target, channel, scale.id, layer);
|
|
80
80
|
}
|
|
81
81
|
|
|
82
|
-
const encodeRadius = action(
|
|
82
|
+
const encodeRadius = /* @__PURE__ */ action(
|
|
83
83
|
{
|
|
84
84
|
op: "encodeRadius",
|
|
85
85
|
description: "Set a constant graphical radius on a point mark."
|
|
@@ -112,7 +112,7 @@ const encodeRadius = action(
|
|
|
112
112
|
}
|
|
113
113
|
);
|
|
114
114
|
|
|
115
|
-
const encodePointRadius = action(
|
|
115
|
+
const encodePointRadius = /* @__PURE__ */ action(
|
|
116
116
|
{
|
|
117
117
|
op: "encodePointRadius",
|
|
118
118
|
description: "Set a constant graphical radius on a point mark."
|
|
@@ -146,7 +146,7 @@ const removePointRadius = /* @__PURE__ */ action(
|
|
|
146
146
|
}
|
|
147
147
|
);
|
|
148
148
|
|
|
149
|
-
const encodeSize = action(
|
|
149
|
+
const encodeSize = /* @__PURE__ */ action(
|
|
150
150
|
{
|
|
151
151
|
op: "encodeSize",
|
|
152
152
|
description: "Encode a quantitative field as equal-area point size."
|
|
@@ -156,7 +156,7 @@ const encodeSize = action(
|
|
|
156
156
|
}
|
|
157
157
|
);
|
|
158
158
|
|
|
159
|
-
const encodeShape = action(
|
|
159
|
+
const encodeShape = /* @__PURE__ */ action(
|
|
160
160
|
{
|
|
161
161
|
op: "encodeShape",
|
|
162
162
|
description: "Encode a nominal field as point shape."
|
|
@@ -10,7 +10,7 @@ import { normalizeBarWidth } from "../../grammar/bars/geometry.js";
|
|
|
10
10
|
|
|
11
11
|
const OPTIONS = Object.freeze(["band", "pixels", "target"]);
|
|
12
12
|
|
|
13
|
-
const encodeBarWidth = action(
|
|
13
|
+
const encodeBarWidth = /* @__PURE__ */ action(
|
|
14
14
|
{
|
|
15
15
|
op: "encodeBarWidth",
|
|
16
16
|
description: "Override aggregate or ranged bar width within its category slot."
|
|
@@ -0,0 +1,415 @@
|
|
|
1
|
+
import {
|
|
2
|
+
action,
|
|
3
|
+
invokeWrappedActionImplementation
|
|
4
|
+
} from "../../core/action.js";
|
|
5
|
+
import { isPlainObject } from "../../core/immutable.js";
|
|
6
|
+
import { validateUserId } from "../../core/identifiers.js";
|
|
7
|
+
import { validateOptionObject } from "../../core/validation.js";
|
|
8
|
+
import { findLayer } from "../../selectors/layers.js";
|
|
9
|
+
import { findSemanticScale } from "../../selectors/scales.js";
|
|
10
|
+
import { findScaleConsumers } from "../scales/consumers/index.js";
|
|
11
|
+
import { resolveScalePreview, validatePendingMeasuredScale } from
|
|
12
|
+
"../scales/preview.js";
|
|
13
|
+
import { isPendingMeasuredRadiusConsumer } from
|
|
14
|
+
"../../materialization/scales/policies/arc.js";
|
|
15
|
+
import {
|
|
16
|
+
getMarkRematerializationStep,
|
|
17
|
+
getScaleConsumerMarkSteps,
|
|
18
|
+
getSourceDependentMarkSteps
|
|
19
|
+
} from "../../materialization/marks/index.js";
|
|
20
|
+
import {
|
|
21
|
+
applyMaterializationPlan,
|
|
22
|
+
planScaleGuideRematerialization
|
|
23
|
+
} from "../../materialization/dependencies.js";
|
|
24
|
+
import { buildMaterializationPlan } from "../../materialization/planner.js";
|
|
25
|
+
import { hasMaterializedLegend } from "../../materialization/legends.js";
|
|
26
|
+
import { rebindPositionGuides } from "./shared.js";
|
|
27
|
+
import { withoutPreviewLayerEncodings } from
|
|
28
|
+
"../primitives/semanticAction.js";
|
|
29
|
+
|
|
30
|
+
export const ENCODING_CHANNEL_ORDER = Object.freeze([
|
|
31
|
+
"x", "y", "x2", "y2", "theta", "r", "xOffset", "yOffset",
|
|
32
|
+
"group", "pathOrder", "color", "stroke", "size", "shape",
|
|
33
|
+
"opacity", "strokeWidth", "strokeDash", "angle", "text"
|
|
34
|
+
]);
|
|
35
|
+
|
|
36
|
+
const CHANNEL_METHODS = Object.freeze({
|
|
37
|
+
x: "encodeX",
|
|
38
|
+
y: "encodeY",
|
|
39
|
+
x2: "encodeX2",
|
|
40
|
+
y2: "encodeY2",
|
|
41
|
+
theta: "encodeTheta",
|
|
42
|
+
r: "encodeR",
|
|
43
|
+
xOffset: "encodeXOffset",
|
|
44
|
+
yOffset: "encodeYOffset",
|
|
45
|
+
group: "encodeGroup",
|
|
46
|
+
pathOrder: "encodePathOrder",
|
|
47
|
+
color: "encodeColor",
|
|
48
|
+
stroke: "encodeStroke",
|
|
49
|
+
size: "encodeSize",
|
|
50
|
+
shape: "encodeShape",
|
|
51
|
+
opacity: "encodeOpacity",
|
|
52
|
+
strokeWidth: "encodeStrokeWidth",
|
|
53
|
+
strokeDash: "encodeStrokeDash",
|
|
54
|
+
angle: "encodeAngle",
|
|
55
|
+
text: "encodeText"
|
|
56
|
+
});
|
|
57
|
+
|
|
58
|
+
const FORBIDDEN_PAYLOAD_KEYS = Object.freeze(["target", "coordinate", "id"]);
|
|
59
|
+
|
|
60
|
+
const DEFERRED_MARK_OPERATIONS = Object.freeze([
|
|
61
|
+
"materializeEmptyMark",
|
|
62
|
+
"rematerializePointMark",
|
|
63
|
+
"rematerializeTickMark",
|
|
64
|
+
"rematerializeLineMark",
|
|
65
|
+
"rematerializeAreaMark",
|
|
66
|
+
"rematerializeArcMark",
|
|
67
|
+
"rematerializeBarMark",
|
|
68
|
+
"rematerializeRuleMark",
|
|
69
|
+
"rematerializeTextMark",
|
|
70
|
+
"rematerializeRectMark",
|
|
71
|
+
"rematerializeMarkHighlights",
|
|
72
|
+
"materializeLabelLayout"
|
|
73
|
+
]);
|
|
74
|
+
|
|
75
|
+
const deferredClassByProgram = new WeakMap();
|
|
76
|
+
|
|
77
|
+
function sameSetting(left, right) {
|
|
78
|
+
if (Object.is(left, right)) return true;
|
|
79
|
+
if (Array.isArray(left) && Array.isArray(right)) {
|
|
80
|
+
return left.length === right.length && left.every(
|
|
81
|
+
(value, index) => sameSetting(value, right[index])
|
|
82
|
+
);
|
|
83
|
+
}
|
|
84
|
+
if (isPlainObject(left) && isPlainObject(right)) {
|
|
85
|
+
const leftKeys = Object.keys(left);
|
|
86
|
+
const rightKeys = Object.keys(right);
|
|
87
|
+
return leftKeys.length === rightKeys.length && leftKeys.every(
|
|
88
|
+
key => Object.hasOwn(right, key) && sameSetting(left[key], right[key])
|
|
89
|
+
);
|
|
90
|
+
}
|
|
91
|
+
return false;
|
|
92
|
+
}
|
|
93
|
+
|
|
94
|
+
function assertCompatibleScaleRequests(requests) {
|
|
95
|
+
const patches = new Map();
|
|
96
|
+
for (const { channel, payload } of requests) {
|
|
97
|
+
if (!isPlainObject(payload.scale) || payload.scale.id === undefined) continue;
|
|
98
|
+
const id = payload.scale.id;
|
|
99
|
+
const previous = patches.get(id) ?? new Map();
|
|
100
|
+
for (const [property, value] of Object.entries(payload.scale)) {
|
|
101
|
+
if (property === "id" || value === undefined) continue;
|
|
102
|
+
const existing = previous.get(property);
|
|
103
|
+
if (existing !== undefined && !sameSetting(existing.value, value)) {
|
|
104
|
+
throw new Error(
|
|
105
|
+
`encodeChannels scale "${id}" has conflicting explicit ${property} requests for ${existing.channel} and ${channel}.`
|
|
106
|
+
);
|
|
107
|
+
}
|
|
108
|
+
if (existing === undefined) previous.set(property, { channel, value });
|
|
109
|
+
}
|
|
110
|
+
patches.set(id, previous);
|
|
111
|
+
}
|
|
112
|
+
}
|
|
113
|
+
|
|
114
|
+
export function normalizeEncodeChannelsArgs(args) {
|
|
115
|
+
validateOptionObject(args, ["target", "channels"], "encodeChannels");
|
|
116
|
+
const target = validateUserId(args.target, "Mark id");
|
|
117
|
+
if (!isPlainObject(args.channels)) {
|
|
118
|
+
throw new TypeError("encodeChannels channels must be a plain object.");
|
|
119
|
+
}
|
|
120
|
+
const keys = Object.keys(args.channels);
|
|
121
|
+
if (keys.length === 0) {
|
|
122
|
+
throw new TypeError("encodeChannels channels must contain at least one channel.");
|
|
123
|
+
}
|
|
124
|
+
for (const key of keys) {
|
|
125
|
+
if (!Object.hasOwn(CHANNEL_METHODS, key)) {
|
|
126
|
+
throw new Error(`encodeChannels does not support channel "${key}".`);
|
|
127
|
+
}
|
|
128
|
+
}
|
|
129
|
+
const requests = ENCODING_CHANNEL_ORDER
|
|
130
|
+
.filter(channel => Object.hasOwn(args.channels, channel))
|
|
131
|
+
.map(channel => {
|
|
132
|
+
const payload = args.channels[channel];
|
|
133
|
+
if (!isPlainObject(payload)) {
|
|
134
|
+
throw new TypeError(
|
|
135
|
+
`encodeChannels ${channel} payload must be a plain object.`
|
|
136
|
+
);
|
|
137
|
+
}
|
|
138
|
+
for (const key of FORBIDDEN_PAYLOAD_KEYS) {
|
|
139
|
+
if (Object.hasOwn(payload, key)) {
|
|
140
|
+
throw new Error(
|
|
141
|
+
`encodeChannels ${channel} payload cannot specify ${key}.`
|
|
142
|
+
);
|
|
143
|
+
}
|
|
144
|
+
}
|
|
145
|
+
return Object.freeze({ channel, payload });
|
|
146
|
+
});
|
|
147
|
+
assertCompatibleScaleRequests(requests);
|
|
148
|
+
return Object.freeze({ target, requests: Object.freeze(requests) });
|
|
149
|
+
}
|
|
150
|
+
|
|
151
|
+
function resolveScaleOnly(program, id) {
|
|
152
|
+
const semanticScale = findSemanticScale(program, id);
|
|
153
|
+
if (semanticScale === undefined) {
|
|
154
|
+
throw new Error(`Unknown scale "${id}".`);
|
|
155
|
+
}
|
|
156
|
+
const consumers = findScaleConsumers(program, id);
|
|
157
|
+
if (
|
|
158
|
+
semanticScale.radialMapping !== undefined &&
|
|
159
|
+
consumers.length > 0 &&
|
|
160
|
+
consumers.every(isPendingMeasuredRadiusConsumer)
|
|
161
|
+
) {
|
|
162
|
+
validatePendingMeasuredScale(program, semanticScale, consumers);
|
|
163
|
+
return program._withoutResolvedScale(id);
|
|
164
|
+
}
|
|
165
|
+
return program._withResolvedScale(
|
|
166
|
+
id,
|
|
167
|
+
resolveScalePreview(program, id).resolvedScale
|
|
168
|
+
);
|
|
169
|
+
}
|
|
170
|
+
|
|
171
|
+
function deferredProgramClass(ProgramClass) {
|
|
172
|
+
const existing = deferredClassByProgram.get(ProgramClass);
|
|
173
|
+
if (existing !== undefined) return existing;
|
|
174
|
+
|
|
175
|
+
class DeferredEncodingProgram extends ProgramClass {
|
|
176
|
+
rematerializeScale({ id } = {}) {
|
|
177
|
+
return resolveScaleOnly(this, id);
|
|
178
|
+
}
|
|
179
|
+
|
|
180
|
+
rematerializeLegend() {
|
|
181
|
+
return this;
|
|
182
|
+
}
|
|
183
|
+
}
|
|
184
|
+
for (const operation of DEFERRED_MARK_OPERATIONS) {
|
|
185
|
+
Object.defineProperty(DeferredEncodingProgram.prototype, operation, {
|
|
186
|
+
configurable: true,
|
|
187
|
+
value() {
|
|
188
|
+
return this;
|
|
189
|
+
}
|
|
190
|
+
});
|
|
191
|
+
}
|
|
192
|
+
deferredClassByProgram.set(ProgramClass, DeferredEncodingProgram);
|
|
193
|
+
return DeferredEncodingProgram;
|
|
194
|
+
}
|
|
195
|
+
|
|
196
|
+
function programState(program) {
|
|
197
|
+
return Object.freeze({
|
|
198
|
+
semanticSpec: program.semanticSpec,
|
|
199
|
+
graphicSpec: program.graphicSpec,
|
|
200
|
+
resolvedScales: program.resolvedScales,
|
|
201
|
+
materializationConfigs: program.materializationConfigs,
|
|
202
|
+
children: program.children,
|
|
203
|
+
compositionSpec: program.compositionSpec,
|
|
204
|
+
context: program.context,
|
|
205
|
+
trace: program.trace,
|
|
206
|
+
actionStack: program.actionStack,
|
|
207
|
+
actionSequence: program._actionSequence
|
|
208
|
+
});
|
|
209
|
+
}
|
|
210
|
+
|
|
211
|
+
function instantiateProgram(state, ProgramClass) {
|
|
212
|
+
return new ProgramClass({
|
|
213
|
+
semanticSpec: state.semanticSpec,
|
|
214
|
+
graphicSpec: state.graphicSpec,
|
|
215
|
+
resolvedScales: state.resolvedScales,
|
|
216
|
+
materializationConfigs: state.materializationConfigs,
|
|
217
|
+
children: state.children,
|
|
218
|
+
compositionSpec: state.compositionSpec,
|
|
219
|
+
context: state.context,
|
|
220
|
+
trace: state.trace,
|
|
221
|
+
actionStack: state.actionStack,
|
|
222
|
+
actionSequence: state.actionSequence
|
|
223
|
+
});
|
|
224
|
+
}
|
|
225
|
+
|
|
226
|
+
function createDeferredProgram(program) {
|
|
227
|
+
return instantiateProgram(
|
|
228
|
+
programState(program),
|
|
229
|
+
deferredProgramClass(program.constructor)
|
|
230
|
+
);
|
|
231
|
+
}
|
|
232
|
+
|
|
233
|
+
function requestedFieldType(request) {
|
|
234
|
+
if (request === undefined) return undefined;
|
|
235
|
+
return request.payload.fieldType ?? "quantitative";
|
|
236
|
+
}
|
|
237
|
+
|
|
238
|
+
function isCategoricalBarType(fieldType) {
|
|
239
|
+
return ["nominal", "ordinal", "temporal"].includes(fieldType);
|
|
240
|
+
}
|
|
241
|
+
|
|
242
|
+
function stageFinalPositionRoles(program, target, requests) {
|
|
243
|
+
const layer = findLayer(program, target);
|
|
244
|
+
if (layer?.mark?.type !== "bar") return program;
|
|
245
|
+
const byChannel = new Map(requests.map(request => [request.channel, request]));
|
|
246
|
+
const nextX = requestedFieldType(byChannel.get("x"));
|
|
247
|
+
const nextY = requestedFieldType(byChannel.get("y"));
|
|
248
|
+
if (nextX === undefined || nextY === undefined) return program;
|
|
249
|
+
const currentX = layer.encoding?.x?.fieldType;
|
|
250
|
+
const currentY = layer.encoding?.y?.fieldType;
|
|
251
|
+
const changesOrientation =
|
|
252
|
+
isCategoricalBarType(currentX) !== isCategoricalBarType(nextX) &&
|
|
253
|
+
isCategoricalBarType(currentY) !== isCategoricalBarType(nextY);
|
|
254
|
+
if (!changesOrientation) return program;
|
|
255
|
+
|
|
256
|
+
return withoutPreviewLayerEncodings(program, {
|
|
257
|
+
id: target,
|
|
258
|
+
channels: ["x", "y"]
|
|
259
|
+
});
|
|
260
|
+
}
|
|
261
|
+
|
|
262
|
+
const INTERNAL_SCALE_CHANNEL = Object.freeze({ r: "radius" });
|
|
263
|
+
|
|
264
|
+
function requestedScaleIds(originalLayer, finalLayer, requests) {
|
|
265
|
+
const requestedChannels = new Set(requests.map(({ channel }) =>
|
|
266
|
+
INTERNAL_SCALE_CHANNEL[channel] ?? channel
|
|
267
|
+
));
|
|
268
|
+
const ids = [];
|
|
269
|
+
for (const channel of [
|
|
270
|
+
"x", "y", "x2", "y2", "theta", "radius", "xOffset", "yOffset",
|
|
271
|
+
"color", "stroke", "size", "shape", "opacity", "strokeWidth",
|
|
272
|
+
"strokeDash", "angle", "text", "group", "pathOrder"
|
|
273
|
+
]) {
|
|
274
|
+
if (!requestedChannels.has(channel)) continue;
|
|
275
|
+
for (const layer of [originalLayer, finalLayer]) {
|
|
276
|
+
const id = layer?.encoding?.[channel]?.scale;
|
|
277
|
+
if (id !== undefined && !ids.includes(id)) ids.push(id);
|
|
278
|
+
}
|
|
279
|
+
}
|
|
280
|
+
return ids;
|
|
281
|
+
}
|
|
282
|
+
|
|
283
|
+
function changedScaleIds(before, after) {
|
|
284
|
+
const beforeById = new Map(before.semanticSpec.scales.map(scale => [scale.id, scale]));
|
|
285
|
+
return after.semanticSpec.scales
|
|
286
|
+
.filter(scale => !sameSetting(scale, beforeById.get(scale.id)))
|
|
287
|
+
.map(scale => scale.id)
|
|
288
|
+
.sort();
|
|
289
|
+
}
|
|
290
|
+
|
|
291
|
+
function finalScaleIds(before, after, originalLayer, finalLayer, requests) {
|
|
292
|
+
const ids = [
|
|
293
|
+
...requestedScaleIds(originalLayer, finalLayer, requests),
|
|
294
|
+
...changedScaleIds(before, after)
|
|
295
|
+
];
|
|
296
|
+
return [...new Set(ids)].filter(id =>
|
|
297
|
+
findSemanticScale(after, id) !== undefined &&
|
|
298
|
+
findScaleConsumers(after, id).length > 0
|
|
299
|
+
);
|
|
300
|
+
}
|
|
301
|
+
|
|
302
|
+
const rematerializeEncodingScales = /* @__PURE__ */ action(
|
|
303
|
+
{
|
|
304
|
+
op: "rematerializeEncodingScales",
|
|
305
|
+
description: "Resolve every scale affected by one atomic encoding assignment."
|
|
306
|
+
},
|
|
307
|
+
function ({ ids } = {}) {
|
|
308
|
+
let next = this;
|
|
309
|
+
for (const id of ids) next = resolveScaleOnly(next, id);
|
|
310
|
+
return next;
|
|
311
|
+
}
|
|
312
|
+
);
|
|
313
|
+
|
|
314
|
+
function finalMaterializationPlan(program, target, scaleIds) {
|
|
315
|
+
const layer = findLayer(program, target);
|
|
316
|
+
const targetStep = layer === undefined
|
|
317
|
+
? undefined
|
|
318
|
+
: getMarkRematerializationStep(program, layer);
|
|
319
|
+
const directMarks = [
|
|
320
|
+
...(targetStep === undefined ? [] : [targetStep]),
|
|
321
|
+
...getScaleConsumerMarkSteps(program, scaleIds)
|
|
322
|
+
];
|
|
323
|
+
const marks = [
|
|
324
|
+
...directMarks,
|
|
325
|
+
...directMarks.flatMap(step =>
|
|
326
|
+
getSourceDependentMarkSteps(program, step.args.id)
|
|
327
|
+
)
|
|
328
|
+
];
|
|
329
|
+
const guides = scaleIds.flatMap(id =>
|
|
330
|
+
planScaleGuideRematerialization(program, id)
|
|
331
|
+
);
|
|
332
|
+
if (hasMaterializedLegend(program)) {
|
|
333
|
+
guides.push({ op: "rematerializeLegend" });
|
|
334
|
+
}
|
|
335
|
+
return buildMaterializationPlan({ marks, guides });
|
|
336
|
+
}
|
|
337
|
+
|
|
338
|
+
function applyEncodingDraft(program, target, requests) {
|
|
339
|
+
let draft = stageFinalPositionRoles(
|
|
340
|
+
createDeferredProgram(program),
|
|
341
|
+
target,
|
|
342
|
+
requests
|
|
343
|
+
);
|
|
344
|
+
for (const { channel, payload } of requests) {
|
|
345
|
+
const focusedAction = draft[CHANNEL_METHODS[channel]];
|
|
346
|
+
draft = invokeWrappedActionImplementation(
|
|
347
|
+
focusedAction,
|
|
348
|
+
draft,
|
|
349
|
+
{ ...payload, target }
|
|
350
|
+
);
|
|
351
|
+
}
|
|
352
|
+
const originalLayer = findLayer(program, target);
|
|
353
|
+
const finalLayer = findLayer(draft, target);
|
|
354
|
+
for (const channel of ["x", "y"]) {
|
|
355
|
+
const previousScale = originalLayer?.encoding?.[channel]?.scale;
|
|
356
|
+
const nextScale = finalLayer?.encoding?.[channel]?.scale;
|
|
357
|
+
if (previousScale !== undefined && nextScale !== undefined) {
|
|
358
|
+
draft = rebindPositionGuides(
|
|
359
|
+
draft,
|
|
360
|
+
channel,
|
|
361
|
+
previousScale,
|
|
362
|
+
nextScale,
|
|
363
|
+
target
|
|
364
|
+
);
|
|
365
|
+
}
|
|
366
|
+
}
|
|
367
|
+
return draft;
|
|
368
|
+
}
|
|
369
|
+
|
|
370
|
+
function planEncodingAssignments(program, target, requests) {
|
|
371
|
+
const originalLayer = findLayer(program, target);
|
|
372
|
+
const draft = applyEncodingDraft(program, target, requests);
|
|
373
|
+
const finalLayer = findLayer(draft, target);
|
|
374
|
+
return Object.freeze({
|
|
375
|
+
target,
|
|
376
|
+
originalLayer,
|
|
377
|
+
finalLayer,
|
|
378
|
+
state: programState(draft),
|
|
379
|
+
scaleIds: Object.freeze(finalScaleIds(
|
|
380
|
+
program,
|
|
381
|
+
draft,
|
|
382
|
+
originalLayer,
|
|
383
|
+
finalLayer,
|
|
384
|
+
requests
|
|
385
|
+
))
|
|
386
|
+
});
|
|
387
|
+
}
|
|
388
|
+
|
|
389
|
+
function applyEncodingAssignments(program, plan) {
|
|
390
|
+
return instantiateProgram(plan.state, program.constructor);
|
|
391
|
+
}
|
|
392
|
+
|
|
393
|
+
export const encodeChannels = /* @__PURE__ */ action(
|
|
394
|
+
{
|
|
395
|
+
op: "encodeChannels",
|
|
396
|
+
description: "Atomically assign multiple encoding channels to one mark."
|
|
397
|
+
},
|
|
398
|
+
function (args = {}) {
|
|
399
|
+
const { target, requests } = normalizeEncodeChannelsArgs(args);
|
|
400
|
+
const plan = planEncodingAssignments(this, target, requests);
|
|
401
|
+
let next = applyEncodingAssignments(this, plan);
|
|
402
|
+
const scaleIds = plan.scaleIds;
|
|
403
|
+
if (scaleIds.length > 0) {
|
|
404
|
+
next = rematerializeEncodingScales.call(next, { ids: scaleIds });
|
|
405
|
+
}
|
|
406
|
+
return applyMaterializationPlan(
|
|
407
|
+
next,
|
|
408
|
+
finalMaterializationPlan(next, target, scaleIds)
|
|
409
|
+
);
|
|
410
|
+
}
|
|
411
|
+
);
|
|
412
|
+
|
|
413
|
+
export function registerAtomicEncodingAction(ProgramClass) {
|
|
414
|
+
ProgramClass.prototype.encodeChannels = encodeChannels;
|
|
415
|
+
}
|
|
@@ -39,7 +39,7 @@ import {
|
|
|
39
39
|
|
|
40
40
|
import { applyTemporalUnit } from "../temporal.js";
|
|
41
41
|
|
|
42
|
-
const encodeColor = action(
|
|
42
|
+
const encodeColor = /* @__PURE__ */ action(
|
|
43
43
|
{
|
|
44
44
|
op: "encodeColor",
|
|
45
45
|
description: "Encode a field as graphical color."
|
|
@@ -150,7 +150,8 @@ const encodeColor = action(
|
|
|
150
150
|
});
|
|
151
151
|
}
|
|
152
152
|
next = applyEncodingScale(next, scale, requestedScale, {
|
|
153
|
-
reassignment: layer.encoding?.color?.scale === scale.id
|
|
153
|
+
reassignment: layer.encoding?.color?.scale === scale.id,
|
|
154
|
+
allowTypeChange: true
|
|
154
155
|
});
|
|
155
156
|
next = applyColorLayoutCompanion(next, {
|
|
156
157
|
target,
|
|
@@ -28,12 +28,12 @@ import {
|
|
|
28
28
|
|
|
29
29
|
const OPTIONS = Object.freeze([
|
|
30
30
|
"field", "target", "source", "groupBy", "bandwidth", "extent", "steps",
|
|
31
|
-
"kernel", "normalization", "as", "densityChannel", "coordinate",
|
|
31
|
+
"kernel", "normalization", "weight", "as", "densityChannel", "coordinate",
|
|
32
32
|
"valueScale", "densityScale", "placement"
|
|
33
33
|
]);
|
|
34
34
|
const EDIT_OPTIONS = Object.freeze([
|
|
35
35
|
"target", "source", "field", "groupBy", "bandwidth", "extent", "steps",
|
|
36
|
-
"kernel", "normalization", "densityChannel", "valueScale", "placement"
|
|
36
|
+
"kernel", "normalization", "weight", "densityChannel", "valueScale", "placement"
|
|
37
37
|
]);
|
|
38
38
|
const EDITABLE = Object.freeze(EDIT_OPTIONS.filter(option => option !== "target"));
|
|
39
39
|
const SCALE_PROPERTIES = Object.freeze([
|
|
@@ -114,7 +114,7 @@ function applyDensityPosition(program, layerId, definition, groupBy) {
|
|
|
114
114
|
return next;
|
|
115
115
|
}
|
|
116
116
|
|
|
117
|
-
const encodeDensity = action(
|
|
117
|
+
const encodeDensity = /* @__PURE__ */ action(
|
|
118
118
|
{
|
|
119
119
|
op: "encodeDensity",
|
|
120
120
|
description: "Derive and encode a baseline or categorical kernel-density area."
|
|
@@ -193,6 +193,7 @@ const encodeDensity = action(
|
|
|
193
193
|
...(args.normalization === undefined
|
|
194
194
|
? {}
|
|
195
195
|
: { normalization: args.normalization }),
|
|
196
|
+
...(args.weight === undefined ? {} : { weight: args.weight }),
|
|
196
197
|
...(args.as === undefined ? {} : { as: args.as }),
|
|
197
198
|
...(placement === undefined ? {} : { placement })
|
|
198
199
|
};
|
|
@@ -258,7 +259,7 @@ function assertGroupingSelectionCompatibility(program, layer, changesGroup) {
|
|
|
258
259
|
}
|
|
259
260
|
}
|
|
260
261
|
|
|
261
|
-
const editDensity = action(
|
|
262
|
+
const editDensity = /* @__PURE__ */ action(
|
|
262
263
|
{
|
|
263
264
|
op: "editDensity",
|
|
264
265
|
description: "Revise one density transform and rematerialize its consumers."
|
|
@@ -350,6 +351,7 @@ const editDensity = action(
|
|
|
350
351
|
const option = property => Object.hasOwn(args, property)
|
|
351
352
|
? args[property]
|
|
352
353
|
: transform[property];
|
|
354
|
+
const weight = option("weight");
|
|
353
355
|
|
|
354
356
|
const dataArgs = {
|
|
355
357
|
id: revision.id,
|
|
@@ -364,6 +366,7 @@ const editDensity = action(
|
|
|
364
366
|
kernel: option("kernel") ?? "gaussian",
|
|
365
367
|
normalization: option("normalization") ?? "unit",
|
|
366
368
|
as: transform.as,
|
|
369
|
+
...(weight === undefined || weight === false ? {} : { weight }),
|
|
367
370
|
...(requestedPlacement === undefined
|
|
368
371
|
? {}
|
|
369
372
|
: { placement: requestedPlacement })
|
|
@@ -3,10 +3,10 @@ import { validateOptions } from "./shared.js";
|
|
|
3
3
|
|
|
4
4
|
const HISTOGRAM_OPTIONS = Object.freeze([
|
|
5
5
|
"field", "target", "coordinate", "maxBins", "binStep", "binBoundaries",
|
|
6
|
-
"stack", "xScale", "yScale"
|
|
6
|
+
"stack", "xScale", "yScale", "weight"
|
|
7
7
|
]);
|
|
8
8
|
|
|
9
|
-
const encodeHistogram = action(
|
|
9
|
+
const encodeHistogram = /* @__PURE__ */ action(
|
|
10
10
|
{
|
|
11
11
|
op: "encodeHistogram",
|
|
12
12
|
description: "Encode a binned count histogram with a configurable layout stack."
|
|
@@ -28,7 +28,8 @@ const encodeHistogram = action(
|
|
|
28
28
|
: { maxBins: args.maxBins ?? 10 };
|
|
29
29
|
const x = {
|
|
30
30
|
field: args.field,
|
|
31
|
-
bin
|
|
31
|
+
bin,
|
|
32
|
+
...(args.weight === undefined ? {} : { weight: args.weight })
|
|
32
33
|
};
|
|
33
34
|
const y = {
|
|
34
35
|
stack: Object.hasOwn(args, "stack") ? args.stack : "zero"
|
|
@@ -1,6 +1,6 @@
|
|
|
1
|
-
import {
|
|
1
|
+
import { closedAction } from "../../core/action.js";
|
|
2
2
|
import { validateUserId } from "../../core/identifiers.js";
|
|
3
|
-
|
|
3
|
+
|
|
4
4
|
import {
|
|
5
5
|
deriveHorizon,
|
|
6
6
|
validateHorizonTransform
|
|
@@ -109,13 +109,12 @@ function applyScaleDefinition(program, current, definition) {
|
|
|
109
109
|
return patch === undefined ? program : program.editScale(patch);
|
|
110
110
|
}
|
|
111
111
|
|
|
112
|
-
const editHorizon =
|
|
112
|
+
const editHorizon = /* @__PURE__ */ closedAction(
|
|
113
113
|
{
|
|
114
114
|
op: "editHorizon",
|
|
115
115
|
description: "Revise one Horizon transform and rematerialize its consumers."
|
|
116
|
-
},
|
|
116
|
+
}, EDIT_OPTIONS,
|
|
117
117
|
function (args = {}) {
|
|
118
|
-
validateOptionObject(args, EDIT_OPTIONS, "editHorizon");
|
|
119
118
|
if (Object.hasOwn(args, "groupBy") && args.groupBy === undefined) {
|
|
120
119
|
throw new Error("editHorizon groupBy requires a field string or false.");
|
|
121
120
|
}
|
|
@@ -278,13 +277,12 @@ const editHorizon = action(
|
|
|
278
277
|
}
|
|
279
278
|
);
|
|
280
279
|
|
|
281
|
-
const encodeHorizon =
|
|
280
|
+
const encodeHorizon = /* @__PURE__ */ closedAction(
|
|
282
281
|
{
|
|
283
282
|
op: "encodeHorizon",
|
|
284
283
|
description: "Derive and encode one folded Horizon area."
|
|
285
|
-
},
|
|
284
|
+
}, OPTIONS,
|
|
286
285
|
function (args = {}) {
|
|
287
|
-
validateOptionObject(args, OPTIONS, "encodeHorizon");
|
|
288
286
|
const layer = findHorizonArea(this, args.target);
|
|
289
287
|
validateUnusedHorizonEncodings(layer);
|
|
290
288
|
const source = resolveHorizonSource(this, layer, args.source);
|
|
@@ -13,8 +13,10 @@ import { registerTextEncodingAction } from "./text.js";
|
|
|
13
13
|
import { registerAppearanceEncodingAction } from "./appearance.js";
|
|
14
14
|
import { registerStrokeDashEncodingActions } from "./strokeDash.js";
|
|
15
15
|
import { registerRuleAppearanceEncodingActions } from "./ruleAppearance.js";
|
|
16
|
+
import { registerStrokeEncodingAction } from "./stroke.js";
|
|
16
17
|
import { registerBarWidthEncodingAction } from "./barWidth.js";
|
|
17
18
|
import { registerEncodingRemovalAction } from "./remove.js";
|
|
19
|
+
import { registerAtomicEncodingAction } from "./channels.js";
|
|
18
20
|
|
|
19
21
|
export function registerEncodingActions(ProgramClass) {
|
|
20
22
|
registerSeriesLayoutAction(ProgramClass);
|
|
@@ -31,7 +33,9 @@ export function registerEncodingActions(ProgramClass) {
|
|
|
31
33
|
registerAppearanceEncodingAction(ProgramClass);
|
|
32
34
|
registerAngleEncodingAction(ProgramClass);
|
|
33
35
|
registerRuleAppearanceEncodingActions(ProgramClass);
|
|
36
|
+
registerStrokeEncodingAction(ProgramClass);
|
|
34
37
|
registerTextEncodingAction(ProgramClass);
|
|
35
38
|
registerParallelEncodingAction(ProgramClass);
|
|
36
39
|
registerEncodingRemovalAction(ProgramClass);
|
|
40
|
+
registerAtomicEncodingAction(ProgramClass);
|
|
37
41
|
}
|