ggaction 0.0.4 → 0.0.6

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 (169) hide show
  1. package/CHANGELOG.md +55 -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 +484 -36
  6. package/src/actions/boxPlots/materialize.js +3 -0
  7. package/src/actions/boxPlots/options.js +11 -4
  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/composition/actions.js +13 -3
  18. package/src/actions/coordinates/parallel.js +50 -0
  19. package/src/actions/data/bin2d.js +260 -0
  20. package/src/actions/data/density.js +54 -13
  21. package/src/actions/data/derived.js +22 -0
  22. package/src/actions/data/filter.js +5 -0
  23. package/src/actions/data/gradientProfile.js +65 -0
  24. package/src/actions/data/horizon.js +71 -0
  25. package/src/actions/data/index.js +34 -2
  26. package/src/actions/data/intervalEdit.js +76 -0
  27. package/src/actions/data/window.js +50 -0
  28. package/src/actions/distributions/revision.js +326 -0
  29. package/src/actions/encodings/appearance.js +35 -1
  30. package/src/actions/encodings/color/index.js +17 -1
  31. package/src/actions/encodings/color/layout.js +8 -0
  32. package/src/actions/encodings/density/resolve.js +109 -0
  33. package/src/actions/encodings/density.js +330 -90
  34. package/src/actions/encodings/horizon/resolve.js +283 -0
  35. package/src/actions/encodings/horizon.js +364 -0
  36. package/src/actions/encodings/index.js +8 -0
  37. package/src/actions/encodings/parallel.js +115 -0
  38. package/src/actions/encodings/pathOrder.js +131 -0
  39. package/src/actions/encodings/position/apply.js +73 -4
  40. package/src/actions/encodings/position/index.js +15 -2
  41. package/src/actions/encodings/position/policies/arc.js +27 -4
  42. package/src/actions/encodings/position/policies/area.js +33 -2
  43. package/src/actions/encodings/position/policies/index.js +7 -2
  44. package/src/actions/encodings/position/policies/line.js +18 -2
  45. package/src/actions/encodings/position/resolve.js +24 -2
  46. package/src/actions/encodings/ranged.js +3 -1
  47. package/src/actions/encodings/remove.js +268 -0
  48. package/src/actions/encodings/ruleAppearance.js +88 -10
  49. package/src/actions/errorBands/edit.js +121 -13
  50. package/src/actions/errorBars/edit.js +45 -8
  51. package/src/actions/errorBars/options.js +7 -1
  52. package/src/actions/facets/actions.js +137 -3
  53. package/src/actions/facets/derive.js +33 -3
  54. package/src/actions/facets/replay.js +7 -36
  55. package/src/actions/gradientPlots/components.js +177 -0
  56. package/src/actions/gradientPlots/create.js +96 -0
  57. package/src/actions/gradientPlots/edit.js +501 -0
  58. package/src/actions/gradientPlots/index.js +24 -0
  59. package/src/actions/gradientPlots/materialize.js +287 -0
  60. package/src/actions/gradientPlots/options.js +120 -0
  61. package/src/actions/gradientPlots/paint.js +107 -0
  62. package/src/actions/gradientPlots/rebind.js +51 -0
  63. package/src/actions/gradientPlots/resolve.js +81 -0
  64. package/src/actions/guides/applicability.js +44 -17
  65. package/src/actions/guides/axes/axes.js +37 -3
  66. package/src/actions/guides/axes/edit.js +129 -47
  67. package/src/actions/guides/axes/index.js +2 -0
  68. package/src/actions/guides/axes/labels.js +11 -6
  69. package/src/actions/guides/axes/parallel/resolve.js +86 -0
  70. package/src/actions/guides/axes/parallel.js +228 -0
  71. package/src/actions/guides/axes/titles.js +11 -8
  72. package/src/actions/guides/guides.js +60 -5
  73. package/src/actions/guides/legends/categorical/actions.js +67 -19
  74. package/src/actions/guides/legends/continuous/common.js +3 -3
  75. package/src/actions/guides/legends/edit.js +63 -0
  76. package/src/actions/guides/legends/index.js +2 -0
  77. package/src/actions/guides/legends/remove.js +124 -30
  78. package/src/actions/guides/legends/strokeWidth.js +198 -0
  79. package/src/actions/index.js +6 -0
  80. package/src/actions/marks/arc/actions.js +46 -14
  81. package/src/actions/marks/area/actions.js +60 -136
  82. package/src/actions/marks/area/materialize.js +163 -0
  83. package/src/actions/marks/index.js +5 -1
  84. package/src/actions/marks/line/actions.js +99 -80
  85. package/src/actions/marks/line/materialize.js +146 -0
  86. package/src/actions/marks/point/create.js +76 -0
  87. package/src/actions/marks/point/edit.js +97 -0
  88. package/src/actions/marks/point/index.js +11 -1
  89. package/src/actions/marks/point/jitter.js +72 -0
  90. package/src/actions/marks/point/{actions.js → materialize.js} +183 -172
  91. package/src/actions/marks/rect/actions.js +3 -0
  92. package/src/actions/marks/remove.js +13 -2
  93. package/src/actions/marks/rule/actions.js +29 -4
  94. package/src/actions/marks/text/actions.js +19 -4
  95. package/src/actions/marks/text/index.js +7 -1
  96. package/src/actions/marks/text/layout.js +321 -0
  97. package/src/actions/primitives/semanticValidation/dataset.js +22 -0
  98. package/src/actions/primitives/semanticValidation/guide.js +43 -0
  99. package/src/actions/primitives/semanticValidation/index.js +23 -0
  100. package/src/actions/primitives/semanticValidation/layer.js +74 -0
  101. package/src/actions/primitives/semanticValidation/scale.js +74 -0
  102. package/src/actions/primitives/semanticValidation/shared.js +5 -0
  103. package/src/actions/primitives/semanticValue.js +1 -204
  104. package/src/actions/regression/edit.js +247 -88
  105. package/src/actions/scales/consumers/common.js +18 -0
  106. package/src/actions/scales/consumers/families.js +14 -3
  107. package/src/actions/scales/definitions.js +30 -0
  108. package/src/actions/scales/edit.js +6 -204
  109. package/src/actions/scales/editPolicy.js +214 -0
  110. package/src/actions/scales/materialize.js +1 -1
  111. package/src/actions/scales/patch.js +26 -0
  112. package/src/actions/selection/actions.js +150 -5
  113. package/src/actions/selection/index.js +6 -0
  114. package/src/actions/violinPlots/create.js +198 -0
  115. package/src/actions/violinPlots/index.js +5 -0
  116. package/src/core/textMetrics.js +47 -0
  117. package/src/core/vocabulary.js +14 -2
  118. package/src/grammar/arcs.js +49 -12
  119. package/src/grammar/areaSeries.js +41 -5
  120. package/src/grammar/bin2d.js +333 -0
  121. package/src/grammar/categoricalDensity.js +192 -0
  122. package/src/grammar/coordinates.js +1 -1
  123. package/src/grammar/curveCommands.js +3 -1
  124. package/src/grammar/density.js +252 -26
  125. package/src/grammar/facets/dependencies.js +3 -11
  126. package/src/grammar/facets/index.js +3 -1
  127. package/src/grammar/gradientProfile.js +213 -0
  128. package/src/grammar/horizon.js +455 -0
  129. package/src/grammar/jitter.js +197 -0
  130. package/src/grammar/lineSeries.js +69 -0
  131. package/src/grammar/paint.js +88 -0
  132. package/src/grammar/parallelCoordinates.js +213 -0
  133. package/src/grammar/pathOrder.js +35 -0
  134. package/src/grammar/pointShapes.js +24 -0
  135. package/src/grammar/rules.js +1 -0
  136. package/src/grammar/scales/appearance.js +21 -0
  137. package/src/grammar/schemas/concreteGraphic.js +11 -1
  138. package/src/grammar/schemas/graphicBounds.js +19 -37
  139. package/src/grammar/schemas/semanticPath.js +17 -2
  140. package/src/grammar/transforms.js +100 -11
  141. package/src/grammar/window.js +339 -0
  142. package/src/layout/labels.js +270 -0
  143. package/src/layout/text.js +4 -1
  144. package/src/layout/title.js +10 -20
  145. package/src/materialization/dataProvenance.js +56 -2
  146. package/src/materialization/dependencies.js +9 -14
  147. package/src/materialization/guides/resources.js +74 -24
  148. package/src/materialization/horizon.js +29 -0
  149. package/src/materialization/layout.js +15 -0
  150. package/src/materialization/marks/capabilities.js +21 -1
  151. package/src/materialization/marks/index.js +3 -0
  152. package/src/materialization/marks/pathOrder.js +71 -0
  153. package/src/materialization/marks/policies.js +6 -2
  154. package/src/materialization/scaleGuideDependencies.js +8 -0
  155. package/src/materialization/scales/resolve.js +2 -0
  156. package/src/materialization/selection/items/path.js +27 -1
  157. package/src/materialization/selection/items/point.js +1 -5
  158. package/src/materialization/selection/items/rect.js +21 -0
  159. package/src/materialization/selection/styles.js +20 -9
  160. package/src/materialization/text.js +12 -4
  161. package/src/renderers/canvas/fill.js +33 -0
  162. package/src/renderers/canvas/index.js +7 -0
  163. package/src/renderers/canvas/path.js +7 -4
  164. package/src/renderers/canvas/rect.js +9 -3
  165. package/src/selectors/datasets.js +4 -0
  166. package/src/theme/defaults.js +4 -0
  167. package/types/extension.d.ts +6 -0
  168. package/types/index.d.ts +77 -0
  169. package/types/program.d.ts +703 -17
