ggaction 0.0.10 → 0.0.12

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 (224) hide show
  1. package/CHANGELOG.md +97 -0
  2. package/README.md +5 -3
  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/intent-taxonomy.json +1 -183
  7. package/knowledge/intent-taxonomy.schema.json +1 -0
  8. package/knowledge/mcp-resources.json +1 -95
  9. package/knowledge/mcp-resources.schema.json +1 -0
  10. package/knowledge/task-packet.schema.json +1 -159
  11. package/knowledge/task-resolver.js +1 -1230
  12. package/package.json +18 -2
  13. package/src/actions/boxPlots/edit.js +45 -298
  14. package/src/actions/boxPlots/options.js +46 -77
  15. package/src/actions/boxPlots/resolve.js +1 -1
  16. package/src/actions/charts/bar.js +3 -0
  17. package/src/actions/charts/heatmap.js +73 -83
  18. package/src/actions/charts/index.js +1 -1
  19. package/src/actions/charts/parallel.js +35 -1
  20. package/src/actions/charts/shared.js +20 -0
  21. package/src/actions/composition/actions.js +46 -49
  22. package/src/actions/data/bin2d.js +105 -2
  23. package/src/actions/data/box.js +17 -17
  24. package/src/actions/data/density.js +42 -78
  25. package/src/actions/data/gradientProfile.js +22 -52
  26. package/src/actions/data/horizon.js +16 -41
  27. package/src/actions/data/index.js +10 -10
  28. package/src/actions/data/interval.js +16 -38
  29. package/src/actions/data/intervalEdit.js +55 -0
  30. package/src/actions/data/regression.js +7 -17
  31. package/src/actions/data/shared.js +47 -0
  32. package/src/actions/data/timeUnit.js +14 -38
  33. package/src/actions/data/window.js +14 -38
  34. package/src/actions/distributions/revision.js +154 -34
  35. package/src/actions/encodings/angle.js +9 -10
  36. package/src/actions/encodings/appearance.js +17 -51
  37. package/src/actions/encodings/density/resolve.js +3 -1
  38. package/src/actions/encodings/density.js +1 -15
  39. package/src/actions/encodings/horizon/resolve.js +13 -3
  40. package/src/actions/encodings/horizon.js +8 -7
  41. package/src/actions/encodings/index.js +9 -9
  42. package/src/actions/encodings/offset.js +41 -45
  43. package/src/actions/encodings/parallel.js +9 -10
  44. package/src/actions/encodings/pathOrder.js +6 -13
  45. package/src/actions/encodings/position/apply.js +30 -0
  46. package/src/actions/encodings/position/policies/arc.js +23 -2
  47. package/src/actions/encodings/position/policies/index.js +4 -4
  48. package/src/actions/encodings/position/policies/line.js +47 -17
  49. package/src/actions/encodings/position/resolve.js +36 -7
  50. package/src/actions/encodings/ranged.js +18 -23
  51. package/src/actions/encodings/remove.js +15 -25
  52. package/src/actions/encodings/ruleAppearance.js +9 -24
  53. package/src/actions/encodings/shared.js +37 -0
  54. package/src/actions/encodings/strokeDash.js +8 -23
  55. package/src/actions/encodings/text.js +9 -10
  56. package/src/actions/errorBands/create.js +105 -39
  57. package/src/actions/errorBands/edit.js +89 -93
  58. package/src/actions/errorBands/index.js +1 -2
  59. package/src/actions/errorBars/create.js +212 -30
  60. package/src/actions/errorBars/edit.js +91 -48
  61. package/src/actions/errorBars/index.js +1 -2
  62. package/src/actions/facets/actions.js +45 -69
  63. package/src/actions/facets/derive.js +38 -53
  64. package/src/actions/facets/replay.js +0 -1
  65. package/src/actions/gradientPlots/components.js +59 -48
  66. package/src/actions/gradientPlots/edit.js +35 -216
  67. package/src/actions/gradientPlots/index.js +11 -10
  68. package/src/actions/gradientPlots/materialize.js +21 -35
  69. package/src/actions/gradientPlots/options.js +5 -7
  70. package/src/actions/gradientPlots/paint.js +9 -6
  71. package/src/actions/gradientPlots/resolve.js +1 -1
  72. package/src/actions/guides/axes/index.js +3 -3
  73. package/src/actions/guides/axes/labels.js +68 -26
  74. package/src/actions/guides/axes/lines.js +22 -2
  75. package/src/actions/guides/axes/policy.js +28 -8
  76. package/src/actions/guides/axes/ticks.js +27 -9
  77. package/src/actions/guides/axes/titles.js +113 -65
  78. package/src/actions/guides/grids/resolve.js +14 -0
  79. package/src/actions/guides/guides.js +2 -4
  80. package/src/actions/guides/index.js +2 -2
  81. package/src/actions/guides/legends/categorical/actions.js +44 -68
  82. package/src/actions/guides/legends/categorical/components.js +6 -1
  83. package/src/actions/guides/legends/categorical/index.js +2 -2
  84. package/src/actions/guides/legends/categorical/layout.js +148 -175
  85. package/src/actions/guides/legends/categorical/recipes.js +5 -0
  86. package/src/actions/guides/legends/categorical/resolve.js +8 -1
  87. package/src/actions/guides/legends/continuous/common.js +117 -66
  88. package/src/actions/guides/legends/continuous/gradient.js +38 -37
  89. package/src/actions/guides/legends/continuous/interval.js +97 -76
  90. package/src/actions/guides/legends/continuous/opacity.js +28 -38
  91. package/src/actions/guides/legends/edit.js +14 -1
  92. package/src/actions/guides/legends/index.js +1 -1
  93. package/src/actions/guides/legends/lane.js +2 -1
  94. package/src/actions/guides/legends/remove.js +8 -0
  95. package/src/actions/guides/legends/size.js +36 -43
  96. package/src/actions/guides/legends/strokeWidth.js +20 -26
  97. package/src/actions/guides/polar/axes/labels.js +17 -1
  98. package/src/actions/guides/polar/axes/shared.js +7 -1
  99. package/src/actions/guides/polar/axes/titles.js +19 -2
  100. package/src/actions/guides/polar/grids.js +4 -0
  101. package/src/actions/guides/polar/resolve.js +6 -0
  102. package/src/actions/index.js +13 -13
  103. package/src/actions/intervals/resolve.js +87 -117
  104. package/src/actions/marks/arc/actions.js +31 -36
  105. package/src/actions/marks/area/actions.js +23 -31
  106. package/src/actions/marks/index.js +6 -6
  107. package/src/actions/marks/line/actions.js +33 -52
  108. package/src/actions/marks/line/materialize.js +7 -5
  109. package/src/actions/marks/point/materialize.js +38 -16
  110. package/src/actions/marks/remove.js +21 -0
  111. package/src/actions/marks/rule/actions.js +79 -54
  112. package/src/actions/marks/shared.js +8 -4
  113. package/src/actions/marks/text/actions.js +14 -6
  114. package/src/actions/marks/text/layout.js +21 -45
  115. package/src/actions/marks/tick/actions.js +22 -21
  116. package/src/actions/primitives/createGraphics.js +4 -0
  117. package/src/actions/primitives/editGraphics.js +4 -0
  118. package/src/actions/primitives/index.js +3 -3
  119. package/src/actions/primitives/semantic.js +1 -1
  120. package/src/actions/primitives/semanticValidation/index.js +2 -2
  121. package/src/actions/primitives/semanticValidation/layer.js +1 -1
  122. package/src/actions/regression/edit.js +3 -43
  123. package/src/actions/scales/consumers/families.js +24 -4
  124. package/src/actions/scales/consumers/index.js +1 -1
  125. package/src/actions/scales/consumers/seriesLayout.js +17 -0
  126. package/src/actions/scales/definitions.js +100 -103
  127. package/src/actions/scales/materialize.js +5 -0
  128. package/src/actions/selection/actions.js +79 -121
  129. package/src/actions/titles/actions.js +48 -94
  130. package/src/actions/titles/resolve.js +14 -27
  131. package/src/actions/violinPlots/create.js +37 -44
  132. package/src/core/textMetrics.js +74 -37
  133. package/src/core/validation.js +18 -0
  134. package/src/core/vocabulary.js +2 -2
  135. package/src/grammar/aggregate.js +48 -28
  136. package/src/grammar/arcs.js +170 -32
  137. package/src/grammar/areaSeries.js +14 -16
  138. package/src/grammar/bin2d.js +37 -23
  139. package/src/grammar/boxPlot.js +14 -13
  140. package/src/grammar/categoricalDensity.js +14 -14
  141. package/src/grammar/categoryOrder.js +8 -14
  142. package/src/grammar/curveCommands.js +87 -20
  143. package/src/grammar/density.js +162 -141
  144. package/src/grammar/facets/index.js +14 -0
  145. package/src/grammar/facets/scales.js +7 -4
  146. package/src/grammar/gradientProfile.js +12 -15
  147. package/src/grammar/histogram.js +145 -83
  148. package/src/grammar/horizon.js +60 -23
  149. package/src/grammar/interval.js +14 -13
  150. package/src/grammar/lineSeries.js +91 -61
  151. package/src/grammar/numeric.js +290 -0
  152. package/src/grammar/paint.js +3 -4
  153. package/src/grammar/palettes.js +21 -32
  154. package/src/grammar/pathCommands.js +6 -0
  155. package/src/grammar/polarPaths.js +5 -5
  156. package/src/grammar/positionCompatibility.js +1 -1
  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/rules.js +2 -0
  161. package/src/grammar/scales/color.js +35 -26
  162. package/src/grammar/scales/continuous.js +71 -24
  163. package/src/grammar/scales/definition.js +1 -1
  164. package/src/grammar/scales/discretized.js +42 -12
  165. package/src/grammar/scales/fields.js +21 -4
  166. package/src/grammar/scales/ordinal.js +139 -60
  167. package/src/grammar/scales/temporal.js +40 -11
  168. package/src/grammar/scales/transformed.js +199 -52
  169. package/src/grammar/schemas/graphicBounds.js +270 -79
  170. package/src/grammar/seriesLayout.js +50 -18
  171. package/src/grammar/ticks.js +123 -53
  172. package/src/grammar/timeUnit.js +18 -8
  173. package/src/grammar/transforms.js +4 -1
  174. package/src/grammar/window.js +70 -57
  175. package/src/index.js +1 -1
  176. package/src/layout/canvas.js +4 -8
  177. package/src/layout/composition.js +39 -40
  178. package/src/layout/facets.js +55 -30
  179. package/src/layout/labels.js +91 -15
  180. package/src/layout/legend.js +22 -20
  181. package/src/layout/legendLane.js +54 -40
  182. package/src/layout/title.js +7 -7
  183. package/src/materialization/bars/aggregate.js +14 -40
  184. package/src/materialization/bars/grouped.js +7 -18
  185. package/src/materialization/bars/histogram.js +2 -19
  186. package/src/materialization/bars/ranged.js +20 -15
  187. package/src/materialization/bars/resolve.js +21 -0
  188. package/src/materialization/facetGuides/legacyCategorical.js +9 -2
  189. package/src/materialization/facetGuides/placement.js +49 -19
  190. package/src/materialization/facetGuides/preparation.js +35 -6
  191. package/src/materialization/facets.js +42 -28
  192. package/src/materialization/guides/resources.js +2 -1
  193. package/src/materialization/marks/capabilities.js +15 -4
  194. package/src/materialization/marks/index.js +29 -6
  195. package/src/materialization/rowEncoding.js +57 -1
  196. package/src/materialization/scales/policies/bar.js +61 -102
  197. package/src/materialization/scales/policies/binnedPosition.js +34 -0
  198. package/src/materialization/scales/policies/offset.js +54 -0
  199. package/src/materialization/scales/policies/series.js +13 -7
  200. package/src/materialization/scales/resolve.js +6 -9
  201. package/src/materialization/selection/items/arc.js +16 -2
  202. package/src/materialization/selection/items/bar.js +4 -2
  203. package/src/materialization/selection/items/common.js +21 -1
  204. package/src/materialization/selection/items/path.js +19 -2
  205. package/src/materialization/selection/items/point.js +4 -16
  206. package/src/materialization/selection/items/tick.js +13 -21
  207. package/src/materialization/selection/point.js +11 -4
  208. package/src/materialization/selection/styles.js +19 -27
  209. package/src/materialization/text.js +4 -1
  210. package/src/mcp/adapter.js +8 -3
  211. package/src/renderers/canvas/fill.js +2 -2
  212. package/src/renderers/canvas/index.js +35 -2
  213. package/src/renderers/canvas/native.js +160 -0
  214. package/src/renderers/pdf.js +14 -0
  215. package/src/renderers/svg.js +37 -4
  216. package/types/index.d.ts +3 -0
  217. package/types/program.d.ts +523 -131
  218. package/types/svg.d.ts +1 -0
  219. package/src/actions/errorBands/components.js +0 -81
  220. package/src/actions/errorBands/options.js +0 -39
  221. package/src/actions/errorBands/resolve.js +0 -28
  222. package/src/actions/errorBars/components.js +0 -62
  223. package/src/actions/errorBars/options.js +0 -58
  224. package/src/actions/errorBars/resolve.js +0 -25
