ggaction 0.0.9 → 0.0.11

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 (222) hide show
  1. package/CHANGELOG.md +84 -0
  2. package/README.md +5 -4
  3. package/knowledge/action-card.schema.json +1 -0
  4. package/knowledge/action-cards.json +1 -10941
  5. package/knowledge/action-cards.schema.json +1 -0
  6. package/knowledge/extension-authoring.md +248 -0
  7. package/knowledge/intent-taxonomy.json +1 -183
  8. package/knowledge/intent-taxonomy.schema.json +1 -0
  9. package/knowledge/mcp-resources.json +1 -95
  10. package/knowledge/mcp-resources.schema.json +1 -0
  11. package/knowledge/task-packet.schema.json +1 -159
  12. package/knowledge/task-resolver.js +1 -1230
  13. package/package.json +19 -2
  14. package/src/actions/boxPlots/edit.js +45 -298
  15. package/src/actions/boxPlots/options.js +46 -77
  16. package/src/actions/boxPlots/resolve.js +1 -1
  17. package/src/actions/charts/bar.js +3 -0
  18. package/src/actions/charts/heatmap.js +73 -83
  19. package/src/actions/charts/index.js +1 -1
  20. package/src/actions/charts/parallel.js +35 -1
  21. package/src/actions/charts/shared.js +20 -0
  22. package/src/actions/composition/actions.js +46 -49
  23. package/src/actions/data/bin2d.js +105 -2
  24. package/src/actions/data/box.js +17 -17
  25. package/src/actions/data/density.js +42 -78
  26. package/src/actions/data/gradientProfile.js +22 -52
  27. package/src/actions/data/horizon.js +16 -41
  28. package/src/actions/data/index.js +10 -10
  29. package/src/actions/data/interval.js +16 -38
  30. package/src/actions/data/intervalEdit.js +55 -0
  31. package/src/actions/data/regression.js +7 -17
  32. package/src/actions/data/shared.js +47 -0
  33. package/src/actions/data/timeUnit.js +14 -38
  34. package/src/actions/data/window.js +14 -38
  35. package/src/actions/distributions/revision.js +154 -34
  36. package/src/actions/encodings/angle.js +9 -10
  37. package/src/actions/encodings/appearance.js +17 -51
  38. package/src/actions/encodings/density/resolve.js +3 -1
  39. package/src/actions/encodings/density.js +1 -15
  40. package/src/actions/encodings/horizon/resolve.js +13 -3
  41. package/src/actions/encodings/horizon.js +8 -7
  42. package/src/actions/encodings/index.js +9 -9
  43. package/src/actions/encodings/offset.js +8 -24
  44. package/src/actions/encodings/parallel.js +9 -10
  45. package/src/actions/encodings/pathOrder.js +6 -13
  46. package/src/actions/encodings/position/policies/index.js +4 -4
  47. package/src/actions/encodings/position/policies/line.js +47 -17
  48. package/src/actions/encodings/position/resolve.js +24 -5
  49. package/src/actions/encodings/ranged.js +18 -23
  50. package/src/actions/encodings/remove.js +15 -25
  51. package/src/actions/encodings/ruleAppearance.js +9 -24
  52. package/src/actions/encodings/shared.js +37 -0
  53. package/src/actions/encodings/strokeDash.js +8 -23
  54. package/src/actions/encodings/text.js +9 -10
  55. package/src/actions/errorBands/create.js +105 -39
  56. package/src/actions/errorBands/edit.js +89 -93
  57. package/src/actions/errorBands/index.js +1 -2
  58. package/src/actions/errorBars/create.js +78 -27
  59. package/src/actions/errorBars/edit.js +81 -48
  60. package/src/actions/errorBars/index.js +1 -2
  61. package/src/actions/facets/actions.js +45 -69
  62. package/src/actions/facets/derive.js +38 -53
  63. package/src/actions/facets/replay.js +0 -1
  64. package/src/actions/gradientPlots/components.js +59 -48
  65. package/src/actions/gradientPlots/edit.js +35 -216
  66. package/src/actions/gradientPlots/index.js +11 -10
  67. package/src/actions/gradientPlots/materialize.js +21 -35
  68. package/src/actions/gradientPlots/options.js +5 -7
  69. package/src/actions/gradientPlots/paint.js +9 -6
  70. package/src/actions/gradientPlots/resolve.js +1 -1
  71. package/src/actions/guides/axes/index.js +3 -3
  72. package/src/actions/guides/axes/labels.js +68 -26
  73. package/src/actions/guides/axes/lines.js +22 -2
  74. package/src/actions/guides/axes/policy.js +28 -8
  75. package/src/actions/guides/axes/ticks.js +27 -9
  76. package/src/actions/guides/axes/titles.js +113 -65
  77. package/src/actions/guides/grids/resolve.js +14 -0
  78. package/src/actions/guides/guides.js +2 -4
  79. package/src/actions/guides/index.js +2 -2
  80. package/src/actions/guides/legends/categorical/actions.js +44 -68
  81. package/src/actions/guides/legends/categorical/components.js +6 -1
  82. package/src/actions/guides/legends/categorical/index.js +2 -2
  83. package/src/actions/guides/legends/categorical/layout.js +148 -175
  84. package/src/actions/guides/legends/categorical/recipes.js +5 -0
  85. package/src/actions/guides/legends/categorical/resolve.js +8 -1
  86. package/src/actions/guides/legends/continuous/common.js +117 -66
  87. package/src/actions/guides/legends/continuous/gradient.js +38 -37
  88. package/src/actions/guides/legends/continuous/interval.js +97 -76
  89. package/src/actions/guides/legends/continuous/opacity.js +28 -38
  90. package/src/actions/guides/legends/edit.js +14 -1
  91. package/src/actions/guides/legends/index.js +1 -1
  92. package/src/actions/guides/legends/lane.js +2 -1
  93. package/src/actions/guides/legends/remove.js +8 -0
  94. package/src/actions/guides/legends/size.js +36 -43
  95. package/src/actions/guides/legends/strokeWidth.js +20 -26
  96. package/src/actions/guides/polar/axes/labels.js +17 -1
  97. package/src/actions/guides/polar/axes/shared.js +7 -1
  98. package/src/actions/guides/polar/axes/titles.js +19 -2
  99. package/src/actions/guides/polar/grids.js +4 -0
  100. package/src/actions/guides/polar/resolve.js +6 -0
  101. package/src/actions/index.js +13 -13
  102. package/src/actions/intervals/resolve.js +87 -117
  103. package/src/actions/marks/arc/actions.js +31 -36
  104. package/src/actions/marks/area/actions.js +23 -31
  105. package/src/actions/marks/index.js +6 -6
  106. package/src/actions/marks/line/actions.js +33 -52
  107. package/src/actions/marks/line/materialize.js +7 -5
  108. package/src/actions/marks/point/materialize.js +5 -3
  109. package/src/actions/marks/remove.js +21 -0
  110. package/src/actions/marks/rule/actions.js +53 -53
  111. package/src/actions/marks/shared.js +8 -4
  112. package/src/actions/marks/text/actions.js +14 -6
  113. package/src/actions/marks/text/layout.js +21 -45
  114. package/src/actions/marks/tick/actions.js +22 -21
  115. package/src/actions/primitives/createGraphics.js +4 -0
  116. package/src/actions/primitives/editGraphics.js +4 -0
  117. package/src/actions/primitives/index.js +3 -3
  118. package/src/actions/primitives/semantic.js +1 -1
  119. package/src/actions/primitives/semanticValidation/index.js +2 -2
  120. package/src/actions/primitives/semanticValidation/layer.js +1 -1
  121. package/src/actions/regression/edit.js +3 -43
  122. package/src/actions/scales/consumers/families.js +24 -4
  123. package/src/actions/scales/consumers/index.js +1 -1
  124. package/src/actions/scales/consumers/seriesLayout.js +17 -0
  125. package/src/actions/scales/definitions.js +100 -103
  126. package/src/actions/scales/materialize.js +5 -0
  127. package/src/actions/selection/actions.js +79 -121
  128. package/src/actions/titles/actions.js +48 -94
  129. package/src/actions/titles/resolve.js +14 -27
  130. package/src/actions/violinPlots/create.js +37 -44
  131. package/src/core/action.js +20 -5
  132. package/src/core/extensionRegistry.js +104 -0
  133. package/src/core/textMetrics.js +74 -37
  134. package/src/core/validation.js +18 -0
  135. package/src/extension.js +8 -1
  136. package/src/grammar/aggregate.js +48 -28
  137. package/src/grammar/arcs.js +58 -11
  138. package/src/grammar/areaSeries.js +14 -16
  139. package/src/grammar/bin2d.js +37 -23
  140. package/src/grammar/boxPlot.js +14 -13
  141. package/src/grammar/categoricalDensity.js +14 -14
  142. package/src/grammar/categoryOrder.js +8 -14
  143. package/src/grammar/curveCommands.js +87 -20
  144. package/src/grammar/density.js +162 -141
  145. package/src/grammar/facets/index.js +14 -0
  146. package/src/grammar/facets/scales.js +7 -4
  147. package/src/grammar/gradientProfile.js +12 -15
  148. package/src/grammar/histogram.js +145 -83
  149. package/src/grammar/horizon.js +60 -23
  150. package/src/grammar/interval.js +14 -13
  151. package/src/grammar/lineSeries.js +91 -61
  152. package/src/grammar/numeric.js +290 -0
  153. package/src/grammar/paint.js +3 -4
  154. package/src/grammar/palettes.js +21 -32
  155. package/src/grammar/pathCommands.js +6 -0
  156. package/src/grammar/polarPaths.js +5 -5
  157. package/src/grammar/regression/derive.js +48 -9
  158. package/src/grammar/regression/models.js +248 -69
  159. package/src/grammar/regression/parameters.js +8 -0
  160. package/src/grammar/scales/color.js +35 -26
  161. package/src/grammar/scales/continuous.js +71 -24
  162. package/src/grammar/scales/definition.js +1 -1
  163. package/src/grammar/scales/discretized.js +42 -12
  164. package/src/grammar/scales/fields.js +21 -4
  165. package/src/grammar/scales/ordinal.js +117 -61
  166. package/src/grammar/scales/temporal.js +40 -11
  167. package/src/grammar/scales/transformed.js +199 -52
  168. package/src/grammar/schemas/graphicBounds.js +270 -79
  169. package/src/grammar/seriesLayout.js +50 -18
  170. package/src/grammar/ticks.js +123 -53
  171. package/src/grammar/timeUnit.js +18 -8
  172. package/src/grammar/transforms.js +4 -1
  173. package/src/grammar/window.js +70 -57
  174. package/src/index.js +1 -1
  175. package/src/layout/canvas.js +4 -8
  176. package/src/layout/composition.js +39 -40
  177. package/src/layout/facets.js +10 -14
  178. package/src/layout/labels.js +91 -15
  179. package/src/layout/legend.js +22 -20
  180. package/src/layout/legendLane.js +54 -40
  181. package/src/layout/title.js +7 -7
  182. package/src/materialization/bars/aggregate.js +14 -40
  183. package/src/materialization/bars/grouped.js +7 -18
  184. package/src/materialization/bars/histogram.js +2 -19
  185. package/src/materialization/bars/ranged.js +20 -15
  186. package/src/materialization/bars/resolve.js +21 -0
  187. package/src/materialization/facetGuides/legacyCategorical.js +2 -1
  188. package/src/materialization/facetGuides/placement.js +34 -19
  189. package/src/materialization/facetGuides/preparation.js +9 -5
  190. package/src/materialization/facets.js +39 -27
  191. package/src/materialization/guides/resources.js +2 -1
  192. package/src/materialization/marks/capabilities.js +5 -2
  193. package/src/materialization/marks/index.js +24 -4
  194. package/src/materialization/scales/policies/bar.js +61 -59
  195. package/src/materialization/scales/policies/binnedPosition.js +34 -0
  196. package/src/materialization/scales/policies/series.js +13 -7
  197. package/src/materialization/scales/resolve.js +4 -5
  198. package/src/materialization/selection/items/arc.js +16 -2
  199. package/src/materialization/selection/items/bar.js +4 -2
  200. package/src/materialization/selection/items/common.js +21 -1
  201. package/src/materialization/selection/items/path.js +19 -2
  202. package/src/materialization/selection/items/point.js +4 -16
  203. package/src/materialization/selection/items/tick.js +13 -21
  204. package/src/materialization/selection/point.js +11 -4
  205. package/src/materialization/selection/styles.js +19 -27
  206. package/src/materialization/text.js +4 -1
  207. package/src/mcp/adapter.js +8 -3
  208. package/src/renderers/canvas/fill.js +2 -2
  209. package/src/renderers/canvas/index.js +35 -2
  210. package/src/renderers/canvas/native.js +160 -0
  211. package/src/renderers/pdf.js +14 -0
  212. package/src/renderers/svg.js +37 -4
  213. package/types/extension.d.ts +19 -0
  214. package/types/index.d.ts +3 -0
  215. package/types/program.d.ts +509 -131
  216. package/types/svg.d.ts +1 -0
  217. package/src/actions/errorBands/components.js +0 -81
  218. package/src/actions/errorBands/options.js +0 -39
  219. package/src/actions/errorBands/resolve.js +0 -28
  220. package/src/actions/errorBars/components.js +0 -62
  221. package/src/actions/errorBars/options.js +0 -58
  222. package/src/actions/errorBars/resolve.js +0 -25
