ggaction 0.0.15 → 0.0.17

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 (270) hide show
  1. package/CHANGELOG.md +88 -0
  2. package/README.md +23 -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 +40 -7
  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 +3 -3
  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 +23 -17
  49. package/src/actions/data/density.js +4 -4
  50. package/src/actions/data/derived.js +25 -15
  51. package/src/actions/data/ecdf.js +2 -2
  52. package/src/actions/data/edit.js +54 -29
  53. package/src/actions/data/filter.js +29 -24
  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 +58 -54
  59. package/src/actions/data/interval.js +4 -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 +9 -7
  63. package/src/actions/data/revise.js +80 -0
  64. package/src/actions/data/revisionBindings.js +13 -33
  65. package/src/actions/data/shared.js +30 -2
  66. package/src/actions/data/sort.js +21 -0
  67. package/src/actions/data/stack.js +2 -2
  68. package/src/actions/data/summary.js +3 -3
  69. package/src/actions/data/timeUnit.js +2 -2
  70. package/src/actions/data/window.js +2 -2
  71. package/src/actions/encodings/angle.js +5 -2
  72. package/src/actions/encodings/appearance.js +10 -6
  73. package/src/actions/encodings/barWidth.js +1 -1
  74. package/src/actions/encodings/channels.js +2 -2
  75. package/src/actions/encodings/color/continuous.js +4 -1
  76. package/src/actions/encodings/color/index.js +5 -2
  77. package/src/actions/encodings/density.js +2 -2
  78. package/src/actions/encodings/histogram.js +1 -1
  79. package/src/actions/encodings/horizon.js +6 -8
  80. package/src/actions/encodings/offset.js +6 -3
  81. package/src/actions/encodings/parallel.js +4 -5
  82. package/src/actions/encodings/pathOrder.js +6 -11
  83. package/src/actions/encodings/position/index.js +4 -4
  84. package/src/actions/encodings/position/resolve.js +6 -1
  85. package/src/actions/encodings/ranged.js +11 -6
  86. package/src/actions/encodings/remove.js +4 -5
  87. package/src/actions/encodings/ruleAppearance.js +5 -2
  88. package/src/actions/encodings/seriesLayout.js +1 -1
  89. package/src/actions/encodings/stroke.js +5 -2
  90. package/src/actions/encodings/strokeDash.js +8 -3
  91. package/src/actions/encodings/text.js +7 -2
  92. package/src/actions/errorBands/create.js +11 -17
  93. package/src/actions/errorBands/edit.js +13 -131
  94. package/src/actions/errorBars/create.js +8 -13
  95. package/src/actions/errorBars/edit.js +10 -121
  96. package/src/actions/facets/actions.js +30 -16
  97. package/src/actions/facets/derive.js +8 -2
  98. package/src/actions/facets/guides.js +4 -5
  99. package/src/actions/facets/replay.js +4 -5
  100. package/src/actions/gradientPlots/components.js +5 -6
  101. package/src/actions/gradientPlots/create.js +4 -5
  102. package/src/actions/gradientPlots/edit.js +4 -5
  103. package/src/actions/gradientPlots/materialize.js +2 -2
  104. package/src/actions/gradientPlots/rebind.js +4 -5
  105. package/src/actions/guides/axes/axes.js +23 -4
  106. package/src/actions/guides/axes/axis.js +2 -2
  107. package/src/actions/guides/axes/edit.js +2 -2
  108. package/src/actions/guides/axes/labels.js +9 -9
  109. package/src/actions/guides/axes/lines.js +9 -7
  110. package/src/actions/guides/axes/parallel/lifecycle.js +13 -13
  111. package/src/actions/guides/axes/parallel.js +5 -5
  112. package/src/actions/guides/axes/remove.js +4 -4
  113. package/src/actions/guides/axes/tickGroups.js +4 -4
  114. package/src/actions/guides/axes/ticks.js +13 -4
  115. package/src/actions/guides/axes/titles.js +10 -10
  116. package/src/actions/guides/grids/grid.js +18 -29
  117. package/src/actions/guides/guides.js +1 -1
  118. package/src/actions/guides/legends/blocks.js +1 -1
  119. package/src/actions/guides/legends/categorical/actions.js +4 -4
  120. package/src/actions/guides/legends/categorical/components.js +38 -33
  121. package/src/actions/guides/legends/categorical/layout.js +1 -1
  122. package/src/actions/guides/legends/categorical/symbols.js +27 -30
  123. package/src/actions/guides/legends/continuous/common.js +46 -8
  124. package/src/actions/guides/legends/continuous/gradient.js +89 -155
  125. package/src/actions/guides/legends/continuous/interval.js +13 -13
  126. package/src/actions/guides/legends/continuous/opacity.js +30 -79
  127. package/src/actions/guides/legends/continuous/stroke.js +22 -322
  128. package/src/actions/guides/legends/edit.js +1 -1
  129. package/src/actions/guides/legends/focused.js +5 -5
  130. package/src/actions/guides/legends/lane.js +6 -6
  131. package/src/actions/guides/legends/remove.js +4 -5
  132. package/src/actions/guides/legends/size.js +21 -82
  133. package/src/actions/guides/legends/strokeWidth.js +17 -77
  134. package/src/actions/guides/polar/axes/facade.js +4 -4
  135. package/src/actions/guides/polar/axes/labels.js +5 -5
  136. package/src/actions/guides/polar/axes/lines.js +9 -15
  137. package/src/actions/guides/polar/axes/ticks.js +9 -15
  138. package/src/actions/guides/polar/axes/titles.js +5 -5
  139. package/src/actions/guides/polar/grids.js +11 -13
  140. package/src/actions/index.js +2 -0
  141. package/src/actions/intervals/revision.js +126 -0
  142. package/src/actions/marks/arc/actions.js +3 -3
  143. package/src/actions/marks/area/actions.js +4 -4
  144. package/src/actions/marks/bar/create.js +9 -2
  145. package/src/actions/marks/bar/edit.js +13 -6
  146. package/src/actions/marks/bar/materialize.js +12 -38
  147. package/src/actions/marks/line/actions.js +3 -3
  148. package/src/actions/marks/point/create.js +9 -2
  149. package/src/actions/marks/point/edit.js +13 -6
  150. package/src/actions/marks/point/jitter.js +6 -8
  151. package/src/actions/marks/point/materialize.js +20 -26
  152. package/src/actions/marks/point/packing.js +6 -8
  153. package/src/actions/marks/rect/actions.js +26 -11
  154. package/src/actions/marks/references.js +8 -10
  155. package/src/actions/marks/remove.js +5 -49
  156. package/src/actions/marks/rule/actions.js +28 -12
  157. package/src/actions/marks/text/actions.js +30 -11
  158. package/src/actions/marks/text/layout.js +12 -20
  159. package/src/actions/marks/text/removal.js +1 -1
  160. package/src/actions/marks/text/selection.js +4 -5
  161. package/src/actions/marks/tick/actions.js +26 -11
  162. package/src/actions/primitives/createGraphics.js +5 -4
  163. package/src/actions/primitives/editGraphics.js +5 -4
  164. package/src/actions/primitives/graphicProperties.js +6 -0
  165. package/src/actions/primitives/semantic.js +10 -3
  166. package/src/actions/primitives/semanticAction.js +44 -7
  167. package/src/actions/primitives/semanticValidation/dataset.js +14 -4
  168. package/src/actions/primitives/semanticValidation/layer.js +22 -2
  169. package/src/actions/primitives/semanticValidation/scale.js +6 -0
  170. package/src/actions/regression/components.js +10 -14
  171. package/src/actions/regression/create.js +28 -8
  172. package/src/actions/regression/edit.js +50 -16
  173. package/src/actions/regression/follow.js +22 -0
  174. package/src/actions/resources/remove.js +12 -11
  175. package/src/actions/scales/channels.js +11 -11
  176. package/src/actions/scales/consumers/common.js +2 -1
  177. package/src/actions/scales/create.js +3 -2
  178. package/src/actions/scales/definitions.js +1 -1
  179. package/src/actions/scales/edit.js +2 -2
  180. package/src/actions/scales/materialize.js +1 -1
  181. package/src/actions/scales/offset.js +2 -2
  182. package/src/actions/scales/parallel.js +2 -2
  183. package/src/actions/scales/patch.js +1 -1
  184. package/src/actions/scales/preview.js +28 -1
  185. package/src/actions/scales/quantitativeColor.js +4 -5
  186. package/src/actions/selection/actions.js +25 -36
  187. package/src/actions/textMetrics/index.js +56 -0
  188. package/src/actions/theme/actions.js +2 -2
  189. package/src/actions/theme/reconcile.js +67 -121
  190. package/src/actions/titles/actions.js +8 -8
  191. package/src/actions/titles/resolve.js +3 -3
  192. package/src/actions/violinPlots/create.js +1 -1
  193. package/src/actions/violinPlots/edit.js +1 -1
  194. package/src/core/action.js +109 -36
  195. package/src/core/diagnostics.js +16 -0
  196. package/src/core/extensionRegistry.js +27 -0
  197. package/src/core/font.js +18 -0
  198. package/src/core/identifiers.js +5 -4
  199. package/src/core/immutable.js +10 -3
  200. package/src/core/optionRequirements.js +8 -0
  201. package/src/core/programState.js +6 -2
  202. package/src/core/resourceReferences.js +15 -6
  203. package/src/core/textMetricProfile.js +28 -0
  204. package/src/core/textMetrics.js +24 -3
  205. package/src/core/validation.js +22 -10
  206. package/src/diagnostics.js +1 -0
  207. package/src/grammar/bin.js +39 -10
  208. package/src/grammar/datasetSchema.js +386 -0
  209. package/src/grammar/density.js +53 -5
  210. package/src/grammar/filter.js +133 -39
  211. package/src/grammar/impute.js +3 -2
  212. package/src/grammar/interval.js +32 -1
  213. package/src/grammar/itemMissing.js +59 -0
  214. package/src/grammar/regression/derive.js +57 -16
  215. package/src/grammar/regression/index.js +1 -0
  216. package/src/grammar/regression/models.js +51 -22
  217. package/src/grammar/regression/parameters.js +56 -4
  218. package/src/grammar/scales/definition.js +7 -0
  219. package/src/grammar/scales/types.js +8 -0
  220. package/src/grammar/schemas/graphicBounds.js +11 -11
  221. package/src/grammar/schemas/semanticPath.js +3 -2
  222. package/src/grammar/sort.js +88 -0
  223. package/src/grammar/summary.js +117 -19
  224. package/src/grammar/transformTopology.js +1 -0
  225. package/src/grammar/transforms.js +21 -11
  226. package/src/inspection.js +495 -0
  227. package/src/inspectionDescriptors.js +3 -0
  228. package/src/layout/labels.js +11 -10
  229. package/src/layout/legend.js +4 -4
  230. package/src/layout/legendItems.js +6 -6
  231. package/src/layout/text.js +10 -9
  232. package/src/layout/title.js +9 -9
  233. package/src/materialization/bars/resolve.js +4 -2
  234. package/src/materialization/facetGuides/placement.js +1 -1
  235. package/src/materialization/facetGuides/preparation.js +1 -1
  236. package/src/materialization/facetHeaders.js +11 -10
  237. package/src/materialization/guides/layout.js +3 -3
  238. package/src/materialization/revisionIdentity.js +19 -0
  239. package/src/materialization/scaleGuideDependencies.js +10 -0
  240. package/src/materialization/scales/resolve.js +67 -4
  241. package/src/materialization/selection/items/common.js +1 -1
  242. package/src/materialization/text.js +6 -4
  243. package/src/materialization/typography.js +31 -0
  244. package/src/mcp/cli.js +5 -3
  245. package/src/persistence/codec.js +65 -0
  246. package/src/persistence/validation.js +185 -0
  247. package/src/persistence.js +147 -0
  248. package/src/renderers/canvas/index.js +5 -4
  249. package/src/renderers/nativeBackend.js +10 -0
  250. package/src/renderers/options.js +13 -0
  251. package/src/renderers/pdf.js +25 -54
  252. package/src/renderers/png.js +22 -17
  253. package/src/renderers/svg.js +10 -14
  254. package/src/renderers/text.js +1 -11
  255. package/src/selectors/coordinates.js +3 -1
  256. package/src/selectors/datasets.js +8 -6
  257. package/src/selectors/layers.js +6 -4
  258. package/src/selectors/markOwners.js +46 -0
  259. package/src/selectors/scales.js +6 -4
  260. package/src/theme/defaults.js +2 -1
  261. package/src/version.js +2 -0
  262. package/types/accessibility.d.ts +37 -0
  263. package/types/basic.d.ts +4 -2
  264. package/types/diagnostics.d.ts +15 -0
  265. package/types/index.d.ts +5 -0
  266. package/types/inspection.d.ts +17 -0
  267. package/types/pdf.d.ts +9 -0
  268. package/types/persistence.d.ts +7 -0
  269. package/types/png.d.ts +9 -0
  270. package/types/program.d.ts +181 -28
