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
@@ -5,6 +5,7 @@ import { readScaleField } from "../../../grammar/scales/index.js";
5
5
  import { findDataset } from "../../../selectors/datasets.js";
6
6
  import { requireSemanticScale } from "../../../selectors/scales.js";
7
7
  import { SCALED_ENCODING_CHANNELS } from "../../../core/vocabulary.js";
8
+ import { applyItemMissingPolicy } from "../../../grammar/itemMissing.js";
8
9
 
9
10
  export function findScale(program, id) {
10
11
  return requireSemanticScale(program, id);
@@ -39,7 +40,7 @@ export function requireConsumerDataset(program, consumer) {
39
40
  `Mark "${consumer.layer.id}" references unknown dataset "${consumer.layer.data}".`
40
41
  );
41
42
  }
42
- return dataset;
43
+ return applyItemMissingPolicy(consumer.layer, dataset);
43
44
  }
44
45
 
45
46
  export function isDirectCategoricalConsumer(consumer) {
@@ -24,6 +24,7 @@ const CREATE_SCALE_OPTIONS = Object.freeze([
24
24
  "id",
25
25
  "type",
26
26
  "domain",
27
+ "emptyDomain",
27
28
  "range",
28
29
  "nice",
29
30
  "zero",
@@ -77,7 +78,7 @@ function assertEquivalentScale(existing, expected) {
77
78
  }
78
79
  }
79
80
 
80
- export const createScale = action(
81
+ export const createScale = /* @__PURE__ */ action(
81
82
  {
82
83
  op: "createScale",
83
84
  description: "Create a named semantic scale."
@@ -164,7 +165,7 @@ export const createScale = action(
164
165
  .editSemantic({ property: `scale[${id}].range`, value: definition.range });
165
166
 
166
167
  for (const property of [
167
- "nice", "zero", "clamp", "reverse", "base", "exponent", "constant",
168
+ "emptyDomain", "nice", "zero", "clamp", "reverse", "base", "exponent", "constant",
168
169
  "paddingInner", "paddingOuter", "padding", "align", "interpolate", "midpoint",
169
170
  "radialMapping", "unknown"
170
171
  ]) {
@@ -37,7 +37,7 @@ import { resolveRequestedOffsetPolicy } from
37
37
  "../../materialization/scales/policies/offset.js";
38
38
  import { findScaleConsumers } from "./consumers/index.js";
39
39
 
40
- const BASE_OPTIONS = ["id", "type", "domain", "range"];
40
+ const BASE_OPTIONS = ["id", "type", "domain", "range", "emptyDomain"];
41
41
  const UNKNOWN_OPTIONS = [...BASE_OPTIONS, "unknown"];
42
42
  const CLAMP_REVERSE = ["clamp", "reverse"];
43
43
  const BOOLEAN_OPTIONS = ["nice", "zero", ...CLAMP_REVERSE];
@@ -26,7 +26,7 @@ import { hasExactLegendSamplingForScale } from
26
26
  "../guides/legends/sampling.js";
27
27
 
28
28
  const OPTIONS = Object.freeze([
29
- "id", "type", "domain", "range", "nice", "zero", "clamp", "reverse",
29
+ "id", "type", "domain", "range", "emptyDomain", "nice", "zero", "clamp", "reverse",
30
30
  "base", "exponent", "constant", "paddingInner", "paddingOuter", "padding",
31
31
  "align", "interpolate", "midpoint", "unknown", "palette", "radialMapping"
32
32
  ]);
@@ -145,7 +145,7 @@ function applyScaleEdit(program, {
145
145
  return next;
146
146
  }
147
147
 
148
- export const editScale = action(
148
+ export const editScale = /* @__PURE__ */ action(
149
149
  {
150
150
  op: "editScale",
151
151
  description: "Edit an existing scale and rematerialize its consumers."
@@ -27,7 +27,7 @@ function validateOptions(args) {
27
27
  }
28
28
  }
29
29
 
30
- export const rematerializeScale = action(
30
+ export const rematerializeScale = /* @__PURE__ */ action(
31
31
  {
32
32
  op: "rematerializeScale",
33
33
  description: "Recompute every concrete consumer of a scale."
@@ -39,8 +39,8 @@ function createOffsetScaleEditor(channel) {
39
39
  );
40
40
  }
41
41
 
42
- export const editXOffsetScale = createOffsetScaleEditor("xOffset");
43
- export const editYOffsetScale = createOffsetScaleEditor("yOffset");
42
+ export const editXOffsetScale = /* @__PURE__ */ createOffsetScaleEditor("xOffset");
43
+ export const editYOffsetScale = /* @__PURE__ */ createOffsetScaleEditor("yOffset");
44
44
 
45
45
  export function registerOffsetScaleActions(ProgramClass) {
46
46
  ProgramClass.prototype.editXOffsetScale = editXOffsetScale;
@@ -6,7 +6,7 @@ import { requireLayer } from "../../selectors/layers.js";
6
6
  import { requireSemanticScale } from "../../selectors/scales.js";
7
7
 
8
8
  const QUANTITATIVE_OPTIONS = Object.freeze([
9
- "type", "domain", "range", "nice", "zero", "clamp", "reverse",
9
+ "type", "domain", "range", "emptyDomain", "nice", "zero", "clamp", "reverse",
10
10
  "base", "exponent", "constant", "unknown"
11
11
  ]);
12
12
  const ORDINAL_OPTIONS = Object.freeze([
@@ -45,7 +45,7 @@ function resolveParallelDimension(program, args) {
45
45
  return dimension;
46
46
  }
47
47
 
48
- export const editParallelScale = action(
48
+ export const editParallelScale = /* @__PURE__ */ action(
49
49
  {
50
50
  op: "editParallelScale",
51
51
  description: "Edit a Parallel-coordinate dimension scale by field identity."
@@ -1,5 +1,5 @@
1
1
  const SCALE_EDIT_PROPERTIES = Object.freeze([
2
- "type", "domain", "range", "nice", "zero", "clamp", "reverse",
2
+ "type", "domain", "range", "emptyDomain", "nice", "zero", "clamp", "reverse",
3
3
  "base", "exponent", "constant", "paddingInner", "paddingOuter",
4
4
  "padding", "align", "interpolate", "midpoint", "unknown"
5
5
  ]);
@@ -9,7 +9,10 @@ import {
9
9
  resolveScaleConsumerBounds
10
10
  } from "../../materialization/coordinateBounds.js";
11
11
  import { requireCoordinate } from "../../selectors/coordinates.js";
12
- import { resolveScaleMaterialization } from "../../materialization/scales/resolve.js";
12
+ import {
13
+ rememberResolvedScaleBinding,
14
+ resolveScaleMaterialization
15
+ } from "../../materialization/scales/resolve.js";
13
16
  import { findScale, findScaleConsumers, resolveConsumerCategoryOrder,
14
17
  resolveConsumerValues, resolveSeriesLayoutScaleValues } from "./consumers/index.js";
15
18
 
@@ -126,6 +129,30 @@ export function resolveScalePreview(program, id) {
126
129
  return resolveScalePreviewAtBounds(program, id, bounds);
127
130
  }
128
131
 
132
+ export function restoreResolvedScaleBindings(program) {
133
+ for (const scale of program.semanticSpec.scales) {
134
+ const resolved = program.resolvedScales[scale.id];
135
+ if (resolved === undefined) continue;
136
+ const consumers = findScaleConsumers(program, scale.id);
137
+ const channels = new Set(consumers.map(consumer =>
138
+ normalizePositionScaleChannel(consumer.channel)
139
+ ));
140
+ const families = new Set([...channels].map(channel =>
141
+ channel === "stroke" ? "color" : channel
142
+ ));
143
+ if (families.size === 1) {
144
+ const channel = channels.size === 1
145
+ ? channels.values().next().value
146
+ : families.values().next().value;
147
+ rememberResolvedScaleBinding(resolved, channel, consumers);
148
+ }
149
+ }
150
+ for (const child of Object.values(program.children)) {
151
+ restoreResolvedScaleBindings(child);
152
+ }
153
+ return program;
154
+ }
155
+
129
156
  export function validatePendingMeasuredScale(program, scale, consumers) {
130
157
  const bounds = resolveScaleConsumerBounds(program, consumers);
131
158
  const range = resolveArcAutoPositionRange({ consumers, scale, channel: "radius",
@@ -1,5 +1,5 @@
1
- import { action } from "../../core/action.js";
2
- import { validateKeys } from "../../core/validation.js";
1
+ import { closedAction } from "../../core/action.js";
2
+
3
3
  import { findSemanticScale } from "../../selectors/scales.js";
4
4
 
5
5
  const OPTIONS = Object.freeze([
@@ -13,13 +13,12 @@ const OPTIONS = Object.freeze([
13
13
  "unknown"
14
14
  ]);
15
15
 
16
- export const setQuantitativeColorScale = action(
16
+ export const setQuantitativeColorScale = /* @__PURE__ */ closedAction(
17
17
  {
18
18
  op: "setQuantitativeColorScale",
19
19
  description: "Create or update an internal quantitative color scale."
20
- },
20
+ }, OPTIONS,
21
21
  function (args = {}) {
22
- validateKeys(args, OPTIONS, "setQuantitativeColorScale");
23
22
  if (!["sequential", "quantize", "quantile", "threshold"].includes(args.type)) {
24
23
  throw new Error(`Unsupported quantitative color scale type "${args.type}".`);
25
24
  }
@@ -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 { isPlainObject } from "../../core/immutable.js";
4
4
  import { validateKeys } from "../../core/validation.js";
@@ -278,10 +278,9 @@ export function rematerializeThemeHighlights(program) {
278
278
  return next;
279
279
  }
280
280
 
281
- export const selectMarks = action(
282
- { op: "selectMarks", description: "Create one reusable selection over final mark items." },
281
+ export const selectMarks = /* @__PURE__ */ closedAction(
282
+ { op: "selectMarks", description: "Create one reusable selection over final mark items." }, SELECT_OPTIONS,
283
283
  function (args = {}) {
284
- validateKeys(args, SELECT_OPTIONS, "selectMarks");
285
284
  const layer = resolveTarget(this, args.target);
286
285
  const resolved = resolveMarkSelection(this, layer.id, selectorFrom(args));
287
286
  const id = resolveSelectionCreationId(this, args.id, layer.id);
@@ -291,13 +290,12 @@ export const selectMarks = action(
291
290
  }
292
291
  );
293
292
 
294
- export const editMarkSelection = action(
293
+ export const editMarkSelection = /* @__PURE__ */ closedAction(
295
294
  {
296
295
  op: "editMarkSelection",
297
296
  description: "Replace one stored mark selector while preserving its identity and target."
298
- },
297
+ }, EDIT_SELECTION_OPTIONS,
299
298
  function (args = {}) {
300
- validateKeys(args, EDIT_SELECTION_OPTIONS, "editMarkSelection");
301
299
  const current = resolveStoredSelection(this, args.selection);
302
300
  const replacement = resolveMarkSelection(
303
301
  this,
@@ -325,13 +323,12 @@ export const editMarkSelection = action(
325
323
  }
326
324
  );
327
325
 
328
- export const removeMarkHighlight = action(
326
+ export const removeMarkHighlight = /* @__PURE__ */ closedAction(
329
327
  {
330
328
  op: "removeMarkHighlight",
331
329
  description: "Remove one stored highlight assignment and restore the clean mark baseline."
332
- },
330
+ }, REMOVE_SELECTION_OPTIONS,
333
331
  function (args = {}) {
334
- validateKeys(args, REMOVE_SELECTION_OPTIONS, "removeMarkHighlight");
335
332
  const current = resolveStoredSelection(this, args.selection);
336
333
  const dependent = Object.entries(
337
334
  this.materializationConfigs.highlights ?? {}
@@ -349,13 +346,12 @@ export const removeMarkHighlight = action(
349
346
  }
350
347
  );
351
348
 
352
- export const removeMarkSelection = action(
349
+ export const removeMarkSelection = /* @__PURE__ */ closedAction(
353
350
  {
354
351
  op: "removeMarkSelection",
355
352
  description: "Remove one stored selection after removing its dependent highlight."
356
- },
353
+ }, REMOVE_SELECTION_OPTIONS,
357
354
  function (args = {}) {
358
- validateKeys(args, REMOVE_SELECTION_OPTIONS, "removeMarkSelection");
359
355
  const current = resolveStoredSelection(this, args.selection);
360
356
  const labelDependents = namedLabelDependents(this, current.id);
361
357
  if (labelDependents.length > 0) {
@@ -376,10 +372,9 @@ export const removeMarkSelection = action(
376
372
  }
377
373
  );
378
374
 
379
- export const applyPointHighlight = action(
380
- { op: "applyPointHighlight", description: "Apply selected point appearance and geometry." },
375
+ export const applyPointHighlight = /* @__PURE__ */ closedAction(
376
+ { op: "applyPointHighlight", description: "Apply selected point appearance and geometry." }, INTERNAL_SELECTION_OPTIONS,
381
377
  function (args = {}) {
382
- validateKeys(args, INTERNAL_SELECTION_OPTIONS, "applyPointHighlight");
383
378
  const resolved = resolveStoredSelection(this, args.selection);
384
379
  const keys = selectedKeys(args, resolved);
385
380
  if (resolved.items[0]?.markType !== "point" && resolved.items.length > 0) {
@@ -432,14 +427,14 @@ function applyRectangularHighlight(
432
427
  transformRectangularHighlightChild(item, args.style, offset));
433
428
  }
434
429
 
435
- export const applyBarHighlight = action(
430
+ export const applyBarHighlight = /* @__PURE__ */ action(
436
431
  { op: "applyBarHighlight", description: "Apply selected bar appearance." },
437
432
  function (args = {}) {
438
433
  return applyRectangularHighlight(this, args, "applyBarHighlight", "bar");
439
434
  }
440
435
  );
441
436
 
442
- export const applyRectHighlight = action(
437
+ export const applyRectHighlight = /* @__PURE__ */ action(
443
438
  { op: "applyRectHighlight", description: "Apply selected rect appearance." },
444
439
  function (args = {}) {
445
440
  return applyRectangularHighlight(
@@ -452,10 +447,9 @@ export const applyRectHighlight = action(
452
447
  }
453
448
  );
454
449
 
455
- export const applyPathHighlight = action(
456
- { op: "applyPathHighlight", description: "Apply selected line or area path appearance and offset." },
450
+ export const applyPathHighlight = /* @__PURE__ */ closedAction(
451
+ { op: "applyPathHighlight", description: "Apply selected line or area path appearance and offset." }, INTERNAL_SELECTION_OPTIONS,
457
452
  function (args = {}) {
458
- validateKeys(args, INTERNAL_SELECTION_OPTIONS, "applyPathHighlight");
459
453
  const resolved = resolveStoredSelection(this, args.selection);
460
454
  const keys = selectedKeys(args, resolved);
461
455
  const markType = resolved.items[0]?.markType;
@@ -473,10 +467,9 @@ export const applyPathHighlight = action(
473
467
  }
474
468
  );
475
469
 
476
- export const applyRuleHighlight = action(
477
- { op: "applyRuleHighlight", description: "Apply selected rule appearance and offset." },
470
+ export const applyRuleHighlight = /* @__PURE__ */ closedAction(
471
+ { op: "applyRuleHighlight", description: "Apply selected rule appearance and offset." }, INTERNAL_SELECTION_OPTIONS,
478
472
  function (args = {}) {
479
- validateKeys(args, INTERNAL_SELECTION_OPTIONS, "applyRuleHighlight");
480
473
  const resolved = resolveStoredSelection(this, args.selection);
481
474
  const keys = selectedKeys(args, resolved);
482
475
  if (
@@ -493,10 +486,9 @@ export const applyRuleHighlight = action(
493
486
  }
494
487
  );
495
488
 
496
- export const dimUnselectedMarkItems = action(
497
- { op: "dimUnselectedMarkItems", description: "Dim the complement of one mark selection." },
489
+ export const dimUnselectedMarkItems = /* @__PURE__ */ closedAction(
490
+ { op: "dimUnselectedMarkItems", description: "Dim the complement of one mark selection." }, INTERNAL_DIM_OPTIONS,
498
491
  function (args = {}) {
499
- validateKeys(args, INTERNAL_DIM_OPTIONS, "dimUnselectedMarkItems");
500
492
  const opacity = validateUnitInterval(args.opacity, "Dim opacity");
501
493
  const resolved = resolveStoredSelection(this, args.selection);
502
494
  const keys = selectedKeys(args, resolved);
@@ -507,10 +499,9 @@ export const dimUnselectedMarkItems = action(
507
499
  }
508
500
  );
509
501
 
510
- export const placeSelectedMarkItemsLast = action(
511
- { op: "placeSelectedMarkItemsLast", description: "Place selected collection items after their complement." },
502
+ export const placeSelectedMarkItemsLast = /* @__PURE__ */ closedAction(
503
+ { op: "placeSelectedMarkItemsLast", description: "Place selected collection items after their complement." }, INTERNAL_ORDER_OPTIONS,
512
504
  function (args = {}) {
513
- validateKeys(args, INTERNAL_ORDER_OPTIONS, "placeSelectedMarkItemsLast");
514
505
  const resolved = resolveStoredSelection(this, args.selection);
515
506
  const keys = selectedKeys(args, resolved);
516
507
  if (keys.length === 0 || keys.length === resolved.items.length) {
@@ -528,10 +519,9 @@ export const placeSelectedMarkItemsLast = action(
528
519
  }
529
520
  );
530
521
 
531
- export const rematerializeMarkHighlights = action(
532
- { op: "rematerializeMarkHighlights", description: "Reapply stored highlight assignments to one rematerialized mark." },
522
+ export const rematerializeMarkHighlights = /* @__PURE__ */ closedAction(
523
+ { op: "rematerializeMarkHighlights", description: "Reapply stored highlight assignments to one rematerialized mark." }, REMATERIALIZE_OPTIONS,
533
524
  function (args = {}) {
534
- validateKeys(args, REMATERIALIZE_OPTIONS, "rematerializeMarkHighlights");
535
525
  validateUserId(args.target, "Highlight target id");
536
526
  if (!Array.isArray(args.highlights)) {
537
527
  throw new TypeError("rematerializeMarkHighlights requires highlight entries.");
@@ -553,10 +543,9 @@ export const rematerializeMarkHighlights = action(
553
543
  }
554
544
  );
555
545
 
556
- export const highlightMarks = action(
557
- { op: "highlightMarks", description: "Select and emphasize final visual mark items." },
546
+ export const highlightMarks = /* @__PURE__ */ closedAction(
547
+ { op: "highlightMarks", description: "Select and emphasize final visual mark items." }, HIGHLIGHT_OPTIONS,
558
548
  function (args = {}) {
559
- validateKeys(args, HIGHLIGHT_OPTIONS, "highlightMarks");
560
549
  if (args.select !== undefined && args.selection !== undefined) {
561
550
  throw new Error("highlightMarks accepts select or selection, not both.");
562
551
  }
@@ -0,0 +1,56 @@
1
+ import { action, closedAction } from "../../core/action.js";
2
+ import { noOptions } from "../../core/validation.js";
3
+ import { normalizeTextMetricProfile } from "../../core/textMetricProfile.js";
4
+ import { rematerializeTypography } from "../../materialization/typography.js";
5
+
6
+ function metricsProgram(parent, child) {
7
+ return typeof child.applyTextMetrics === "function" ? child : new parent.constructor({
8
+ ...child, actionSequence: child._actionSequence
9
+ });
10
+ }
11
+
12
+ export function inheritTextMetrics(parent, child) {
13
+ const profile = parent.materializationConfigs.textMetrics;
14
+ return profile === undefined ? child : metricsProgram(parent, child).applyTextMetrics({ profile });
15
+ }
16
+
17
+ function applyProfile(program, profile) {
18
+ let next = profile === undefined
19
+ ? program._withoutMaterializationConfig(["textMetrics"])
20
+ : program._withMaterializationConfig(["textMetrics"], profile);
21
+ if (next.compositionSpec !== undefined) {
22
+ const children = Object.fromEntries(next.compositionSpec.children.map(id => {
23
+ const child = next.children[id];
24
+ return [id, profile === undefined
25
+ ? child.materializationConfigs.textMetrics === undefined ? child : metricsProgram(next, child).removeTextMetrics()
26
+ : inheritTextMetrics(next, child)];
27
+ }));
28
+ next = next._withCompositionState({ children, compositionSpec: next.compositionSpec });
29
+ for (const id of next.compositionSpec.children) next = next.useProgram({ id });
30
+ return next.materializeComposition();
31
+ }
32
+ return rematerializeTypography(next);
33
+ }
34
+
35
+ export const applyTextMetrics = /* @__PURE__ */ closedAction(
36
+ { op: "applyTextMetrics", description: "Apply measured text widths to chart layout.", scope: "any" }, ["profile"],
37
+ function (args = {}) {
38
+ const profile = normalizeTextMetricProfile(args.profile);
39
+ applyProfile(this, profile);
40
+ return applyProfile(this, profile);
41
+ }
42
+ );
43
+
44
+ export const removeTextMetrics = /* @__PURE__ */ action(
45
+ { op: "removeTextMetrics", description: "Restore estimated text layout.", scope: "any" },
46
+ function (args = {}) {
47
+ noOptions(args, "removeTextMetrics");
48
+ if (this.materializationConfigs.textMetrics === undefined) throw new Error("removeTextMetrics requires an active profile.");
49
+ applyProfile(this, undefined);
50
+ return applyProfile(this, undefined);
51
+ }
52
+ );
53
+
54
+ export function registerTextMetricActions(ProgramClass) {
55
+ Object.assign(ProgramClass.prototype, { applyTextMetrics, removeTextMetrics });
56
+ }
@@ -28,7 +28,7 @@ function requireCompositionThemeHandlers() {
28
28
  return compositionThemeHandlers;
29
29
  }
30
30
 
31
- export const applyTheme = action(
31
+ export const applyTheme = /* @__PURE__ */ action(
32
32
  {
33
33
  op: "applyTheme",
34
34
  description: "Apply persistent visual defaults to the chart program.",
@@ -70,7 +70,7 @@ export const applyTheme = action(
70
70
  }
71
71
  );
72
72
 
73
- export const removeTheme = action(
73
+ export const removeTheme = /* @__PURE__ */ action(
74
74
  {
75
75
  op: "removeTheme",
76
76
  description: "Remove program theme defaults while preserving local styles.",