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.
Files changed (157) hide show
  1. package/CHANGELOG.md +30 -0
  2. package/README.md +35 -13
  3. package/package.json +18 -7
  4. package/src/actions/boxPlots/create.js +13 -7
  5. package/src/actions/boxPlots/edit.js +31 -35
  6. package/src/actions/boxPlots/materialize.js +3 -0
  7. package/src/actions/boxPlots/options.js +8 -1
  8. package/src/actions/boxPlots/resolve.js +10 -2
  9. package/src/actions/charts/bar.js +50 -0
  10. package/src/actions/charts/heatmap.js +205 -0
  11. package/src/actions/charts/histogram.js +58 -0
  12. package/src/actions/charts/index.js +15 -0
  13. package/src/actions/charts/line.js +69 -0
  14. package/src/actions/charts/parallel.js +76 -0
  15. package/src/actions/charts/scatter.js +56 -0
  16. package/src/actions/charts/shared.js +121 -0
  17. package/src/actions/coordinates/parallel.js +50 -0
  18. package/src/actions/data/bin2d.js +137 -0
  19. package/src/actions/data/density.js +54 -13
  20. package/src/actions/data/derived.js +22 -0
  21. package/src/actions/data/filter.js +5 -0
  22. package/src/actions/data/gradientProfile.js +65 -0
  23. package/src/actions/data/horizon.js +71 -0
  24. package/src/actions/data/index.js +29 -2
  25. package/src/actions/data/window.js +50 -0
  26. package/src/actions/encodings/color/index.js +17 -1
  27. package/src/actions/encodings/color/layout.js +8 -0
  28. package/src/actions/encodings/density/resolve.js +109 -0
  29. package/src/actions/encodings/density.js +193 -88
  30. package/src/actions/encodings/horizon/resolve.js +283 -0
  31. package/src/actions/encodings/horizon.js +364 -0
  32. package/src/actions/encodings/index.js +6 -0
  33. package/src/actions/encodings/parallel.js +115 -0
  34. package/src/actions/encodings/pathOrder.js +131 -0
  35. package/src/actions/encodings/position/apply.js +73 -4
  36. package/src/actions/encodings/position/index.js +15 -2
  37. package/src/actions/encodings/position/policies/arc.js +27 -4
  38. package/src/actions/encodings/position/policies/area.js +33 -2
  39. package/src/actions/encodings/position/policies/index.js +7 -2
  40. package/src/actions/encodings/position/policies/line.js +18 -2
  41. package/src/actions/encodings/position/resolve.js +24 -2
  42. package/src/actions/encodings/ranged.js +3 -1
  43. package/src/actions/encodings/ruleAppearance.js +88 -10
  44. package/src/actions/facets/actions.js +1 -2
  45. package/src/actions/facets/derive.js +33 -3
  46. package/src/actions/facets/replay.js +7 -36
  47. package/src/actions/gradientPlots/components.js +177 -0
  48. package/src/actions/gradientPlots/create.js +96 -0
  49. package/src/actions/gradientPlots/edit.js +153 -0
  50. package/src/actions/gradientPlots/index.js +24 -0
  51. package/src/actions/gradientPlots/materialize.js +287 -0
  52. package/src/actions/gradientPlots/options.js +120 -0
  53. package/src/actions/gradientPlots/paint.js +107 -0
  54. package/src/actions/gradientPlots/rebind.js +51 -0
  55. package/src/actions/gradientPlots/resolve.js +81 -0
  56. package/src/actions/guides/applicability.js +44 -17
  57. package/src/actions/guides/axes/axes.js +37 -3
  58. package/src/actions/guides/axes/index.js +2 -0
  59. package/src/actions/guides/axes/labels.js +11 -6
  60. package/src/actions/guides/axes/parallel/resolve.js +86 -0
  61. package/src/actions/guides/axes/parallel.js +228 -0
  62. package/src/actions/guides/axes/titles.js +11 -8
  63. package/src/actions/guides/guides.js +60 -5
  64. package/src/actions/guides/legends/categorical/actions.js +48 -11
  65. package/src/actions/guides/legends/edit.js +5 -0
  66. package/src/actions/guides/legends/index.js +2 -0
  67. package/src/actions/guides/legends/remove.js +4 -11
  68. package/src/actions/guides/legends/strokeWidth.js +170 -0
  69. package/src/actions/index.js +6 -0
  70. package/src/actions/marks/area/actions.js +60 -136
  71. package/src/actions/marks/area/materialize.js +163 -0
  72. package/src/actions/marks/index.js +5 -1
  73. package/src/actions/marks/line/actions.js +99 -80
  74. package/src/actions/marks/line/materialize.js +146 -0
  75. package/src/actions/marks/point/create.js +76 -0
  76. package/src/actions/marks/point/edit.js +85 -0
  77. package/src/actions/marks/point/index.js +11 -1
  78. package/src/actions/marks/point/jitter.js +72 -0
  79. package/src/actions/marks/point/{actions.js → materialize.js} +175 -170
  80. package/src/actions/marks/rect/actions.js +3 -0
  81. package/src/actions/marks/remove.js +13 -2
  82. package/src/actions/marks/rule/actions.js +25 -3
  83. package/src/actions/marks/text/actions.js +19 -4
  84. package/src/actions/marks/text/index.js +7 -1
  85. package/src/actions/marks/text/layout.js +321 -0
  86. package/src/actions/primitives/semanticValidation/dataset.js +22 -0
  87. package/src/actions/primitives/semanticValidation/guide.js +43 -0
  88. package/src/actions/primitives/semanticValidation/index.js +23 -0
  89. package/src/actions/primitives/semanticValidation/layer.js +74 -0
  90. package/src/actions/primitives/semanticValidation/scale.js +74 -0
  91. package/src/actions/primitives/semanticValidation/shared.js +5 -0
  92. package/src/actions/primitives/semanticValue.js +1 -204
  93. package/src/actions/regression/edit.js +19 -21
  94. package/src/actions/scales/consumers/common.js +18 -0
  95. package/src/actions/scales/consumers/families.js +14 -3
  96. package/src/actions/scales/definitions.js +30 -0
  97. package/src/actions/scales/edit.js +6 -204
  98. package/src/actions/scales/editPolicy.js +214 -0
  99. package/src/actions/scales/materialize.js +1 -1
  100. package/src/actions/scales/patch.js +26 -0
  101. package/src/actions/selection/actions.js +28 -3
  102. package/src/actions/violinPlots/create.js +198 -0
  103. package/src/actions/violinPlots/index.js +5 -0
  104. package/src/core/textMetrics.js +47 -0
  105. package/src/core/vocabulary.js +7 -2
  106. package/src/grammar/arcs.js +49 -12
  107. package/src/grammar/areaSeries.js +41 -5
  108. package/src/grammar/bin2d.js +333 -0
  109. package/src/grammar/categoricalDensity.js +192 -0
  110. package/src/grammar/coordinates.js +1 -1
  111. package/src/grammar/curveCommands.js +3 -1
  112. package/src/grammar/density.js +252 -26
  113. package/src/grammar/facets/dependencies.js +3 -11
  114. package/src/grammar/facets/index.js +3 -1
  115. package/src/grammar/gradientProfile.js +213 -0
  116. package/src/grammar/horizon.js +455 -0
  117. package/src/grammar/jitter.js +197 -0
  118. package/src/grammar/lineSeries.js +69 -0
  119. package/src/grammar/paint.js +88 -0
  120. package/src/grammar/parallelCoordinates.js +213 -0
  121. package/src/grammar/pathOrder.js +35 -0
  122. package/src/grammar/pointShapes.js +24 -0
  123. package/src/grammar/rules.js +1 -0
  124. package/src/grammar/scales/appearance.js +21 -0
  125. package/src/grammar/schemas/concreteGraphic.js +11 -1
  126. package/src/grammar/schemas/graphicBounds.js +19 -37
  127. package/src/grammar/schemas/semanticPath.js +17 -2
  128. package/src/grammar/transforms.js +100 -11
  129. package/src/grammar/window.js +339 -0
  130. package/src/layout/labels.js +270 -0
  131. package/src/layout/text.js +4 -1
  132. package/src/layout/title.js +10 -20
  133. package/src/materialization/dataProvenance.js +56 -2
  134. package/src/materialization/dependencies.js +9 -14
  135. package/src/materialization/guides/resources.js +74 -24
  136. package/src/materialization/horizon.js +29 -0
  137. package/src/materialization/layout.js +15 -0
  138. package/src/materialization/marks/capabilities.js +21 -1
  139. package/src/materialization/marks/index.js +3 -0
  140. package/src/materialization/marks/pathOrder.js +71 -0
  141. package/src/materialization/marks/policies.js +6 -2
  142. package/src/materialization/scaleGuideDependencies.js +8 -0
  143. package/src/materialization/scales/resolve.js +2 -0
  144. package/src/materialization/selection/items/path.js +27 -1
  145. package/src/materialization/selection/items/point.js +1 -5
  146. package/src/materialization/selection/items/rect.js +21 -0
  147. package/src/materialization/selection/styles.js +20 -9
  148. package/src/materialization/text.js +12 -4
  149. package/src/renderers/canvas/fill.js +33 -0
  150. package/src/renderers/canvas/index.js +7 -0
  151. package/src/renderers/canvas/path.js +7 -4
  152. package/src/renderers/canvas/rect.js +9 -3
  153. package/src/selectors/datasets.js +4 -0
  154. package/src/theme/defaults.js +4 -0
  155. package/types/extension.d.ts +6 -0
  156. package/types/index.d.ts +76 -0
  157. package/types/program.d.ts +632 -10
