ggaction 0.0.15 → 0.0.16

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 (236) hide show
  1. package/CHANGELOG.md +68 -0
  2. package/README.md +22 -2
  3. package/knowledge/action-cards.json +1 -1
  4. package/knowledge/intent-taxonomy.json +1 -1
  5. package/knowledge/mcp-resources.json +1 -1
  6. package/knowledge/task-packet.schema.json +1 -1
  7. package/knowledge/task-resolver.js +1 -1
  8. package/package.json +33 -6
  9. package/src/BasicChartProgram.js +3 -1
  10. package/src/ChartProgram.js +2 -0
  11. package/src/accessibility.js +157 -0
  12. package/src/actions/boxPlots/components.js +6 -8
  13. package/src/actions/boxPlots/create.js +4 -5
  14. package/src/actions/boxPlots/edit.js +3 -4
  15. package/src/actions/boxPlots/materialize.js +1 -1
  16. package/src/actions/canvas/actions.js +3 -3
  17. package/src/actions/canvas/fitting.js +1 -1
  18. package/src/actions/categoryOrder/index.js +6 -8
  19. package/src/actions/charts/area.js +1 -1
  20. package/src/actions/charts/bar.js +1 -1
  21. package/src/actions/charts/beeswarm.js +1 -1
  22. package/src/actions/charts/density.js +1 -1
  23. package/src/actions/charts/ecdf.js +2 -2
  24. package/src/actions/charts/endpoints.js +4 -4
  25. package/src/actions/charts/heatmap.js +1 -1
  26. package/src/actions/charts/histogram.js +1 -1
  27. package/src/actions/charts/horizon.js +1 -1
  28. package/src/actions/charts/interval-regression.js +2 -2
  29. package/src/actions/charts/line.js +1 -1
  30. package/src/actions/charts/parallel.js +1 -1
  31. package/src/actions/charts/pie.js +1 -1
  32. package/src/actions/charts/polar.js +2 -2
  33. package/src/actions/charts/radar.js +1 -1
  34. package/src/actions/charts/radial.js +2 -2
  35. package/src/actions/charts/raincloud.js +2 -2
  36. package/src/actions/charts/rug-strip.js +2 -2
  37. package/src/actions/charts/scatter.js +1 -1
  38. package/src/actions/composition/actions.js +20 -24
  39. package/src/actions/coordinates/actions.js +1 -1
  40. package/src/actions/coordinates/edit.js +1 -1
  41. package/src/actions/data/basicBin2d.js +4 -5
  42. package/src/actions/data/bin.js +2 -2
  43. package/src/actions/data/bin2d.js +6 -8
  44. package/src/actions/data/bin2dMaterialize.js +4 -5
  45. package/src/actions/data/box.js +4 -4
  46. package/src/actions/data/complete.js +2 -2
  47. package/src/actions/data/computed.js +2 -2
  48. package/src/actions/data/create.js +5 -12
  49. package/src/actions/data/density.js +3 -3
  50. package/src/actions/data/derived.js +10 -14
  51. package/src/actions/data/ecdf.js +2 -2
  52. package/src/actions/data/edit.js +35 -23
  53. package/src/actions/data/filter.js +14 -20
  54. package/src/actions/data/fold.js +2 -2
  55. package/src/actions/data/gradientProfile.js +2 -2
  56. package/src/actions/data/horizon.js +2 -2
  57. package/src/actions/data/impute.js +2 -2
  58. package/src/actions/data/index.js +55 -54
  59. package/src/actions/data/interval.js +2 -2
  60. package/src/actions/data/intervalEdit.js +26 -18
  61. package/src/actions/data/normalize.js +2 -2
  62. package/src/actions/data/regression.js +5 -6
  63. package/src/actions/data/revise.js +48 -0
  64. package/src/actions/data/revisionBindings.js +13 -33
  65. package/src/actions/data/stack.js +2 -2
  66. package/src/actions/data/summary.js +2 -2
  67. package/src/actions/data/timeUnit.js +2 -2
  68. package/src/actions/data/window.js +2 -2
  69. package/src/actions/encodings/angle.js +1 -1
  70. package/src/actions/encodings/appearance.js +4 -4
  71. package/src/actions/encodings/barWidth.js +1 -1
  72. package/src/actions/encodings/channels.js +2 -2
  73. package/src/actions/encodings/color/index.js +1 -1
  74. package/src/actions/encodings/density.js +2 -2
  75. package/src/actions/encodings/histogram.js +1 -1
  76. package/src/actions/encodings/horizon.js +6 -8
  77. package/src/actions/encodings/offset.js +2 -2
  78. package/src/actions/encodings/parallel.js +4 -5
  79. package/src/actions/encodings/pathOrder.js +6 -11
  80. package/src/actions/encodings/position/index.js +4 -4
  81. package/src/actions/encodings/ranged.js +5 -5
  82. package/src/actions/encodings/remove.js +4 -5
  83. package/src/actions/encodings/ruleAppearance.js +1 -1
  84. package/src/actions/encodings/seriesLayout.js +1 -1
  85. package/src/actions/encodings/stroke.js +1 -1
  86. package/src/actions/encodings/strokeDash.js +2 -2
  87. package/src/actions/encodings/text.js +1 -1
  88. package/src/actions/errorBands/create.js +11 -17
  89. package/src/actions/errorBands/edit.js +13 -131
  90. package/src/actions/errorBars/create.js +8 -13
  91. package/src/actions/errorBars/edit.js +10 -121
  92. package/src/actions/facets/actions.js +30 -16
  93. package/src/actions/facets/derive.js +8 -2
  94. package/src/actions/facets/guides.js +4 -5
  95. package/src/actions/facets/replay.js +4 -5
  96. package/src/actions/gradientPlots/components.js +5 -6
  97. package/src/actions/gradientPlots/create.js +4 -5
  98. package/src/actions/gradientPlots/edit.js +4 -5
  99. package/src/actions/gradientPlots/materialize.js +2 -2
  100. package/src/actions/gradientPlots/rebind.js +4 -5
  101. package/src/actions/guides/axes/axes.js +23 -4
  102. package/src/actions/guides/axes/axis.js +2 -2
  103. package/src/actions/guides/axes/edit.js +2 -2
  104. package/src/actions/guides/axes/labels.js +9 -9
  105. package/src/actions/guides/axes/lines.js +9 -7
  106. package/src/actions/guides/axes/parallel/lifecycle.js +13 -13
  107. package/src/actions/guides/axes/parallel.js +5 -5
  108. package/src/actions/guides/axes/remove.js +4 -4
  109. package/src/actions/guides/axes/tickGroups.js +4 -4
  110. package/src/actions/guides/axes/ticks.js +13 -4
  111. package/src/actions/guides/axes/titles.js +10 -10
  112. package/src/actions/guides/grids/grid.js +18 -29
  113. package/src/actions/guides/guides.js +1 -1
  114. package/src/actions/guides/legends/blocks.js +1 -1
  115. package/src/actions/guides/legends/categorical/actions.js +4 -4
  116. package/src/actions/guides/legends/categorical/components.js +38 -33
  117. package/src/actions/guides/legends/categorical/layout.js +1 -1
  118. package/src/actions/guides/legends/categorical/symbols.js +27 -30
  119. package/src/actions/guides/legends/continuous/common.js +46 -8
  120. package/src/actions/guides/legends/continuous/gradient.js +89 -155
  121. package/src/actions/guides/legends/continuous/interval.js +13 -13
  122. package/src/actions/guides/legends/continuous/opacity.js +30 -79
  123. package/src/actions/guides/legends/continuous/stroke.js +22 -322
  124. package/src/actions/guides/legends/edit.js +1 -1
  125. package/src/actions/guides/legends/focused.js +5 -5
  126. package/src/actions/guides/legends/lane.js +6 -6
  127. package/src/actions/guides/legends/remove.js +4 -5
  128. package/src/actions/guides/legends/size.js +21 -82
  129. package/src/actions/guides/legends/strokeWidth.js +17 -77
  130. package/src/actions/guides/polar/axes/facade.js +4 -4
  131. package/src/actions/guides/polar/axes/labels.js +5 -5
  132. package/src/actions/guides/polar/axes/lines.js +9 -15
  133. package/src/actions/guides/polar/axes/ticks.js +9 -15
  134. package/src/actions/guides/polar/axes/titles.js +5 -5
  135. package/src/actions/guides/polar/grids.js +11 -13
  136. package/src/actions/index.js +2 -0
  137. package/src/actions/intervals/revision.js +126 -0
  138. package/src/actions/marks/arc/actions.js +3 -3
  139. package/src/actions/marks/area/actions.js +4 -4
  140. package/src/actions/marks/bar/create.js +1 -1
  141. package/src/actions/marks/bar/edit.js +1 -1
  142. package/src/actions/marks/bar/materialize.js +12 -38
  143. package/src/actions/marks/line/actions.js +3 -3
  144. package/src/actions/marks/point/create.js +1 -1
  145. package/src/actions/marks/point/edit.js +1 -1
  146. package/src/actions/marks/point/jitter.js +6 -8
  147. package/src/actions/marks/point/materialize.js +16 -24
  148. package/src/actions/marks/point/packing.js +6 -8
  149. package/src/actions/marks/rect/actions.js +3 -3
  150. package/src/actions/marks/references.js +8 -10
  151. package/src/actions/marks/remove.js +5 -49
  152. package/src/actions/marks/rule/actions.js +4 -4
  153. package/src/actions/marks/text/actions.js +5 -5
  154. package/src/actions/marks/text/layout.js +12 -20
  155. package/src/actions/marks/text/removal.js +1 -1
  156. package/src/actions/marks/text/selection.js +4 -5
  157. package/src/actions/marks/tick/actions.js +3 -3
  158. package/src/actions/primitives/createGraphics.js +5 -4
  159. package/src/actions/primitives/editGraphics.js +5 -4
  160. package/src/actions/primitives/graphicProperties.js +6 -0
  161. package/src/actions/primitives/semantic.js +10 -3
  162. package/src/actions/primitives/semanticAction.js +7 -4
  163. package/src/actions/primitives/semanticValidation/dataset.js +2 -4
  164. package/src/actions/regression/components.js +10 -14
  165. package/src/actions/regression/create.js +3 -4
  166. package/src/actions/regression/edit.js +3 -4
  167. package/src/actions/resources/remove.js +12 -11
  168. package/src/actions/scales/create.js +1 -1
  169. package/src/actions/scales/edit.js +1 -1
  170. package/src/actions/scales/materialize.js +1 -1
  171. package/src/actions/scales/offset.js +2 -2
  172. package/src/actions/scales/parallel.js +1 -1
  173. package/src/actions/scales/quantitativeColor.js +4 -5
  174. package/src/actions/selection/actions.js +25 -36
  175. package/src/actions/textMetrics/index.js +56 -0
  176. package/src/actions/theme/actions.js +2 -2
  177. package/src/actions/theme/reconcile.js +65 -121
  178. package/src/actions/titles/actions.js +8 -8
  179. package/src/actions/titles/resolve.js +3 -3
  180. package/src/actions/violinPlots/create.js +1 -1
  181. package/src/actions/violinPlots/edit.js +1 -1
  182. package/src/core/action.js +107 -35
  183. package/src/core/diagnostics.js +16 -0
  184. package/src/core/extensionRegistry.js +27 -0
  185. package/src/core/font.js +18 -0
  186. package/src/core/identifiers.js +5 -4
  187. package/src/core/immutable.js +10 -3
  188. package/src/core/optionRequirements.js +8 -0
  189. package/src/core/programState.js +1 -1
  190. package/src/core/resourceReferences.js +15 -6
  191. package/src/core/textMetricProfile.js +28 -0
  192. package/src/core/textMetrics.js +24 -3
  193. package/src/core/validation.js +22 -10
  194. package/src/diagnostics.js +1 -0
  195. package/src/grammar/impute.js +3 -2
  196. package/src/grammar/scales/types.js +8 -0
  197. package/src/grammar/schemas/graphicBounds.js +11 -11
  198. package/src/layout/labels.js +11 -10
  199. package/src/layout/legend.js +4 -4
  200. package/src/layout/legendItems.js +6 -6
  201. package/src/layout/text.js +10 -9
  202. package/src/layout/title.js +9 -9
  203. package/src/materialization/facetGuides/placement.js +1 -1
  204. package/src/materialization/facetGuides/preparation.js +1 -1
  205. package/src/materialization/facetHeaders.js +11 -10
  206. package/src/materialization/guides/layout.js +3 -3
  207. package/src/materialization/scaleGuideDependencies.js +10 -0
  208. package/src/materialization/selection/items/common.js +1 -1
  209. package/src/materialization/text.js +2 -2
  210. package/src/materialization/typography.js +31 -0
  211. package/src/mcp/cli.js +5 -3
  212. package/src/persistence/codec.js +65 -0
  213. package/src/persistence/validation.js +185 -0
  214. package/src/persistence.js +74 -0
  215. package/src/renderers/canvas/index.js +5 -4
  216. package/src/renderers/nativeBackend.js +10 -0
  217. package/src/renderers/options.js +13 -0
  218. package/src/renderers/pdf.js +25 -54
  219. package/src/renderers/png.js +22 -17
  220. package/src/renderers/svg.js +10 -14
  221. package/src/renderers/text.js +1 -11
  222. package/src/selectors/coordinates.js +3 -1
  223. package/src/selectors/datasets.js +8 -6
  224. package/src/selectors/layers.js +6 -4
  225. package/src/selectors/markOwners.js +46 -0
  226. package/src/selectors/scales.js +6 -4
  227. package/src/theme/defaults.js +2 -1
  228. package/src/version.js +2 -0
  229. package/types/accessibility.d.ts +37 -0
  230. package/types/basic.d.ts +4 -2
  231. package/types/diagnostics.d.ts +15 -0
  232. package/types/index.d.ts +5 -0
  233. package/types/pdf.d.ts +9 -0
  234. package/types/persistence.d.ts +7 -0
  235. package/types/png.d.ts +9 -0
  236. package/types/program.d.ts +34 -1
