ggaction 0.0.12 → 0.0.15
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 +127 -0
- package/README.md +20 -11
- package/knowledge/action-card.schema.json +1 -1
- package/knowledge/action-cards.json +1 -1
- package/knowledge/action-cards.schema.json +1 -1
- package/knowledge/extension-authoring.md +2 -1
- package/knowledge/intent-taxonomy.json +1 -1
- package/knowledge/mcp-resources.json +1 -1
- package/knowledge/task-resolver.js +1 -1
- package/package.json +10 -3
- package/src/actions/basic.js +4 -2
- package/src/actions/boxPlots/components.js +14 -4
- package/src/actions/boxPlots/edit.js +31 -5
- package/src/actions/boxPlots/materialize.js +13 -4
- package/src/actions/boxPlots/options.js +48 -16
- package/src/actions/canvas/actions.js +3 -1
- package/src/actions/canvas/fitting.js +211 -0
- package/src/actions/canvas/index.js +2 -0
- package/src/actions/categoryOrder/index.js +18 -6
- package/src/actions/charts/area.js +51 -0
- package/src/actions/charts/bar.js +13 -6
- package/src/actions/charts/beeswarm.js +70 -0
- package/src/actions/charts/density.js +48 -0
- package/src/actions/charts/ecdf.js +186 -0
- package/src/actions/charts/endpoints.js +473 -0
- package/src/actions/charts/heatmap.js +4 -3
- package/src/actions/charts/histogram.js +5 -4
- package/src/actions/charts/horizon.js +73 -0
- package/src/actions/charts/index.js +37 -0
- package/src/actions/charts/interval-regression.js +172 -0
- package/src/actions/charts/line.js +8 -6
- package/src/actions/charts/parallel.js +8 -2
- package/src/actions/charts/pie.js +52 -0
- package/src/actions/charts/polar.js +134 -0
- package/src/actions/charts/radar.js +305 -0
- package/src/actions/charts/radial.js +50 -0
- package/src/actions/charts/raincloud.js +422 -0
- package/src/actions/charts/rug-strip.js +283 -0
- package/src/actions/charts/scatter.js +11 -3
- package/src/actions/charts/shared.js +69 -10
- package/src/actions/composition/actions.js +129 -3
- package/src/actions/coordinates/actions.js +1 -1
- package/src/actions/coordinates/edit.js +76 -0
- package/src/actions/data/bin.js +29 -0
- package/src/actions/data/bin2d.js +57 -185
- package/src/actions/data/complete.js +26 -0
- package/src/actions/data/computed.js +24 -0
- package/src/actions/data/create.js +2 -2
- package/src/actions/data/density.js +12 -20
- package/src/actions/data/derived.js +111 -15
- package/src/actions/data/ecdf.js +38 -0
- package/src/actions/data/edit.js +539 -0
- package/src/actions/data/filter.js +226 -30
- package/src/actions/data/fold.js +24 -0
- package/src/actions/data/impute.js +26 -0
- package/src/actions/data/index.js +38 -0
- package/src/actions/data/interval.js +2 -0
- package/src/actions/data/intervalEdit.js +86 -4
- package/src/actions/data/normalize.js +27 -0
- package/src/actions/data/regression.js +19 -21
- package/src/actions/data/revisionBindings.js +145 -0
- package/src/actions/data/shared.js +20 -4
- package/src/actions/data/stack.js +26 -0
- package/src/actions/data/summary.js +26 -0
- package/src/actions/data/timeUnit.js +4 -1
- package/src/actions/data/window.js +1 -1
- package/src/actions/encodings/appearance.js +32 -13
- package/src/actions/encodings/barWidth.js +8 -0
- package/src/actions/encodings/basic.js +2 -0
- package/src/actions/encodings/channels.js +415 -0
- package/src/actions/encodings/color/continuous.js +19 -59
- package/src/actions/encodings/color/index.js +30 -23
- package/src/actions/encodings/color/layout.js +3 -97
- package/src/actions/encodings/color/policy.js +5 -8
- package/src/actions/encodings/density/resolve.js +37 -5
- package/src/actions/encodings/density.js +124 -34
- package/src/actions/encodings/histogram.js +3 -2
- package/src/actions/encodings/horizon/resolve.js +8 -4
- package/src/actions/encodings/horizon.js +18 -8
- package/src/actions/encodings/index.js +6 -0
- package/src/actions/encodings/offset.js +30 -29
- package/src/actions/encodings/parallel.js +2 -8
- package/src/actions/encodings/position/apply.js +63 -11
- package/src/actions/encodings/position/index.js +52 -6
- package/src/actions/encodings/position/policies/arc.js +14 -0
- package/src/actions/encodings/position/policies/area.js +4 -42
- package/src/actions/encodings/position/policies/bar.js +57 -13
- package/src/actions/encodings/position/resolve.js +88 -26
- package/src/actions/encodings/ranged.js +123 -97
- package/src/actions/encodings/remove.js +44 -34
- package/src/actions/encodings/ruleAppearance.js +24 -32
- package/src/actions/encodings/seriesLayout.js +105 -0
- package/src/actions/encodings/shared.js +107 -37
- package/src/actions/encodings/stroke.js +226 -0
- package/src/actions/encodings/strokeDash.js +9 -6
- package/src/actions/encodings/temporal.js +7 -0
- package/src/actions/encodings/text.js +30 -15
- package/src/actions/errorBands/create.js +41 -8
- package/src/actions/errorBands/edit.js +360 -25
- package/src/actions/errorBars/create.js +56 -17
- package/src/actions/errorBars/edit.js +372 -21
- package/src/actions/facets/actions.js +619 -41
- package/src/actions/facets/derive.js +139 -25
- package/src/actions/gradientPlots/components.js +43 -13
- package/src/actions/gradientPlots/edit.js +14 -4
- package/src/actions/gradientPlots/materialize.js +8 -8
- package/src/actions/gradientPlots/options.js +10 -2
- package/src/actions/guides/applicability.js +28 -19
- package/src/actions/guides/axes/axes.js +4 -3
- package/src/actions/guides/axes/axis.js +18 -18
- package/src/actions/guides/axes/components.js +43 -0
- package/src/actions/guides/axes/edit.js +16 -51
- package/src/actions/guides/axes/labels.js +184 -28
- package/src/actions/guides/axes/lines.js +13 -7
- package/src/actions/guides/axes/parallel/lifecycle.js +117 -0
- package/src/actions/guides/axes/parallel/policy.js +137 -0
- package/src/actions/guides/axes/parallel/resolve.js +50 -25
- package/src/actions/guides/axes/parallel.js +93 -217
- package/src/actions/guides/axes/policy.js +21 -67
- package/src/actions/guides/axes/tickGroups.js +15 -8
- package/src/actions/guides/axes/ticks.js +11 -6
- package/src/actions/guides/axes/titles.js +32 -11
- package/src/actions/guides/basic.js +2 -0
- package/src/actions/guides/facade.js +106 -0
- package/src/actions/guides/facadeAxes.js +200 -0
- package/src/actions/guides/facadeLegend.js +63 -0
- package/src/actions/guides/grids/grid.js +37 -33
- package/src/actions/guides/grids/resolve.js +17 -4
- package/src/actions/guides/guides.js +54 -31
- package/src/actions/guides/legends/blocks.js +426 -0
- package/src/actions/guides/legends/categorical/actions.js +309 -279
- package/src/actions/guides/legends/categorical/components.js +21 -17
- package/src/actions/guides/legends/categorical/index.js +37 -33
- package/src/actions/guides/legends/categorical/layout.js +123 -354
- package/src/actions/guides/legends/categorical/options.js +32 -16
- package/src/actions/guides/legends/categorical/recipes.js +114 -9
- package/src/actions/guides/legends/categorical/resolve.js +30 -15
- package/src/actions/guides/legends/categorical/symbols.js +87 -33
- package/src/actions/guides/legends/continuous/common.js +99 -26
- package/src/actions/guides/legends/continuous/gradient.js +120 -89
- package/src/actions/guides/legends/continuous/index.js +8 -2
- package/src/actions/guides/legends/continuous/interval.js +79 -95
- package/src/actions/guides/legends/continuous/opacity.js +113 -89
- package/src/actions/guides/legends/continuous/stroke.js +525 -0
- package/src/actions/guides/legends/creation.js +40 -0
- package/src/actions/guides/legends/edit.js +321 -90
- package/src/actions/guides/legends/focused.js +2 -2
- package/src/actions/guides/legends/index.js +2 -0
- package/src/actions/guides/legends/lane.js +149 -102
- package/src/actions/guides/legends/lifecycle.js +143 -0
- package/src/actions/guides/legends/remove.js +43 -78
- package/src/actions/guides/legends/sampling.js +140 -0
- package/src/actions/guides/legends/size.js +213 -116
- package/src/actions/guides/legends/strokeWidth.js +121 -73
- package/src/actions/guides/legends/target.js +123 -0
- package/src/actions/guides/legends/transition.js +192 -0
- package/src/actions/guides/polar/axes/facade.js +81 -66
- package/src/actions/guides/polar/axes/labels.js +28 -8
- package/src/actions/guides/polar/axes/lines.js +12 -5
- package/src/actions/guides/polar/axes/shared.js +22 -0
- package/src/actions/guides/polar/axes/ticks.js +6 -5
- package/src/actions/guides/polar/axes/titles.js +6 -5
- package/src/actions/guides/polar/grids.js +8 -8
- package/src/actions/guides/polar/resolve.js +12 -8
- package/src/actions/guides/reuse.js +44 -0
- package/src/actions/guides/tickValues.js +19 -21
- package/src/actions/index.js +15 -2
- package/src/actions/intervals/resolve.js +35 -15
- package/src/actions/marks/arc/actions.js +78 -20
- package/src/actions/marks/area/actions.js +51 -12
- package/src/actions/marks/area/materialize.js +22 -3
- package/src/actions/marks/bar/create.js +11 -2
- package/src/actions/marks/bar/edit.js +20 -3
- package/src/actions/marks/bar/materialize.js +33 -9
- package/src/actions/marks/index.js +14 -0
- package/src/actions/marks/line/actions.js +71 -113
- package/src/actions/marks/line/materialize.js +57 -56
- package/src/actions/marks/point/create.js +8 -2
- package/src/actions/marks/point/edit.js +29 -21
- package/src/actions/marks/point/index.js +1 -0
- package/src/actions/marks/point/jitter.js +3 -0
- package/src/actions/marks/point/materialize.js +154 -16
- package/src/actions/marks/point/packing.js +68 -0
- package/src/actions/marks/rect/actions.js +33 -12
- package/src/actions/marks/references.js +658 -0
- package/src/actions/marks/remove.js +87 -4
- package/src/actions/marks/rule/actions.js +77 -9
- package/src/actions/marks/rule/appearance.js +26 -0
- package/src/actions/marks/shared.js +13 -13
- package/src/actions/marks/text/actions.js +296 -13
- package/src/actions/marks/text/index.js +4 -0
- package/src/actions/marks/text/layout.js +156 -8
- package/src/actions/marks/text/removal.js +173 -0
- package/src/actions/marks/text/selection.js +73 -0
- package/src/actions/marks/tick/actions.js +22 -5
- package/src/actions/primitives/createGraphics.js +3 -1
- package/src/actions/primitives/editGraphics.js +26 -0
- package/src/actions/primitives/semantic.js +3 -2
- package/src/actions/primitives/semanticAction.js +120 -10
- package/src/actions/primitives/semanticValidation/guide.js +10 -0
- package/src/actions/primitives/semanticValidation/index.js +9 -1
- package/src/actions/primitives/semanticValidation/layer.js +23 -1
- package/src/actions/primitives/semanticValidation/scale.js +38 -8
- package/src/actions/regression/components.js +26 -11
- package/src/actions/regression/create.js +11 -3
- package/src/actions/regression/edit.js +40 -13
- package/src/actions/regression/resolve.js +1 -1
- package/src/actions/resources/index.js +7 -0
- package/src/actions/resources/remove.js +172 -0
- package/src/actions/scales/channels.js +212 -0
- package/src/actions/scales/consumers/common.js +21 -54
- package/src/actions/scales/consumers/families.js +28 -14
- package/src/actions/scales/consumers/index.js +42 -4
- package/src/actions/scales/consumers/seriesLayout.js +57 -12
- package/src/actions/scales/create.js +58 -26
- package/src/actions/scales/definitions.js +109 -39
- package/src/actions/scales/edit.js +101 -34
- package/src/actions/scales/editPolicy.js +95 -35
- package/src/actions/scales/index.js +6 -0
- package/src/actions/scales/materialize.js +14 -49
- package/src/actions/scales/offset.js +48 -0
- package/src/actions/scales/parallel.js +71 -0
- package/src/actions/scales/patch.js +1 -1
- package/src/actions/scales/preview.js +140 -0
- package/src/actions/scales/quantitativeColor.js +9 -5
- package/src/actions/selection/actions.js +154 -30
- package/src/actions/selection/index.js +3 -0
- package/src/actions/theme/actions.js +98 -0
- package/src/actions/theme/composition.js +238 -0
- package/src/actions/theme/index.js +16 -0
- package/src/actions/theme/reconcile.js +1130 -0
- package/src/actions/theme/state.js +160 -0
- package/src/actions/titles/actions.js +11 -10
- package/src/actions/titles/resolve.js +1 -40
- package/src/actions/violinPlots/create.js +90 -43
- package/src/actions/violinPlots/edit.js +192 -0
- package/src/actions/violinPlots/index.js +2 -0
- package/src/core/ChartProgram.js +7 -0
- package/src/core/action.js +32 -2
- package/src/core/compositionState.js +141 -8
- package/src/core/programState.js +20 -0
- package/src/core/resourceReferences.js +332 -0
- package/src/core/vocabulary.js +16 -3
- package/src/grammar/aggregate.js +66 -23
- package/src/grammar/arcs.js +58 -1
- package/src/grammar/areaEndpoints.js +46 -0
- package/src/grammar/areaSeries.js +87 -41
- package/src/grammar/bars/aggregate.js +37 -13
- package/src/grammar/bars/geometry.js +44 -0
- package/src/grammar/bars/policy.js +9 -7
- package/src/grammar/bin.js +226 -0
- package/src/grammar/categoryOrder.js +34 -0
- package/src/grammar/complete.js +279 -0
- package/src/grammar/computed.js +351 -0
- package/src/grammar/coordinates.js +37 -0
- package/src/grammar/density.js +239 -37
- package/src/grammar/displayLabels.js +57 -0
- package/src/grammar/ecdf.js +198 -0
- package/src/grammar/facets/dependencies.js +133 -1
- package/src/grammar/facets/guides.js +3 -0
- package/src/grammar/facets/index.js +123 -52
- package/src/grammar/facets/scales.js +15 -18
- package/src/grammar/fold.js +123 -0
- package/src/grammar/horizon.js +6 -4
- package/src/grammar/impute.js +340 -0
- package/src/grammar/interval.js +37 -20
- package/src/grammar/lineSeries.js +20 -63
- package/src/grammar/markFilter.js +22 -4
- package/src/grammar/markLabelSelection.js +57 -0
- package/src/grammar/markLabels.js +110 -0
- package/src/grammar/normalize.js +366 -0
- package/src/grammar/parallelAxisTitles.js +16 -0
- package/src/grammar/pathSeries.js +109 -0
- package/src/grammar/pointPacking.js +183 -0
- package/src/grammar/pointShapes.js +13 -4
- package/src/grammar/polar.js +90 -8
- package/src/grammar/positionDatum.js +12 -0
- package/src/grammar/rects.js +9 -1
- package/src/grammar/regression/derive.js +4 -0
- package/src/grammar/regression/index.js +8 -2
- package/src/grammar/regression/models.js +22 -7
- package/src/grammar/regression/parameters.js +63 -13
- package/src/grammar/rotation.js +29 -0
- package/src/grammar/roundedRect.js +180 -0
- package/src/grammar/rules.js +8 -21
- package/src/grammar/scales/color.js +23 -1
- package/src/grammar/scales/colorConsumers.js +57 -0
- package/src/grammar/scales/continuous.js +2 -2
- package/src/grammar/scales/definition.js +42 -5
- package/src/grammar/scales/discretized.js +11 -5
- package/src/grammar/scales/fields.js +38 -8
- package/src/grammar/scales/index.js +1 -0
- package/src/grammar/scales/mapping.js +2 -0
- package/src/grammar/scales/ordinal.js +12 -3
- package/src/grammar/scales/policies.js +2 -2
- package/src/grammar/scales/radial.js +55 -0
- package/src/grammar/scales/size.js +456 -0
- package/src/grammar/scales/types.js +1 -0
- package/src/grammar/schemas/concreteGraphic.js +14 -2
- package/src/grammar/schemas/graphic.js +15 -0
- package/src/grammar/schemas/graphicBounds.js +179 -30
- package/src/grammar/schemas/semanticPath.js +23 -4
- package/src/grammar/stack.js +170 -0
- package/src/grammar/statisticalReference.js +103 -0
- package/src/grammar/statistics/confidenceInterval.js +101 -0
- package/src/grammar/strokeStyle.js +77 -0
- package/src/grammar/summary.js +245 -0
- package/src/grammar/text.js +22 -16
- package/src/grammar/timeUnit.js +234 -13
- package/src/grammar/transformTopology.js +10 -0
- package/src/grammar/transforms.js +418 -16
- package/src/grammar/valueFormat.js +112 -0
- package/src/grammar/weightedStatistics.js +374 -0
- package/src/grammar/window.js +232 -21
- package/src/layout/aspect.js +80 -0
- package/src/layout/facets.js +100 -12
- package/src/layout/guideCollisions.js +12 -0
- package/src/layout/labels.js +343 -0
- package/src/layout/legend.js +2 -10
- package/src/layout/legendItems.js +102 -0
- package/src/layout/legendLane.js +100 -11
- package/src/materialization/bars/aggregate.js +56 -147
- package/src/materialization/bars/histogram.js +104 -20
- package/src/materialization/bars/ranged.js +19 -3
- package/src/materialization/bars/resolve.js +7 -4
- package/src/materialization/categorySlotOffset.js +40 -0
- package/src/materialization/composition.js +3 -1
- package/src/materialization/compositionSnapshot.js +1 -1
- package/src/materialization/coordinateBounds.js +204 -0
- package/src/materialization/dependencies.js +93 -16
- package/src/materialization/encodings.js +1 -1
- package/src/materialization/facetGuides/legacyCategorical.js +3 -0
- package/src/materialization/facetGuides/placement.js +8 -2
- package/src/materialization/facetGuides/preparation.js +12 -7
- package/src/materialization/facetHeaders.js +346 -0
- package/src/materialization/facets.js +23 -66
- package/src/materialization/guides/layout.js +57 -0
- package/src/materialization/guides/resources.js +28 -2
- package/src/materialization/legends.js +11 -2
- package/src/materialization/marks/capabilities.js +20 -5
- package/src/materialization/marks/grouping.js +52 -0
- package/src/materialization/marks/index.js +68 -27
- package/src/materialization/marks/policies.js +4 -1
- package/src/materialization/rect.js +55 -42
- package/src/materialization/rectConfig.js +5 -1
- package/src/materialization/rowEncoding.js +13 -13
- package/src/materialization/scaleGuideDependencies.js +8 -5
- package/src/materialization/scales/map.js +6 -3
- package/src/materialization/scales/policies/arc.js +42 -0
- package/src/materialization/scales/policies/binnedPosition.js +7 -4
- package/src/materialization/scales/policies/offset.js +50 -8
- package/src/materialization/scales/policies/series.js +5 -1
- package/src/materialization/scales/resolve.js +65 -17
- package/src/materialization/selection/compatibility.js +11 -0
- package/src/materialization/selection/items/arc.js +28 -4
- package/src/materialization/selection/items/bar.js +42 -71
- package/src/materialization/selection/items/common.js +27 -6
- package/src/materialization/selection/items/path.js +3 -13
- package/src/materialization/selection/items/rect.js +35 -8
- package/src/materialization/selection/path.js +1 -1
- package/src/materialization/selection/point.js +3 -1
- package/src/materialization/text.js +324 -14
- package/src/mcp/adapter.js +2 -2
- package/src/renderers/canvas/circle.js +2 -3
- 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/svg.js +19 -0
- package/src/selectors/datasets.js +44 -0
- package/src/selectors/layers.js +7 -2
- package/src/selectors/scales.js +6 -0
- package/src/theme/defaults.js +140 -0
- package/types/basic.d.ts +17 -2
- package/types/index.d.ts +211 -0
- package/types/program.d.ts +2182 -204
- package/src/materialization/bars/grouped.js +0 -144
|
@@ -0,0 +1,160 @@
|
|
|
1
|
+
import {
|
|
2
|
+
cloneAndFreeze,
|
|
3
|
+
freezeOwned,
|
|
4
|
+
isPlainObject
|
|
5
|
+
} from "../../core/immutable.js";
|
|
6
|
+
import {
|
|
7
|
+
normalizeThemeDefinition,
|
|
8
|
+
resolveThemeTokens
|
|
9
|
+
} from "../../theme/defaults.js";
|
|
10
|
+
|
|
11
|
+
export const LOCAL_THEME_OWNER = "local";
|
|
12
|
+
|
|
13
|
+
function ownArray(value) {
|
|
14
|
+
return freezeOwned([...(value ?? [])]);
|
|
15
|
+
}
|
|
16
|
+
|
|
17
|
+
function requireThemeScope(value) {
|
|
18
|
+
if (!["self", "descendants"].includes(value)) {
|
|
19
|
+
throw new Error(`Unsupported theme scope "${value}".`);
|
|
20
|
+
}
|
|
21
|
+
return value;
|
|
22
|
+
}
|
|
23
|
+
|
|
24
|
+
function requireThemeOwner(value) {
|
|
25
|
+
if (typeof value !== "string" || value.length === 0) {
|
|
26
|
+
throw new TypeError("Theme frame owner must be a non-empty string.");
|
|
27
|
+
}
|
|
28
|
+
return value;
|
|
29
|
+
}
|
|
30
|
+
|
|
31
|
+
export function compositionThemeOwner(id, scope = "descendants") {
|
|
32
|
+
if (typeof id !== "string" || id.length === 0) {
|
|
33
|
+
throw new TypeError("Composition theme owner requires a non-empty id.");
|
|
34
|
+
}
|
|
35
|
+
requireThemeScope(scope);
|
|
36
|
+
return scope === "self" ? `composition:${id}:self` : `composition:${id}`;
|
|
37
|
+
}
|
|
38
|
+
|
|
39
|
+
export function createThemeFrame({
|
|
40
|
+
owner = LOCAL_THEME_OWNER,
|
|
41
|
+
scope = "self",
|
|
42
|
+
definition
|
|
43
|
+
}) {
|
|
44
|
+
const normalized = normalizeThemeDefinition(definition);
|
|
45
|
+
return freezeOwned({
|
|
46
|
+
owner: requireThemeOwner(owner),
|
|
47
|
+
scope: requireThemeScope(scope),
|
|
48
|
+
name: normalized.name,
|
|
49
|
+
tokens: normalized.tokens
|
|
50
|
+
});
|
|
51
|
+
}
|
|
52
|
+
|
|
53
|
+
export function upsertThemeFrame(frames = [], frame) {
|
|
54
|
+
if (!Array.isArray(frames)) {
|
|
55
|
+
throw new TypeError("Theme frames must be an array.");
|
|
56
|
+
}
|
|
57
|
+
if (!isPlainObject(frame)) {
|
|
58
|
+
throw new TypeError("Theme frame must be a plain object.");
|
|
59
|
+
}
|
|
60
|
+
return freezeOwned([
|
|
61
|
+
...frames.filter(current => current.owner !== frame.owner),
|
|
62
|
+
frame
|
|
63
|
+
]);
|
|
64
|
+
}
|
|
65
|
+
|
|
66
|
+
export function removeThemeFrameOwner(frames = [], owner) {
|
|
67
|
+
if (!Array.isArray(frames)) {
|
|
68
|
+
throw new TypeError("Theme frames must be an array.");
|
|
69
|
+
}
|
|
70
|
+
requireThemeOwner(owner);
|
|
71
|
+
const next = frames.filter(frame => frame.owner !== owner);
|
|
72
|
+
return freezeOwned({
|
|
73
|
+
frames: freezeOwned(next),
|
|
74
|
+
removed: next.length !== frames.length
|
|
75
|
+
});
|
|
76
|
+
}
|
|
77
|
+
|
|
78
|
+
export function moveLocalThemeScope(localOrder = [], scope) {
|
|
79
|
+
if (!Array.isArray(localOrder)) {
|
|
80
|
+
throw new TypeError("Theme localOrder must be an array.");
|
|
81
|
+
}
|
|
82
|
+
requireThemeScope(scope);
|
|
83
|
+
return freezeOwned([
|
|
84
|
+
...localOrder.filter(current => current !== scope),
|
|
85
|
+
scope
|
|
86
|
+
]);
|
|
87
|
+
}
|
|
88
|
+
|
|
89
|
+
function ownCanonicalThemeState(state, composition) {
|
|
90
|
+
const frames = ownArray(state.frames);
|
|
91
|
+
const localOrder = ownArray(state.localOrder);
|
|
92
|
+
const overrides = ownArray(state.overrides);
|
|
93
|
+
const result = { frames, localOrder, overrides };
|
|
94
|
+
if (composition || state.descendantFrames !== undefined) {
|
|
95
|
+
result.descendantFrames = ownArray(state.descendantFrames);
|
|
96
|
+
}
|
|
97
|
+
return cloneAndFreeze(result);
|
|
98
|
+
}
|
|
99
|
+
|
|
100
|
+
export function normalizeThemeState(state, { composition = false } = {}) {
|
|
101
|
+
if (state === undefined) {
|
|
102
|
+
return freezeOwned({
|
|
103
|
+
frames: freezeOwned([]),
|
|
104
|
+
...(composition ? { descendantFrames: freezeOwned([]) } : {}),
|
|
105
|
+
localOrder: freezeOwned([]),
|
|
106
|
+
overrides: freezeOwned([])
|
|
107
|
+
});
|
|
108
|
+
}
|
|
109
|
+
if (!isPlainObject(state)) {
|
|
110
|
+
throw new TypeError("Program theme state must be a plain object.");
|
|
111
|
+
}
|
|
112
|
+
if (Array.isArray(state.frames)) {
|
|
113
|
+
return ownCanonicalThemeState(state, composition);
|
|
114
|
+
}
|
|
115
|
+
|
|
116
|
+
const name = state.name ?? "light";
|
|
117
|
+
const tokens = state.tokens ?? {};
|
|
118
|
+
const scope = state.scope ?? "self";
|
|
119
|
+
const origin = state.origin?.ownerCompositionId;
|
|
120
|
+
const owner = origin === undefined
|
|
121
|
+
? LOCAL_THEME_OWNER
|
|
122
|
+
: compositionThemeOwner(origin, "descendants");
|
|
123
|
+
const frame = createThemeFrame({
|
|
124
|
+
owner,
|
|
125
|
+
scope,
|
|
126
|
+
definition: { base: name, tokens }
|
|
127
|
+
});
|
|
128
|
+
return freezeOwned({
|
|
129
|
+
frames: freezeOwned([frame]),
|
|
130
|
+
...(composition && scope === "descendants"
|
|
131
|
+
? { descendantFrames: freezeOwned([frame]) }
|
|
132
|
+
: composition
|
|
133
|
+
? { descendantFrames: freezeOwned([]) }
|
|
134
|
+
: {}),
|
|
135
|
+
localOrder: origin === undefined ? freezeOwned([scope]) : freezeOwned([]),
|
|
136
|
+
overrides: cloneAndFreeze(state.overrides ?? [])
|
|
137
|
+
});
|
|
138
|
+
}
|
|
139
|
+
|
|
140
|
+
export function resolveEffectiveThemeFrame(state) {
|
|
141
|
+
const frames = state?.frames;
|
|
142
|
+
return Array.isArray(frames) ? frames.at(-1) : undefined;
|
|
143
|
+
}
|
|
144
|
+
|
|
145
|
+
export function resolveEffectiveThemeTokens(state) {
|
|
146
|
+
const frame = resolveEffectiveThemeFrame(state);
|
|
147
|
+
return frame === undefined
|
|
148
|
+
? resolveThemeTokens("light")
|
|
149
|
+
: resolveThemeTokens({ base: frame.name, tokens: frame.tokens });
|
|
150
|
+
}
|
|
151
|
+
|
|
152
|
+
export function setThemeStateOverrides(state, overrides) {
|
|
153
|
+
if (!Array.isArray(overrides)) {
|
|
154
|
+
throw new TypeError("Theme overrides must be an array.");
|
|
155
|
+
}
|
|
156
|
+
return freezeOwned({
|
|
157
|
+
...state,
|
|
158
|
+
overrides: cloneAndFreeze([...overrides].sort())
|
|
159
|
+
});
|
|
160
|
+
}
|
|
@@ -1,3 +1,4 @@
|
|
|
1
|
+
import { withGuideLayoutValidation } from "../../materialization/guides/layout.js";
|
|
1
2
|
import { action } from "../../core/action.js";
|
|
2
3
|
import { noOptions } from "../../core/validation.js";
|
|
3
4
|
import {
|
|
@@ -92,7 +93,7 @@ function titleTextAction(kind, create) {
|
|
|
92
93
|
return action({
|
|
93
94
|
op,
|
|
94
95
|
description: `${create ? "Create" : "Rematerialize"} chart ${kind} text.`
|
|
95
|
-
}, function (args = {}) {
|
|
96
|
+
}, withGuideLayoutValidation(function (args = {}) {
|
|
96
97
|
noOptions(args, op);
|
|
97
98
|
const config = requireTitleConfig(this);
|
|
98
99
|
if (create && this.graphicSpec.objects[id] !== undefined) {
|
|
@@ -111,7 +112,7 @@ function titleTextAction(kind, create) {
|
|
|
111
112
|
...(component.lines.length > 1 ? { length: component.lines.length } : {}),
|
|
112
113
|
...resolveCanvasGraphicPlacement(this)
|
|
113
114
|
})[`edit${suffix}`]();
|
|
114
|
-
});
|
|
115
|
+
}));
|
|
115
116
|
}
|
|
116
117
|
|
|
117
118
|
export const editTitleText = titleTextAction("title", false);
|
|
@@ -121,7 +122,7 @@ export const createSubtitleText = titleTextAction("subtitle", true);
|
|
|
121
122
|
|
|
122
123
|
export const rematerializeTitle = action(
|
|
123
124
|
{ op: "rematerializeTitle", description: "Rematerialize chart title graphics." },
|
|
124
|
-
function (args = {}) {
|
|
125
|
+
withGuideLayoutValidation(function (args = {}) {
|
|
125
126
|
noOptions(args, "rematerializeTitle");
|
|
126
127
|
requireTitleConfig(this);
|
|
127
128
|
if (this.graphicSpec.objects.chartTitle?.type !== "text") {
|
|
@@ -138,7 +139,7 @@ export const rematerializeTitle = action(
|
|
|
138
139
|
next = next.editGraphics({ target: "chartSubtitle", remove: true });
|
|
139
140
|
}
|
|
140
141
|
return next;
|
|
141
|
-
}
|
|
142
|
+
})
|
|
142
143
|
);
|
|
143
144
|
|
|
144
145
|
export const createTitle = action(
|
|
@@ -147,7 +148,7 @@ export const createTitle = action(
|
|
|
147
148
|
description: "Create a chart title and optional subtitle.",
|
|
148
149
|
scope: "any"
|
|
149
150
|
},
|
|
150
|
-
function (args = {}) {
|
|
151
|
+
withGuideLayoutValidation(function (args = {}) {
|
|
151
152
|
assertTitleScope(this, "createTitle");
|
|
152
153
|
const options = normalizeTitleOptions(args);
|
|
153
154
|
if (Object.keys(this.semanticSpec.title).length > 0) {
|
|
@@ -172,7 +173,7 @@ export const createTitle = action(
|
|
|
172
173
|
next = next.createTitleText();
|
|
173
174
|
if (subtitle !== undefined) next = next.createSubtitleText();
|
|
174
175
|
return next;
|
|
175
|
-
}
|
|
176
|
+
})
|
|
176
177
|
);
|
|
177
178
|
|
|
178
179
|
export const editTitle = action(
|
|
@@ -181,7 +182,7 @@ export const editTitle = action(
|
|
|
181
182
|
description: "Edit one stable chart title resource.",
|
|
182
183
|
scope: "any"
|
|
183
184
|
},
|
|
184
|
-
function (args = {}) {
|
|
185
|
+
withGuideLayoutValidation(function (args = {}) {
|
|
185
186
|
assertTitleScope(this, "editTitle");
|
|
186
187
|
if (this.semanticSpec.title.text === undefined) {
|
|
187
188
|
throw new Error("editTitle requires an existing chart title.");
|
|
@@ -210,7 +211,7 @@ export const editTitle = action(
|
|
|
210
211
|
}
|
|
211
212
|
resolveTitleLayout(next, normalized.config);
|
|
212
213
|
return next.rematerializeTitle();
|
|
213
|
-
}
|
|
214
|
+
})
|
|
214
215
|
);
|
|
215
216
|
|
|
216
217
|
export const removeTitle = action(
|
|
@@ -219,7 +220,7 @@ export const removeTitle = action(
|
|
|
219
220
|
description: "Remove the complete chart title resource.",
|
|
220
221
|
scope: "any"
|
|
221
222
|
},
|
|
222
|
-
function (args = {}) {
|
|
223
|
+
withGuideLayoutValidation(function (args = {}) {
|
|
223
224
|
assertTitleScope(this, "removeTitle");
|
|
224
225
|
noOptions(args, "removeTitle");
|
|
225
226
|
if (
|
|
@@ -246,5 +247,5 @@ export const removeTitle = action(
|
|
|
246
247
|
return next.compositionSpec?.type === "facet"
|
|
247
248
|
? next.materializeComposition()
|
|
248
249
|
: next;
|
|
249
|
-
}
|
|
250
|
+
})
|
|
250
251
|
);
|
|
@@ -7,12 +7,10 @@ import {
|
|
|
7
7
|
validatePositiveFinite
|
|
8
8
|
} from "../../core/validation.js";
|
|
9
9
|
import { resolveGraphicBounds } from "../../layout/canvas.js";
|
|
10
|
-
import { resolveConcreteGraphicBounds } from "../../grammar/schemas/graphicBounds.js";
|
|
11
10
|
import {
|
|
12
11
|
alignedTextAnchor,
|
|
13
12
|
alignedTitleAnchor,
|
|
14
13
|
buildTitleReadingBlock,
|
|
15
|
-
layoutBoundsIntersect,
|
|
16
14
|
resolveTitleComponentBounds,
|
|
17
15
|
unionTitleBounds
|
|
18
16
|
} from "../../layout/title.js";
|
|
@@ -176,35 +174,7 @@ export function requireTitleConfig(program) {
|
|
|
176
174
|
return program.titleConfig;
|
|
177
175
|
}
|
|
178
176
|
|
|
179
|
-
function
|
|
180
|
-
const ids = [];
|
|
181
|
-
const axisChannel = ["top", "bottom"].includes(position) ? "x" : "y";
|
|
182
|
-
const axis = program.guideConfigs.axis?.[axisChannel];
|
|
183
|
-
if (axis && Object.values(axis).some(config => config?.position === position)) {
|
|
184
|
-
const prefix = axisChannel === "x" ? "xAxis" : "yAxis";
|
|
185
|
-
ids.push(`${prefix}Line`, `${prefix}Ticks`, `${prefix}Labels`, `${prefix}Title`);
|
|
186
|
-
}
|
|
187
|
-
const prefixes = {
|
|
188
|
-
series: "seriesLegend",
|
|
189
|
-
color: "colorLegend",
|
|
190
|
-
gradient: "colorGradient",
|
|
191
|
-
opacity: "opacityLegend"
|
|
192
|
-
};
|
|
193
|
-
for (const [kind, config] of Object.entries(program.guideConfigs.legend ?? {})) {
|
|
194
|
-
if (config?.position !== position || prefixes[kind] === undefined) continue;
|
|
195
|
-
ids.push(...Object.keys(program.graphicSpec.objects).filter(
|
|
196
|
-
id => id.startsWith(prefixes[kind])
|
|
197
|
-
));
|
|
198
|
-
if (kind === "series" && program.guideConfigs.legend?.size !== undefined) {
|
|
199
|
-
ids.push(...Object.keys(program.graphicSpec.objects).filter(
|
|
200
|
-
id => id.startsWith("sizeLegend")
|
|
201
|
-
));
|
|
202
|
-
}
|
|
203
|
-
}
|
|
204
|
-
return [...new Set(ids)];
|
|
205
|
-
}
|
|
206
|
-
|
|
207
|
-
function validateLayout(program, position, titleBounds, plot, canvas) {
|
|
177
|
+
function validateLayout(position, titleBounds, plot, canvas) {
|
|
208
178
|
if (
|
|
209
179
|
titleBounds.left < 0 || titleBounds.top < 0 ||
|
|
210
180
|
titleBounds.right > canvas.width || titleBounds.bottom > canvas.height
|
|
@@ -220,14 +190,6 @@ function validateLayout(program, position, titleBounds, plot, canvas) {
|
|
|
220
190
|
if (!outsidePlot) {
|
|
221
191
|
throw new Error(`Chart title requires more ${position}-margin space.`);
|
|
222
192
|
}
|
|
223
|
-
for (const id of reservedGraphicIds(program, position)) {
|
|
224
|
-
const bounds = program.graphicSpec.objects[id] === undefined
|
|
225
|
-
? undefined
|
|
226
|
-
: resolveConcreteGraphicBounds(program.graphicSpec, id);
|
|
227
|
-
if (bounds !== undefined && layoutBoundsIntersect(titleBounds, bounds)) {
|
|
228
|
-
throw new Error(`Chart title and ${position} guides require more margin space.`);
|
|
229
|
-
}
|
|
230
|
-
}
|
|
231
193
|
}
|
|
232
194
|
|
|
233
195
|
export function resolveTitleLayout(program, config) {
|
|
@@ -293,7 +255,6 @@ export function resolveTitleLayout(program, config) {
|
|
|
293
255
|
: [resolveTitleComponentBounds(subtitle, config.subtitleStyle)])
|
|
294
256
|
]);
|
|
295
257
|
validateLayout(
|
|
296
|
-
program,
|
|
297
258
|
config.position,
|
|
298
259
|
titleBounds,
|
|
299
260
|
plot,
|
|
@@ -1,6 +1,8 @@
|
|
|
1
1
|
import { action } from "../../core/action.js";
|
|
2
2
|
import { validateOptionObject } from "../../core/validation.js";
|
|
3
3
|
import { findDataset } from "../../selectors/datasets.js";
|
|
4
|
+
import { findLayer } from "../../selectors/layers.js";
|
|
5
|
+
import { STROKE_STYLE_PROPERTIES } from "../../grammar/strokeStyle.js";
|
|
4
6
|
import {
|
|
5
7
|
applyFacadeGuides,
|
|
6
8
|
normalizeAppearance,
|
|
@@ -19,16 +21,16 @@ const OPTIONS = Object.freeze([
|
|
|
19
21
|
]);
|
|
20
22
|
const POSITION_OPTIONS = Object.freeze(["field", "fieldType", "scale"]);
|
|
21
23
|
const DENSITY_OPTIONS = Object.freeze([
|
|
22
|
-
"bandwidth", "extent", "steps", "kernel", "normalization", "width"
|
|
24
|
+
"bandwidth", "extent", "steps", "kernel", "normalization", "weight", "width", "side"
|
|
23
25
|
]);
|
|
24
26
|
const WIDTH_OPTIONS = Object.freeze(["band", "resolve"]);
|
|
25
27
|
const SPLIT_OPTIONS = Object.freeze(["field", "domain"]);
|
|
26
28
|
const AREA_OPTIONS = Object.freeze([
|
|
27
|
-
"fill", "opacity", "stroke", "strokeWidth", "curve"
|
|
29
|
+
"fill", "opacity", "stroke", "strokeWidth", "curve",
|
|
30
|
+
...STROKE_STYLE_PROPERTIES
|
|
28
31
|
]);
|
|
29
32
|
const CATEGORICAL_TYPES = Object.freeze(["nominal", "ordinal"]);
|
|
30
33
|
const OPERATION = "createViolinPlot";
|
|
31
|
-
const ROLE_ERROR = `${OPERATION} requires one categorical axis and one quantitative axis.`;
|
|
32
34
|
|
|
33
35
|
function inferFieldType(dataset, encoding, label) {
|
|
34
36
|
if (encoding.fieldType !== undefined) return encoding.fieldType;
|
|
@@ -44,7 +46,7 @@ function inferFieldType(dataset, encoding, label) {
|
|
|
44
46
|
return values.every(Number.isFinite) ? "quantitative" : "nominal";
|
|
45
47
|
}
|
|
46
48
|
|
|
47
|
-
function
|
|
49
|
+
export function normalizeViolinPosition(dataset, value, label) {
|
|
48
50
|
const encoding = normalizeFieldEncoding(value, label);
|
|
49
51
|
validateOptionObject(encoding, POSITION_OPTIONS, label);
|
|
50
52
|
return {
|
|
@@ -53,6 +55,54 @@ function normalizePosition(dataset, value, label) {
|
|
|
53
55
|
};
|
|
54
56
|
}
|
|
55
57
|
|
|
58
|
+
export function resolveViolinRoles(dataset, xValue, yValue, operation) {
|
|
59
|
+
const x = normalizeViolinPosition(dataset, xValue, `${operation} x`);
|
|
60
|
+
const y = normalizeViolinPosition(dataset, yValue, `${operation} y`);
|
|
61
|
+
const xCategorical = CATEGORICAL_TYPES.includes(x.fieldType);
|
|
62
|
+
const yCategorical = CATEGORICAL_TYPES.includes(y.fieldType);
|
|
63
|
+
const roleError = `${operation} requires one categorical axis and one quantitative axis.`;
|
|
64
|
+
if (xCategorical === yCategorical || (
|
|
65
|
+
x.fieldType !== "quantitative" && y.fieldType !== "quantitative"
|
|
66
|
+
)) {
|
|
67
|
+
throw new Error(roleError);
|
|
68
|
+
}
|
|
69
|
+
const category = xCategorical ? x : y;
|
|
70
|
+
const value = xCategorical ? y : x;
|
|
71
|
+
if (value.fieldType !== "quantitative") throw new Error(roleError);
|
|
72
|
+
return {
|
|
73
|
+
x,
|
|
74
|
+
y,
|
|
75
|
+
category,
|
|
76
|
+
value,
|
|
77
|
+
orientation: xCategorical ? "vertical" : "horizontal",
|
|
78
|
+
densityChannel: xCategorical ? "x" : "y"
|
|
79
|
+
};
|
|
80
|
+
}
|
|
81
|
+
|
|
82
|
+
export function resolveViolinSplit(value, category, operation, { removable = false } = {}) {
|
|
83
|
+
if (removable && value === false) return undefined;
|
|
84
|
+
if (value === undefined) return undefined;
|
|
85
|
+
validateOptionObject(value, SPLIT_OPTIONS, `${operation} split`);
|
|
86
|
+
if (typeof value.field !== "string" || value.field.length === 0) {
|
|
87
|
+
throw new TypeError(`${operation} split.field must be a non-empty string.`);
|
|
88
|
+
}
|
|
89
|
+
const split = { ...value };
|
|
90
|
+
if (split.field === category.field) {
|
|
91
|
+
throw new Error(`${operation} split field must differ from its category field.`);
|
|
92
|
+
}
|
|
93
|
+
return split;
|
|
94
|
+
}
|
|
95
|
+
|
|
96
|
+
export function resolveViolinDensity(value, current = {}, operation = OPERATION) {
|
|
97
|
+
if (value !== undefined) {
|
|
98
|
+
validateOptionObject(value, DENSITY_OPTIONS, `${operation} density`);
|
|
99
|
+
if (value.width !== undefined) {
|
|
100
|
+
validateOptionObject(value.width, WIDTH_OPTIONS, `${operation} density.width`);
|
|
101
|
+
}
|
|
102
|
+
}
|
|
103
|
+
return { ...current, ...(value ?? {}) };
|
|
104
|
+
}
|
|
105
|
+
|
|
56
106
|
function axisGuideOptions(value, field) {
|
|
57
107
|
if (value === false) return false;
|
|
58
108
|
return {
|
|
@@ -95,31 +145,9 @@ export const createViolinPlot = action(
|
|
|
95
145
|
});
|
|
96
146
|
const data = resolveFacadeData(this, args.data, OPERATION);
|
|
97
147
|
const dataset = findDataset(this, data);
|
|
98
|
-
const
|
|
99
|
-
const
|
|
100
|
-
const
|
|
101
|
-
const yCategorical = CATEGORICAL_TYPES.includes(y.fieldType);
|
|
102
|
-
if (xCategorical === yCategorical || (
|
|
103
|
-
x.fieldType !== "quantitative" && y.fieldType !== "quantitative"
|
|
104
|
-
)) {
|
|
105
|
-
throw new Error(ROLE_ERROR);
|
|
106
|
-
}
|
|
107
|
-
const category = xCategorical ? x : y;
|
|
108
|
-
const value = xCategorical ? y : x;
|
|
109
|
-
if (value.fieldType !== "quantitative") {
|
|
110
|
-
throw new Error(ROLE_ERROR);
|
|
111
|
-
}
|
|
112
|
-
let split = args.split;
|
|
113
|
-
if (split !== undefined) {
|
|
114
|
-
validateOptionObject(split, SPLIT_OPTIONS, `${OPERATION} split`);
|
|
115
|
-
if (typeof split.field !== "string" || split.field.length === 0) {
|
|
116
|
-
throw new TypeError(`${OPERATION} split.field must be a non-empty string.`);
|
|
117
|
-
}
|
|
118
|
-
split = { ...split };
|
|
119
|
-
}
|
|
120
|
-
if (split?.field === category.field) {
|
|
121
|
-
throw new Error(`${OPERATION} split field must differ from its category field.`);
|
|
122
|
-
}
|
|
148
|
+
const roles = resolveViolinRoles(dataset, args.x, args.y, OPERATION);
|
|
149
|
+
const { x, y, category, value } = roles;
|
|
150
|
+
const split = resolveViolinSplit(args.split, category, OPERATION);
|
|
123
151
|
const color = normalizeEncoding(args.color, `${OPERATION} color`);
|
|
124
152
|
if (
|
|
125
153
|
color !== undefined &&
|
|
@@ -129,18 +157,8 @@ export const createViolinPlot = action(
|
|
|
129
157
|
`${OPERATION} color must encode its category or split field.`
|
|
130
158
|
);
|
|
131
159
|
}
|
|
132
|
-
const density = args.density
|
|
133
|
-
|
|
134
|
-
validateOptionObject(density, DENSITY_OPTIONS, `${OPERATION} density`);
|
|
135
|
-
if (density.width !== undefined) {
|
|
136
|
-
validateOptionObject(
|
|
137
|
-
density.width,
|
|
138
|
-
WIDTH_OPTIONS,
|
|
139
|
-
`${OPERATION} density.width`
|
|
140
|
-
);
|
|
141
|
-
}
|
|
142
|
-
}
|
|
143
|
-
const { width: densityWidth, ...densityOptions } = density;
|
|
160
|
+
const density = resolveViolinDensity(args.density);
|
|
161
|
+
const { width: densityWidth, side: densitySide, ...densityOptions } = density;
|
|
144
162
|
const area = normalizeAppearance(
|
|
145
163
|
args.area,
|
|
146
164
|
AREA_OPTIONS,
|
|
@@ -174,18 +192,47 @@ export const createViolinPlot = action(
|
|
|
174
192
|
source: data,
|
|
175
193
|
field: value.field,
|
|
176
194
|
groupBy: category.field,
|
|
177
|
-
densityChannel:
|
|
195
|
+
densityChannel: roles.densityChannel,
|
|
178
196
|
...(args.coordinate === undefined ? {} : { coordinate: args.coordinate }),
|
|
179
197
|
...(value.scale === undefined ? {} : { valueScale: value.scale }),
|
|
180
198
|
...densityOptions,
|
|
181
199
|
placement: {
|
|
182
200
|
type: "category",
|
|
201
|
+
...(densitySide === undefined ? {} : { side: densitySide }),
|
|
183
202
|
...(densityWidth === undefined ? {} : { width: densityWidth }),
|
|
184
203
|
...(split === undefined ? {} : { split }),
|
|
185
204
|
...(category.scale === undefined ? {} : { scale: category.scale })
|
|
186
205
|
}
|
|
187
206
|
});
|
|
188
207
|
if (color !== undefined) next = next.encodeColor(targetArgs(color, id));
|
|
189
|
-
|
|
208
|
+
next = applyFacadeGuides(next, guides, id, args.guides ?? {});
|
|
209
|
+
const transform = findDataset(next, findLayer(next, id).data).transform[0];
|
|
210
|
+
return next._withMarkConfig(id, {
|
|
211
|
+
...next.markConfigs[id],
|
|
212
|
+
violinPlot: {
|
|
213
|
+
materialized: true,
|
|
214
|
+
source: data,
|
|
215
|
+
orientation: roles.orientation,
|
|
216
|
+
category: category.field,
|
|
217
|
+
categoryType: category.fieldType,
|
|
218
|
+
value: value.field,
|
|
219
|
+
split: transform.placement.split,
|
|
220
|
+
density: {
|
|
221
|
+
bandwidth: transform.bandwidth,
|
|
222
|
+
extent: transform.extent,
|
|
223
|
+
steps: transform.steps,
|
|
224
|
+
kernel: transform.kernel,
|
|
225
|
+
normalization: transform.normalization,
|
|
226
|
+
...(transform.weight === undefined ? {} : { weight: transform.weight }),
|
|
227
|
+
width: transform.placement.width,
|
|
228
|
+
side: transform.placement.side
|
|
229
|
+
},
|
|
230
|
+
colorRole: color === undefined
|
|
231
|
+
? undefined
|
|
232
|
+
: color.field === category.field
|
|
233
|
+
? "category"
|
|
234
|
+
: color.field === split?.field ? "split" : undefined
|
|
235
|
+
}
|
|
236
|
+
});
|
|
190
237
|
}
|
|
191
238
|
);
|