@@ -0,0 +1,177 @@
1
+ import { action } from "../../core/action.js";
2
+ import { validateKeys } from "../../core/validation.js";
3
+ import { GRADIENT_PROFILE_FIELDS } from "../../grammar/gradientProfile.js";
4
+ import { resolveGraphicBounds } from "../../layout/canvas.js";
5
+ import { findLayer } from "../../selectors/layers.js";
6
+ import { createDensityLegendPaint } from "./paint.js";
7
+
8
+ const CENTER_OPTIONS = Object.freeze([
9
+ "id", "owner", "data", "category", "categoryType", "coordinate",
10
+ "categoryScale", "measureScale", "orientation", "size", "stroke",
11
+ "strokeWidth"
12
+ ]);
13
+ const LEGEND_OPTIONS = Object.freeze(["owner", "title", "position"]);
14
+
15
+ export const createGradientPlotCenter = action(
16
+ {
17
+ op: "createGradientPlotCenter",
18
+ description: "Create the optional center rule for one gradient plot."
19
+ },
20
+ function (args = {}) {
21
+ validateKeys(args, CENTER_OPTIONS, "createGradientPlotCenter");
22
+ const categoryAction = args.orientation === "vertical" ? "encodeX" : "encodeY";
23
+ const measureAction = args.orientation === "vertical" ? "encodeY" : "encodeX";
24
+ const spanOrientation = args.orientation === "vertical" ? "horizontal" : "vertical";
25
+ let next = this.createRuleMark({ id: args.id, data: args.data });
26
+ next = next[categoryAction]({
27
+ target: args.id,
28
+ field: args.category,
29
+ fieldType: args.categoryType,
30
+ coordinate: args.coordinate,
31
+ scale: { id: args.categoryScale }
32
+ });
33
+ next = next[measureAction]({
34
+ target: args.id,
35
+ field: GRADIENT_PROFILE_FIELDS.center,
36
+ fieldType: "quantitative",
37
+ coordinate: args.coordinate,
38
+ scale: { id: args.measureScale }
39
+ });
40
+ return next
41
+ .encodeStroke({ target: args.id, value: args.stroke })
42
+ .encodeStrokeWidth({ target: args.id, value: args.strokeWidth })
43
+ .materializeRuleSpan({
44
+ id: args.id,
45
+ orientation: spanOrientation,
46
+ size: args.size
47
+ });
48
+ }
49
+ );
50
+
51
+ function legendIds(owner) {
52
+ return {
53
+ strip: `${owner}DensityLegend`,
54
+ labels: `${owner}DensityLegendLabels`,
55
+ title: `${owner}DensityLegendTitle`
56
+ };
57
+ }
58
+
59
+ function requireLegendOwner(program, owner) {
60
+ const layer = findLayer(program, owner);
61
+ const config = program.markConfigs[owner]?.gradientPlot;
62
+ if (layer === undefined || config?.materialized !== true) {
63
+ throw new Error(`Unknown gradient-plot legend owner "${owner}".`);
64
+ }
65
+ return { layer, config };
66
+ }
67
+
68
+ export const rematerializeGradientPlotLegend = action(
69
+ {
70
+ op: "rematerializeGradientPlotLegend",
71
+ description: "Rematerialize one gradient plot density legend."
72
+ },
73
+ function ({ owner } = {}) {
74
+ const { config } = requireLegendOwner(this, owner);
75
+ const ids = legendIds(owner);
76
+ const bounds = resolveGraphicBounds(this);
77
+ const position = config.guides.legend.position;
78
+ if (position !== "right") {
79
+ throw new Error('Gradient plot density legend currently requires position "right".');
80
+ }
81
+ const x = bounds.x + bounds.width + 50;
82
+ const y = bounds.y + 50;
83
+ const width = 22;
84
+ const height = Math.min(170, Math.max(80, bounds.height - 110));
85
+ return this
86
+ .editGraphics({ target: ids.strip, property: "x", value: x })
87
+ .editGraphics({ target: ids.strip, property: "y", value: y })
88
+ .editGraphics({ target: ids.strip, property: "width", value: width })
89
+ .editGraphics({ target: ids.strip, property: "height", value: height })
90
+ .editGraphics({
91
+ target: ids.strip,
92
+ property: "fill",
93
+ value: createDensityLegendPaint(config.gradient.opacity)
94
+ })
95
+ .editGraphics({ target: ids.strip, property: "stroke", value: "#cbd5e1" })
96
+ .editGraphics({ target: ids.strip, property: "strokeWidth", value: 1 })
97
+ .editGraphics({ target: ids.labels, property: "x", value: x + width + 10 })
98
+ .editGraphics({ target: ids.labels, property: "y", value: [y + height, y] })
99
+ .editGraphics({ target: ids.labels, property: "text", value: ["Low", "High"] })
100
+ .editGraphics({ target: ids.labels, property: "fill", value: "#64748b" })
101
+ .editGraphics({ target: ids.labels, property: "fontSize", value: 11 })
102
+ .editGraphics({ target: ids.labels, property: "fontFamily", value: "sans-serif" })
103
+ .editGraphics({ target: ids.labels, property: "textAlign", value: "left" })
104
+ .editGraphics({ target: ids.labels, property: "textBaseline", value: "middle" })
105
+ .editGraphics({ target: ids.title, property: "x", value: x })
106
+ .editGraphics({ target: ids.title, property: "y", value: y - 18 })
107
+ .editGraphics({ target: ids.title, property: "text", value: config.guides.legend.title })
108
+ .editGraphics({ target: ids.title, property: "fill", value: "#334155" })
109
+ .editGraphics({ target: ids.title, property: "fontSize", value: 12 })
110
+ .editGraphics({ target: ids.title, property: "fontFamily", value: "sans-serif" })
111
+ .editGraphics({ target: ids.title, property: "fontWeight", value: 600 })
112
+ .editGraphics({ target: ids.title, property: "textAlign", value: "left" })
113
+ .editGraphics({ target: ids.title, property: "textBaseline", value: "middle" });
114
+ }
115
+ );
116
+
117
+ export const createGradientPlotLegend = action(
118
+ {
119
+ op: "createGradientPlotLegend",
120
+ description: "Create the neutral density legend owned by one gradient plot."
121
+ },
122
+ function (args = {}) {
123
+ validateKeys(args, LEGEND_OPTIONS, "createGradientPlotLegend");
124
+ requireLegendOwner(this, args.owner);
125
+ if (args.position !== undefined && args.position !== "right") {
126
+ throw new Error('Gradient plot density legend currently requires position "right".');
127
+ }
128
+ if (args.title !== undefined && (typeof args.title !== "string" || args.title.length === 0)) {
129
+ throw new TypeError("Gradient plot density legend title must be a non-empty string.");
130
+ }
131
+ const ids = legendIds(args.owner);
132
+ const densityScale = `${args.owner}Density`;
133
+ let next = this
134
+ .editSemantic({ property: `scale[${densityScale}].type`, value: "sequential" })
135
+ .editSemantic({
136
+ property: `scale[${densityScale}].domain`,
137
+ value: this.markConfigs[args.owner].gradientPlot.intensityDomain
138
+ })
139
+ .editSemantic({
140
+ property: `scale[${densityScale}].range`,
141
+ value: { palette: { name: "greys" } }
142
+ })
143
+ .editSemantic({ property: "guide.legend.color.scale", value: densityScale })
144
+ .editSemantic({
145
+ property: "guide.legend.color.title",
146
+ value: args.title ?? "Relative density"
147
+ })
148
+ .createGraphics({ id: ids.strip, type: "rect", parent: "canvas" })
149
+ .createGraphics({ id: ids.labels, type: "text", length: 2, parent: "canvas" })
150
+ .createGraphics({ id: ids.title, type: "text", parent: "canvas" });
151
+ next = next._withMarkConfig(args.owner, {
152
+ ...next.markConfigs[args.owner],
153
+ gradientPlot: {
154
+ ...next.markConfigs[args.owner].gradientPlot,
155
+ guides: {
156
+ ...next.markConfigs[args.owner].gradientPlot.guides,
157
+ legend: {
158
+ title: args.title ?? "Relative density",
159
+ position: args.position ?? "right"
160
+ }
161
+ }
162
+ }
163
+ });
164
+ return next.rematerializeGradientPlotLegend({ owner: args.owner });
165
+ }
166
+ );
167
+
168
+ export function removeGradientPlotLegend(program, owner) {
169
+ const ids = legendIds(owner);
170
+ let next = program;
171
+ for (const id of Object.values(ids)) {
172
+ if (next.graphicSpec.objects[id] !== undefined) {
173
+ next = next.editGraphics({ target: id, remove: true });
174
+ }
175
+ }
176
+ return next;
177
+ }
@@ -0,0 +1,96 @@
1
+ import { action } from "../../core/action.js";
2
+ import { validateKeys } from "../../core/validation.js";
3
+ import { findDataset } from "../../selectors/datasets.js";
4
+ import { findSemanticScale } from "../../selectors/scales.js";
5
+ import {
6
+ GRADIENT_PLOT_OPTIONS,
7
+ gradientEncodingArgs,
8
+ resolveGradientAppearance,
9
+ resolveGradientCenter,
10
+ resolveGradientDensity,
11
+ resolveGradientGuides,
12
+ resolveGradientPosition,
13
+ resolveGradientWidth
14
+ } from "./options.js";
15
+ import {
16
+ normalizeGradientPositionTypes,
17
+ resolveGradientPlotId,
18
+ resolveGradientSourceLayer
19
+ } from "./resolve.js";
20
+
21
+ export const createGradientPlot = action(
22
+ {
23
+ op: "createGradientPlot",
24
+ description: "Create a categorical density gradient plot."
25
+ },
26
+ function (args = {}) {
27
+ validateKeys(args, GRADIENT_PLOT_OPTIONS, "createGradientPlot");
28
+ const id = resolveGradientPlotId(this, args.id);
29
+ const source = resolveGradientSourceLayer(this, args.target);
30
+ const data = args.data ?? source?.data ?? this.context.currentData ??
31
+ (this.semanticSpec.datasets.length === 1
32
+ ? this.semanticSpec.datasets[0].id
33
+ : undefined);
34
+ if (findDataset(this, data) === undefined) {
35
+ throw new Error("createGradientPlot requires data or one inferable dataset.");
36
+ }
37
+ const positions = normalizeGradientPositionTypes(
38
+ resolveGradientPosition(args.x, "x") ?? source?.encoding?.x,
39
+ resolveGradientPosition(args.y, "y") ?? source?.encoding?.y
40
+ );
41
+ if (
42
+ positions.x !== undefined && positions.y !== undefined &&
43
+ positions.orientation === undefined
44
+ ) {
45
+ throw new Error(
46
+ "createGradientPlot requires one categorical axis and one quantitative axis."
47
+ );
48
+ }
49
+ const density = resolveGradientDensity(args.density);
50
+ const width = resolveGradientWidth(args.width);
51
+ const gradient = resolveGradientAppearance(args.gradient);
52
+ const center = resolveGradientCenter(args.center);
53
+ const guides = resolveGradientGuides(args.guides);
54
+ const category = positions.orientation === "vertical"
55
+ ? positions.x
56
+ : positions.orientation === "horizontal"
57
+ ? positions.y
58
+ : undefined;
59
+ const categoryScaleId = typeof category?.scale === "string"
60
+ ? category.scale
61
+ : category?.scale?.id;
62
+ const categoryScale = findSemanticScale(this, categoryScaleId);
63
+ let next = categoryScale?.type === "point"
64
+ ? this.editScale({ id: categoryScaleId, type: "band" })
65
+ : this;
66
+ next = next.createRectMark({ id, data })._withMarkConfig(id, {
67
+ ...this.markConfigs[id],
68
+ gradientPlot: {
69
+ materialized: false,
70
+ density,
71
+ width,
72
+ gradient,
73
+ center,
74
+ guides
75
+ },
76
+ itemFilterable: false,
77
+ stroke: false,
78
+ strokeWidth: 0
79
+ });
80
+ if (positions.x !== undefined) {
81
+ next = next.encodeX({
82
+ ...gradientEncodingArgs(positions.x),
83
+ target: id,
84
+ coordinate: args.coordinate ?? source?.coordinate
85
+ });
86
+ }
87
+ if (positions.y !== undefined) {
88
+ next = next.encodeY({
89
+ ...gradientEncodingArgs(positions.y),
90
+ target: id,
91
+ coordinate: args.coordinate ?? source?.coordinate
92
+ });
93
+ }
94
+ return next.materializeGradientPlot({ id });
95
+ }
96
+ );
@@ -0,0 +1,153 @@
1
+ import { action } from "../../core/action.js";
2
+ import { isPlainObject } from "../../core/immutable.js";
3
+ import { validateKeys } from "../../core/validation.js";
4
+ import { planDerivedDataRevision } from "../../materialization/dataProvenance.js";
5
+ import { findDataset } from "../../selectors/datasets.js";
6
+ import { findLayer } from "../../selectors/layers.js";
7
+ import { removeGradientPlotLegend } from "./components.js";
8
+ import {
9
+ resolveGradientAppearance,
10
+ resolveGradientCenter,
11
+ resolveGradientDensity,
12
+ resolveGradientWidth
13
+ } from "./options.js";
14
+ import { resolveGradientOwner } from "./resolve.js";
15
+
16
+ const OPTIONS = Object.freeze([
17
+ "target", "density", "width", "gradient", "center"
18
+ ]);
19
+
20
+ function patch(value, label) {
21
+ if (!isPlainObject(value)) {
22
+ throw new TypeError(`editGradientPlot ${label} must be a plain object.`);
23
+ }
24
+ return value;
25
+ }
26
+
27
+ function removeCenter(program, id) {
28
+ let next = program;
29
+ if (findLayer(next, id) !== undefined) {
30
+ next = next.editSemantic({ property: `layer[${id}]`, remove: true });
31
+ }
32
+ if (next.graphicSpec.objects[id] !== undefined) {
33
+ next = next.editGraphics({ target: id, remove: true });
34
+ }
35
+ return next._withoutMaterializationConfig(["marks", id]);
36
+ }
37
+
38
+ export const editGradientPlot = action(
39
+ {
40
+ op: "editGradientPlot",
41
+ description: "Edit one stable categorical gradient plot."
42
+ },
43
+ function (args = {}) {
44
+ validateKeys(args, OPTIONS, "editGradientPlot");
45
+ if (!OPTIONS.slice(1).some(key => Object.hasOwn(args, key))) {
46
+ throw new Error("editGradientPlot requires at least one gradient-plot option.");
47
+ }
48
+ const owner = resolveGradientOwner(this, args.target, "editGradientPlot");
49
+ const current = this.markConfigs[owner.id].gradientPlot;
50
+ const density = Object.hasOwn(args, "density")
51
+ ? resolveGradientDensity(patch(args.density, "density"), current.density, "editGradientPlot")
52
+ : current.density;
53
+ const width = Object.hasOwn(args, "width")
54
+ ? resolveGradientWidth(patch(args.width, "width"), current.width, "editGradientPlot")
55
+ : current.width;
56
+ const gradient = Object.hasOwn(args, "gradient")
57
+ ? resolveGradientAppearance(
58
+ patch(args.gradient, "gradient"),
59
+ current.gradient,
60
+ "editGradientPlot"
61
+ )
62
+ : current.gradient;
63
+ const center = Object.hasOwn(args, "center")
64
+ ? resolveGradientCenter(
65
+ args.center === false ? false : patch(args.center, "center"),
66
+ current.center === false ? undefined : current.center,
67
+ "editGradientPlot"
68
+ )
69
+ : current.center;
70
+ const densityChanged = JSON.stringify(density) !== JSON.stringify(current.density);
71
+ const centerTypeChanged = center !== false && current.center !== false &&
72
+ center.type !== current.center.type;
73
+ const statistical = densityChanged || centerTypeChanged;
74
+ let next = this;
75
+ let profileId = current.profileId;
76
+ if (statistical) {
77
+ const consumers = [owner.id, ...(findLayer(next, current.centerId) ? [current.centerId] : [])];
78
+ const revision = planDerivedDataRevision(next, {
79
+ owner: owner.id,
80
+ role: "ProfileData",
81
+ previous: current.profileId,
82
+ consumers
83
+ });
84
+ profileId = revision.id;
85
+ next = next.createGradientProfileData({
86
+ id: profileId,
87
+ source: current.source,
88
+ category: current.category,
89
+ field: current.measure,
90
+ ...density,
91
+ center: center === false ? "median" : center.type
92
+ });
93
+ for (const rebind of revision.rebinds) next = next.rebindLayerData(rebind);
94
+ next = next.releaseDerivedData(revision.release);
95
+ }
96
+ const profile = findDataset(next, profileId);
97
+ next = next._withMarkConfig(owner.id, {
98
+ ...next.markConfigs[owner.id],
99
+ gradientPlot: {
100
+ ...current,
101
+ density,
102
+ width,
103
+ gradient,
104
+ center,
105
+ profileId,
106
+ intensityDomain: profile.transform[0].resolved.intensityDomain
107
+ }
108
+ });
109
+ const hadCenter = findLayer(next, current.centerId) !== undefined;
110
+ if (center === false && hadCenter) {
111
+ next = removeCenter(next, current.centerId);
112
+ } else if (center !== false && !hadCenter) {
113
+ const categoryEncoding = owner.encoding[current.orientation === "vertical" ? "x" : "y"];
114
+ const measureEncoding = owner.encoding[current.orientation === "vertical" ? "y" : "x"];
115
+ next = next.createGradientPlotCenter({
116
+ id: current.centerId,
117
+ owner: owner.id,
118
+ data: profileId,
119
+ category: current.category,
120
+ categoryType: current.categoryType,
121
+ coordinate: owner.coordinate,
122
+ categoryScale: categoryEncoding.scale,
123
+ measureScale: measureEncoding.scale,
124
+ orientation: current.orientation,
125
+ size: 1,
126
+ stroke: center.stroke,
127
+ strokeWidth: center.strokeWidth
128
+ });
129
+ } else if (center !== false) {
130
+ next = next
131
+ .encodeStroke({ target: current.centerId, value: center.stroke })
132
+ .encodeStrokeWidth({ target: current.centerId, value: center.strokeWidth });
133
+ }
134
+ next = next.materializeGradientPlotFill({ id: owner.id });
135
+ if (center !== false && findLayer(next, current.centerId) !== undefined) {
136
+ const categoryChannel = current.orientation === "vertical" ? "x" : "y";
137
+ const categoryScale = next.resolvedScales[owner.encoding[categoryChannel].scale];
138
+ next = next.materializeRuleSpan({
139
+ id: current.centerId,
140
+ orientation: current.orientation === "vertical" ? "horizontal" : "vertical",
141
+ size: Math.max(1, categoryScale.bandwidth * width.band - 16)
142
+ });
143
+ }
144
+ if (current.guides?.legend !== false && current.guides?.legend !== undefined) {
145
+ next = removeGradientPlotLegend(next, owner.id)
146
+ .createGradientPlotLegend({
147
+ owner: owner.id,
148
+ ...current.guides.legend
149
+ });
150
+ }
151
+ return next._withContext({ currentMark: owner.id, currentData: current.source });
152
+ }
153
+ );
@@ -0,0 +1,24 @@
1
+ import {
2
+ createGradientPlotCenter,
3
+ createGradientPlotLegend,
4
+ rematerializeGradientPlotLegend
5
+ } from "./components.js";
6
+ import { createGradientPlot } from "./create.js";
7
+ import { editGradientPlot } from "./edit.js";
8
+ import {
9
+ materializeGradientPlot,
10
+ materializeGradientPlotFill
11
+ } from "./materialize.js";
12
+ import { rebindGradientPlotProfile } from "./rebind.js";
13
+
14
+ export function registerGradientPlotActions(ProgramClass) {
15
+ ProgramClass.prototype.createGradientPlot = createGradientPlot;
16
+ ProgramClass.prototype.editGradientPlot = editGradientPlot;
17
+ ProgramClass.prototype.materializeGradientPlot = materializeGradientPlot;
18
+ ProgramClass.prototype.materializeGradientPlotFill = materializeGradientPlotFill;
19
+ ProgramClass.prototype.createGradientPlotCenter = createGradientPlotCenter;
20
+ ProgramClass.prototype.createGradientPlotLegend = createGradientPlotLegend;
21
+ ProgramClass.prototype.rematerializeGradientPlotLegend =
22
+ rematerializeGradientPlotLegend;
23
+ ProgramClass.prototype.rebindGradientPlotProfile = rebindGradientPlotProfile;
24
+ }