@@ -14,6 +14,7 @@ import { resolveGraphicBounds } from "../../../layout/canvas.js";
14
14
  import { canMaterializeText } from "../../../materialization/marks/index.js";
15
15
  import { resolveTextGraphicEntries } from "../../../materialization/text.js";
16
16
  import { findLayer, resolveEligibleLayer } from "../../../selectors/layers.js";
17
+ import { editMarkGraphic } from "../shared.js";
17
18
 
18
19
  const LAYOUT_OPTIONS = Object.freeze([
19
20
  "target", "axis", "padding", "maxDisplacement", "bounds", "leader"
@@ -170,42 +171,22 @@ function materializeLeaders(program, layer, config, resolved) {
170
171
  if (config.leader === false) return { program: next, count: 0 };
171
172
  const leaders = resolved.items.map(resolveLabelLeader).filter(Boolean);
172
173
  if (leaders.length === 0) return { program: next, count: 0 };
173
- next = next
174
- .createGraphics({
174
+ next = next.createGraphics({
175
175
  id: config.leaderId,
176
176
  type: "line",
177
177
  length: leaders.length,
178
178
  ...leaderPlacement(next, layer)
179
- })
180
- .editGraphics({
181
- target: config.leaderId,
182
- property: "x1",
183
- value: leaders.map(line => line.x1)
184
- })
185
- .editGraphics({
186
- target: config.leaderId,
187
- property: "y1",
188
- value: leaders.map(line => line.y1)
189
- })
190
- .editGraphics({
191
- target: config.leaderId,
192
- property: "x2",
193
- value: leaders.map(line => line.x2)
194
- })
195
- .editGraphics({
196
- target: config.leaderId,
197
- property: "y2",
198
- value: leaders.map(line => line.y2)
199
179
  });
200
- for (const property of ["stroke", "strokeWidth", "strokeDash", "opacity"]) {
201
- next = next.editGraphics({
202
- target: config.leaderId,
203
- property,
204
- value: property === "strokeDash"
205
- ? leaders.map(() => config.leader.strokeDash)
206
- : config.leader[property]
207
- });
208
- }
180
+ next = editMarkGraphic(next, config.leaderId, {
181
+ x1: leaders.map(line => line.x1),
182
+ y1: leaders.map(line => line.y1),
183
+ x2: leaders.map(line => line.x2),
184
+ y2: leaders.map(line => line.y2),
185
+ stroke: config.leader.stroke,
186
+ strokeWidth: config.leader.strokeWidth,
187
+ strokeDash: leaders.map(() => config.leader.strokeDash),
188
+ opacity: config.leader.opacity
189
+ });
209
190
  return { program: next, count: leaders.length };
210
191
  }
211
192
 
@@ -237,17 +218,10 @@ const materializeLabelLayout = action(
237
218
  padding: config.padding,
238
219
  maxDisplacement: config.maxDisplacement
239
220
  });
240
- next = next
241
- .editGraphics({
242
- target: id,
243
- property: "x",
244
- value: resolved.items.map(item => item.x)
245
- })
246
- .editGraphics({
247
- target: id,
248
- property: "y",
249
- value: resolved.items.map(item => item.y)
250
- });
221
+ next = editMarkGraphic(next, id, {
222
+ x: resolved.items.map(item => item.x),
223
+ y: resolved.items.map(item => item.y)
224
+ });
251
225
  const leaders = materializeLeaders(next, layer, config, resolved);
252
226
  next = leaders.program;
253
227
  return next._withMaterializationConfig(["labelLayouts", id], {
@@ -315,7 +289,9 @@ const removeLabelLayout = action(
315
289
  );
316
290
 
317
291
  export function registerTextLabelLayoutActions(ProgramClass) {
318
- ProgramClass.prototype.layoutLabels = layoutLabels;
319
- ProgramClass.prototype.removeLabelLayout = removeLabelLayout;
320
- ProgramClass.prototype.materializeLabelLayout = materializeLabelLayout;
292
+ Object.assign(ProgramClass.prototype, {
293
+ layoutLabels,
294
+ removeLabelLayout,
295
+ materializeLabelLayout
296
+ });
321
297
  }
@@ -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
  );