ggaction 0.0.4 → 0.0.5
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 +30 -0
- package/README.md +35 -13
- package/package.json +18 -7
- package/src/actions/boxPlots/create.js +13 -7
- package/src/actions/boxPlots/edit.js +31 -35
- package/src/actions/boxPlots/materialize.js +3 -0
- package/src/actions/boxPlots/options.js +8 -1
- package/src/actions/boxPlots/resolve.js +10 -2
- package/src/actions/charts/bar.js +50 -0
- package/src/actions/charts/heatmap.js +205 -0
- package/src/actions/charts/histogram.js +58 -0
- package/src/actions/charts/index.js +15 -0
- package/src/actions/charts/line.js +69 -0
- package/src/actions/charts/parallel.js +76 -0
- package/src/actions/charts/scatter.js +56 -0
- package/src/actions/charts/shared.js +121 -0
- package/src/actions/coordinates/parallel.js +50 -0
- package/src/actions/data/bin2d.js +137 -0
- package/src/actions/data/density.js +54 -13
- package/src/actions/data/derived.js +22 -0
- package/src/actions/data/filter.js +5 -0
- package/src/actions/data/gradientProfile.js +65 -0
- package/src/actions/data/horizon.js +71 -0
- package/src/actions/data/index.js +29 -2
- package/src/actions/data/window.js +50 -0
- package/src/actions/encodings/color/index.js +17 -1
- package/src/actions/encodings/color/layout.js +8 -0
- package/src/actions/encodings/density/resolve.js +109 -0
- package/src/actions/encodings/density.js +193 -88
- package/src/actions/encodings/horizon/resolve.js +283 -0
- package/src/actions/encodings/horizon.js +364 -0
- package/src/actions/encodings/index.js +6 -0
- package/src/actions/encodings/parallel.js +115 -0
- package/src/actions/encodings/pathOrder.js +131 -0
- package/src/actions/encodings/position/apply.js +73 -4
- package/src/actions/encodings/position/index.js +15 -2
- package/src/actions/encodings/position/policies/arc.js +27 -4
- package/src/actions/encodings/position/policies/area.js +33 -2
- package/src/actions/encodings/position/policies/index.js +7 -2
- package/src/actions/encodings/position/policies/line.js +18 -2
- package/src/actions/encodings/position/resolve.js +24 -2
- package/src/actions/encodings/ranged.js +3 -1
- package/src/actions/encodings/ruleAppearance.js +88 -10
- package/src/actions/facets/actions.js +1 -2
- package/src/actions/facets/derive.js +33 -3
- package/src/actions/facets/replay.js +7 -36
- package/src/actions/gradientPlots/components.js +177 -0
- package/src/actions/gradientPlots/create.js +96 -0
- package/src/actions/gradientPlots/edit.js +153 -0
- package/src/actions/gradientPlots/index.js +24 -0
- package/src/actions/gradientPlots/materialize.js +287 -0
- package/src/actions/gradientPlots/options.js +120 -0
- package/src/actions/gradientPlots/paint.js +107 -0
- package/src/actions/gradientPlots/rebind.js +51 -0
- package/src/actions/gradientPlots/resolve.js +81 -0
- package/src/actions/guides/applicability.js +44 -17
- package/src/actions/guides/axes/axes.js +37 -3
- package/src/actions/guides/axes/index.js +2 -0
- package/src/actions/guides/axes/labels.js +11 -6
- package/src/actions/guides/axes/parallel/resolve.js +86 -0
- package/src/actions/guides/axes/parallel.js +228 -0
- package/src/actions/guides/axes/titles.js +11 -8
- package/src/actions/guides/guides.js +60 -5
- package/src/actions/guides/legends/categorical/actions.js +48 -11
- package/src/actions/guides/legends/edit.js +5 -0
- package/src/actions/guides/legends/index.js +2 -0
- package/src/actions/guides/legends/remove.js +4 -11
- package/src/actions/guides/legends/strokeWidth.js +170 -0
- package/src/actions/index.js +6 -0
- package/src/actions/marks/area/actions.js +60 -136
- package/src/actions/marks/area/materialize.js +163 -0
- package/src/actions/marks/index.js +5 -1
- package/src/actions/marks/line/actions.js +99 -80
- package/src/actions/marks/line/materialize.js +146 -0
- package/src/actions/marks/point/create.js +76 -0
- package/src/actions/marks/point/edit.js +85 -0
- package/src/actions/marks/point/index.js +11 -1
- package/src/actions/marks/point/jitter.js +72 -0
- package/src/actions/marks/point/{actions.js → materialize.js} +175 -170
- package/src/actions/marks/rect/actions.js +3 -0
- package/src/actions/marks/remove.js +13 -2
- package/src/actions/marks/rule/actions.js +25 -3
- package/src/actions/marks/text/actions.js +19 -4
- package/src/actions/marks/text/index.js +7 -1
- package/src/actions/marks/text/layout.js +321 -0
- package/src/actions/primitives/semanticValidation/dataset.js +22 -0
- package/src/actions/primitives/semanticValidation/guide.js +43 -0
- package/src/actions/primitives/semanticValidation/index.js +23 -0
- package/src/actions/primitives/semanticValidation/layer.js +74 -0
- package/src/actions/primitives/semanticValidation/scale.js +74 -0
- package/src/actions/primitives/semanticValidation/shared.js +5 -0
- package/src/actions/primitives/semanticValue.js +1 -204
- package/src/actions/regression/edit.js +19 -21
- package/src/actions/scales/consumers/common.js +18 -0
- package/src/actions/scales/consumers/families.js +14 -3
- package/src/actions/scales/definitions.js +30 -0
- package/src/actions/scales/edit.js +6 -204
- package/src/actions/scales/editPolicy.js +214 -0
- package/src/actions/scales/materialize.js +1 -1
- package/src/actions/scales/patch.js +26 -0
- package/src/actions/selection/actions.js +28 -3
- package/src/actions/violinPlots/create.js +198 -0
- package/src/actions/violinPlots/index.js +5 -0
- package/src/core/textMetrics.js +47 -0
- package/src/core/vocabulary.js +7 -2
- package/src/grammar/arcs.js +49 -12
- package/src/grammar/areaSeries.js +41 -5
- package/src/grammar/bin2d.js +333 -0
- package/src/grammar/categoricalDensity.js +192 -0
- package/src/grammar/coordinates.js +1 -1
- package/src/grammar/curveCommands.js +3 -1
- package/src/grammar/density.js +252 -26
- package/src/grammar/facets/dependencies.js +3 -11
- package/src/grammar/facets/index.js +3 -1
- package/src/grammar/gradientProfile.js +213 -0
- package/src/grammar/horizon.js +455 -0
- package/src/grammar/jitter.js +197 -0
- package/src/grammar/lineSeries.js +69 -0
- package/src/grammar/paint.js +88 -0
- package/src/grammar/parallelCoordinates.js +213 -0
- package/src/grammar/pathOrder.js +35 -0
- package/src/grammar/pointShapes.js +24 -0
- package/src/grammar/rules.js +1 -0
- package/src/grammar/scales/appearance.js +21 -0
- package/src/grammar/schemas/concreteGraphic.js +11 -1
- package/src/grammar/schemas/graphicBounds.js +19 -37
- package/src/grammar/schemas/semanticPath.js +17 -2
- package/src/grammar/transforms.js +100 -11
- package/src/grammar/window.js +339 -0
- package/src/layout/labels.js +270 -0
- package/src/layout/text.js +4 -1
- package/src/layout/title.js +10 -20
- package/src/materialization/dataProvenance.js +56 -2
- package/src/materialization/dependencies.js +9 -14
- package/src/materialization/guides/resources.js +74 -24
- package/src/materialization/horizon.js +29 -0
- package/src/materialization/layout.js +15 -0
- package/src/materialization/marks/capabilities.js +21 -1
- package/src/materialization/marks/index.js +3 -0
- package/src/materialization/marks/pathOrder.js +71 -0
- package/src/materialization/marks/policies.js +6 -2
- package/src/materialization/scaleGuideDependencies.js +8 -0
- package/src/materialization/scales/resolve.js +2 -0
- package/src/materialization/selection/items/path.js +27 -1
- package/src/materialization/selection/items/point.js +1 -5
- package/src/materialization/selection/items/rect.js +21 -0
- package/src/materialization/selection/styles.js +20 -9
- package/src/materialization/text.js +12 -4
- package/src/renderers/canvas/fill.js +33 -0
- package/src/renderers/canvas/index.js +7 -0
- package/src/renderers/canvas/path.js +7 -4
- package/src/renderers/canvas/rect.js +9 -3
- package/src/selectors/datasets.js +4 -0
- package/src/theme/defaults.js +4 -0
- package/types/extension.d.ts +6 -0
- package/types/index.d.ts +76 -0
- package/types/program.d.ts +632 -10
|
@@ -3,9 +3,11 @@ import { validateUserId } from "../../core/identifiers.js";
|
|
|
3
3
|
import { validateKeys } from "../../core/validation.js";
|
|
4
4
|
import { hasDataset } from "../../selectors/index.js";
|
|
5
5
|
import { findDataset } from "../../selectors/datasets.js";
|
|
6
|
+
import { requireLayer } from "../../selectors/layers.js";
|
|
6
7
|
|
|
7
8
|
const OPTIONS = Object.freeze(["id", "source", "transform"]);
|
|
8
9
|
const RELEASE_OPTIONS = Object.freeze(["id"]);
|
|
10
|
+
const REBIND_OPTIONS = Object.freeze(["id", "data"]);
|
|
9
11
|
|
|
10
12
|
export const createDerivedData = action(
|
|
11
13
|
{ op: "createDerivedData", description: "Create an immutable derived dataset definition." },
|
|
@@ -50,3 +52,23 @@ export const releaseDerivedData = action(
|
|
|
50
52
|
});
|
|
51
53
|
}
|
|
52
54
|
);
|
|
55
|
+
|
|
56
|
+
export const rebindLayerData = action(
|
|
57
|
+
{
|
|
58
|
+
op: "rebindLayerData",
|
|
59
|
+
description: "Rebind one semantic layer to an existing dataset."
|
|
60
|
+
},
|
|
61
|
+
function (args = {}) {
|
|
62
|
+
validateKeys(args, REBIND_OPTIONS, "rebindLayerData");
|
|
63
|
+
const id = validateUserId(args.id, "Layer id");
|
|
64
|
+
const data = validateUserId(args.data, "Layer dataset id");
|
|
65
|
+
requireLayer(this, id);
|
|
66
|
+
if (!hasDataset(this, data)) {
|
|
67
|
+
throw new Error(`Layer dataset "${data}" does not exist.`);
|
|
68
|
+
}
|
|
69
|
+
return this.editSemantic({
|
|
70
|
+
property: `layer[${id}].data`,
|
|
71
|
+
value: data
|
|
72
|
+
});
|
|
73
|
+
}
|
|
74
|
+
);
|
|
@@ -125,6 +125,11 @@ export const filterMarks = action(
|
|
|
125
125
|
candidate.data !== undefined &&
|
|
126
126
|
findSelectionPolicy(candidate.mark?.type) !== undefined
|
|
127
127
|
});
|
|
128
|
+
if (this.markConfigs[layer.id]?.itemFilterable === false) {
|
|
129
|
+
throw new Error(
|
|
130
|
+
`filterMarks does not support composite mark "${layer.id}"; filter its source dataset first.`
|
|
131
|
+
);
|
|
132
|
+
}
|
|
128
133
|
const derivedId = `${layer.id}FilteredData`;
|
|
129
134
|
if (hasDataset(this, derivedId)) {
|
|
130
135
|
throw new Error(`Dataset "${derivedId}" already exists.`);
|
|
@@ -0,0 +1,65 @@
|
|
|
1
|
+
import { action } from "../../core/action.js";
|
|
2
|
+
import { validateUserId } from "../../core/identifiers.js";
|
|
3
|
+
import { validateKeys } from "../../core/validation.js";
|
|
4
|
+
import {
|
|
5
|
+
deriveGradientProfiles,
|
|
6
|
+
normalizeGradientProfileTransform
|
|
7
|
+
} from "../../grammar/gradientProfile.js";
|
|
8
|
+
import { MATERIALIZE_OPTIONS, requireDerivedDataset } from "./shared.js";
|
|
9
|
+
|
|
10
|
+
const OPTIONS = Object.freeze([
|
|
11
|
+
"id", "source", "category", "field", "bandwidth", "extent", "steps",
|
|
12
|
+
"kernel", "normalization", "center", "as"
|
|
13
|
+
]);
|
|
14
|
+
|
|
15
|
+
export const materializeGradientProfileData = action(
|
|
16
|
+
{
|
|
17
|
+
op: "materializeGradientProfileData",
|
|
18
|
+
description: "Materialize one categorical density-profile dataset."
|
|
19
|
+
},
|
|
20
|
+
function (args = {}) {
|
|
21
|
+
validateKeys(
|
|
22
|
+
args,
|
|
23
|
+
MATERIALIZE_OPTIONS,
|
|
24
|
+
"materializeGradientProfileData"
|
|
25
|
+
);
|
|
26
|
+
const { id, source, transform } = requireDerivedDataset(
|
|
27
|
+
this,
|
|
28
|
+
args.id,
|
|
29
|
+
"gradientProfile"
|
|
30
|
+
);
|
|
31
|
+
const result = deriveGradientProfiles(source.values, transform);
|
|
32
|
+
return this
|
|
33
|
+
.editSemantic({
|
|
34
|
+
property: `dataset[${id}].transform`,
|
|
35
|
+
value: [{
|
|
36
|
+
...transform,
|
|
37
|
+
resolved: {
|
|
38
|
+
bandwidth: result.bandwidth,
|
|
39
|
+
extent: result.extent,
|
|
40
|
+
intensityDomain: result.intensityDomain
|
|
41
|
+
}
|
|
42
|
+
}]
|
|
43
|
+
})
|
|
44
|
+
.editSemantic({ property: `dataset[${id}].values`, value: result.values });
|
|
45
|
+
}
|
|
46
|
+
);
|
|
47
|
+
|
|
48
|
+
export const createGradientProfileData = action(
|
|
49
|
+
{
|
|
50
|
+
op: "createGradientProfileData",
|
|
51
|
+
description: "Create one immutable categorical density-profile dataset."
|
|
52
|
+
},
|
|
53
|
+
function (args = {}) {
|
|
54
|
+
validateKeys(args, OPTIONS, "createGradientProfileData");
|
|
55
|
+
const id = validateUserId(args.id, "Gradient profile dataset id");
|
|
56
|
+
const source = validateUserId(
|
|
57
|
+
args.source ?? this.context.currentData,
|
|
58
|
+
"Gradient profile source dataset id"
|
|
59
|
+
);
|
|
60
|
+
const transform = normalizeGradientProfileTransform(args);
|
|
61
|
+
return this
|
|
62
|
+
.createDerivedData({ id, source, transform: [transform] })
|
|
63
|
+
.materializeGradientProfileData({ id });
|
|
64
|
+
}
|
|
65
|
+
);
|
|
@@ -0,0 +1,71 @@
|
|
|
1
|
+
import { action } from "../../core/action.js";
|
|
2
|
+
import { validateUserId } from "../../core/identifiers.js";
|
|
3
|
+
import { validateKeys } from "../../core/validation.js";
|
|
4
|
+
import {
|
|
5
|
+
deriveHorizon,
|
|
6
|
+
validateHorizonTransform
|
|
7
|
+
} from "../../grammar/horizon.js";
|
|
8
|
+
import { MATERIALIZE_OPTIONS, requireDerivedDataset } from "./shared.js";
|
|
9
|
+
|
|
10
|
+
const OPTIONS = Object.freeze([
|
|
11
|
+
"id", "source", "x", "y", "groupBy", "bands", "baseline", "extent",
|
|
12
|
+
"resolve", "missing", "overflow", "palette", "as"
|
|
13
|
+
]);
|
|
14
|
+
|
|
15
|
+
function requestedTransform(args) {
|
|
16
|
+
return validateHorizonTransform({
|
|
17
|
+
type: "horizon",
|
|
18
|
+
x: args.x,
|
|
19
|
+
y: args.y,
|
|
20
|
+
...(args.groupBy === undefined ? {} : { groupBy: args.groupBy }),
|
|
21
|
+
bands: args.bands ?? 3,
|
|
22
|
+
baseline: args.baseline ?? 0,
|
|
23
|
+
extent: args.extent ?? "auto",
|
|
24
|
+
resolve: args.resolve ?? "shared",
|
|
25
|
+
missing: args.missing ?? "break",
|
|
26
|
+
overflow: args.overflow ?? "clip",
|
|
27
|
+
palette: args.palette ?? {},
|
|
28
|
+
as: args.as
|
|
29
|
+
});
|
|
30
|
+
}
|
|
31
|
+
|
|
32
|
+
export const materializeHorizonData = action(
|
|
33
|
+
{
|
|
34
|
+
op: "materializeHorizonData",
|
|
35
|
+
description: "Materialize one immutable Horizon band dataset."
|
|
36
|
+
},
|
|
37
|
+
function (args = {}) {
|
|
38
|
+
validateKeys(args, MATERIALIZE_OPTIONS, "materializeHorizonData");
|
|
39
|
+
const { id, source, transform } = requireDerivedDataset(
|
|
40
|
+
this,
|
|
41
|
+
args.id,
|
|
42
|
+
"horizon"
|
|
43
|
+
);
|
|
44
|
+
const result = deriveHorizon(source.values, transform);
|
|
45
|
+
return this
|
|
46
|
+
.editSemantic({
|
|
47
|
+
property: `dataset[${id}].transform`,
|
|
48
|
+
value: [{ ...result.transform, resolved: result.resolved }]
|
|
49
|
+
})
|
|
50
|
+
.editSemantic({
|
|
51
|
+
property: `dataset[${id}].values`,
|
|
52
|
+
value: result.values
|
|
53
|
+
});
|
|
54
|
+
}
|
|
55
|
+
);
|
|
56
|
+
|
|
57
|
+
export const createHorizonData = action(
|
|
58
|
+
{
|
|
59
|
+
op: "createHorizonData",
|
|
60
|
+
description: "Create one immutable Horizon band dataset."
|
|
61
|
+
},
|
|
62
|
+
function (args = {}) {
|
|
63
|
+
validateKeys(args, OPTIONS, "createHorizonData");
|
|
64
|
+
const id = validateUserId(args.id, "Horizon dataset id");
|
|
65
|
+
const source = validateUserId(args.source, "Horizon source dataset id");
|
|
66
|
+
const transform = requestedTransform(args);
|
|
67
|
+
return this
|
|
68
|
+
.createDerivedData({ id, source, transform: [transform] })
|
|
69
|
+
.materializeHorizonData({ id });
|
|
70
|
+
}
|
|
71
|
+
);
|
|
@@ -1,5 +1,9 @@
|
|
|
1
1
|
import { createData } from "./create.js";
|
|
2
|
-
import {
|
|
2
|
+
import {
|
|
3
|
+
createDerivedData,
|
|
4
|
+
rebindLayerData,
|
|
5
|
+
releaseDerivedData
|
|
6
|
+
} from "./derived.js";
|
|
3
7
|
import {
|
|
4
8
|
filterData,
|
|
5
9
|
filterMarks,
|
|
@@ -7,24 +11,47 @@ import {
|
|
|
7
11
|
materializeMarkFilteredData
|
|
8
12
|
} from "./filter.js";
|
|
9
13
|
import { createRegressionData, materializeRegressionData } from "./regression.js";
|
|
10
|
-
import {
|
|
14
|
+
import {
|
|
15
|
+
createCategoricalDensityData,
|
|
16
|
+
createDensityData,
|
|
17
|
+
materializeDensityData
|
|
18
|
+
} from "./density.js";
|
|
19
|
+
import {
|
|
20
|
+
createGradientProfileData,
|
|
21
|
+
materializeGradientProfileData
|
|
22
|
+
} from "./gradientProfile.js";
|
|
11
23
|
import { createIntervalData, materializeIntervalData } from "./interval.js";
|
|
24
|
+
import { createHorizonData, materializeHorizonData } from "./horizon.js";
|
|
25
|
+
import { createWindowData, materializeWindowData } from "./window.js";
|
|
26
|
+
import { createBin2DData, materializeBin2DData } from "./bin2d.js";
|
|
12
27
|
import { createBoxSummaryData, createBoxOutlierData, materializeBoxSummaryData, materializeBoxOutlierData } from "./box.js";
|
|
13
28
|
|
|
14
29
|
export function registerDataActions(ProgramClass) {
|
|
15
30
|
ProgramClass.prototype.createData = createData;
|
|
16
31
|
ProgramClass.prototype.createDerivedData = createDerivedData;
|
|
17
32
|
ProgramClass.prototype.releaseDerivedData = releaseDerivedData;
|
|
33
|
+
ProgramClass.prototype.rebindLayerData = rebindLayerData;
|
|
18
34
|
ProgramClass.prototype.createDensityData = createDensityData;
|
|
35
|
+
ProgramClass.prototype.createCategoricalDensityData =
|
|
36
|
+
createCategoricalDensityData;
|
|
19
37
|
ProgramClass.prototype.materializeFilteredData = materializeFilteredData;
|
|
20
38
|
ProgramClass.prototype.materializeMarkFilteredData = materializeMarkFilteredData;
|
|
21
39
|
ProgramClass.prototype.filterData = filterData;
|
|
22
40
|
ProgramClass.prototype.filterMarks = filterMarks;
|
|
23
41
|
ProgramClass.prototype.materializeRegressionData = materializeRegressionData;
|
|
24
42
|
ProgramClass.prototype.materializeDensityData = materializeDensityData;
|
|
43
|
+
ProgramClass.prototype.createGradientProfileData = createGradientProfileData;
|
|
44
|
+
ProgramClass.prototype.materializeGradientProfileData =
|
|
45
|
+
materializeGradientProfileData;
|
|
25
46
|
ProgramClass.prototype.createRegressionData = createRegressionData;
|
|
26
47
|
ProgramClass.prototype.materializeIntervalData = materializeIntervalData;
|
|
27
48
|
ProgramClass.prototype.createIntervalData = createIntervalData;
|
|
49
|
+
ProgramClass.prototype.createHorizonData = createHorizonData;
|
|
50
|
+
ProgramClass.prototype.materializeHorizonData = materializeHorizonData;
|
|
51
|
+
ProgramClass.prototype.createWindowData = createWindowData;
|
|
52
|
+
ProgramClass.prototype.materializeWindowData = materializeWindowData;
|
|
53
|
+
ProgramClass.prototype.createBin2DData = createBin2DData;
|
|
54
|
+
ProgramClass.prototype.materializeBin2DData = materializeBin2DData;
|
|
28
55
|
ProgramClass.prototype.createBoxSummaryData = createBoxSummaryData;
|
|
29
56
|
ProgramClass.prototype.createBoxOutlierData = createBoxOutlierData;
|
|
30
57
|
ProgramClass.prototype.materializeBoxSummaryData = materializeBoxSummaryData;
|
|
@@ -0,0 +1,50 @@
|
|
|
1
|
+
import { action } from "../../core/action.js";
|
|
2
|
+
import { validateUserId } from "../../core/identifiers.js";
|
|
3
|
+
import { validateKeys } from "../../core/validation.js";
|
|
4
|
+
import {
|
|
5
|
+
deriveWindowRows,
|
|
6
|
+
normalizeWindowTransform
|
|
7
|
+
} from "../../grammar/window.js";
|
|
8
|
+
import { MATERIALIZE_OPTIONS, requireDerivedDataset } from "./shared.js";
|
|
9
|
+
|
|
10
|
+
const OPTIONS = Object.freeze([
|
|
11
|
+
"id", "source", "partitionBy", "sortBy", "operations"
|
|
12
|
+
]);
|
|
13
|
+
|
|
14
|
+
export const materializeWindowData = action(
|
|
15
|
+
{
|
|
16
|
+
op: "materializeWindowData",
|
|
17
|
+
description: "Materialize one immutable window-derived dataset."
|
|
18
|
+
},
|
|
19
|
+
function (args = {}) {
|
|
20
|
+
validateKeys(args, MATERIALIZE_OPTIONS, "materializeWindowData");
|
|
21
|
+
const { id, source, transform } = requireDerivedDataset(
|
|
22
|
+
this,
|
|
23
|
+
args.id,
|
|
24
|
+
"window"
|
|
25
|
+
);
|
|
26
|
+
return this.editSemantic({
|
|
27
|
+
property: `dataset[${id}].values`,
|
|
28
|
+
value: deriveWindowRows(source.values, transform)
|
|
29
|
+
});
|
|
30
|
+
}
|
|
31
|
+
);
|
|
32
|
+
|
|
33
|
+
export const createWindowData = action(
|
|
34
|
+
{
|
|
35
|
+
op: "createWindowData",
|
|
36
|
+
description: "Create immutable partitioned window values."
|
|
37
|
+
},
|
|
38
|
+
function (args = {}) {
|
|
39
|
+
validateKeys(args, OPTIONS, "createWindowData");
|
|
40
|
+
const id = validateUserId(args.id, "Window dataset id");
|
|
41
|
+
const source = validateUserId(
|
|
42
|
+
args.source ?? this.context.currentData,
|
|
43
|
+
"Source dataset id"
|
|
44
|
+
);
|
|
45
|
+
const transform = normalizeWindowTransform(args);
|
|
46
|
+
return this
|
|
47
|
+
.createDerivedData({ id, source, transform: [transform] })
|
|
48
|
+
.materializeWindowData({ id });
|
|
49
|
+
}
|
|
50
|
+
);
|
|
@@ -19,6 +19,8 @@ import { applyMaterializationPlan } from "../../../materialization/dependencies.
|
|
|
19
19
|
import {
|
|
20
20
|
planEncodingRematerialization
|
|
21
21
|
} from "../../../materialization/encodings.js";
|
|
22
|
+
import { findUpstreamTransform } from
|
|
23
|
+
"../../../materialization/dataProvenance.js";
|
|
22
24
|
import { encodeContinuousColor } from "./continuous.js";
|
|
23
25
|
import {
|
|
24
26
|
applyColorLayoutCompanion,
|
|
@@ -56,10 +58,24 @@ const encodeColor = action(
|
|
|
56
58
|
"color mark"
|
|
57
59
|
);
|
|
58
60
|
assertNoConstantColor(this, layer);
|
|
61
|
+
const densityTransform = dataset.transform?.length === 1 &&
|
|
62
|
+
dataset.transform[0].type === "density"
|
|
63
|
+
? dataset.transform[0]
|
|
64
|
+
: undefined;
|
|
65
|
+
const densitySeriesFields = densityTransform?.placement?.type === "category"
|
|
66
|
+
? [densityTransform.groupBy, densityTransform.placement.split?.field]
|
|
67
|
+
.filter(Boolean)
|
|
68
|
+
: [];
|
|
69
|
+
const horizonTransform = findUpstreamTransform(this, dataset, "horizon");
|
|
70
|
+
const horizonColor = horizonTransform !== undefined &&
|
|
71
|
+
horizonTransform.as?.color === args.field &&
|
|
72
|
+
layer.encoding?.group?.field === horizonTransform.as?.group;
|
|
59
73
|
if (
|
|
60
74
|
layer.mark.type === "area" &&
|
|
61
75
|
(layer.encoding?.group?.field === undefined ||
|
|
62
|
-
layer.encoding.group.field !== args.field)
|
|
76
|
+
layer.encoding.group.field !== args.field) &&
|
|
77
|
+
!densitySeriesFields.includes(args.field) &&
|
|
78
|
+
!horizonColor
|
|
63
79
|
) {
|
|
64
80
|
throw new Error(
|
|
65
81
|
"Area color encoding must match an existing group encoding."
|
|
@@ -18,6 +18,14 @@ export function applyColorLayoutCompanion(
|
|
|
18
18
|
) {
|
|
19
19
|
return program;
|
|
20
20
|
}
|
|
21
|
+
if (
|
|
22
|
+
layer.mark.type === "area" &&
|
|
23
|
+
[layer.encoding?.x, layer.encoding?.y].some(
|
|
24
|
+
encoding => ["nominal", "ordinal"].includes(encoding?.fieldType)
|
|
25
|
+
)
|
|
26
|
+
) {
|
|
27
|
+
return program;
|
|
28
|
+
}
|
|
21
29
|
if (isRangedArea(layer)) return program;
|
|
22
30
|
const channels = layer.mark.type === "bar"
|
|
23
31
|
? resolveBarChannels(layer)
|
|
@@ -0,0 +1,109 @@
|
|
|
1
|
+
import { isPlainObject } from "../../../core/immutable.js";
|
|
2
|
+
import { findSemanticScale } from "../../../selectors/scales.js";
|
|
3
|
+
|
|
4
|
+
export function requireDensityField(value, label) {
|
|
5
|
+
if (typeof value !== "string" || value.length === 0) {
|
|
6
|
+
throw new TypeError(`${label} must be a non-empty string.`);
|
|
7
|
+
}
|
|
8
|
+
return value;
|
|
9
|
+
}
|
|
10
|
+
|
|
11
|
+
export function resolveDensityScaleOptions(value, defaults, label) {
|
|
12
|
+
if (value !== undefined && !isPlainObject(value)) {
|
|
13
|
+
throw new TypeError(`${label} must be a plain object.`);
|
|
14
|
+
}
|
|
15
|
+
return { ...defaults, ...(value ?? {}) };
|
|
16
|
+
}
|
|
17
|
+
|
|
18
|
+
export function resolveDensityCategoryScaleOptions(value, fallbackId) {
|
|
19
|
+
const scale = resolveDensityScaleOptions(
|
|
20
|
+
value,
|
|
21
|
+
{ type: "band" },
|
|
22
|
+
"Density placement scale"
|
|
23
|
+
);
|
|
24
|
+
if ((scale.type ?? "band") !== "band") {
|
|
25
|
+
throw new Error('Density category placement requires scale type "band".');
|
|
26
|
+
}
|
|
27
|
+
return {
|
|
28
|
+
...(fallbackId === undefined ? {} : { id: fallbackId }),
|
|
29
|
+
...scale,
|
|
30
|
+
type: "band"
|
|
31
|
+
};
|
|
32
|
+
}
|
|
33
|
+
|
|
34
|
+
function valueScaleForTransition(program, layer, transform) {
|
|
35
|
+
const densityChannel = transform.placement?.channel ?? (
|
|
36
|
+
layer.encoding.x.field === transform.as[1] ? "x" : "y"
|
|
37
|
+
);
|
|
38
|
+
const valueChannel = densityChannel === "x" ? "y" : "x";
|
|
39
|
+
return findSemanticScale(program, layer.encoding[valueChannel].scale);
|
|
40
|
+
}
|
|
41
|
+
|
|
42
|
+
export function resolveDensityTransitionScaleDefinitions(
|
|
43
|
+
program,
|
|
44
|
+
layer,
|
|
45
|
+
transform,
|
|
46
|
+
placement,
|
|
47
|
+
rawPlacement
|
|
48
|
+
) {
|
|
49
|
+
const valueScale = valueScaleForTransition(program, layer, transform);
|
|
50
|
+
if (valueScale === undefined) {
|
|
51
|
+
throw new Error(`Density area "${layer.id}" requires its value scale.`);
|
|
52
|
+
}
|
|
53
|
+
const { id: _valueId, range: _valueRange, ...valueDefinition } = valueScale;
|
|
54
|
+
void _valueId;
|
|
55
|
+
void _valueRange;
|
|
56
|
+
const valueChannel = placement?.channel === "x" ? "y" : "x";
|
|
57
|
+
const companionChannel = valueChannel === "x" ? "y" : "x";
|
|
58
|
+
const companionDefinition = placement === undefined
|
|
59
|
+
? { type: "linear", domain: "auto", range: "auto", nice: true, zero: true }
|
|
60
|
+
: resolveDensityCategoryScaleOptions(rawPlacement.scale);
|
|
61
|
+
return {
|
|
62
|
+
[valueChannel]: { ...valueDefinition, range: "auto" },
|
|
63
|
+
[companionChannel]: companionDefinition
|
|
64
|
+
};
|
|
65
|
+
}
|
|
66
|
+
|
|
67
|
+
export function resolveDensityPositionDefinition({
|
|
68
|
+
layer,
|
|
69
|
+
output,
|
|
70
|
+
groupBy,
|
|
71
|
+
placement,
|
|
72
|
+
coordinate,
|
|
73
|
+
valueScale,
|
|
74
|
+
densityScale,
|
|
75
|
+
placementScale
|
|
76
|
+
}) {
|
|
77
|
+
if (placement === undefined) {
|
|
78
|
+
const xIsDensity = layer.densityChannel === "x";
|
|
79
|
+
return {
|
|
80
|
+
x: {
|
|
81
|
+
field: output[xIsDensity ? 1 : 0],
|
|
82
|
+
fieldType: "quantitative",
|
|
83
|
+
scale: xIsDensity ? densityScale : valueScale,
|
|
84
|
+
coordinate
|
|
85
|
+
},
|
|
86
|
+
y: {
|
|
87
|
+
field: output[xIsDensity ? 0 : 1],
|
|
88
|
+
fieldType: "quantitative",
|
|
89
|
+
scale: xIsDensity ? valueScale : densityScale,
|
|
90
|
+
coordinate
|
|
91
|
+
}
|
|
92
|
+
};
|
|
93
|
+
}
|
|
94
|
+
const category = {
|
|
95
|
+
field: placement.categoryField,
|
|
96
|
+
fieldType: "nominal",
|
|
97
|
+
scale: placementScale,
|
|
98
|
+
coordinate
|
|
99
|
+
};
|
|
100
|
+
const value = {
|
|
101
|
+
field: output[0],
|
|
102
|
+
fieldType: "quantitative",
|
|
103
|
+
scale: valueScale,
|
|
104
|
+
coordinate
|
|
105
|
+
};
|
|
106
|
+
return placement.channel === "x"
|
|
107
|
+
? { x: category, y: value }
|
|
108
|
+
: { x: value, y: category };
|
|
109
|
+
}
|