ggaction 0.0.3 → 0.0.4
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 +28 -3
- package/README.md +95 -83
- package/package.json +11 -6
- package/src/actions/data/regression.js +1 -1
- package/src/actions/encodings/appearance.js +1 -1
- package/src/actions/encodings/color/continuous.js +137 -0
- package/src/actions/encodings/color/index.js +151 -0
- package/src/actions/encodings/color/layout.js +91 -0
- package/src/actions/encodings/color/policy.js +88 -0
- package/src/actions/encodings/index.js +2 -2
- package/src/actions/encodings/offset.js +1 -1
- package/src/actions/encodings/{position.js → position/index.js} +6 -6
- package/src/actions/encodings/position/resolve.js +1 -1
- package/src/actions/encodings/ranged.js +2 -2
- package/src/actions/encodings/strokeDash.js +1 -1
- package/src/actions/encodings/text.js +1 -1
- package/src/actions/errorBands/options.js +1 -1
- package/src/actions/errorBars/options.js +1 -1
- package/src/actions/facets/actions.js +1 -1
- package/src/actions/facets/derive.js +2 -2
- package/src/actions/facets/guides.js +1 -1
- package/src/actions/guides/axes/labels.js +1 -1
- package/src/actions/guides/axes/ticks.js +1 -1
- package/src/actions/guides/axes/titles.js +1 -1
- package/src/actions/guides/grids/resolve.js +1 -1
- package/src/actions/guides/legends/categorical/layout.js +4 -2
- package/src/actions/guides/legends/continuous/interval.js +1 -1
- package/src/actions/guides/legends/continuous/opacity.js +1 -1
- package/src/actions/guides/legends/edit.js +2 -20
- package/src/actions/guides/legends/remove.js +2 -20
- package/src/actions/guides/legends/size.js +1 -1
- package/src/actions/guides/legends/target.js +25 -0
- package/src/actions/guides/polar/{axes.js → axes/index.js} +5 -5
- package/src/actions/guides/polar/index.js +1 -1
- package/src/actions/guides/polar/resolve.js +1 -1
- package/src/actions/guides/tickValues.js +1 -1
- package/src/actions/intervals/resolve.js +1 -1
- package/src/actions/marks/arc/actions.js +2 -2
- package/src/actions/marks/area/actions.js +2 -2
- package/src/actions/marks/bar/edit.js +1 -1
- package/src/actions/marks/line/actions.js +3 -3
- package/src/actions/marks/rect/actions.js +1 -1
- package/src/actions/marks/rule/actions.js +1 -1
- package/src/actions/marks/shared.js +1 -1
- package/src/actions/marks/text/actions.js +1 -1
- package/src/actions/primitives/semanticValue.js +1 -1
- package/src/actions/regression/components.js +1 -1
- package/src/actions/regression/create.js +1 -1
- package/src/actions/regression/edit.js +1 -1
- package/src/actions/scales/consumers/common.js +91 -0
- package/src/actions/scales/consumers/families.js +47 -0
- package/src/actions/scales/consumers/index.js +41 -0
- package/src/actions/scales/{consumers.js → consumers/seriesLayout.js} +10 -132
- package/src/actions/scales/create.js +1 -1
- package/src/actions/scales/definitions.js +2 -2
- package/src/actions/scales/edit.js +3 -3
- package/src/actions/scales/materialize.js +2 -2
- package/src/core/ChartProgram.js +22 -236
- package/src/core/compositionState.js +169 -0
- package/src/core/materializationState.js +65 -0
- package/src/core/programState.js +28 -0
- package/src/grammar/arcs.js +1 -1
- package/src/grammar/areaSeries.js +1 -1
- package/src/grammar/bars/aggregate.js +1 -1
- package/src/grammar/density.js +1 -1
- package/src/grammar/{facets.js → facets/index.js} +5 -5
- package/src/grammar/interval.js +2 -96
- package/src/grammar/lineSeries.js +1 -1
- package/src/grammar/palettes.js +5 -7
- package/src/grammar/polarLineCommands.js +1 -1
- package/src/grammar/regression/derive.js +97 -0
- package/src/grammar/regression/index.js +22 -0
- package/src/grammar/regression/models.js +282 -0
- package/src/grammar/regression/parameters.js +106 -0
- package/src/grammar/rules.js +1 -1
- package/src/grammar/scales/color.js +4 -2
- package/src/grammar/statistics/studentT.js +98 -0
- package/src/grammar/transforms.js +1 -1
- package/src/materialization/bars/aggregate.js +1 -1
- package/src/materialization/bars/grouped.js +1 -1
- package/src/materialization/bars/histogram.js +1 -1
- package/src/materialization/bars/ranged.js +1 -1
- package/src/materialization/density.js +1 -1
- package/src/materialization/dependencies.js +6 -87
- package/src/materialization/encodings.js +2 -2
- package/src/materialization/facetGuides/index.js +2 -0
- package/src/materialization/facetGuides/legacyCategorical.js +125 -0
- package/src/materialization/facetGuides/placement.js +126 -0
- package/src/materialization/facetGuides/preparation.js +188 -0
- package/src/materialization/facets.js +1 -1
- package/src/materialization/marks/capabilities.js +141 -0
- package/src/materialization/marks/index.js +105 -0
- package/src/materialization/marks/policies.js +87 -0
- package/src/materialization/rect.js +1 -1
- package/src/materialization/rowEncoding.js +1 -1
- package/src/materialization/scaleGuideDependencies.js +94 -0
- package/src/materialization/scales/map.js +1 -1
- package/src/materialization/scales/policies/series.js +1 -1
- package/src/materialization/scales/resolve.js +1 -1
- package/src/materialization/selection/items/bar.js +1 -1
- package/src/materialization/selection/styles.js +1 -1
- package/src/renderers/canvas/text.js +14 -1
- package/types/extension.d.ts +4 -1
- package/src/actions/encodings/color.js +0 -424
- package/src/grammar/regression.js +0 -578
- package/src/grammar/scales.js +0 -1
- package/src/materialization/facetGuides.js +0 -426
- package/src/materialization/marks.js +0 -316
|
@@ -5,7 +5,7 @@ import {
|
|
|
5
5
|
validateNonNegativeFinite,
|
|
6
6
|
validateUnitInterval
|
|
7
7
|
} from "../../../core/validation.js";
|
|
8
|
-
import { canMaterializeBar } from "../../../materialization/marks.js";
|
|
8
|
+
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";
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
import { action } from "../../../core/action.js";
|
|
2
2
|
import { deriveLineSeries } from "../../../grammar/lineSeries.js";
|
|
3
|
-
import { mapContinuousScaleValues, mapOrdinalValues } from "../../../grammar/scales.js";
|
|
3
|
+
import { mapContinuousScaleValues, mapOrdinalValues } from "../../../grammar/scales/index.js";
|
|
4
4
|
import { validateUserId } from "../../../core/identifiers.js";
|
|
5
5
|
import {
|
|
6
6
|
validateNonEmptyString,
|
|
@@ -26,8 +26,8 @@ import {
|
|
|
26
26
|
import { buildPolarLinePathCommands } from "../../../grammar/polarLineCommands.js";
|
|
27
27
|
import { resolvePolarFrame } from "../../../grammar/polar.js";
|
|
28
28
|
import { resolveGraphicBounds } from "../../../layout/canvas.js";
|
|
29
|
-
import { normalizeStrokeDashPattern } from "../../../grammar/scales.js";
|
|
30
|
-
import { canMaterializeLine } from "../../../materialization/marks.js";
|
|
29
|
+
import { normalizeStrokeDashPattern } from "../../../grammar/scales/index.js";
|
|
30
|
+
import { canMaterializeLine } from "../../../materialization/marks/index.js";
|
|
31
31
|
import { resolveMarkGraphicPlacement } from
|
|
32
32
|
"../../../materialization/graphicHierarchy.js";
|
|
33
33
|
import { rematerializeHighlightBaseline } from "../lifecycle.js";
|
|
@@ -6,7 +6,7 @@ import {
|
|
|
6
6
|
} from "../../../materialization/rectConfig.js";
|
|
7
7
|
import {
|
|
8
8
|
canMaterializeRect
|
|
9
|
-
} from "../../../materialization/marks.js";
|
|
9
|
+
} from "../../../materialization/marks/index.js";
|
|
10
10
|
import { resolveRectGraphicItems } from "../../../materialization/rect.js";
|
|
11
11
|
import { findDataset } from "../../../selectors/datasets.js";
|
|
12
12
|
import { findLayer, resolveEligibleLayer } from "../../../selectors/layers.js";
|
|
@@ -6,7 +6,7 @@ import {
|
|
|
6
6
|
mapOrdinalPositionValues,
|
|
7
7
|
mapOrdinalValues,
|
|
8
8
|
normalizeStrokeDashPattern
|
|
9
|
-
} from "../../../grammar/scales.js";
|
|
9
|
+
} from "../../../grammar/scales/index.js";
|
|
10
10
|
import { deriveRuleValues, resolveRuleMode } from "../../../grammar/rules.js";
|
|
11
11
|
import { resolveGraphicBounds } from "../../../layout/canvas.js";
|
|
12
12
|
import { findDataset } from "../../../selectors/datasets.js";
|
|
@@ -6,7 +6,7 @@ import { findDataset } from "../../selectors/datasets.js";
|
|
|
6
6
|
import { findLayer, hasLayer } from "../../selectors/layers.js";
|
|
7
7
|
import { findSemanticScale } from "../../selectors/scales.js";
|
|
8
8
|
import { resolveMarkPositionPolicy } from "../encodings/position/policies/index.js";
|
|
9
|
-
import { getMarkMaterializationStep } from "../../materialization/marks.js";
|
|
9
|
+
import { getMarkMaterializationStep } from "../../materialization/marks/index.js";
|
|
10
10
|
import {
|
|
11
11
|
POLAR_POSITION_CHANNELS,
|
|
12
12
|
CARTESIAN_POSITION_CHANNELS,
|
|
@@ -4,7 +4,7 @@ import {
|
|
|
4
4
|
DEFAULT_TEXT_MARK,
|
|
5
5
|
normalizeTextMarkConfig
|
|
6
6
|
} from "../../../grammar/text.js";
|
|
7
|
-
import { canMaterializeText } from "../../../materialization/marks.js";
|
|
7
|
+
import { canMaterializeText } from "../../../materialization/marks/index.js";
|
|
8
8
|
import { resolveTextGraphicItems } from "../../../materialization/text.js";
|
|
9
9
|
import { findLayer, resolveEligibleLayer } from "../../../selectors/layers.js";
|
|
10
10
|
import {
|
|
@@ -22,7 +22,7 @@ import {
|
|
|
22
22
|
validateSemanticScaleDomain,
|
|
23
23
|
validateSemanticScaleRange,
|
|
24
24
|
validateSemanticScaleType
|
|
25
|
-
} from "../../grammar/scales.js";
|
|
25
|
+
} from "../../grammar/scales/index.js";
|
|
26
26
|
|
|
27
27
|
function nonEmptyString(value, label) {
|
|
28
28
|
if (typeof value !== "string" || value.length === 0) {
|
|
@@ -7,7 +7,7 @@ import { resolveEligibleLayer } from "../../selectors/layers.js";
|
|
|
7
7
|
import {
|
|
8
8
|
REGRESSION_LOWER_FIELD,
|
|
9
9
|
REGRESSION_UPPER_FIELD
|
|
10
|
-
} from "../../grammar/regression.js";
|
|
10
|
+
} from "../../grammar/regression/index.js";
|
|
11
11
|
import { validateAreaCreateOutline } from "../marks/area/index.js";
|
|
12
12
|
|
|
13
13
|
const BAND_OPTIONS = Object.freeze([
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
import { action } from "../../core/action.js";
|
|
2
2
|
import { validateKeys } from "../../core/validation.js";
|
|
3
|
-
import { normalizeRegressionParameters } from "../../grammar/regression.js";
|
|
3
|
+
import { normalizeRegressionParameters } from "../../grammar/regression/index.js";
|
|
4
4
|
import {
|
|
5
5
|
findRegressionPoint,
|
|
6
6
|
inferRegressionGroup,
|
|
@@ -7,7 +7,7 @@ import {
|
|
|
7
7
|
validateNonNegativeFinite,
|
|
8
8
|
validateUnitInterval
|
|
9
9
|
} from "../../core/validation.js";
|
|
10
|
-
import { normalizeRegressionParameters } from "../../grammar/regression.js";
|
|
10
|
+
import { normalizeRegressionParameters } from "../../grammar/regression/index.js";
|
|
11
11
|
import { validateCurveInterpolation } from "../../grammar/curveCommands.js";
|
|
12
12
|
import { hasDataset } from "../../selectors/index.js";
|
|
13
13
|
import { findLayer } from "../../selectors/layers.js";
|
|
@@ -0,0 +1,91 @@
|
|
|
1
|
+
import {
|
|
2
|
+
readNominalField,
|
|
3
|
+
readQuantitativeField,
|
|
4
|
+
readScaleField,
|
|
5
|
+
readTemporalField
|
|
6
|
+
} from "../../../grammar/scales/index.js";
|
|
7
|
+
import { findDataset } from "../../../selectors/datasets.js";
|
|
8
|
+
import { requireSemanticScale } from "../../../selectors/scales.js";
|
|
9
|
+
import { SCALED_ENCODING_CHANNELS } from "../../../core/vocabulary.js";
|
|
10
|
+
|
|
11
|
+
export function findScale(program, id) {
|
|
12
|
+
return requireSemanticScale(program, id);
|
|
13
|
+
}
|
|
14
|
+
|
|
15
|
+
export function findScaleConsumers(program, id) {
|
|
16
|
+
const consumers = [];
|
|
17
|
+
for (const layer of program.semanticSpec.layers) {
|
|
18
|
+
for (const channel of SCALED_ENCODING_CHANNELS) {
|
|
19
|
+
const encoding = layer.encoding?.[channel];
|
|
20
|
+
if (encoding?.scale === id) consumers.push({ layer, channel, encoding });
|
|
21
|
+
}
|
|
22
|
+
}
|
|
23
|
+
return consumers;
|
|
24
|
+
}
|
|
25
|
+
|
|
26
|
+
export function requireConsumerDataset(program, consumer) {
|
|
27
|
+
const dataset = findDataset(program, consumer.layer.data);
|
|
28
|
+
if (dataset === undefined) {
|
|
29
|
+
throw new Error(
|
|
30
|
+
`Mark "${consumer.layer.id}" references unknown dataset "${consumer.layer.data}".`
|
|
31
|
+
);
|
|
32
|
+
}
|
|
33
|
+
return dataset;
|
|
34
|
+
}
|
|
35
|
+
|
|
36
|
+
export function isDirectCategoricalConsumer(consumer) {
|
|
37
|
+
return ["color", "strokeDash", "xOffset", "yOffset", "shape"].includes(
|
|
38
|
+
consumer.channel
|
|
39
|
+
) && consumer.encoding.fieldType === "nominal";
|
|
40
|
+
}
|
|
41
|
+
|
|
42
|
+
export function readConsumerFieldValues(
|
|
43
|
+
program,
|
|
44
|
+
consumer,
|
|
45
|
+
dataset,
|
|
46
|
+
scale = findScale(program, consumer.encoding.scale)
|
|
47
|
+
) {
|
|
48
|
+
const allowUnknown = Object.hasOwn(scale, "unknown");
|
|
49
|
+
if (isDirectCategoricalConsumer(consumer)) {
|
|
50
|
+
return allowUnknown
|
|
51
|
+
? readScaleField(
|
|
52
|
+
dataset.values,
|
|
53
|
+
consumer.encoding.field,
|
|
54
|
+
consumer.encoding.fieldType,
|
|
55
|
+
{ allowUnknown: true }
|
|
56
|
+
)
|
|
57
|
+
: readNominalField(dataset.values, consumer.encoding.field);
|
|
58
|
+
}
|
|
59
|
+
if (consumer.encoding.fieldType === "temporal") {
|
|
60
|
+
return allowUnknown
|
|
61
|
+
? readScaleField(dataset.values, consumer.encoding.field, "temporal", {
|
|
62
|
+
allowUnknown: true
|
|
63
|
+
})
|
|
64
|
+
: readTemporalField(dataset.values, consumer.encoding.field);
|
|
65
|
+
}
|
|
66
|
+
if (["nominal", "ordinal"].includes(consumer.encoding.fieldType)) {
|
|
67
|
+
if (!["ordinal", "band", "point"].includes(scale.type)) {
|
|
68
|
+
throw new Error(
|
|
69
|
+
`Scale materialization requires a quantitative encoding on mark "${consumer.layer.id}".`
|
|
70
|
+
);
|
|
71
|
+
}
|
|
72
|
+
return allowUnknown
|
|
73
|
+
? readScaleField(
|
|
74
|
+
dataset.values,
|
|
75
|
+
consumer.encoding.field,
|
|
76
|
+
consumer.encoding.fieldType,
|
|
77
|
+
{ allowUnknown: true }
|
|
78
|
+
)
|
|
79
|
+
: readNominalField(dataset.values, consumer.encoding.field);
|
|
80
|
+
}
|
|
81
|
+
if (consumer.encoding.fieldType !== "quantitative") {
|
|
82
|
+
throw new Error(
|
|
83
|
+
`Scale materialization requires a quantitative encoding on mark "${consumer.layer.id}".`
|
|
84
|
+
);
|
|
85
|
+
}
|
|
86
|
+
return allowUnknown
|
|
87
|
+
? readScaleField(dataset.values, consumer.encoding.field, "quantitative", {
|
|
88
|
+
allowUnknown: true
|
|
89
|
+
})
|
|
90
|
+
: readQuantitativeField(dataset.values, consumer.encoding.field);
|
|
91
|
+
}
|
|
@@ -0,0 +1,47 @@
|
|
|
1
|
+
import { deriveBarAggregates } from "../../../grammar/bars/aggregate.js";
|
|
2
|
+
import {
|
|
3
|
+
BAR_GRAINS,
|
|
4
|
+
resolveBarGrain
|
|
5
|
+
} from "../../../grammar/bars/policy.js";
|
|
6
|
+
import { deriveLineSeries } from "../../../grammar/lineSeries.js";
|
|
7
|
+
import { isAggregate } from "../../../grammar/aggregate.js";
|
|
8
|
+
import {
|
|
9
|
+
resolveRectConsumerValues
|
|
10
|
+
} from "../../../materialization/rect.js";
|
|
11
|
+
|
|
12
|
+
export function resolveMarkFamilyConsumerValues(consumer, dataset) {
|
|
13
|
+
if (consumer.layer.mark?.type === "rect") {
|
|
14
|
+
return {
|
|
15
|
+
matched: true,
|
|
16
|
+
values: resolveRectConsumerValues(
|
|
17
|
+
consumer.layer,
|
|
18
|
+
dataset,
|
|
19
|
+
consumer.channel
|
|
20
|
+
)
|
|
21
|
+
};
|
|
22
|
+
}
|
|
23
|
+
if (
|
|
24
|
+
consumer.layer.mark?.type === "line" &&
|
|
25
|
+
isAggregate(consumer.layer.encoding?.y?.aggregate)
|
|
26
|
+
) {
|
|
27
|
+
const derived = deriveLineSeries(dataset.values, consumer.layer);
|
|
28
|
+
return {
|
|
29
|
+
matched: true,
|
|
30
|
+
values: consumer.channel === "x" ? derived.xValues : derived.yValues
|
|
31
|
+
};
|
|
32
|
+
}
|
|
33
|
+
if (resolveBarGrain(consumer.layer) === BAR_GRAINS.aggregate) {
|
|
34
|
+
const derived = deriveBarAggregates(dataset.values, consumer.layer);
|
|
35
|
+
if (consumer.channel === "color") {
|
|
36
|
+
return {
|
|
37
|
+
matched: true,
|
|
38
|
+
values: derived.values.map(value => value.color)
|
|
39
|
+
};
|
|
40
|
+
}
|
|
41
|
+
return {
|
|
42
|
+
matched: true,
|
|
43
|
+
values: consumer.channel === "x" ? derived.xValues : derived.yValues
|
|
44
|
+
};
|
|
45
|
+
}
|
|
46
|
+
return { matched: false };
|
|
47
|
+
}
|
|
@@ -0,0 +1,41 @@
|
|
|
1
|
+
import { normalizeRuleDatum } from "../../../grammar/rules.js";
|
|
2
|
+
import {
|
|
3
|
+
findScale,
|
|
4
|
+
isDirectCategoricalConsumer,
|
|
5
|
+
readConsumerFieldValues,
|
|
6
|
+
requireConsumerDataset
|
|
7
|
+
} from "./common.js";
|
|
8
|
+
import { resolveMarkFamilyConsumerValues } from "./families.js";
|
|
9
|
+
|
|
10
|
+
export { findScale, findScaleConsumers } from "./common.js";
|
|
11
|
+
export {
|
|
12
|
+
resolveHistogramCountValues,
|
|
13
|
+
resolveSeriesLayoutScaleValues
|
|
14
|
+
} from "./seriesLayout.js";
|
|
15
|
+
|
|
16
|
+
export function resolveConsumerValues(program, consumer) {
|
|
17
|
+
const dataset = requireConsumerDataset(program, consumer);
|
|
18
|
+
if (Object.hasOwn(consumer.encoding, "datum")) {
|
|
19
|
+
return [normalizeRuleDatum(
|
|
20
|
+
consumer.encoding.datum,
|
|
21
|
+
consumer.encoding.fieldType,
|
|
22
|
+
consumer.channel
|
|
23
|
+
)];
|
|
24
|
+
}
|
|
25
|
+
if (
|
|
26
|
+
consumer.channel === "strokeDash" &&
|
|
27
|
+
!["line", "rule"].includes(consumer.layer.mark?.type)
|
|
28
|
+
) {
|
|
29
|
+
throw new Error(
|
|
30
|
+
"strokeDash scale materialization requires a line mark or rule mark."
|
|
31
|
+
);
|
|
32
|
+
}
|
|
33
|
+
const scale = findScale(program, consumer.encoding.scale);
|
|
34
|
+
if (isDirectCategoricalConsumer(consumer)) {
|
|
35
|
+
return readConsumerFieldValues(program, consumer, dataset, scale);
|
|
36
|
+
}
|
|
37
|
+
const family = resolveMarkFamilyConsumerValues(consumer, dataset);
|
|
38
|
+
return family.matched
|
|
39
|
+
? family.values
|
|
40
|
+
: readConsumerFieldValues(program, consumer, dataset, scale);
|
|
41
|
+
}
|
|
@@ -1,144 +1,26 @@
|
|
|
1
|
-
import { deriveBarAggregates } from "
|
|
1
|
+
import { deriveBarAggregates } from "../../../grammar/bars/aggregate.js";
|
|
2
2
|
import {
|
|
3
3
|
BAR_GRAINS,
|
|
4
4
|
resolveBarChannels,
|
|
5
5
|
resolveBarColorLayout,
|
|
6
6
|
resolveBarGrain
|
|
7
|
-
} from "
|
|
7
|
+
} from "../../../grammar/bars/policy.js";
|
|
8
8
|
import {
|
|
9
9
|
countHistogramBins,
|
|
10
10
|
findHistogramBinIndex,
|
|
11
11
|
resolveHistogramBins
|
|
12
|
-
} from "
|
|
13
|
-
import { deriveDensityAreaSeries } from "
|
|
14
|
-
import {
|
|
15
|
-
|
|
12
|
+
} from "../../../grammar/histogram.js";
|
|
13
|
+
import { deriveDensityAreaSeries } from "../../../grammar/areaSeries.js";
|
|
14
|
+
import {
|
|
15
|
+
resolveSeriesLayoutDomainValues
|
|
16
|
+
} from "../../../grammar/seriesLayout.js";
|
|
16
17
|
import {
|
|
17
18
|
readNominalField,
|
|
18
19
|
readQuantitativeField,
|
|
19
|
-
readScaleField,
|
|
20
|
-
readTemporalField,
|
|
21
20
|
resolveOrdinalDomain
|
|
22
|
-
} from "
|
|
23
|
-
import { findDataset } from "
|
|
24
|
-
import {
|
|
25
|
-
import { isAggregate } from "../../grammar/aggregate.js";
|
|
26
|
-
import { normalizeRuleDatum } from "../../grammar/rules.js";
|
|
27
|
-
import { SCALED_ENCODING_CHANNELS } from "../../core/vocabulary.js";
|
|
28
|
-
import { resolveRectConsumerValues } from "../../materialization/rect.js";
|
|
29
|
-
|
|
30
|
-
export function findScale(program, id) {
|
|
31
|
-
return requireSemanticScale(program, id);
|
|
32
|
-
}
|
|
33
|
-
|
|
34
|
-
export function findScaleConsumers(program, id) {
|
|
35
|
-
const consumers = [];
|
|
36
|
-
for (const layer of program.semanticSpec.layers) {
|
|
37
|
-
for (const channel of SCALED_ENCODING_CHANNELS) {
|
|
38
|
-
const encoding = layer.encoding?.[channel];
|
|
39
|
-
if (encoding?.scale === id) consumers.push({ layer, channel, encoding });
|
|
40
|
-
}
|
|
41
|
-
}
|
|
42
|
-
return consumers;
|
|
43
|
-
}
|
|
44
|
-
|
|
45
|
-
export function resolveConsumerValues(program, consumer) {
|
|
46
|
-
const dataset = findDataset(program, consumer.layer.data);
|
|
47
|
-
if (dataset === undefined) {
|
|
48
|
-
throw new Error(
|
|
49
|
-
`Mark "${consumer.layer.id}" references unknown dataset "${consumer.layer.data}".`
|
|
50
|
-
);
|
|
51
|
-
}
|
|
52
|
-
|
|
53
|
-
if (Object.hasOwn(consumer.encoding, "datum")) {
|
|
54
|
-
return [normalizeRuleDatum(
|
|
55
|
-
consumer.encoding.datum,
|
|
56
|
-
consumer.encoding.fieldType,
|
|
57
|
-
consumer.channel
|
|
58
|
-
)];
|
|
59
|
-
}
|
|
60
|
-
|
|
61
|
-
if (
|
|
62
|
-
consumer.channel === "strokeDash" &&
|
|
63
|
-
!["line", "rule"].includes(consumer.layer.mark?.type)
|
|
64
|
-
) {
|
|
65
|
-
throw new Error("strokeDash scale materialization requires a line mark or rule mark.");
|
|
66
|
-
}
|
|
67
|
-
const scale = findScale(program, consumer.encoding.scale);
|
|
68
|
-
const allowUnknown = Object.hasOwn(scale, "unknown");
|
|
69
|
-
if (consumer.layer.mark?.type === "rect") {
|
|
70
|
-
return resolveRectConsumerValues(
|
|
71
|
-
consumer.layer,
|
|
72
|
-
dataset,
|
|
73
|
-
consumer.channel
|
|
74
|
-
);
|
|
75
|
-
}
|
|
76
|
-
|
|
77
|
-
if (
|
|
78
|
-
["color", "strokeDash", "xOffset", "yOffset", "shape"].includes(consumer.channel) &&
|
|
79
|
-
consumer.encoding.fieldType === "nominal"
|
|
80
|
-
) {
|
|
81
|
-
return allowUnknown
|
|
82
|
-
? readScaleField(
|
|
83
|
-
dataset.values,
|
|
84
|
-
consumer.encoding.field,
|
|
85
|
-
consumer.encoding.fieldType,
|
|
86
|
-
{ allowUnknown: true }
|
|
87
|
-
)
|
|
88
|
-
: readNominalField(dataset.values, consumer.encoding.field);
|
|
89
|
-
}
|
|
90
|
-
|
|
91
|
-
if (
|
|
92
|
-
consumer.layer.mark?.type === "line" &&
|
|
93
|
-
isAggregate(consumer.layer.encoding?.y?.aggregate)
|
|
94
|
-
) {
|
|
95
|
-
const derived = deriveLineSeries(dataset.values, consumer.layer);
|
|
96
|
-
return consumer.channel === "x" ? derived.xValues : derived.yValues;
|
|
97
|
-
}
|
|
98
|
-
|
|
99
|
-
if (
|
|
100
|
-
resolveBarGrain(consumer.layer) === BAR_GRAINS.aggregate
|
|
101
|
-
) {
|
|
102
|
-
const derived = deriveBarAggregates(dataset.values, consumer.layer);
|
|
103
|
-
if (consumer.channel === "color") {
|
|
104
|
-
return derived.values.map(value => value.color);
|
|
105
|
-
}
|
|
106
|
-
return consumer.channel === "x" ? derived.xValues : derived.yValues;
|
|
107
|
-
}
|
|
108
|
-
|
|
109
|
-
if (consumer.encoding.fieldType === "temporal") {
|
|
110
|
-
return allowUnknown
|
|
111
|
-
? readScaleField(dataset.values, consumer.encoding.field, "temporal", {
|
|
112
|
-
allowUnknown: true
|
|
113
|
-
})
|
|
114
|
-
: readTemporalField(dataset.values, consumer.encoding.field);
|
|
115
|
-
}
|
|
116
|
-
if (["nominal", "ordinal"].includes(consumer.encoding.fieldType)) {
|
|
117
|
-
if (!["ordinal", "band", "point"].includes(scale.type)) {
|
|
118
|
-
throw new Error(
|
|
119
|
-
`Scale materialization requires a quantitative encoding on mark "${consumer.layer.id}".`
|
|
120
|
-
);
|
|
121
|
-
}
|
|
122
|
-
return allowUnknown
|
|
123
|
-
? readScaleField(
|
|
124
|
-
dataset.values,
|
|
125
|
-
consumer.encoding.field,
|
|
126
|
-
consumer.encoding.fieldType,
|
|
127
|
-
{ allowUnknown: true }
|
|
128
|
-
)
|
|
129
|
-
: readNominalField(dataset.values, consumer.encoding.field);
|
|
130
|
-
}
|
|
131
|
-
if (consumer.encoding.fieldType !== "quantitative") {
|
|
132
|
-
throw new Error(
|
|
133
|
-
`Scale materialization requires a quantitative encoding on mark "${consumer.layer.id}".`
|
|
134
|
-
);
|
|
135
|
-
}
|
|
136
|
-
return allowUnknown
|
|
137
|
-
? readScaleField(dataset.values, consumer.encoding.field, "quantitative", {
|
|
138
|
-
allowUnknown: true
|
|
139
|
-
})
|
|
140
|
-
: readQuantitativeField(dataset.values, consumer.encoding.field);
|
|
141
|
-
}
|
|
21
|
+
} from "../../../grammar/scales/index.js";
|
|
22
|
+
import { findDataset } from "../../../selectors/datasets.js";
|
|
23
|
+
import { findScale } from "./common.js";
|
|
142
24
|
|
|
143
25
|
export function resolveHistogramCountValues(program, consumer) {
|
|
144
26
|
const xEncoding = consumer.layer.encoding?.x;
|
|
@@ -146,7 +28,6 @@ export function resolveHistogramCountValues(program, consumer) {
|
|
|
146
28
|
? undefined
|
|
147
29
|
: findScale(program, xEncoding.scale);
|
|
148
30
|
const dataset = findDataset(program, consumer.layer.data);
|
|
149
|
-
|
|
150
31
|
if (xEncoding?.bin === undefined || xScale === undefined) {
|
|
151
32
|
throw new Error(
|
|
152
33
|
`Histogram mark "${consumer.layer.id}" requires a binned x scale.`
|
|
@@ -157,7 +38,6 @@ export function resolveHistogramCountValues(program, consumer) {
|
|
|
157
38
|
`Histogram mark "${consumer.layer.id}" requires an existing dataset.`
|
|
158
39
|
);
|
|
159
40
|
}
|
|
160
|
-
|
|
161
41
|
const xValues = readQuantitativeField(dataset.values, xEncoding.field);
|
|
162
42
|
const bins = resolveHistogramBins({
|
|
163
43
|
values: xValues,
|
|
@@ -186,7 +66,6 @@ function resolveHistogramPartitions(program, consumer) {
|
|
|
186
66
|
if (colorEncoding?.scale === undefined) {
|
|
187
67
|
return countHistogramBins(xValues, bins.boundaries).map(value => [value]);
|
|
188
68
|
}
|
|
189
|
-
|
|
190
69
|
const colorScale = findScale(program, colorEncoding.scale);
|
|
191
70
|
const colorValues = readNominalField(dataset.values, colorEncoding.field);
|
|
192
71
|
const colorDomain = resolveOrdinalDomain(colorScale.domain, colorValues);
|
|
@@ -224,7 +103,6 @@ function resolveAggregatePartitions(program, consumer) {
|
|
|
224
103
|
]));
|
|
225
104
|
return categoryDomain.map(value => [byCategory.get(value) ?? 0]);
|
|
226
105
|
}
|
|
227
|
-
|
|
228
106
|
const colorScale = findScale(program, colorEncoding.scale);
|
|
229
107
|
const colorValues = readNominalField(dataset.values, colorEncoding.field);
|
|
230
108
|
const colorDomain = resolveOrdinalDomain(colorScale.domain, colorValues);
|
|
@@ -15,7 +15,7 @@ import {
|
|
|
15
15
|
isContinuousColorScaleType,
|
|
16
16
|
isDiscretizedColorScaleType,
|
|
17
17
|
normalizeScaleDefinition
|
|
18
|
-
} from "../../grammar/scales.js";
|
|
18
|
+
} from "../../grammar/scales/index.js";
|
|
19
19
|
import { findSemanticScale } from "../../selectors/scales.js";
|
|
20
20
|
|
|
21
21
|
const CREATE_SCALE_OPTIONS = Object.freeze([
|
|
@@ -22,12 +22,12 @@ import {
|
|
|
22
22
|
validateScalePropertyForType,
|
|
23
23
|
validateScaleTypeForRole,
|
|
24
24
|
isDiscretePositionScaleType
|
|
25
|
-
} from "../../grammar/scales.js";
|
|
25
|
+
} from "../../grammar/scales/index.js";
|
|
26
26
|
import {
|
|
27
27
|
validateRadialRange,
|
|
28
28
|
validateThetaRange
|
|
29
29
|
} from "../../grammar/polar.js";
|
|
30
|
-
import { withScaleUnknown } from "../../grammar/scales.js";
|
|
30
|
+
import { withScaleUnknown } from "../../grammar/scales/index.js";
|
|
31
31
|
import { findSemanticScale } from "../../selectors/scales.js";
|
|
32
32
|
|
|
33
33
|
const BASE_OPTIONS = Object.freeze(["id", "type", "domain", "range"]);
|
|
@@ -21,12 +21,12 @@ import {
|
|
|
21
21
|
isDiscretePositionScaleType,
|
|
22
22
|
hasOrdinalDomain,
|
|
23
23
|
normalizeScaleDefinition
|
|
24
|
-
} from "../../grammar/scales.js";
|
|
24
|
+
} from "../../grammar/scales/index.js";
|
|
25
25
|
import {
|
|
26
26
|
validateRadialRange,
|
|
27
27
|
validateThetaRange
|
|
28
28
|
} from "../../grammar/polar.js";
|
|
29
|
-
import { getMarkMaterializationStep } from "../../materialization/marks.js";
|
|
29
|
+
import { getMarkMaterializationStep } from "../../materialization/marks/index.js";
|
|
30
30
|
import {
|
|
31
31
|
applyMaterializationPlan
|
|
32
32
|
} from "../../materialization/dependencies.js";
|
|
@@ -34,7 +34,7 @@ import {
|
|
|
34
34
|
findSemanticScale,
|
|
35
35
|
requireSemanticScale
|
|
36
36
|
} from "../../selectors/scales.js";
|
|
37
|
-
import { findScaleConsumers } from "./consumers.js";
|
|
37
|
+
import { findScaleConsumers } from "./consumers/index.js";
|
|
38
38
|
import { normalizePositionScaleChannel } from "../../core/vocabulary.js";
|
|
39
39
|
|
|
40
40
|
const OPTIONS = Object.freeze([
|
|
@@ -11,7 +11,7 @@ import {
|
|
|
11
11
|
canDeferScaleConsumerApplication,
|
|
12
12
|
getMarkRematerializationStep,
|
|
13
13
|
getScaleConsumerMaterializationMode
|
|
14
|
-
} from "../../materialization/marks.js";
|
|
14
|
+
} from "../../materialization/marks/index.js";
|
|
15
15
|
import { mapScaleConsumerValues } from
|
|
16
16
|
"../../materialization/scales/map.js";
|
|
17
17
|
import { resolveScaleMaterialization } from
|
|
@@ -21,7 +21,7 @@ import {
|
|
|
21
21
|
findScaleConsumers,
|
|
22
22
|
resolveConsumerValues,
|
|
23
23
|
resolveSeriesLayoutScaleValues
|
|
24
|
-
} from "./consumers.js";
|
|
24
|
+
} from "./consumers/index.js";
|
|
25
25
|
|
|
26
26
|
const OPTIONS = Object.freeze(["id", "guides", "marks"]);
|
|
27
27
|
|