@@ -21,6 +21,7 @@ import { rematerializeHighlightBaseline } from "../lifecycle.js";
21
21
  import {
22
22
  applyLayeredMarkInheritance,
23
23
  assertMarkAvailable,
24
+ editMarkGraphic,
24
25
  materializeInheritedMark,
25
26
  resolveLayeredMarkInheritance,
26
27
  resolveMarkData,
@@ -28,12 +29,11 @@ import {
28
29
  validateMarkOptions
29
30
  } from "../shared.js";
30
31
 
31
- const CREATE_OPTIONS = Object.freeze([
32
- "id", "data", "length", "stroke", "strokeWidth", "opacity"
33
- ]);
34
- const EDIT_OPTIONS = Object.freeze([
35
- "target", "length", "stroke", "strokeWidth", "opacity"
32
+ const APPEARANCE_OPTIONS = Object.freeze([
33
+ "length", "stroke", "strokeWidth", "opacity"
36
34
  ]);
35
+ const CREATE_OPTIONS = Object.freeze(["id", "data", ...APPEARANCE_OPTIONS]);
36
+ const EDIT_OPTIONS = Object.freeze(["target", ...APPEARANCE_OPTIONS]);
37
37
  const REMATERIALIZE_OPTIONS = Object.freeze(["id"]);
38
38
 
39
39
  export const DEFAULT_TICK_CONFIG = Object.freeze({
@@ -116,8 +116,7 @@ export const createTickMark = action(
116
116
  ._withMarkConfig(id, DEFAULT_TICK_CONFIG);
117
117
  const materialized = materializeInheritedMark(created, id);
118
118
  const appearance = Object.fromEntries(
119
- ["length", "stroke", "strokeWidth", "opacity"]
120
- .filter(property => Object.hasOwn(args, property))
119
+ APPEARANCE_OPTIONS.filter(property => Object.hasOwn(args, property))
121
120
  .map(property => [property, config[property]])
122
121
  );
123
122
  return Object.keys(appearance).length === 0
@@ -133,8 +132,7 @@ export const editTickMark = action(
133
132
  },
134
133
  function (args = {}) {
135
134
  validateMarkOptions(args, EDIT_OPTIONS, "editTickMark");
136
- const editable = ["length", "stroke", "strokeWidth", "opacity"];
137
- if (!editable.some(property => Object.hasOwn(args, property))) {
135
+ if (!APPEARANCE_OPTIONS.some(property => Object.hasOwn(args, property))) {
138
136
  throw new Error(
139
137
  "editTickMark requires length, stroke, strokeWidth, or opacity."
140
138
  );
@@ -206,20 +204,23 @@ export const rematerializeTickMark = action(
206
204
  })
207
205
  );
208
206
 
209
- return this
210
- .editGraphics({ target: id, property: "length", value: segments.length })
211
- .editGraphics({ target: id, property: "x1", value: segments.map(item => item.x1) })
212
- .editGraphics({ target: id, property: "y1", value: segments.map(item => item.y1) })
213
- .editGraphics({ target: id, property: "x2", value: segments.map(item => item.x2) })
214
- .editGraphics({ target: id, property: "y2", value: segments.map(item => item.y2) })
215
- .editGraphics({ target: id, property: "stroke", value: config.stroke })
216
- .editGraphics({ target: id, property: "strokeWidth", value: config.strokeWidth })
217
- .editGraphics({ target: id, property: "opacity", value: config.opacity });
207
+ return editMarkGraphic(this, id, {
208
+ length: segments.length,
209
+ x1: segments.map(item => item.x1),
210
+ y1: segments.map(item => item.y1),
211
+ x2: segments.map(item => item.x2),
212
+ y2: segments.map(item => item.y2),
213
+ stroke: config.stroke,
214
+ strokeWidth: config.strokeWidth,
215
+ opacity: config.opacity
216
+ });
218
217
  }
219
218
  );
220
219
 
221
220
  export function registerTickMarkActions(ProgramClass) {
222
- ProgramClass.prototype.createTickMark = createTickMark;
223
- ProgramClass.prototype.editTickMark = editTickMark;
224
- ProgramClass.prototype.rematerializeTickMark = rematerializeTickMark;
221
+ Object.assign(ProgramClass.prototype, {
222
+ createTickMark,
223
+ editTickMark,
224
+ rematerializeTickMark
225
+ });
225
226
  }
@@ -1,6 +1,7 @@
1
1
  import { action } from "../../core/action.js";
2
2
  import { validateUserId } from "../../core/identifiers.js";
3
3
  import { freezeOwned } from "../../core/immutable.js";
4
+ import { validateGeneratedItemLimit } from "../../core/validation.js";
4
5
  import {
5
6
  isDrawableGraphicType,
6
7
  isGraphicContainerType,
@@ -115,6 +116,9 @@ const createGraphics = action(
115
116
  if (length !== undefined && (!Number.isInteger(length) || length < 0)) {
116
117
  throw new TypeError("createGraphics length must be a non-negative integer.");
117
118
  }
119
+ if (length !== undefined) {
120
+ validateGeneratedItemLimit(length, "createGraphics length");
121
+ }
118
122
  if (validatedType === "collection" && length !== undefined) {
119
123
  throw new Error("Heterogeneous collections use editGraphics items instead of length.");
120
124
  }
@@ -1,5 +1,6 @@
1
1
  import { action } from "../../core/action.js";
2
2
  import { cloneAndFreeze, freezeOwned, isPlainObject } from "../../core/immutable.js";
3
+ import { validateGeneratedItemLimit } from "../../core/validation.js";
3
4
  import {
4
5
  isPrimitiveDrawableGraphicType,
5
6
  isStructuralGraphicType,
@@ -44,6 +45,7 @@ function validateCollectionItem(item, ownerId, index) {
44
45
 
45
46
  function replaceCollectionItems(value, id) {
46
47
  if (!Array.isArray(value)) throw new TypeError("collection.items must be an array.");
48
+ validateGeneratedItemLimit(value.length, "collection.items length");
47
49
  return freezeOwned(value.map((item, index) => validateCollectionItem(item, id, index)));
48
50
  }
49
51
 
@@ -82,6 +84,7 @@ function editItems(owner, property, value, id) {
82
84
  if (!Number.isInteger(value) || value < 0) {
83
85
  throw new TypeError("Graphic collection length must be a non-negative integer.");
84
86
  }
87
+ validateGeneratedItemLimit(value, "Graphic collection length");
85
88
  const items = owner.items.slice(0, value);
86
89
  for (let index = items.length; index < value; index += 1) {
87
90
  if (owner.type === "collection") {
@@ -187,6 +190,7 @@ const editGraphics = action(
187
190
  if (!Number.isInteger(value) || value < 0) {
188
191
  throw new TypeError("Graphic collection length must be a non-negative integer.");
189
192
  }
193
+ validateGeneratedItemLimit(value, "Graphic collection length");
190
194
  updated = freezeOwned({
191
195
  type: owner.type,
192
196
  items: freezeOwned(Array.from({ length: value }, (_, index) => freezeOwned({
@@ -1,10 +1,10 @@
1
+ import { createSemanticValueValidator } from "./semanticValidation/index.js";
1
2
  import { isPlainObject } from "../../core/immutable.js";
2
3
  import { validateBin2DTransform } from "../../grammar/bin2d.js";
3
- import { registerCreateGraphicsAction } from "./createGraphics.js";
4
- import { registerEditGraphicsAction } from "./editGraphics.js";
5
4
  import { registerSemanticPrimitiveAction } from "./semantic.js";
5
+ import { registerEditGraphicsAction } from "./editGraphics.js";
6
+ import { registerCreateGraphicsAction } from "./createGraphics.js";
6
7
  import { createSemanticPrimitiveAction } from "./semanticAction.js";
7
- import { createSemanticValueValidator } from "./semanticValidation/index.js";
8
8
 
9
9
  function validateBasicDatasetTransforms(value) {
10
10
  if (!Array.isArray(value) || value.length !== 1 || !isPlainObject(value[0])) {
@@ -21,7 +21,7 @@ export function registerSemanticPrimitiveAction(ProgramClass) {
21
21
  const validateSemanticValue = createSemanticValueValidator({
22
22
  validateDatasetTransforms,
23
23
  validateParallel,
24
- sourceMarkTypes: ["point", "bar", "rule", "rect"]
24
+ sourceMarkTypes: ["point", "bar", "rule", "rect", "arc"]
25
25
  });
26
26
  ProgramClass.prototype.editSemantic =
27
27
  createSemanticPrimitiveAction(validateSemanticValue);
@@ -1,8 +1,8 @@
1
1
  import { validateCoordinateType } from "../../../grammar/coordinates.js";
2
+ import { validateScaleSemanticValue } from "./scale.js";
2
3
  import { validateDatasetSemanticValue } from "./dataset.js";
3
- import { validateGuideSemanticValue } from "./guide.js";
4
4
  import { validateLayerSemanticValue } from "./layer.js";
5
- import { validateScaleSemanticValue } from "./scale.js";
5
+ import { validateGuideSemanticValue } from "./guide.js";
6
6
  import { validateNonEmptySemanticString } from "./shared.js";
7
7
 
8
8
  export function createSemanticValueValidator({
@@ -40,7 +40,7 @@ export function validateLayerSemanticValue(
40
40
  parsed,
41
41
  value,
42
42
  {
43
- sourceMarkTypes = ["point", "bar", "rule", "rect"],
43
+ sourceMarkTypes = ["point", "bar", "rule", "rect", "arc"],
44
44
  validateParallel
45
45
  } = {}
46
46
  ) {
@@ -12,7 +12,8 @@ import { validateCurveInterpolation } from "../../grammar/curveCommands.js";
12
12
  import { planDerivedDataRevision } from
13
13
  "../../materialization/dataProvenance.js";
14
14
  import { findLayer } from "../../selectors/layers.js";
15
- import { removeLegendKinds } from "../guides/legends/remove.js";
15
+ import { removeOwnedMark } from "../marks/remove.js";
16
+ import { removeOwnedColorLegends } from "../guides/legends/remove.js";
16
17
  import { requireRegressionField } from "./resolve.js";
17
18
 
18
19
  const OPTIONS = Object.freeze([
@@ -118,46 +119,6 @@ function resolveParameters(previous, args) {
118
119
  return normalizeRegressionParameters(raw);
119
120
  }
120
121
 
121
- function removeOwnedColorLegends(program, target) {
122
- const kinds = Object.entries(program.guideConfigs.legend ?? {})
123
- .filter(([kind, config]) =>
124
- config?.target === target &&
125
- (
126
- config.channels?.includes("color") ||
127
- ["gradient", "interval"].includes(kind)
128
- )
129
- )
130
- .map(([kind]) => kind);
131
- return kinds.length === 0 ? program : removeLegendKinds(program, kinds);
132
- }
133
-
134
- function removeBand(program, id) {
135
- const selectionIds = Object.entries(
136
- program.materializationConfigs.selections ?? {}
137
- ).filter(([, config]) => config.target === id).map(([selection]) => selection);
138
- let next = program;
139
- for (const [highlight, config] of Object.entries(
140
- program.materializationConfigs.highlights ?? {}
141
- )) {
142
- if (config.target === id || selectionIds.includes(config.selection)) {
143
- next = next._withoutMaterializationConfig(["highlights", highlight]);
144
- }
145
- }
146
- for (const selection of selectionIds) {
147
- next = next._withoutMaterializationConfig(["selections", selection]);
148
- }
149
- return next
150
- .editSemantic({ property: `layer[${id}]`, remove: true })
151
- .editGraphics({ target: id, remove: true })
152
- ._withoutMaterializationConfig(["marks", id])
153
- ._withContext({
154
- ...(program.context.currentMark === id ? { currentMark: undefined } : {}),
155
- ...(selectionIds.includes(program.context.currentSelection)
156
- ? { currentSelection: undefined }
157
- : {})
158
- });
159
- }
160
-
161
122
  function regressionColorScale(owner, current, groupBy) {
162
123
  if (groupBy === undefined || groupBy === current.groupBy) {
163
124
  return current.colorScale;
@@ -331,7 +292,7 @@ export const editRegression = action(
331
292
 
332
293
  let bandId = current.bandId;
333
294
  if (hadBand && !wantsBand) {
334
- next = removeBand(next, current.bandId);
295
+ next = removeOwnedMark(next, current.bandId);
335
296
  bandId = undefined;
336
297
  } else if (!hadBand && wantsBand) {
337
298
  bandId = `${owner.id}RegressionBands`;
@@ -400,7 +361,6 @@ export const editRegression = action(
400
361
  }
401
362
  });
402
363
  };
403
- if (changesStatistics || hadBand !== wantsBand) applyEdit(this);
404
364
  return applyEdit(this);
405
365
  }
406
366
  );
@@ -5,14 +5,27 @@ import {
5
5
  } from "../../../grammar/bars/policy.js";
6
6
  import {
7
7
  deriveLineSeries,
8
- deriveLineSeriesFieldValues
8
+ deriveLineSeriesFieldValues,
9
+ resolveLineBins
9
10
  } from "../../../grammar/lineSeries.js";
10
11
  import { isAggregate } from "../../../grammar/aggregate.js";
11
12
  import {
12
13
  resolveRectConsumerValues
13
14
  } from "../../../materialization/rect.js";
15
+ import { findScale } from "./common.js";
14
16
 
15
- export function resolveMarkFamilyConsumerValues(consumer, dataset) {
17
+ function lineDerivationOptions(program, consumer, dataset) {
18
+ const x = consumer.layer.encoding?.x;
19
+ if (x?.bin === undefined) return undefined;
20
+ const bins = resolveLineBins(
21
+ dataset.values,
22
+ consumer.layer,
23
+ findScale(program, x.scale)
24
+ );
25
+ return { xBinBoundaries: bins.boundaries };
26
+ }
27
+
28
+ export function resolveMarkFamilyConsumerValues(program, consumer, dataset) {
16
29
  if (consumer.layer.mark?.type === "rect") {
17
30
  return {
18
31
  matched: true,
@@ -25,10 +38,17 @@ export function resolveMarkFamilyConsumerValues(consumer, dataset) {
25
38
  }
26
39
  if (
27
40
  consumer.layer.mark?.type === "line" &&
28
- (isAggregate(consumer.layer.encoding?.y?.aggregate) ||
41
+ ((consumer.layer.encoding?.x !== undefined &&
42
+ isAggregate(consumer.layer.encoding?.y?.aggregate) &&
43
+ !(consumer.channel === "x" &&
44
+ consumer.layer.encoding?.x?.bin !== undefined)) ||
29
45
  consumer.channel === "strokeWidth")
30
46
  ) {
31
- const derived = deriveLineSeries(dataset.values, consumer.layer);
47
+ const derived = deriveLineSeries(
48
+ dataset.values,
49
+ consumer.layer,
50
+ lineDerivationOptions(program, consumer, dataset)
51
+ );
32
52
  return {
33
53
  matched: true,
34
54
  values: consumer.channel === "strokeWidth"
@@ -35,7 +35,7 @@ export function resolveConsumerValues(program, consumer) {
35
35
  if (isDirectCategoricalConsumer(consumer)) {
36
36
  return readConsumerFieldValues(program, consumer, dataset, scale);
37
37
  }
38
- const family = resolveMarkFamilyConsumerValues(consumer, dataset);
38
+ const family = resolveMarkFamilyConsumerValues(program, consumer, dataset);
39
39
  return family.matched
40
40
  ? family.values
41
41
  : readConsumerFieldValues(program, consumer, dataset, scale);
@@ -1,4 +1,5 @@
1
1
  import { deriveBarAggregates } from "../../../grammar/bars/aggregate.js";
2
+ import { validateGeneratedItemLimit } from "../../../core/validation.js";
2
3
  import {
3
4
  BAR_GRAINS,
4
5
  resolveBarChannels,
@@ -72,6 +73,10 @@ function resolveHistogramPartitions(program, consumer) {
72
73
  const colorScale = findScale(program, colorEncoding.scale);
73
74
  const colorValues = readNominalField(dataset.values, colorEncoding.field);
74
75
  const colorDomain = resolveOrdinalDomain(colorScale.domain, colorValues);
76
+ validateGeneratedItemLimit(
77
+ (bins.boundaries.length - 1) * colorDomain.length,
78
+ "Histogram layout cell count"
79
+ );
75
80
  const colorIndex = new Map(colorDomain.map((value, index) => [value, index]));
76
81
  const partitions = bins.boundaries.slice(0, -1).map(() =>
77
82
  colorDomain.map(() => 0)
@@ -109,6 +114,10 @@ function resolveAggregatePartitions(program, consumer) {
109
114
  const colorScale = findScale(program, colorEncoding.scale);
110
115
  const colorValues = readNominalField(dataset.values, colorEncoding.field);
111
116
  const colorDomain = resolveOrdinalDomain(colorScale.domain, colorValues);
117
+ validateGeneratedItemLimit(
118
+ categoryDomain.length * colorDomain.length,
119
+ "Aggregate layout cell count"
120
+ );
112
121
  const cells = new Map(derived.values.map(value => [
113
122
  JSON.stringify([value[channels.category], value.color]),
114
123
  value[channels.measure]
@@ -131,6 +140,10 @@ function resolveAreaPartitions(program, consumer) {
131
140
  layer.encoding?.x !== undefined
132
141
  ) {
133
142
  const derived = deriveCenteredAreaSeries(dataset.values, layer);
143
+ validateGeneratedItemLimit(
144
+ derived.series[0].values.length * derived.series.length,
145
+ "Area layout cell count"
146
+ );
134
147
  return Array.from({ length: derived.series[0].values.length }, (_, index) =>
135
148
  derived.series.map(series => series.values[index].y)
136
149
  );
@@ -142,6 +155,10 @@ function resolveAreaPartitions(program, consumer) {
142
155
  if (derived.series.some(series => series.values.length !== sampleCount)) {
143
156
  throw new Error(`Area mark "${layer.id}" requires aligned layout samples.`);
144
157
  }
158
+ validateGeneratedItemLimit(
159
+ sampleCount * derived.series.length,
160
+ "Area layout cell count"
161
+ );
145
162
  return Array.from({ length: sampleCount }, (_, index) =>
146
163
  derived.series.map(series => series.values[index].y)
147
164
  );