@@ -5,12 +5,6 @@ import {
5
5
  validateNonNegativeFinite,
6
6
  validateUnitInterval
7
7
  } from "../../../core/validation.js";
8
- import {
9
- deriveAreaSeries,
10
- deriveDensityAreaSeries,
11
- layoutDensityAreaSeries
12
- } from "../../../grammar/areaSeries.js";
13
- import { mapContinuousScaleValues, mapOrdinalValues } from "../../../grammar/scales/index.js";
14
8
  import {
15
9
  assertMarkAvailable,
16
10
  applyLayeredMarkInheritance,
@@ -23,17 +17,14 @@ import {
23
17
  import { DEFAULT_COLORS } from "../../../theme/defaults.js";
24
18
  import { findDataset } from "../../../selectors/datasets.js";
25
19
  import { findLayer } from "../../../selectors/layers.js";
26
- import {
27
- buildAreaCurvePathCommands,
28
- validateCurveInterpolation
29
- } from "../../../grammar/curveCommands.js";
30
- import { buildLinearPathCommands } from "../../../grammar/pathCommands.js";
20
+ import { validateCurveInterpolation } from "../../../grammar/curveCommands.js";
31
21
  import { resolveEligibleLayer } from "../../../selectors/layers.js";
32
22
  import { canMaterializeArea } from "../../../materialization/marks/index.js";
33
23
  import { findUpstreamTransform } from "../../../materialization/dataProvenance.js";
34
24
  import { resolveMarkGraphicPlacement } from
35
25
  "../../../materialization/graphicHierarchy.js";
36
26
  import { rematerializeHighlightBaseline } from "../lifecycle.js";
27
+ import { resolveAreaMaterialization } from "./materialize.js";
37
28
 
38
29
  const CREATE_OPTIONS = Object.freeze([
39
30
  "id", "data", "fill", "opacity", "stroke", "strokeWidth", "curve"
@@ -42,6 +33,7 @@ const EDIT_OPTIONS = Object.freeze([
42
33
  "target", "fill", "opacity", "stroke", "strokeWidth", "curve"
43
34
  ]);
44
35
  const REMATERIALIZE_OPTIONS = Object.freeze(["id", "scales"]);
36
+ const STROKE_FROM_FILL_OPTIONS = Object.freeze(["id", "strokeWidth"]);
45
37
 
46
38
  export function validateAreaCreateOutline(args, operation = "createAreaMark") {
47
39
  if (Object.hasOwn(args, "strokeWidth") && !Object.hasOwn(args, "stroke")) {
@@ -103,6 +95,35 @@ const createAreaMark = action(
103
95
  }
104
96
  );
105
97
 
98
+ const configureAreaStrokeFromFill = action(
99
+ {
100
+ op: "configureAreaStrokeFromFill",
101
+ description: "Use each area path fill as its outline color."
102
+ },
103
+ function (args = {}) {
104
+ validateMarkOptions(
105
+ args,
106
+ STROKE_FROM_FILL_OPTIONS,
107
+ "configureAreaStrokeFromFill"
108
+ );
109
+ const id = validateUserId(args.id, "Area mark id");
110
+ const layer = findLayer(this, id);
111
+ if (layer?.mark?.type !== "area") {
112
+ throw new Error(`Unknown area mark "${id}".`);
113
+ }
114
+ const { stroke: _stroke, ...config } = this.markConfigs[id] ?? {};
115
+ void _stroke;
116
+ return this._withMarkConfig(id, {
117
+ ...config,
118
+ strokeFromFill: true,
119
+ strokeWidth: validateNonNegativeFinite(
120
+ args.strokeWidth ?? 1,
121
+ "Area strokeWidth"
122
+ )
123
+ });
124
+ }
125
+ );
126
+
106
127
  const rematerializeAreaMark = action(
107
128
  {
108
129
  op: "rematerializeAreaMark",
@@ -149,14 +170,7 @@ const rematerializeAreaMark = action(
149
170
  : `Density area mark "${id}" requires x and y scales.`
150
171
  );
151
172
  }
152
- const rawDerived = densityTransform === undefined
153
- ? deriveAreaSeries(dataset.values, layer)
154
- : deriveDensityAreaSeries(dataset.values, layer, densityTransform);
155
173
  const colorEncoding = layer.encoding?.color;
156
- const layout = colorEncoding?.layout ?? "overlay";
157
- const derived = densityTransform === undefined
158
- ? rawDerived
159
- : layoutDensityAreaSeries(rawDerived, layout);
160
174
  let resolved = args.scales === false
161
175
  ? this
162
176
  : this
@@ -165,122 +179,17 @@ const rematerializeAreaMark = action(
165
179
  if (args.scales !== false && colorEncoding?.scale !== undefined) {
166
180
  resolved = resolved.rematerializeScale({ id: colorEncoding.scale });
167
181
  }
168
- const xScale = resolved.resolvedScales[xScaleId];
169
- const yScale = resolved.resolvedScales[yScaleId];
170
- const densityScale = densityTransform === undefined
171
- ? undefined
172
- : derived.mode === "y-density" ? yScale : xScale;
173
- if (
174
- densityScale !== undefined &&
175
- (densityScale.domain[0] > 0 || densityScale.domain[1] < 0)
176
- ) {
177
- throw new Error(`Density area mark "${id}" requires a scale domain containing zero.`);
178
- }
179
- const paths = derived.series.map(series => {
180
- const curve = this.markConfigs[id]?.curve ?? "linear";
181
- if (densityTransform === undefined && derived.orientation === "horizontal") {
182
- const y = mapContinuousScaleValues(
183
- series.values.map(value => value.y),
184
- yScale
185
- );
186
- const lower = mapContinuousScaleValues(
187
- series.values.map(value => value.x),
188
- xScale
189
- );
190
- const upper = mapContinuousScaleValues(
191
- series.values.map(value => value.x2),
192
- xScale
193
- );
194
- return buildAreaCurvePathCommands(
195
- y.map((value, index) => ({ x: lower[index], y: value })),
196
- y.map((value, index) => ({ x: upper[index], y: value })),
197
- curve,
198
- { independentAxis: "y" }
199
- );
200
- }
201
- if (densityTransform !== undefined && derived.mode === "x-density") {
202
- const y = mapContinuousScaleValues(
203
- series.values.map(value => value.y),
204
- yScale
205
- );
206
- const upper = mapContinuousScaleValues(
207
- series.values.map(value => value.x),
208
- xScale
209
- );
210
- const baseline = mapContinuousScaleValues(
211
- [0],
212
- densityScale
213
- )[0];
214
- if (curve === "linear") {
215
- return buildLinearPathCommands([
216
- { x: baseline, y: y[0] },
217
- ...y.map((value, index) => ({ x: upper[index], y: value })),
218
- { x: baseline, y: y.at(-1) }
219
- ], { close: true });
220
- }
221
- return buildAreaCurvePathCommands(
222
- y.map(value => ({ x: baseline, y: value })),
223
- y.map((value, index) => ({ x: upper[index], y: value })),
224
- curve,
225
- { independentAxis: "y" }
226
- );
227
- }
228
- const x = mapContinuousScaleValues(
229
- series.values.map(value => value.x),
230
- xScale
231
- );
232
- const lowerValues = densityTransform === undefined
233
- ? series.values.map(value => value.y)
234
- : derived.mode === "y-density"
235
- ? series.values.map(value => value.lower)
236
- : series.values.map(value => value.y);
237
- const lower = mapContinuousScaleValues(
238
- lowerValues,
239
- yScale
240
- );
241
- const upperValues = densityTransform === undefined
242
- ? series.values.map(value => value.y2)
243
- : series.values.map(value => value.upper);
244
- const upper = mapContinuousScaleValues(
245
- upperValues,
246
- yScale
247
- );
248
- if (densityTransform !== undefined && layout === "overlay") {
249
- const baseline = mapContinuousScaleValues(
250
- [0],
251
- yScale
252
- )[0];
253
- if (curve === "linear") {
254
- return buildLinearPathCommands([
255
- { x: x[0], y: baseline },
256
- ...x.map((value, index) => ({ x: value, y: upper[index] })),
257
- { x: x.at(-1), y: baseline }
258
- ], { close: true });
259
- }
260
- return buildAreaCurvePathCommands(
261
- x.map(value => ({ x: value, y: baseline })),
262
- x.map((value, index) => ({ x: value, y: upper[index] })),
263
- curve
264
- );
265
- }
266
- return buildAreaCurvePathCommands(
267
- x.map((value, index) => ({ x: value, y: lower[index] })),
268
- x.map((value, index) => ({ x: value, y: upper[index] })),
269
- curve
270
- );
271
- });
272
182
  const config = this.markConfigs[id];
273
- const fills = config.errorBand?.fill !== undefined
274
- ? paths.map(() => config.errorBand.fill)
275
- : colorEncoding?.scale === undefined
276
- ? paths.map(() => config.fill)
277
- : mapOrdinalValues(
278
- derived.series.map(series => series.key[colorEncoding.field]),
279
- resolved.resolvedScales[colorEncoding.scale].domain,
280
- resolved.resolvedScales[colorEncoding.scale].range
281
- );
183
+ const { paths, fills } = resolveAreaMaterialization({
184
+ rows: dataset.values,
185
+ layer,
186
+ densityTransform,
187
+ resolvedScales: resolved.resolvedScales,
188
+ config
189
+ });
282
190
  const existingChildren = resolved.graphicSpec.objects[id].items ?? [];
283
- const removesOutline = config.stroke === undefined && existingChildren.some(
191
+ const hasOutline = config.stroke !== undefined || config.strokeFromFill === true;
192
+ const removesOutline = !hasOutline && existingChildren.some(
284
193
  child => child.properties.stroke !== undefined
285
194
  );
286
195
  let next = removesOutline
@@ -292,9 +201,13 @@ const rematerializeAreaMark = action(
292
201
  .editGraphics({ target: id, property: "commands", value: paths })
293
202
  .editGraphics({ target: id, property: "fill", value: fills })
294
203
  .editGraphics({ target: id, property: "opacity", value: config.opacity });
295
- if (config.stroke !== undefined) {
204
+ if (hasOutline) {
296
205
  next = next
297
- .editGraphics({ target: id, property: "stroke", value: config.stroke })
206
+ .editGraphics({
207
+ target: id,
208
+ property: "stroke",
209
+ value: config.strokeFromFill === true ? fills : config.stroke
210
+ })
298
211
  .editGraphics({
299
212
  target: id,
300
213
  property: "strokeWidth",
@@ -347,12 +260,21 @@ const editAreaMark = action(
347
260
  }
348
261
  if (Object.hasOwn(args, "stroke")) {
349
262
  if (args.stroke === false) {
350
- const { stroke: removedStroke, strokeWidth: removedWidth, ...rest } = config;
263
+ const {
264
+ stroke: removedStroke,
265
+ strokeFromFill: removedStrokeFromFill,
266
+ strokeWidth: removedWidth,
267
+ ...rest
268
+ } = config;
351
269
  void removedStroke;
270
+ void removedStrokeFromFill;
352
271
  void removedWidth;
353
272
  config = rest;
354
273
  } else {
355
- const hadStroke = config.stroke !== undefined;
274
+ const hadStroke = config.stroke !== undefined || config.strokeFromFill === true;
275
+ const { strokeFromFill: _strokeFromFill, ...withoutFillStroke } = config;
276
+ void _strokeFromFill;
277
+ config = withoutFillStroke;
356
278
  config.stroke = validateNonEmptyString(args.stroke, "Area stroke");
357
279
  config.strokeWidth = Object.hasOwn(args, "strokeWidth")
358
280
  ? validateNonNegativeFinite(args.strokeWidth, "Area strokeWidth")
@@ -377,6 +299,8 @@ const editAreaMark = action(
377
299
 
378
300
  export function registerAreaMarkActions(ProgramClass) {
379
301
  ProgramClass.prototype.createAreaMark = createAreaMark;
302
+ ProgramClass.prototype.configureAreaStrokeFromFill =
303
+ configureAreaStrokeFromFill;
380
304
  ProgramClass.prototype.editAreaMark = editAreaMark;
381
305
  ProgramClass.prototype.rematerializeAreaMark = rematerializeAreaMark;
382
306
  }
@@ -0,0 +1,163 @@
1
+ import {
2
+ deriveAreaSeries,
3
+ deriveDensityAreaSeries,
4
+ layoutDensityAreaSeries
5
+ } from "../../../grammar/areaSeries.js";
6
+ import {
7
+ mapContinuousScaleValues,
8
+ mapOrdinalValues
9
+ } from "../../../grammar/scales/index.js";
10
+ import { buildAreaCurvePathCommands } from
11
+ "../../../grammar/curveCommands.js";
12
+ import { buildLinearPathCommands } from
13
+ "../../../grammar/pathCommands.js";
14
+ import { buildCategoricalDensityPaths } from
15
+ "../../../grammar/categoricalDensity.js";
16
+
17
+ function resolveAreaPaths({
18
+ derived,
19
+ densityTransform,
20
+ categoricalDensity,
21
+ xScale,
22
+ yScale,
23
+ densityScale,
24
+ layout,
25
+ curve
26
+ }) {
27
+ if (categoricalDensity) {
28
+ return buildCategoricalDensityPaths(derived, {
29
+ categoryScale: densityTransform.placement.channel === "x" ? xScale : yScale,
30
+ valueScale: densityTransform.placement.channel === "x" ? yScale : xScale,
31
+ curve
32
+ });
33
+ }
34
+ return derived.series.map(series => {
35
+ if (densityTransform === undefined && derived.orientation === "horizontal") {
36
+ const y = mapContinuousScaleValues(
37
+ series.values.map(value => value.y),
38
+ yScale
39
+ );
40
+ const lower = mapContinuousScaleValues(
41
+ series.values.map(value => value.x),
42
+ xScale
43
+ );
44
+ const upper = mapContinuousScaleValues(
45
+ series.values.map(value => value.x2),
46
+ xScale
47
+ );
48
+ return buildAreaCurvePathCommands(
49
+ y.map((value, index) => ({ x: lower[index], y: value })),
50
+ y.map((value, index) => ({ x: upper[index], y: value })),
51
+ curve,
52
+ { independentAxis: "y" }
53
+ );
54
+ }
55
+ if (densityTransform !== undefined && derived.mode === "x-density") {
56
+ const y = mapContinuousScaleValues(
57
+ series.values.map(value => value.y),
58
+ yScale
59
+ );
60
+ const upper = mapContinuousScaleValues(
61
+ series.values.map(value => value.x),
62
+ xScale
63
+ );
64
+ const baseline = mapContinuousScaleValues([0], densityScale)[0];
65
+ if (curve === "linear") {
66
+ return buildLinearPathCommands([
67
+ { x: baseline, y: y[0] },
68
+ ...y.map((value, index) => ({ x: upper[index], y: value })),
69
+ { x: baseline, y: y.at(-1) }
70
+ ], { close: true });
71
+ }
72
+ return buildAreaCurvePathCommands(
73
+ y.map(value => ({ x: baseline, y: value })),
74
+ y.map((value, index) => ({ x: upper[index], y: value })),
75
+ curve,
76
+ { independentAxis: "y" }
77
+ );
78
+ }
79
+ const x = mapContinuousScaleValues(
80
+ series.values.map(value => value.x),
81
+ xScale
82
+ );
83
+ const lowerValues = densityTransform === undefined
84
+ ? series.values.map(value => value.y)
85
+ : derived.mode === "y-density"
86
+ ? series.values.map(value => value.lower)
87
+ : series.values.map(value => value.y);
88
+ const lower = mapContinuousScaleValues(lowerValues, yScale);
89
+ const upperValues = densityTransform === undefined
90
+ ? series.values.map(value => value.y2)
91
+ : series.values.map(value => value.upper);
92
+ const upper = mapContinuousScaleValues(upperValues, yScale);
93
+ if (densityTransform !== undefined && layout === "overlay") {
94
+ const baseline = mapContinuousScaleValues([0], yScale)[0];
95
+ if (curve === "linear") {
96
+ return buildLinearPathCommands([
97
+ { x: x[0], y: baseline },
98
+ ...x.map((value, index) => ({ x: value, y: upper[index] })),
99
+ { x: x.at(-1), y: baseline }
100
+ ], { close: true });
101
+ }
102
+ return buildAreaCurvePathCommands(
103
+ x.map(value => ({ x: value, y: baseline })),
104
+ x.map((value, index) => ({ x: value, y: upper[index] })),
105
+ curve
106
+ );
107
+ }
108
+ return buildAreaCurvePathCommands(
109
+ x.map((value, index) => ({ x: value, y: lower[index] })),
110
+ x.map((value, index) => ({ x: value, y: upper[index] })),
111
+ curve
112
+ );
113
+ });
114
+ }
115
+
116
+ export function resolveAreaMaterialization({
117
+ rows,
118
+ layer,
119
+ densityTransform,
120
+ resolvedScales,
121
+ config
122
+ }) {
123
+ const xScale = resolvedScales[layer.encoding.x.scale];
124
+ const yScale = resolvedScales[layer.encoding.y.scale];
125
+ const rawDerived = densityTransform === undefined
126
+ ? deriveAreaSeries(rows, layer)
127
+ : deriveDensityAreaSeries(rows, layer, densityTransform);
128
+ const colorEncoding = layer.encoding?.color;
129
+ const layout = colorEncoding?.layout ?? "overlay";
130
+ const categoricalDensity = densityTransform?.placement?.type === "category";
131
+ const derived = densityTransform === undefined || categoricalDensity
132
+ ? rawDerived
133
+ : layoutDensityAreaSeries(rawDerived, layout);
134
+ const densityScale = densityTransform === undefined || categoricalDensity
135
+ ? undefined
136
+ : derived.mode === "y-density" ? yScale : xScale;
137
+ if (
138
+ densityScale !== undefined &&
139
+ (densityScale.domain[0] > 0 || densityScale.domain[1] < 0)
140
+ ) {
141
+ throw new Error(`Density area mark "${layer.id}" requires a scale domain containing zero.`);
142
+ }
143
+ const paths = resolveAreaPaths({
144
+ derived,
145
+ densityTransform,
146
+ categoricalDensity,
147
+ xScale,
148
+ yScale,
149
+ densityScale,
150
+ layout,
151
+ curve: config.curve ?? "linear"
152
+ });
153
+ const fills = config.errorBand?.fill !== undefined
154
+ ? paths.map(() => config.errorBand.fill)
155
+ : colorEncoding?.scale === undefined
156
+ ? paths.map(() => config.fill)
157
+ : mapOrdinalValues(
158
+ derived.series.map(series => series.key[colorEncoding.field]),
159
+ resolvedScales[colorEncoding.scale].domain,
160
+ resolvedScales[colorEncoding.scale].range
161
+ );
162
+ return { paths, fills };
163
+ }
@@ -2,7 +2,10 @@ import { registerBarMarkActions } from "./bar/index.js";
2
2
  import { registerAreaMarkActions } from "./area/index.js";
3
3
  import { registerArcMarkActions } from "./arc/index.js";
4
4
  import { registerLineMarkActions } from "./line/index.js";
5
- import { registerPointMarkActions } from "./point/index.js";
5
+ import {
6
+ registerPointJitterActions,
7
+ registerPointMarkActions
8
+ } from "./point/index.js";
6
9
  import { registerRectMarkActions } from "./rect/index.js";
7
10
  import { registerRuleMarkActions } from "./rule/index.js";
8
11
  import { registerTextMarkActions } from "./text/index.js";
@@ -10,6 +13,7 @@ import { removeMark } from "./remove.js";
10
13
 
11
14
  export function registerMarkActions(ProgramClass) {
12
15
  registerPointMarkActions(ProgramClass);
16
+ registerPointJitterActions(ProgramClass);
13
17
  registerRectMarkActions(ProgramClass);
14
18
  registerAreaMarkActions(ProgramClass);
15
19
  registerArcMarkActions(ProgramClass);