@@ -25,6 +25,8 @@ import {
25
25
  setEncodingProperties,
26
26
  validateOptions
27
27
  } from "./shared.js";
28
+ import { applyRequestedItemMissingPolicy } from
29
+ "../../grammar/itemMissing.js";
28
30
 
29
31
  const RADIUS_OPTIONS = Object.freeze(["value", "target"]);
30
32
  const REMOVE_RADIUS_OPTIONS = Object.freeze(["target"]);
@@ -34,13 +36,14 @@ const OPACITY_OPTIONS = Object.freeze([
34
36
  const FIELD_OPTIONS = Object.freeze(["field", "target", "fieldType", "scale"]);
35
37
  function encodeAppearanceField(program, channel, args, operation) {
36
38
  validateOptions(args, FIELD_OPTIONS, operation);
37
- const { id: target, dataset, layer } = resolveTarget(
39
+ const { id: target, dataset: sourceDataset, layer } = resolveTarget(
38
40
  program,
39
41
  args.target,
40
42
  ["point"],
41
43
  "point mark"
42
44
  );
43
45
  const expectedFieldType = channel === "shape" ? "nominal" : "quantitative";
46
+ const dataset = applyRequestedItemMissingPolicy(layer, sourceDataset, args.field);
44
47
  const fieldType = args.fieldType ?? expectedFieldType;
45
48
  if (fieldType !== expectedFieldType) {
46
49
  throw new Error(`${operation} requires a ${expectedFieldType} field.`);
@@ -79,7 +82,7 @@ function encodeAppearanceField(program, channel, args, operation) {
79
82
  return rematerializeEncoding(next, target, channel, scale.id, layer);
80
83
  }
81
84
 
82
- const encodeRadius = action(
85
+ const encodeRadius = /* @__PURE__ */ action(
83
86
  {
84
87
  op: "encodeRadius",
85
88
  description: "Set a constant graphical radius on a point mark."
@@ -112,7 +115,7 @@ const encodeRadius = action(
112
115
  }
113
116
  );
114
117
 
115
- const encodePointRadius = action(
118
+ const encodePointRadius = /* @__PURE__ */ action(
116
119
  {
117
120
  op: "encodePointRadius",
118
121
  description: "Set a constant graphical radius on a point mark."
@@ -146,7 +149,7 @@ const removePointRadius = /* @__PURE__ */ action(
146
149
  }
147
150
  );
148
151
 
149
- const encodeSize = action(
152
+ const encodeSize = /* @__PURE__ */ action(
150
153
  {
151
154
  op: "encodeSize",
152
155
  description: "Encode a quantitative field as equal-area point size."
@@ -156,7 +159,7 @@ const encodeSize = action(
156
159
  }
157
160
  );
158
161
 
159
- const encodeShape = action(
162
+ const encodeShape = /* @__PURE__ */ action(
160
163
  {
161
164
  op: "encodeShape",
162
165
  description: "Encode a nominal field as point shape."
@@ -196,7 +199,7 @@ const encodeOpacity = /* @__PURE__ */ action(
196
199
  if (hasValue && (args.fieldType !== undefined || args.scale !== undefined)) {
197
200
  throw new Error("Constant opacity does not accept fieldType or scale.");
198
201
  }
199
- const { id: target, dataset, layer } = resolveTarget(
202
+ const { id: target, dataset: sourceDataset, layer } = resolveTarget(
200
203
  this,
201
204
  args.target,
202
205
  ["point", "rule", "line"],
@@ -222,6 +225,7 @@ const encodeOpacity = /* @__PURE__ */ action(
222
225
  : next.rematerializePointMark({ id: target });
223
226
  return applyDetachedScaleRematerialization(materialized, [layer]);
224
227
  }
228
+ const dataset = applyRequestedItemMissingPolicy(layer, sourceDataset, args.field);
225
229
  const fieldType = args.fieldType ?? "quantitative";
226
230
  if (fieldType !== "quantitative") {
227
231
  throw new Error("encodeOpacity requires a quantitative field.");
@@ -10,7 +10,7 @@ import { normalizeBarWidth } from "../../grammar/bars/geometry.js";
10
10
 
11
11
  const OPTIONS = Object.freeze(["band", "pixels", "target"]);
12
12
 
13
- const encodeBarWidth = action(
13
+ const encodeBarWidth = /* @__PURE__ */ action(
14
14
  {
15
15
  op: "encodeBarWidth",
16
16
  description: "Override aggregate or ranged bar width within its category slot."
@@ -299,7 +299,7 @@ function finalScaleIds(before, after, originalLayer, finalLayer, requests) {
299
299
  );
300
300
  }
301
301
 
302
- const rematerializeEncodingScales = action(
302
+ const rematerializeEncodingScales = /* @__PURE__ */ action(
303
303
  {
304
304
  op: "rematerializeEncodingScales",
305
305
  description: "Resolve every scale affected by one atomic encoding assignment."
@@ -390,7 +390,7 @@ function applyEncodingAssignments(program, plan) {
390
390
  return instantiateProgram(plan.state, program.constructor);
391
391
  }
392
392
 
393
- export const encodeChannels = action(
393
+ export const encodeChannels = /* @__PURE__ */ action(
394
394
  {
395
395
  op: "encodeChannels",
396
396
  description: "Atomically assign multiple encoding channels to one mark."
@@ -26,6 +26,8 @@ import {
26
26
  } from "./policy.js";
27
27
 
28
28
  import { applyTemporalUnit } from "../temporal.js";
29
+ import { applyRequestedItemMissingPolicy } from
30
+ "../../../grammar/itemMissing.js";
29
31
 
30
32
  export function encodeContinuousColor(program, args) {
31
33
  if (!["quantitative", "temporal"].includes(args.fieldType)) {
@@ -34,12 +36,13 @@ export function encodeContinuousColor(program, args) {
34
36
  if (args.layout !== undefined) {
35
37
  throw new Error("Continuous color does not support layout.");
36
38
  }
37
- const { id: target, dataset, layer } = resolveTarget(
39
+ const { id: target, dataset: sourceDataset, layer } = resolveTarget(
38
40
  program,
39
41
  args.target,
40
42
  ["point", "bar", "rect"],
41
43
  "continuous color mark"
42
44
  );
45
+ const dataset = applyRequestedItemMissingPolicy(layer, sourceDataset, args.field);
43
46
  assertNoConstantColor(program, layer);
44
47
  const temporalUnit = resolveTemporalUnit(args, args.fieldType, layer.encoding?.color);
45
48
  const requestedScale = resolveReassignmentScaleOptions(
@@ -38,8 +38,10 @@ import {
38
38
  } from "./policy.js";
39
39
 
40
40
  import { applyTemporalUnit } from "../temporal.js";
41
+ import { applyRequestedItemMissingPolicy } from
42
+ "../../../grammar/itemMissing.js";
41
43
 
42
- const encodeColor = action(
44
+ const encodeColor = /* @__PURE__ */ action(
43
45
  {
44
46
  op: "encodeColor",
45
47
  description: "Encode a field as graphical color."
@@ -58,12 +60,13 @@ const encodeColor = action(
58
60
  }
59
61
  const fieldType = validateCategoricalFieldType(requestedFieldType);
60
62
  resolveTemporalUnit(args, fieldType);
61
- const { id: target, dataset, layer } = resolveTarget(
63
+ const { id: target, dataset: sourceDataset, layer } = resolveTarget(
62
64
  this,
63
65
  args.target,
64
66
  ["point", "line", "bar", "area", "arc", "rect"],
65
67
  "color mark"
66
68
  );
69
+ const dataset = applyRequestedItemMissingPolicy(layer, sourceDataset, args.field);
67
70
  assertNoConstantColor(this, layer);
68
71
  const densityTransform = dataset.transform?.length === 1 &&
69
72
  dataset.transform[0].type === "density"
@@ -114,7 +114,7 @@ function applyDensityPosition(program, layerId, definition, groupBy) {
114
114
  return next;
115
115
  }
116
116
 
117
- const encodeDensity = action(
117
+ const encodeDensity = /* @__PURE__ */ action(
118
118
  {
119
119
  op: "encodeDensity",
120
120
  description: "Derive and encode a baseline or categorical kernel-density area."
@@ -259,7 +259,7 @@ function assertGroupingSelectionCompatibility(program, layer, changesGroup) {
259
259
  }
260
260
  }
261
261
 
262
- const editDensity = action(
262
+ const editDensity = /* @__PURE__ */ action(
263
263
  {
264
264
  op: "editDensity",
265
265
  description: "Revise one density transform and rematerialize its consumers."
@@ -6,7 +6,7 @@ const HISTOGRAM_OPTIONS = Object.freeze([
6
6
  "stack", "xScale", "yScale", "weight"
7
7
  ]);
8
8
 
9
- const encodeHistogram = action(
9
+ const encodeHistogram = /* @__PURE__ */ action(
10
10
  {
11
11
  op: "encodeHistogram",
12
12
  description: "Encode a binned count histogram with a configurable layout stack."
@@ -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 { validateOptionObject } from "../../core/validation.js";
3
+
4
4
  import {
5
5
  deriveHorizon,
6
6
  validateHorizonTransform
@@ -109,13 +109,12 @@ function applyScaleDefinition(program, current, definition) {
109
109
  return patch === undefined ? program : program.editScale(patch);
110
110
  }
111
111
 
112
- const editHorizon = action(
112
+ const editHorizon = /* @__PURE__ */ closedAction(
113
113
  {
114
114
  op: "editHorizon",
115
115
  description: "Revise one Horizon transform and rematerialize its consumers."
116
- },
116
+ }, EDIT_OPTIONS,
117
117
  function (args = {}) {
118
- validateOptionObject(args, EDIT_OPTIONS, "editHorizon");
119
118
  if (Object.hasOwn(args, "groupBy") && args.groupBy === undefined) {
120
119
  throw new Error("editHorizon groupBy requires a field string or false.");
121
120
  }
@@ -278,13 +277,12 @@ const editHorizon = action(
278
277
  }
279
278
  );
280
279
 
281
- const encodeHorizon = action(
280
+ const encodeHorizon = /* @__PURE__ */ closedAction(
282
281
  {
283
282
  op: "encodeHorizon",
284
283
  description: "Derive and encode one folded Horizon area."
285
- },
284
+ }, OPTIONS,
286
285
  function (args = {}) {
287
- validateOptionObject(args, OPTIONS, "encodeHorizon");
288
286
  const layer = findHorizonArea(this, args.target);
289
287
  validateUnusedHorizonEncodings(layer);
290
288
  const source = resolveHorizonSource(this, layer, args.source);
@@ -18,6 +18,8 @@ import {
18
18
  resolveBarChannels,
19
19
  resolveBarGrain
20
20
  } from "../../grammar/bars/policy.js";
21
+ import { applyRequestedItemMissingPolicy } from
22
+ "../../grammar/itemMissing.js";
21
23
 
22
24
  const ENCODING_OPTIONS = Object.freeze([
23
25
  "field", "target", "fieldType", "scale", "paddingInner", "paddingOuter"
@@ -33,12 +35,13 @@ function createOffsetEncoding(channel) {
33
35
  function (args = {}) {
34
36
  validateOptions(args, ENCODING_OPTIONS, operation);
35
37
  const fieldType = validateCategoricalFieldType(args.fieldType ?? "nominal");
36
- const { id: target, dataset, layer } = resolveTarget(
38
+ const { id: target, dataset: sourceDataset, layer } = resolveTarget(
37
39
  this,
38
40
  args.target,
39
41
  ["bar", "point", "rule"],
40
42
  "offset-compatible mark"
41
43
  );
44
+ const dataset = applyRequestedItemMissingPolicy(layer, sourceDataset, args.field);
42
45
 
43
46
  if (layer.mark.type === "bar") {
44
47
  const channels = resolveBarChannels(layer);
@@ -110,8 +113,8 @@ function createOffsetEncoding(channel) {
110
113
  );
111
114
  }
112
115
 
113
- const encodeXOffset = createOffsetEncoding("xOffset");
114
- const encodeYOffset = createOffsetEncoding("yOffset");
116
+ const encodeXOffset = /* @__PURE__ */ createOffsetEncoding("xOffset");
117
+ const encodeYOffset = /* @__PURE__ */ createOffsetEncoding("yOffset");
115
118
 
116
119
  export function registerOffsetEncodingAction(ProgramClass) {
117
120
  ProgramClass.prototype.encodeXOffset = encodeXOffset;
@@ -1,5 +1,5 @@
1
- import { action } from "../../core/action.js";
2
- import { validateOptionObject } from "../../core/validation.js";
1
+ import { closedAction } from "../../core/action.js";
2
+
3
3
  import {
4
4
  normalizeParallelDimensions,
5
5
  validateParallelKeyField,
@@ -19,13 +19,12 @@ const OPTIONS = Object.freeze([
19
19
  "target", "coordinate", "dimensions", "key", "missing"
20
20
  ]);
21
21
 
22
- export const encodeParallelCoordinates = action(
22
+ export const encodeParallelCoordinates = /* @__PURE__ */ closedAction(
23
23
  {
24
24
  op: "encodeParallelCoordinates",
25
25
  description: "Atomically encode ordered Parallel-coordinate dimensions."
26
- },
26
+ }, OPTIONS,
27
27
  function (args = {}) {
28
- validateOptionObject(args, OPTIONS, "encodeParallelCoordinates");
29
28
  const { id: target, dataset, layer } = resolveTarget(
30
29
  this,
31
30
  args.target,
@@ -1,9 +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 {
4
- validateNonEmptyString,
5
- validateOptionObject
6
- } from "../../core/validation.js";
3
+ import { validateNonEmptyString } from "../../core/validation.js";
7
4
  import { readQuantitativeField } from "../../grammar/scales/index.js";
8
5
  import { validatePathOrderDirection } from "../../grammar/pathOrder.js";
9
6
  import {
@@ -76,13 +73,12 @@ function rematerializePath(program, layer) {
76
73
  : program;
77
74
  }
78
75
 
79
- const encodePathOrder = action(
76
+ const encodePathOrder = /* @__PURE__ */ closedAction(
80
77
  {
81
78
  op: "encodePathOrder",
82
79
  description: "Order vertices within each Cartesian path series."
83
- },
80
+ }, ENCODE_OPTIONS,
84
81
  function (args = {}) {
85
- validateOptionObject(args, ENCODE_OPTIONS, "encodePathOrder");
86
82
  const field = validateNonEmptyString(args.field, "Path order field");
87
83
  const fieldType = args.fieldType ?? "quantitative";
88
84
  if (fieldType !== "quantitative") {
@@ -102,13 +98,12 @@ const encodePathOrder = action(
102
98
  }
103
99
  );
104
100
 
105
- const removePathOrder = action(
101
+ const removePathOrder = /* @__PURE__ */ closedAction(
106
102
  {
107
103
  op: "removePathOrder",
108
104
  description: "Remove explicit path order and restore automatic ordering."
109
- },
105
+ }, REMOVE_OPTIONS,
110
106
  function (args = {}) {
111
- validateOptionObject(args, REMOVE_OPTIONS, "removePathOrder");
112
107
  const layer = resolvePathOrderLayer(this, args.target, { active: true });
113
108
  const next = this.editSemantic({
114
109
  property: `layer[${layer.id}].encoding.pathOrder`,
@@ -141,7 +141,7 @@ function encodePosition(program, channel, args, operation) {
141
141
  return applyDetachedScaleRematerialization(next, [layer]);
142
142
  }
143
143
 
144
- const encodeX = action(
144
+ const encodeX = /* @__PURE__ */ action(
145
145
  {
146
146
  op: "encodeX",
147
147
  description: "Encode a field as horizontal position."
@@ -151,7 +151,7 @@ const encodeX = action(
151
151
  }
152
152
  );
153
153
 
154
- const encodeY = action(
154
+ const encodeY = /* @__PURE__ */ action(
155
155
  {
156
156
  op: "encodeY",
157
157
  description: "Encode a field as vertical position."
@@ -161,7 +161,7 @@ const encodeY = action(
161
161
  }
162
162
  );
163
163
 
164
- const encodeTheta = action(
164
+ const encodeTheta = /* @__PURE__ */ action(
165
165
  {
166
166
  op: "encodeTheta",
167
167
  description: "Encode a field as Polar angle in clockwise degrees."
@@ -171,7 +171,7 @@ const encodeTheta = action(
171
171
  }
172
172
  );
173
173
 
174
- const encodeR = action(
174
+ const encodeR = /* @__PURE__ */ action(
175
175
  {
176
176
  op: "encodeR",
177
177
  description: "Encode a quantitative field as Polar radius."
@@ -13,6 +13,8 @@ import {
13
13
  validateFieldType,
14
14
  validatePositionChannel
15
15
  } from "../../../grammar/scales/index.js";
16
+ import { applyRequestedItemMissingPolicy } from
17
+ "../../../grammar/itemMissing.js";
16
18
  import { resolvePositionScaleDefinition } from "../../scales/definitions.js";
17
19
  import { findCoordinate } from "../../../selectors/coordinates.js";
18
20
  import {
@@ -92,7 +94,7 @@ function resolveCoordinate(program, channel, layer, requestedId) {
92
94
  export function resolvePositionEncoding(program, channel, args, operation) {
93
95
  validateOptions(args, POSITION_ENCODING_OPTIONS, operation);
94
96
  validatePositionChannel(channel);
95
- const { id: target, dataset, layer } = resolveTarget(
97
+ const { id: target, dataset: sourceDataset, layer } = resolveTarget(
96
98
  program,
97
99
  args.target,
98
100
  getPositionChannelDefinition(channel).markTypes
@@ -157,6 +159,9 @@ export function resolvePositionEncoding(program, channel, args, operation) {
157
159
  xEncoding?.bin !== undefined && args.field === undefined
158
160
  ? xEncoding.field
159
161
  : args.field;
162
+ const dataset = hasField
163
+ ? applyRequestedItemMissingPolicy(layer, sourceDataset, field)
164
+ : applyRequestedItemMissingPolicy(layer, sourceDataset);
160
165
  const datum = args.datum;
161
166
  const temporalUnit = resolveTemporalUnit({ ...args, ...(hasDatum ? {} : { field }) }, fieldType, previous);
162
167
  const usesField = !countRadius && (!["rule", "area", "rect", "text", "point", "tick"].includes(layer.mark.type) || hasField);
@@ -14,6 +14,8 @@ import { deriveAreaSeries } from "../../grammar/areaSeries.js";
14
14
  import { resolvePositionEncoding } from "./position/resolve.js";
15
15
  import { resolveScalePreview } from "../scales/preview.js";
16
16
  import { findUpstreamTransform } from "../../materialization/dataProvenance.js";
17
+ import { applyRequestedItemMissingPolicy } from
18
+ "../../grammar/itemMissing.js";
17
19
 
18
20
  const SECONDARY_OPTIONS = Object.freeze([
19
21
  "field", "datum", "target", "fieldType", "scale", "coordinate", "temporalUnit"
@@ -46,7 +48,7 @@ function validateSecondaryField(dataset, field, fieldType, temporalUnit) {
46
48
 
47
49
  function encodeSecondaryPosition(program, channel, args, operation, types) {
48
50
  validateOptions(args, SECONDARY_OPTIONS, operation);
49
- const { id: target, dataset, layer } = resolveTarget(
51
+ const { id: target, dataset: sourceDataset, layer } = resolveTarget(
50
52
  program,
51
53
  args.target,
52
54
  types,
@@ -72,6 +74,9 @@ function encodeSecondaryPosition(program, channel, args, operation, types) {
72
74
  const rect = layer.mark.type === "rect";
73
75
  const hasField = Object.hasOwn(args, "field");
74
76
  const hasDatum = Object.hasOwn(args, "datum");
77
+ const dataset = hasField
78
+ ? applyRequestedItemMissingPolicy(layer, sourceDataset, args.field)
79
+ : applyRequestedItemMissingPolicy(layer, sourceDataset);
75
80
  if ((rule || area || rect) && hasField === hasDatum) {
76
81
  throw new Error(`${operation} requires exactly one of field or datum for a ${layer.mark.type} mark.`);
77
82
  }
@@ -159,7 +164,7 @@ function encodeSecondaryPosition(program, channel, args, operation, types) {
159
164
  return next;
160
165
  }
161
166
 
162
- const encodeX2 = action(
167
+ const encodeX2 = /* @__PURE__ */ action(
163
168
  {
164
169
  op: "encodeX2",
165
170
  description: "Encode a secondary horizontal endpoint."
@@ -175,7 +180,7 @@ const encodeX2 = action(
175
180
  }
176
181
  );
177
182
 
178
- const encodeY2 = action(
183
+ const encodeY2 = /* @__PURE__ */ action(
179
184
  {
180
185
  op: "encodeY2",
181
186
  description: "Encode a secondary vertical endpoint."
@@ -222,10 +227,10 @@ function rangeAction(channel) {
222
227
  });
223
228
  }
224
229
 
225
- const encodeYRange = rangeAction("y");
226
- const encodeXRange = rangeAction("x");
230
+ const encodeYRange = /* @__PURE__ */ rangeAction("y");
231
+ const encodeXRange = /* @__PURE__ */ rangeAction("x");
227
232
 
228
- const encodeGroup = action(
233
+ const encodeGroup = /* @__PURE__ */ action(
229
234
  {
230
235
  op: "encodeGroup",
231
236
  description: "Split path geometry by nominal identity fields without a scale."
@@ -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 { validateOptionObject } from "../../core/validation.js";
3
+
4
4
  import {
5
5
  getPositionChannelDefinition,
6
6
  POSITION_ENCODING_CHANNELS
@@ -203,13 +203,12 @@ function rematerializeTarget(program, target) {
203
203
  return next;
204
204
  }
205
205
 
206
- export const removeEncoding = action(
206
+ export const removeEncoding = /* @__PURE__ */ closedAction(
207
207
  {
208
208
  op: "removeEncoding",
209
209
  description: "Remove one semantic encoding and its owned materialized state."
210
- },
210
+ }, OPTIONS,
211
211
  function (args = {}) {
212
- validateOptionObject(args, OPTIONS, "removeEncoding");
213
212
  if (!REMOVABLE_CHANNELS.includes(args.channel)) {
214
213
  throw new Error(
215
214
  `Unsupported removable encoding channel "${args.channel}".`
@@ -14,12 +14,14 @@ import {
14
14
  import { findLayer } from "../../selectors/layers.js";
15
15
  import { validatePathSeriesAppearance } from "../../grammar/pathSeries.js";
16
16
  import { assertEncodingSelectionCompatibility } from "../../materialization/selection/compatibility.js";
17
+ import { applyRequestedItemMissingPolicy } from
18
+ "../../grammar/itemMissing.js";
17
19
 
18
20
  const WIDTH_OPTIONS = Object.freeze([
19
21
  "target", "value", "field", "fieldType", "scale"
20
22
  ]);
21
23
 
22
- const encodeStrokeWidth = action(
24
+ const encodeStrokeWidth = /* @__PURE__ */ action(
23
25
  {
24
26
  op: "encodeStrokeWidth",
25
27
  description: "Assign constant or field-driven line or rule stroke width."
@@ -57,12 +59,13 @@ const encodeStrokeWidth = action(
57
59
  next = next.rematerializeRuleMark({ id });
58
60
  return applyDetachedScaleRematerialization(next, [layer]);
59
61
  }
60
- const { id, dataset, layer } = resolveTarget(
62
+ const { id, dataset: sourceDataset, layer } = resolveTarget(
61
63
  this,
62
64
  args.target,
63
65
  ["rule", "line"],
64
66
  "rule or line mark"
65
67
  );
68
+ const dataset = applyRequestedItemMissingPolicy(layer, sourceDataset, args.field);
66
69
  const fieldType = args.fieldType ?? "quantitative";
67
70
  if (fieldType !== "quantitative") {
68
71
  throw new Error("encodeStrokeWidth requires a quantitative field.");
@@ -15,7 +15,7 @@ export function stackLayoutMode(stack) {
15
15
  return stack === "normalize" ? "fill" : stack === "center" ? "center" : stack === null ? "overlay" : "stack";
16
16
  }
17
17
 
18
- export const layoutSeries = action({ op: "layoutSeries", description: "Assign series placement independently of color." }, function (args = {}) {
18
+ export const layoutSeries = /* @__PURE__ */ action({ op: "layoutSeries", description: "Assign series placement independently of color." }, function (args = {}) {
19
19
  validateOptions(args, ["target", "mode"], "layoutSeries");
20
20
  const mode = validateColorLayout(args.mode);
21
21
  const { id: target, layer, dataset } = resolveTarget(this, args.target, ["bar", "area"], "series mark");
@@ -26,6 +26,8 @@ import {
26
26
  setEncodingProperties,
27
27
  validateOptions
28
28
  } from "./shared.js";
29
+ import { applyRequestedItemMissingPolicy } from
30
+ "../../grammar/itemMissing.js";
29
31
 
30
32
  const OPTIONS = Object.freeze([
31
33
  "target", "value", "field", "fieldType", "temporalUnit", "scale"
@@ -101,7 +103,7 @@ function validateStrokeField(dataset, layer, args, scale, temporalUnit) {
101
103
  }
102
104
  }
103
105
 
104
- export const encodeStroke = action(
106
+ export const encodeStroke = /* @__PURE__ */ action(
105
107
  {
106
108
  op: "encodeStroke",
107
109
  description: "Assign constant or field-driven graphical stroke color."
@@ -122,7 +124,7 @@ export const encodeStroke = action(
122
124
  "Constant stroke does not accept fieldType, temporalUnit, or scale."
123
125
  );
124
126
  }
125
- const { id: target, dataset, layer } = resolveTarget(
127
+ const { id: target, dataset: sourceDataset, layer } = resolveTarget(
126
128
  this,
127
129
  args.target,
128
130
  MARK_TYPES,
@@ -155,6 +157,7 @@ export const encodeStroke = action(
155
157
  }
156
158
 
157
159
  const fieldType = args.fieldType ?? "nominal";
160
+ const dataset = applyRequestedItemMissingPolicy(layer, sourceDataset, args.field);
158
161
  const previous = layer.encoding?.stroke;
159
162
  const temporalUnit = resolveTemporalUnit(args, fieldType, previous);
160
163
  const requestedScale = resolveReassignmentScaleOptions(
@@ -15,12 +15,14 @@ import {
15
15
  } from "./shared.js";
16
16
  import { findLayer } from "../../selectors/layers.js";
17
17
  import { validatePathSeriesAppearance } from "../../grammar/pathSeries.js";
18
+ import { applyRequestedItemMissingPolicy } from
19
+ "../../grammar/itemMissing.js";
18
20
 
19
21
  const STROKE_DASH_ENCODING_OPTIONS = Object.freeze([
20
22
  "field", "value", "target", "fieldType", "scale"
21
23
  ]);
22
24
 
23
- const clearStrokeDashEncoding = action(
25
+ const clearStrokeDashEncoding = /* @__PURE__ */ action(
24
26
  {
25
27
  op: "clearStrokeDashEncoding",
26
28
  description: "Remove the current semantic stroke-dash assignment."
@@ -58,7 +60,7 @@ function reconcileLegendAfterDashRemoval(program, target) {
58
60
  .rematerializeLegend();
59
61
  }
60
62
 
61
- const encodeStrokeDash = action(
63
+ const encodeStrokeDash = /* @__PURE__ */ action(
62
64
  {
63
65
  op: "encodeStrokeDash",
64
66
  description: "Encode a nominal field as line stroke dash."
@@ -73,12 +75,15 @@ const encodeStrokeDash = action(
73
75
  if (hasValue && (args.fieldType !== undefined || args.scale !== undefined)) {
74
76
  throw new Error("Constant stroke dash does not accept fieldType or scale.");
75
77
  }
76
- const { id: target, dataset, layer } = resolveTarget(
78
+ const { id: target, dataset: sourceDataset, layer } = resolveTarget(
77
79
  this,
78
80
  args.target,
79
81
  ["line", "rule"],
80
82
  "line or rule mark"
81
83
  );
84
+ const dataset = hasField
85
+ ? applyRequestedItemMissingPolicy(layer, sourceDataset, args.field)
86
+ : sourceDataset;
82
87
  if (hasValue) {
83
88
  normalizeStrokeDashPattern(args.value);
84
89
  validatePathSeriesAppearance(dataset.values, {
@@ -9,6 +9,8 @@ import {
9
9
  setEncodingProperties,
10
10
  validateOptions
11
11
  } from "./shared.js";
12
+ import { applyRequestedItemMissingPolicy } from
13
+ "../../grammar/itemMissing.js";
12
14
 
13
15
  const OPTIONS = Object.freeze(["target", "field", "value", "content", "normalizeBy", "format"]);
14
16
 
@@ -25,7 +27,7 @@ function validateTextField(rows, field, format) {
25
27
  if (!found) throw new Error(`Unknown text field "${field}".`);
26
28
  }
27
29
 
28
- export const encodeText = action(
30
+ export const encodeText = /* @__PURE__ */ action(
29
31
  {
30
32
  op: "encodeText",
31
33
  description: "Assign field, constant, or source semantic text content."
@@ -41,12 +43,15 @@ export const encodeText = action(
41
43
  if (Object.hasOwn(args, "normalizeBy") && (!hasContent || args.content !== "share")) {
42
44
  throw new Error("Text normalizeBy is only supported with share content.");
43
45
  }
44
- const { id: target, dataset, layer } = resolveTarget(
46
+ const { id: target, dataset: sourceDataset, layer } = resolveTarget(
45
47
  this,
46
48
  args.target,
47
49
  ["text"],
48
50
  "text mark"
49
51
  );
52
+ const dataset = hasField
53
+ ? applyRequestedItemMissingPolicy(layer, sourceDataset, args.field)
54
+ : applyRequestedItemMissingPolicy(layer, sourceDataset);
50
55
  const previous = layer.encoding?.text;
51
56
  const format = validateTextFormat(args.format ?? previous?.format ?? "auto");
52
57
  const content = hasContent