@@ -57,7 +57,7 @@ export function validateAreaCreateOutline(args, operation = "createAreaMark") {
57
57
  };
58
58
  }
59
59
 
60
- const createAreaMark = action(
60
+ const createAreaMark = /* @__PURE__ */ action(
61
61
  {
62
62
  op: "createAreaMark",
63
63
  description: "Create a semantic area mark and empty path collection."
@@ -109,7 +109,7 @@ const createAreaMark = action(
109
109
  }
110
110
  );
111
111
 
112
- const configureAreaStrokeFromFill = action(
112
+ const configureAreaStrokeFromFill = /* @__PURE__ */ action(
113
113
  {
114
114
  op: "configureAreaStrokeFromFill",
115
115
  description: "Use each area path fill as its outline color."
@@ -138,7 +138,7 @@ const configureAreaStrokeFromFill = action(
138
138
  }
139
139
  );
140
140
 
141
- const rematerializeAreaMark = action(
141
+ const rematerializeAreaMark = /* @__PURE__ */ action(
142
142
  {
143
143
  op: "rematerializeAreaMark",
144
144
  description: "Recompute grouped closed area paths."
@@ -231,7 +231,7 @@ const rematerializeAreaMark = action(
231
231
  }
232
232
  );
233
233
 
234
- const editAreaMark = action(
234
+ const editAreaMark = /* @__PURE__ */ action(
235
235
  {
236
236
  op: "editAreaMark",
237
237
  description: "Edit area curve and constant appearance."
@@ -20,7 +20,7 @@ const CREATE_OPTIONS = Object.freeze([
20
20
  "cornerRadius", ...STROKE_STYLE_PROPERTIES
21
21
  ]);
22
22
 
23
- export const createBarMark = action(
23
+ export const createBarMark = /* @__PURE__ */ action(
24
24
  {
25
25
  op: "createBarMark",
26
26
  description: "Create a semantic bar mark and empty rect collection."
@@ -20,7 +20,7 @@ const EDIT_OPTIONS = Object.freeze([
20
20
  ...STROKE_STYLE_PROPERTIES
21
21
  ]);
22
22
 
23
- export const editBarMark = action(
23
+ export const editBarMark = /* @__PURE__ */ action(
24
24
  {
25
25
  op: "editBarMark",
26
26
  description: "Edit whole-bar fill, opacity, and outline appearance."
@@ -1,3 +1,4 @@
1
+ import { editGraphicProperties } from "../../primitives/graphicProperties.js";
1
2
  import { action } from "../../../core/action.js";
2
3
  import { validateUserId } from "../../../core/identifiers.js";
3
4
  import { validateMarkOptions } from "../shared.js";
@@ -32,43 +33,16 @@ function editRectangles(program, id, rectangles) {
32
33
  rectangles.map(rectangle => materializeRectItem(rectangle, radius))
33
34
  );
34
35
  }
35
- let next = program
36
- .editGraphics({ target: id, property: "length", value: rectangles.length })
37
- .editGraphics({
38
- target: id,
39
- property: "x",
40
- value: rectangles.map(rect => rect.x)
41
- })
42
- .editGraphics({
43
- target: id,
44
- property: "y",
45
- value: rectangles.map(rect => rect.y)
46
- })
47
- .editGraphics({
48
- target: id,
49
- property: "width",
50
- value: rectangles.map(rect => rect.width)
51
- })
52
- .editGraphics({
53
- target: id,
54
- property: "height",
55
- value: rectangles.map(rect => rect.height)
56
- })
57
- .editGraphics({
58
- target: id,
59
- property: "fill",
60
- value: rectangles.map(rect => rect.fill)
61
- })
62
- .editGraphics({
63
- target: id,
64
- property: "stroke",
65
- value: rectangles.map(rect => rect.stroke)
66
- })
67
- .editGraphics({
68
- target: id,
69
- property: "strokeWidth",
70
- value: rectangles.map(rect => rect.strokeWidth)
71
- });
36
+ let next = editGraphicProperties(program, id, {
37
+ length: rectangles.length,
38
+ x: rectangles.map(rect => rect.x),
39
+ y: rectangles.map(rect => rect.y),
40
+ width: rectangles.map(rect => rect.width),
41
+ height: rectangles.map(rect => rect.height),
42
+ fill: rectangles.map(rect => rect.fill),
43
+ stroke: rectangles.map(rect => rect.stroke),
44
+ strokeWidth: rectangles.map(rect => rect.strokeWidth)
45
+ });
72
46
  if (rectangles.some(rect => rect.opacity !== undefined)) {
73
47
  next = next.editGraphics({
74
48
  target: id,
@@ -79,7 +53,7 @@ function editRectangles(program, id, rectangles) {
79
53
  return next;
80
54
  }
81
55
 
82
- export const rematerializeBarMark = action(
56
+ export const rematerializeBarMark = /* @__PURE__ */ action(
83
57
  {
84
58
  op: "rematerializeBarMark",
85
59
  description: "Recompute concrete bar graphics from complete semantics."
@@ -93,7 +93,7 @@ function applyLineMaterialization(program, id, materialization, config) {
93
93
  });
94
94
  }
95
95
 
96
- const createLineMark = action(
96
+ const createLineMark = /* @__PURE__ */ action(
97
97
  {
98
98
  op: "createLineMark",
99
99
  description: "Create a semantic line mark and empty path collection."
@@ -186,7 +186,7 @@ function requireLine(program, id) {
186
186
  return { dataset, layer };
187
187
  }
188
188
 
189
- const rematerializeLineMark = action(
189
+ const rematerializeLineMark = /* @__PURE__ */ action(
190
190
  {
191
191
  op: "rematerializeLineMark",
192
192
  description: "Recompute aggregate series and concrete line paths."
@@ -268,7 +268,7 @@ const rematerializeLineMark = action(
268
268
  }
269
269
  );
270
270
 
271
- const editLineMark = action(
271
+ const editLineMark = /* @__PURE__ */ action(
272
272
  {
273
273
  op: "editLineMark",
274
274
  description: "Edit line-mark curve and stroke width."
@@ -22,7 +22,7 @@ const OPTIONS = Object.freeze([
22
22
  ...STROKE_STYLE_PROPERTIES
23
23
  ]);
24
24
 
25
- export const createPointMark = action(
25
+ export const createPointMark = /* @__PURE__ */ action(
26
26
  {
27
27
  op: "createPointMark",
28
28
  description: "Create a semantic point mark and concrete point graphics."
@@ -19,7 +19,7 @@ const OPTIONS = Object.freeze([
19
19
  ...STROKE_STYLE_PROPERTIES
20
20
  ]);
21
21
 
22
- export const editPointMark = action(
22
+ export const editPointMark = /* @__PURE__ */ action(
23
23
  {
24
24
  op: "editPointMark",
25
25
  description: "Edit constant point-mark appearance."
@@ -1,6 +1,6 @@
1
- import { action } from "../../../core/action.js";
1
+ import { closedAction } from "../../../core/action.js";
2
2
  import { validateUserId } from "../../../core/identifiers.js";
3
- import { validateKeys } from "../../../core/validation.js";
3
+
4
4
  import { normalizePointJitterPolicy } from "../../../grammar/jitter.js";
5
5
  import { findCoordinate } from "../../../selectors/coordinates.js";
6
6
  import { resolveEligibleLayer } from "../../../selectors/layers.js";
@@ -28,13 +28,12 @@ function resolveJitterTarget(program, target, channel) {
28
28
  });
29
29
  }
30
30
 
31
- export const jitterPoints = action(
31
+ export const jitterPoints = /* @__PURE__ */ closedAction(
32
32
  {
33
33
  op: "jitterPoints",
34
34
  description: "Apply deterministic bounded graphical jitter to a point mark."
35
- },
35
+ }, JITTER_OPTIONS,
36
36
  function (args = {}) {
37
- validateKeys(args, JITTER_OPTIONS, "jitterPoints");
38
37
  const policy = normalizePointJitterPolicy(args);
39
38
  const layer = resolveJitterTarget(this, args.target, policy.channel);
40
39
  if (this.materializationConfigs.pointPacking?.[layer.id] !== undefined) {
@@ -46,13 +45,12 @@ export const jitterPoints = action(
46
45
  }
47
46
  );
48
47
 
49
- export const removeJitter = action(
48
+ export const removeJitter = /* @__PURE__ */ closedAction(
50
49
  {
51
50
  op: "removeJitter",
52
51
  description: "Remove point jitter and restore semantic scale positions."
53
- },
52
+ }, REMOVE_OPTIONS,
54
53
  function (args = {}) {
55
- validateKeys(args, REMOVE_OPTIONS, "removeJitter");
56
54
  const requested = args.target === undefined
57
55
  ? undefined
58
56
  : validateUserId(args.target, "Point jitter target");
@@ -1,3 +1,4 @@
1
+ import { editGraphicProperties } from "../../primitives/graphicProperties.js";
1
2
  import { action } from "../../../core/action.js";
2
3
  import { validateUserId } from "../../../core/identifiers.js";
3
4
  import { getPointGraphicType } from "../../../grammar/schemas/mark.js";
@@ -300,7 +301,7 @@ function applyPointPacking(program, {
300
301
  };
301
302
  }
302
303
 
303
- export const rematerializePointMark = action(
304
+ export const rematerializePointMark = /* @__PURE__ */ action(
304
305
  {
305
306
  op: "rematerializePointMark",
306
307
  description: "Recompute concrete point geometry and appearance."
@@ -515,19 +516,12 @@ export const rematerializePointMark = action(
515
516
  value: centersY.map((value, index) => value - (Array.isArray(sides) ? sides[index] : sides) / 2)
516
517
  });
517
518
  }
518
- next = next
519
- .editGraphics({ target: id, property: "width", value: sides })
520
- .editGraphics({ target: id, property: "height", value: sides })
521
- .editGraphics({
522
- target: id,
523
- property: "stroke",
524
- value: mappedStroke ?? fill ?? DEFAULT_POINT_FILL
525
- })
526
- .editGraphics({
527
- target: id,
528
- property: "strokeWidth",
529
- value: mappedStroke === undefined ? 0 : config.strokeWidth ?? 1
530
- });
519
+ next = editGraphicProperties(next, id, {
520
+ width: sides,
521
+ height: sides,
522
+ stroke: mappedStroke ?? fill ?? DEFAULT_POINT_FILL,
523
+ strokeWidth: mappedStroke === undefined ? 0 : config.strokeWidth ?? 1
524
+ });
531
525
  }
532
526
  if (config.opacity !== undefined) {
533
527
  next = next.editGraphics({ target: id, property: "opacity", value: config.opacity });
@@ -535,17 +529,15 @@ export const rematerializePointMark = action(
535
529
  next = next.editGraphics({ target: id, property: "opacity", value: encodedOpacity });
536
530
  }
537
531
  if (mappedStroke !== undefined) {
538
- next = next
539
- .editGraphics({ target: id, property: "stroke", value: mappedStroke })
540
- .editGraphics({
541
- target: id,
542
- property: "strokeWidth",
543
- value: config.strokeWidth ?? 1
544
- });
532
+ next = editGraphicProperties(next, id, {
533
+ stroke: mappedStroke,
534
+ strokeWidth: config.strokeWidth ?? 1
535
+ });
545
536
  } else if (config.stroke === false) {
546
- next = next
547
- .editGraphics({ target: id, property: "stroke", value: "transparent" })
548
- .editGraphics({ target: id, property: "strokeWidth", value: 0 });
537
+ next = editGraphicProperties(next, id, {
538
+ stroke: "transparent",
539
+ strokeWidth: 0
540
+ });
549
541
  } else if (config.stroke !== undefined) {
550
542
  next = next.editGraphics({ target: id, property: "stroke", value: config.stroke });
551
543
  next = next.editGraphics({
@@ -1,6 +1,6 @@
1
- import { action } from "../../../core/action.js";
1
+ import { closedAction } from "../../../core/action.js";
2
2
  import { validateUserId } from "../../../core/identifiers.js";
3
- import { validateKeys } from "../../../core/validation.js";
3
+
4
4
  import { normalizePointPackingPolicy } from "../../../grammar/pointPacking.js";
5
5
  import { findCoordinate } from "../../../selectors/coordinates.js";
6
6
  import { resolveEligibleLayer } from "../../../selectors/layers.js";
@@ -28,10 +28,9 @@ function target(program, requested, channel) {
28
28
  });
29
29
  }
30
30
 
31
- export const packPoints = action(
32
- { op: "packPoints", description: "Pack point glyphs deterministically within categorical slots." },
31
+ export const packPoints = /* @__PURE__ */ closedAction(
32
+ { op: "packPoints", description: "Pack point glyphs deterministically within categorical slots." }, OPTIONS,
33
33
  function (args = {}) {
34
- validateKeys(args, OPTIONS, "packPoints");
35
34
  const policy = normalizePointPackingPolicy(args);
36
35
  const layer = target(this, args.target, policy.channel);
37
36
  if (this.materializationConfigs.jitters?.[layer.id] !== undefined) {
@@ -43,10 +42,9 @@ export const packPoints = action(
43
42
  }
44
43
  );
45
44
 
46
- export const removePointPacking = action(
47
- { op: "removePointPacking", description: "Remove point packing and restore semantic positions." },
45
+ export const removePointPacking = /* @__PURE__ */ closedAction(
46
+ { op: "removePointPacking", description: "Remove point packing and restore semantic positions." }, REMOVE_OPTIONS,
48
47
  function (args = {}) {
49
- validateKeys(args, REMOVE_OPTIONS, "removePointPacking");
50
48
  const requested = args.target === undefined
51
49
  ? undefined
52
50
  : validateUserId(args.target, "Point packing target");
@@ -49,7 +49,7 @@ function requireRectLayer(program, requested, operation) {
49
49
  });
50
50
  }
51
51
 
52
- const createRectMark = action(
52
+ const createRectMark = /* @__PURE__ */ action(
53
53
  { op: "createRectMark", description: "Create a semantic rectangular cell layer." },
54
54
  function (args = {}) {
55
55
  validateMarkOptions(args, CREATE_OPTIONS, "createRectMark");
@@ -90,7 +90,7 @@ const createRectMark = action(
90
90
  }
91
91
  );
92
92
 
93
- const rematerializeRectMark = action(
93
+ const rematerializeRectMark = /* @__PURE__ */ action(
94
94
  { op: "rematerializeRectMark", description: "Recompute concrete rectangular cells." },
95
95
  function (args = {}) {
96
96
  validateMarkOptions(args, REMATERIALIZE_OPTIONS, "rematerializeRectMark");
@@ -146,7 +146,7 @@ const rematerializeRectMark = action(
146
146
  }
147
147
  );
148
148
 
149
- const editRectMark = action(
149
+ const editRectMark = /* @__PURE__ */ action(
150
150
  { op: "editRectMark", description: "Edit rectangular cell appearance." },
151
151
  function (args = {}) {
152
152
  validateMarkOptions(args, EDIT_OPTIONS, "editRectMark");
@@ -1,8 +1,8 @@
1
1
  import { isSourceOwnedText } from "../../grammar/text.js";
2
- import { action } from "../../core/action.js";
2
+ import { action, closedAction } from "../../core/action.js";
3
3
  import { isPlainObject } from "../../core/immutable.js";
4
4
  import { validateUserId } from "../../core/identifiers.js";
5
- import { validateKeys } from "../../core/validation.js";
5
+
6
6
  import { findCoordinate } from "../../selectors/coordinates.js";
7
7
  import {
8
8
  findDataset,
@@ -465,13 +465,12 @@ function syncReferenceEncoding(program, id, source, config) {
465
465
  return next;
466
466
  }
467
467
 
468
- export const materializeStatisticalReferenceData = action(
468
+ export const materializeStatisticalReferenceData = /* @__PURE__ */ closedAction(
469
469
  {
470
470
  op: "materializeStatisticalReferenceData",
471
471
  description: "Materialize one owned statistical reference value dataset."
472
- },
472
+ }, MATERIALIZE_OPTIONS,
473
473
  function (args = {}) {
474
- validateKeys(args, MATERIALIZE_OPTIONS, "materializeStatisticalReferenceData");
475
474
  const { id, source, transform } = requireDerivedDataset(
476
475
  this,
477
476
  args.id,
@@ -485,13 +484,12 @@ export const materializeStatisticalReferenceData = action(
485
484
  }
486
485
  );
487
486
 
488
- export const rematerializeStatisticalReference = action(
487
+ export const rematerializeStatisticalReference = /* @__PURE__ */ closedAction(
489
488
  {
490
489
  op: "rematerializeStatisticalReference",
491
490
  description: "Recompute one source-dependent statistical reference."
492
- },
491
+ }, MATERIALIZE_OPTIONS,
493
492
  function (args = {}) {
494
- validateKeys(args, MATERIALIZE_OPTIONS, "rematerializeStatisticalReference");
495
493
  const id = validateUserId(args.id, "Statistical reference mark id");
496
494
  const config = this.markConfigs[id]?.statisticalReference;
497
495
  const { source } = requireStatisticalSource(this, config, id);
@@ -637,7 +635,7 @@ function createReference(program, args, band) {
637
635
  : createLiteralReference(program, args, band);
638
636
  }
639
637
 
640
- export const createReferenceLine = action(
638
+ export const createReferenceLine = /* @__PURE__ */ action(
641
639
  {
642
640
  op: "createReferenceLine",
643
641
  description: "Create a constant or statistical reference line."
@@ -647,7 +645,7 @@ export const createReferenceLine = action(
647
645
  }
648
646
  );
649
647
 
650
- export const createReferenceBand = action(
648
+ export const createReferenceBand = /* @__PURE__ */ action(
651
649
  {
652
650
  op: "createReferenceBand",
653
651
  description: "Create a constant or statistical reference interval."
@@ -1,7 +1,8 @@
1
+ import { ownedChildren, ownership } from "../../selectors/markOwners.js";
1
2
  import { isSourceOwnedText } from "../../grammar/text.js";
2
- import { action } from "../../core/action.js";
3
+ import { closedAction } from "../../core/action.js";
3
4
  import { validateUserId } from "../../core/identifiers.js";
4
- import { validateKeys } from "../../core/validation.js";
5
+
5
6
  import { findDataset } from "../../selectors/datasets.js";
6
7
  import { findLayer } from "../../selectors/layers.js";
7
8
  import { applyDetachedScaleRematerialization } from "../../materialization/dependencies.js";
@@ -23,50 +24,6 @@ const REMOVE_AXIS = Object.freeze({
23
24
  radius: "removeRadialAxis"
24
25
  });
25
26
 
26
- function ownedChildren(program, id) {
27
- const config = program.markConfigs[id] ?? {};
28
- return [
29
- config.errorBar?.lowerCapId,
30
- config.errorBar?.upperCapId,
31
- config.errorBand?.lowerBoundaryId,
32
- config.errorBand?.upperBoundaryId,
33
- config.regression?.bandId,
34
- config.regression?.lineId,
35
- config.boxPlot?.whiskerId,
36
- config.boxPlot?.medianId,
37
- config.boxPlot?.outlierId,
38
- config.gradientPlot?.centerId,
39
- config.intervalPlot?.intervalId,
40
- config.endpointPlot?.roles?.stemId,
41
- config.endpointPlot?.roles?.startId,
42
- config.endpointPlot?.roles?.connectorId,
43
- ...(config.raincloudPlot?.ownedChildIds ?? [])
44
- ].concat(
45
- program.semanticSpec.layers
46
- .filter(layer => layer.source === id)
47
- .map(layer => layer.id)
48
- ).concat(
49
- program.semanticSpec.layers
50
- .filter(layer =>
51
- program.markConfigs[layer.id]?.statisticalReference?.source === id
52
- )
53
- .map(layer => layer.id)
54
- ).filter(child => child !== undefined && child !== id && findLayer(program, child) !== undefined);
55
- }
56
-
57
- function ownership(program) {
58
- const ownerByChild = new Map();
59
- for (const layer of program.semanticSpec.layers) {
60
- for (const child of ownedChildren(program, layer.id)) {
61
- if (program.markConfigs[child]?.statisticalReference !== undefined) {
62
- continue;
63
- }
64
- ownerByChild.set(child, layer.id);
65
- }
66
- }
67
- return ownerByChild;
68
- }
69
-
70
27
  function resolveOwner(program, requested) {
71
28
  const ownerByChild = ownership(program);
72
29
  const stable = program.semanticSpec.layers.filter(
@@ -248,10 +205,9 @@ function cleanupPositionGuides(program, scales) {
248
205
  return next;
249
206
  }
250
207
 
251
- export const removeMark = action(
252
- { op: "removeMark", description: "Remove one stable mark owner and owned state." },
208
+ export const removeMark = /* @__PURE__ */ closedAction(
209
+ { op: "removeMark", description: "Remove one stable mark owner and owned state." }, OPTIONS,
253
210
  function (args = {}) {
254
- validateKeys(args, OPTIONS, "removeMark");
255
211
  const owner = resolveOwner(this, args.target);
256
212
  const ids = collectClosure(this, owner.id);
257
213
  const external = externalMarkReferences(this, ids);
@@ -92,7 +92,7 @@ function validateEndpointBindings(layer) {
92
92
  }
93
93
  }
94
94
 
95
- const createRuleMark = action(
95
+ const createRuleMark = /* @__PURE__ */ action(
96
96
  {
97
97
  op: "createRuleMark",
98
98
  description: "Create a semantic rule mark and empty line collection."
@@ -142,7 +142,7 @@ const createRuleMark = action(
142
142
  }
143
143
  );
144
144
 
145
- const editRuleMark = action(
145
+ const editRuleMark = /* @__PURE__ */ action(
146
146
  { op: "editRuleMark", description: "Edit constant rule appearance through its encoding owners." },
147
147
  function (args = {}) {
148
148
  validateMarkOptions(args, EDIT_OPTIONS, "editRuleMark");
@@ -168,7 +168,7 @@ const editRuleMark = action(
168
168
  }
169
169
  );
170
170
 
171
- const rematerializeRuleMark = action(
171
+ const rematerializeRuleMark = /* @__PURE__ */ action(
172
172
  {
173
173
  op: "rematerializeRuleMark",
174
174
  description: "Recompute concrete rule endpoints and appearance."
@@ -377,7 +377,7 @@ const rematerializeRuleMark = action(
377
377
  }
378
378
  );
379
379
 
380
- export const materializeRuleSpan = action(
380
+ export const materializeRuleSpan = /* @__PURE__ */ action(
381
381
  {
382
382
  op: "materializeRuleSpan",
383
383
  description: "Materialize a fixed-pixel span around a rule anchor."
@@ -125,7 +125,7 @@ function requireTextLayer(program, requested, operation) {
125
125
  });
126
126
  }
127
127
 
128
- const createTextMark = action(
128
+ const createTextMark = /* @__PURE__ */ action(
129
129
  {
130
130
  op: "createTextMark",
131
131
  description: "Create a semantic text annotation layer."
@@ -254,7 +254,7 @@ function resolveAnnotationBinding(program, args) {
254
254
  };
255
255
  }
256
256
 
257
- const createAnnotation = action(
257
+ const createAnnotation = /* @__PURE__ */ action(
258
258
  {
259
259
  op: "createAnnotation",
260
260
  description: "Create text at a final mark, data, or plot anchor."
@@ -327,7 +327,7 @@ const createAnnotation = action(
327
327
  }
328
328
  );
329
329
 
330
- const createMarkLabels = action(
330
+ const createMarkLabels = /* @__PURE__ */ action(
331
331
  {
332
332
  op: "createMarkLabels",
333
333
  description: "Create final-item text labels attached to an existing mark."
@@ -412,7 +412,7 @@ const createMarkLabels = action(
412
412
  }
413
413
  );
414
414
 
415
- const rematerializeTextMark = action(
415
+ const rematerializeTextMark = /* @__PURE__ */ action(
416
416
  {
417
417
  op: "rematerializeTextMark",
418
418
  description: "Recompute concrete text content, anchors, and typography."
@@ -458,7 +458,7 @@ const rematerializeTextMark = action(
458
458
  }
459
459
  );
460
460
 
461
- const editTextMark = action(
461
+ const editTextMark = /* @__PURE__ */ action(
462
462
  {
463
463
  op: "editTextMark",
464
464
  description: "Edit text typography, alignment, rotation, and offsets."
@@ -1,4 +1,4 @@
1
- import { action } from "../../../core/action.js";
1
+ import { action, closedAction } from "../../../core/action.js";
2
2
  import { validateUserId } from "../../../core/identifiers.js";
3
3
  import { validateOptionObject } from "../../../core/validation.js";
4
4
  import { DEFAULT_TEXT_MARK } from "../../../grammar/text.js";
@@ -221,22 +221,17 @@ function placementLeaderItems(program, layer) {
221
221
  sourceY: entry.anchor.y,
222
222
  dx: properties.x - entry.anchor.x,
223
223
  dy: properties.y - entry.anchor.y,
224
- bounds: resolveTextBounds(properties)
224
+ bounds: resolveTextBounds(properties, program.materializationConfigs.textMetrics)
225
225
  };
226
226
  });
227
227
  }
228
228
 
229
- const materializeMarkLabelPlacement = action(
229
+ const materializeMarkLabelPlacement = /* @__PURE__ */ closedAction(
230
230
  {
231
231
  op: "materializeMarkLabelPlacement",
232
232
  description: "Reconcile semantic attached-label placement leaders."
233
- },
233
+ }, MATERIALIZE_PLACEMENT_OPTIONS,
234
234
  function (args = {}) {
235
- validateOptionObject(
236
- args,
237
- MATERIALIZE_PLACEMENT_OPTIONS,
238
- "materializeMarkLabelPlacement"
239
- );
240
235
  const id = validateUserId(args.id, "Attached label id");
241
236
  const layer = findLayer(this, id);
242
237
  if (!isSourceOwnedText(layer)) {
@@ -267,13 +262,12 @@ const materializeMarkLabelPlacement = action(
267
262
  }
268
263
  );
269
264
 
270
- const materializeLabelLayout = action(
265
+ const materializeLabelLayout = /* @__PURE__ */ closedAction(
271
266
  {
272
267
  op: "materializeLabelLayout",
273
268
  description: "Resolve concrete label positions and optional leader lines."
274
- },
269
+ }, MATERIALIZE_OPTIONS,
275
270
  function (args = {}) {
276
- validateOptionObject(args, MATERIALIZE_OPTIONS, "materializeLabelLayout");
277
271
  const id = validateUserId(args.id, "Text mark id");
278
272
  const rematerializeBase = args.rematerializeBase ?? true;
279
273
  if (typeof rematerializeBase !== "boolean") {
@@ -294,7 +288,7 @@ const materializeLabelLayout = action(
294
288
  axis: config.axis,
295
289
  padding: config.padding,
296
290
  maxDisplacement: config.maxDisplacement
297
- });
291
+ }, next.materializationConfigs.textMetrics);
298
292
  next = editMarkGraphic(next, id, {
299
293
  x: resolved.items.map(item => item.x),
300
294
  y: resolved.items.map(item => item.y)
@@ -326,13 +320,12 @@ const materializeLabelLayout = action(
326
320
  }
327
321
  );
328
322
 
329
- const layoutLabels = action(
323
+ const layoutLabels = /* @__PURE__ */ closedAction(
330
324
  {
331
325
  op: "layoutLabels",
332
326
  description: "Assign deterministic collision-aware layout to a text mark."
333
- },
327
+ }, TEXT_LABEL_LAYOUT_OPTIONS,
334
328
  function (args = {}) {
335
- validateOptionObject(args, TEXT_LABEL_LAYOUT_OPTIONS, "layoutLabels");
336
329
  const layer = requireCompleteText(this, args.target, "layoutLabels");
337
330
  const policy = normalizePolicy(args);
338
331
  const placement = this.markConfigs[layer.id]?.labelAuthoring?.placement;
@@ -358,7 +351,7 @@ const layoutLabels = action(
358
351
  }
359
352
  );
360
353
 
361
- const editMarkLabelPlacement = action(
354
+ const editMarkLabelPlacement = /* @__PURE__ */ action(
362
355
  {
363
356
  op: "editMarkLabelPlacement",
364
357
  description: "Replace or reset semantic placement for one attached label layer."
@@ -418,13 +411,12 @@ const editMarkLabelPlacement = action(
418
411
  }
419
412
  );
420
413
 
421
- const removeLabelLayout = action(
414
+ const removeLabelLayout = /* @__PURE__ */ closedAction(
422
415
  {
423
416
  op: "removeLabelLayout",
424
417
  description: "Remove label layout and restore semantic base text positions."
425
- },
418
+ }, REMOVE_OPTIONS,
426
419
  function (args = {}) {
427
- validateOptionObject(args, REMOVE_OPTIONS, "removeLabelLayout");
428
420
  const layer = requireConfiguredText(this, args.target);
429
421
  const config = this.materializationConfigs.labelLayouts[layer.id];
430
422
  return removeLeaderGraphic(
@@ -140,7 +140,7 @@ function removeLabelState(program, plan) {
140
140
  return Object.keys(context).length === 0 ? next : next._withContext(context);
141
141
  }
142
142
 
143
- export const removeMarkLabels = action(
143
+ export const removeMarkLabels = /* @__PURE__ */ action(
144
144
  {
145
145
  op: "removeMarkLabels",
146
146
  description: "Remove attached label layers while preserving their source mark."