ggaction 0.0.17 → 0.0.19

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 (315) hide show
  1. package/CHANGELOG.md +96 -0
  2. package/README.md +6 -2
  3. package/knowledge/action-card.schema.json +1 -1
  4. package/knowledge/action-cards.json +1 -1
  5. package/knowledge/intent-taxonomy.json +1 -1
  6. package/knowledge/mcp-resources.json +1 -1
  7. package/knowledge/task-resolver.js +1 -1
  8. package/package.json +3 -3
  9. package/src/BasicChartProgram.js +1 -1
  10. package/src/accessibility.js +3 -2
  11. package/src/actions/boxPlots/create.js +14 -4
  12. package/src/actions/boxPlots/edit.js +39 -33
  13. package/src/actions/boxPlots/materialize.js +7 -3
  14. package/src/actions/boxPlots/options.js +37 -11
  15. package/src/actions/canvas/actions.js +70 -95
  16. package/src/actions/canvas/fitting.js +20 -1
  17. package/src/actions/canvas/index.js +3 -0
  18. package/src/actions/canvas/plotBorder.js +28 -0
  19. package/src/actions/charts/area.js +2 -2
  20. package/src/actions/charts/bar.js +34 -7
  21. package/src/actions/charts/ecdf.js +4 -18
  22. package/src/actions/charts/endpoints.js +4 -18
  23. package/src/actions/charts/heatmap.js +8 -7
  24. package/src/actions/charts/index.js +2 -0
  25. package/src/actions/charts/interval-regression.js +2 -2
  26. package/src/actions/charts/line.js +1 -1
  27. package/src/actions/charts/pie.js +3 -47
  28. package/src/actions/charts/radial.js +34 -12
  29. package/src/actions/charts/scatter.js +16 -2
  30. package/src/actions/charts/shared.js +2 -2
  31. package/src/actions/charts/text.js +35 -0
  32. package/src/actions/composition/actions.js +6 -2
  33. package/src/actions/data/box.js +2 -1
  34. package/src/actions/data/derived.js +11 -1
  35. package/src/actions/data/edit.js +3 -1
  36. package/src/actions/data/index.js +4 -0
  37. package/src/actions/data/regression.js +25 -16
  38. package/src/actions/data/regressionStatistics.js +73 -0
  39. package/src/actions/data/shared.js +8 -4
  40. package/src/actions/data/stack.js +3 -1
  41. package/src/actions/distributions/revision.js +24 -18
  42. package/src/actions/encodings/appearance.js +37 -29
  43. package/src/actions/encodings/barWidth.js +36 -11
  44. package/src/actions/encodings/channels.js +0 -1
  45. package/src/actions/encodings/color/continuous.js +1 -1
  46. package/src/actions/encodings/color/index.js +1 -1
  47. package/src/actions/encodings/color/policy.js +10 -3
  48. package/src/actions/encodings/density/resolve.js +1 -6
  49. package/src/actions/encodings/position/policies/arc.js +12 -10
  50. package/src/actions/encodings/position/policies/area.js +3 -3
  51. package/src/actions/encodings/position/policies/bar.js +15 -6
  52. package/src/actions/encodings/position/policies/line.js +17 -6
  53. package/src/actions/encodings/position/resolve.js +3 -2
  54. package/src/actions/encodings/ranged.js +17 -0
  55. package/src/actions/encodings/remove.js +14 -8
  56. package/src/actions/encodings/seriesLayout.js +1 -0
  57. package/src/actions/encodings/shared.js +26 -24
  58. package/src/actions/encodings/text.js +6 -3
  59. package/src/actions/errorBands/create.js +2 -2
  60. package/src/actions/errorBands/edit.js +2 -1
  61. package/src/actions/facets/actions.js +176 -247
  62. package/src/actions/facets/guides.js +2 -1
  63. package/src/actions/gradientPlots/resolve.js +2 -17
  64. package/src/actions/guides/applicability.js +1 -1
  65. package/src/actions/guides/axes/axes.js +30 -11
  66. package/src/actions/guides/axes/axis.js +72 -10
  67. package/src/actions/guides/axes/components.js +13 -13
  68. package/src/actions/guides/axes/edit.js +36 -24
  69. package/src/actions/guides/axes/labels.js +155 -71
  70. package/src/actions/guides/axes/lines.js +27 -24
  71. package/src/actions/guides/axes/parallel/lifecycle.js +1 -1
  72. package/src/actions/guides/axes/parallel/policy.js +8 -7
  73. package/src/actions/guides/axes/remove.js +13 -8
  74. package/src/actions/guides/axes/tickGroups.js +11 -7
  75. package/src/actions/guides/axes/ticks.js +36 -24
  76. package/src/actions/guides/axes/titles.js +107 -69
  77. package/src/actions/guides/basic.js +2 -0
  78. package/src/actions/guides/facadeAxes.js +33 -24
  79. package/src/actions/guides/facadeLegend.js +12 -4
  80. package/src/actions/guides/grids/grid.js +8 -2
  81. package/src/actions/guides/grids/resolve.js +102 -58
  82. package/src/actions/guides/legends/blocks.js +46 -20
  83. package/src/actions/guides/legends/categorical/actions.js +95 -19
  84. package/src/actions/guides/legends/categorical/components.js +15 -18
  85. package/src/actions/guides/legends/categorical/index.js +8 -0
  86. package/src/actions/guides/legends/categorical/layout.js +45 -20
  87. package/src/actions/guides/legends/categorical/options.js +39 -22
  88. package/src/actions/guides/legends/categorical/recipes.js +7 -3
  89. package/src/actions/guides/legends/categorical/resolve.js +11 -4
  90. package/src/actions/guides/legends/categorical/symbols.js +38 -18
  91. package/src/actions/guides/legends/categorical/validation.js +1 -6
  92. package/src/actions/guides/legends/colorSize.js +110 -0
  93. package/src/actions/guides/legends/combine.js +37 -0
  94. package/src/actions/guides/legends/continuous/colorSymbols.js +1 -0
  95. package/src/actions/guides/legends/continuous/common.js +1 -447
  96. package/src/actions/guides/legends/continuous/gradient.js +73 -46
  97. package/src/actions/guides/legends/continuous/interval.js +4 -4
  98. package/src/actions/guides/legends/continuous/opacity.js +33 -21
  99. package/src/actions/guides/legends/creation.js +2 -0
  100. package/src/actions/guides/legends/edit.js +1 -604
  101. package/src/actions/guides/legends/focused.js +8 -7
  102. package/src/actions/guides/legends/group.js +1 -0
  103. package/src/actions/guides/legends/lane.js +1 -516
  104. package/src/actions/guides/legends/lifecycle.js +2 -1
  105. package/src/actions/guides/legends/remove.js +9 -3
  106. package/src/actions/guides/legends/sampling.js +1 -1
  107. package/src/actions/guides/legends/size.js +65 -47
  108. package/src/actions/guides/legends/strokeWidth.js +13 -29
  109. package/src/actions/guides/legends/target.js +2 -79
  110. package/src/actions/guides/legends/transition.js +44 -11
  111. package/src/actions/guides/polar/axes/labels.js +4 -2
  112. package/src/actions/guides/polar/axes/titles.js +7 -5
  113. package/src/actions/guides/polar/resolve.js +6 -14
  114. package/src/actions/guides/tickValues.js +8 -5
  115. package/src/actions/index.js +16 -16
  116. package/src/actions/marks/arc/actions.js +3 -10
  117. package/src/actions/marks/area/actions.js +8 -5
  118. package/src/actions/marks/area/materialize.js +8 -9
  119. package/src/actions/marks/bar/create.js +10 -4
  120. package/src/actions/marks/bar/edit.js +29 -14
  121. package/src/actions/marks/bar/materialize.js +15 -7
  122. package/src/actions/marks/line/actions.js +11 -4
  123. package/src/actions/marks/line/materialize.js +9 -5
  124. package/src/actions/marks/point/edit.js +1 -1
  125. package/src/actions/marks/point/materialize.js +5 -1
  126. package/src/actions/marks/rect/actions.js +3 -3
  127. package/src/actions/marks/remove.js +12 -10
  128. package/src/actions/marks/rule/actions.js +7 -4
  129. package/src/actions/marks/text/actions.js +17 -5
  130. package/src/actions/marks/text/layout.js +3 -0
  131. package/src/actions/primitives/createGraphics.js +3 -2
  132. package/src/actions/primitives/editGraphics.js +15 -11
  133. package/src/actions/primitives/graphicProperties.js +1 -6
  134. package/src/actions/primitives/semanticAction.js +27 -1
  135. package/src/actions/primitives/semanticValidation/guide.js +11 -1
  136. package/src/actions/primitives/semanticValidation/layer.js +8 -0
  137. package/src/actions/regression/create.js +1 -1
  138. package/src/actions/regression/edit.js +18 -6
  139. package/src/actions/regression/resolve.js +2 -6
  140. package/src/actions/scales/channels.js +9 -4
  141. package/src/actions/scales/consumers/families.js +16 -5
  142. package/src/actions/scales/create.js +10 -5
  143. package/src/actions/scales/definitions.js +1 -425
  144. package/src/actions/scales/edit.js +3 -3
  145. package/src/actions/scales/editPolicy.js +12 -3
  146. package/src/actions/scales/materialize.js +1 -1
  147. package/src/actions/scales/patch.js +1 -1
  148. package/src/actions/scales/preview.js +21 -1
  149. package/src/actions/scales/quantitativeColor.js +8 -3
  150. package/src/actions/selection/actions.js +1 -13
  151. package/src/actions/theme/reconcile.js +126 -45
  152. package/src/actions/theme/state.js +12 -0
  153. package/src/actions/titles/actions.js +5 -18
  154. package/src/actions/titles/resolve.js +41 -19
  155. package/src/actions/violinPlots/edit.js +3 -20
  156. package/src/core/compositionState.js +6 -3
  157. package/src/core/font.js +9 -2
  158. package/src/core/graphicProperties.js +1 -0
  159. package/src/core/optionRequirements.js +1 -0
  160. package/src/core/programState.js +4 -0
  161. package/src/core/resourceReferences.js +5 -2
  162. package/src/core/textMetricProfile.js +3 -2
  163. package/src/core/textMetrics.js +41 -4
  164. package/src/core/validation.js +35 -0
  165. package/src/core/vocabulary.js +7 -0
  166. package/src/grammar/aggregate.js +4 -18
  167. package/src/grammar/arcs.js +1 -386
  168. package/src/grammar/areaPaint.js +10 -0
  169. package/src/grammar/areaSeries.js +18 -10
  170. package/src/grammar/axisTextPlacement.js +1 -0
  171. package/src/grammar/bars/geometry.js +30 -3
  172. package/src/grammar/bars/policy.js +12 -1
  173. package/src/grammar/bin.js +2 -12
  174. package/src/grammar/bin2d.js +1 -6
  175. package/src/grammar/boxPlot.js +56 -9
  176. package/src/grammar/categoryOrder.js +1 -6
  177. package/src/grammar/colorSizeLegend.js +39 -0
  178. package/src/grammar/complete.js +15 -19
  179. package/src/grammar/computed.js +115 -26
  180. package/src/grammar/curveCommands.js +29 -16
  181. package/src/grammar/datasetSchema.js +13 -9
  182. package/src/grammar/displayLabels.js +36 -0
  183. package/src/grammar/ecdf.js +2 -9
  184. package/src/grammar/facets/dependencies.js +6 -2
  185. package/src/grammar/facets/guides.js +58 -30
  186. package/src/grammar/facets/index.js +2 -5
  187. package/src/grammar/facets/legendIntent.js +65 -0
  188. package/src/grammar/fold.js +2 -12
  189. package/src/grammar/gradientProfile.js +1 -6
  190. package/src/grammar/guideDash.js +1 -0
  191. package/src/grammar/impute.js +21 -48
  192. package/src/grammar/interval.js +2 -9
  193. package/src/grammar/legendBlocks.js +1 -0
  194. package/src/grammar/legendBorder.js +9 -0
  195. package/src/grammar/legendClip.js +19 -0
  196. package/src/grammar/legendCombinations.js +45 -0
  197. package/src/grammar/legendGradient.js +27 -0
  198. package/src/grammar/legendGroups.js +1 -0
  199. package/src/grammar/legendOpacity.js +6 -0
  200. package/src/grammar/legendTitleStyle.js +22 -0
  201. package/src/grammar/lineSeries.js +32 -17
  202. package/src/grammar/markLabels.js +5 -2
  203. package/src/grammar/normalize.js +4 -54
  204. package/src/grammar/numeric.js +1 -290
  205. package/src/grammar/parallelCoordinates.js +1 -6
  206. package/src/grammar/parseTime.js +41 -0
  207. package/src/grammar/pathCommands.js +11 -4
  208. package/src/grammar/pointShapes.js +16 -2
  209. package/src/grammar/polar.js +1 -184
  210. package/src/grammar/positionCompatibility.js +3 -3
  211. package/src/grammar/regression/derive.js +16 -2
  212. package/src/grammar/regression/models.js +142 -54
  213. package/src/grammar/regression/parameters.js +23 -4
  214. package/src/grammar/regression/statistics.js +64 -0
  215. package/src/grammar/roundedRect.js +42 -54
  216. package/src/grammar/scales/appearance.js +1 -206
  217. package/src/grammar/scales/color.js +1 -382
  218. package/src/grammar/scales/colorConsumers.js +5 -2
  219. package/src/grammar/scales/definition.js +1 -197
  220. package/src/grammar/scales/discretized.js +1 -195
  221. package/src/grammar/scales/size.js +1 -456
  222. package/src/grammar/scales/temporal.js +2 -13
  223. package/src/grammar/scales/transformed.js +1 -383
  224. package/src/grammar/scales/types.js +1 -1
  225. package/src/grammar/scales/validation.js +1 -66
  226. package/src/grammar/schemas/concreteGraphic.js +14 -0
  227. package/src/grammar/schemas/graphic.js +6 -0
  228. package/src/grammar/schemas/graphicBounds.js +31 -7
  229. package/src/grammar/schemas/semanticPath.js +19 -3
  230. package/src/grammar/stack.js +2 -10
  231. package/src/grammar/statisticalReference.js +1 -6
  232. package/src/grammar/summary.js +4 -27
  233. package/src/grammar/text.js +19 -0
  234. package/src/grammar/timeUnit.js +22 -11
  235. package/src/grammar/transformKeys.js +47 -0
  236. package/src/grammar/transformTopology.js +1 -0
  237. package/src/grammar/transforms.js +15 -2
  238. package/src/grammar/valueFormat.js +17 -5
  239. package/src/grammar/weightedStatistics.js +1 -6
  240. package/src/grammar/window.js +4 -58
  241. package/src/inspectionDescriptors.js +1 -1
  242. package/src/layout/canvas.js +1 -110
  243. package/src/layout/facets.js +1 -244
  244. package/src/layout/guideCollisions.js +9 -1
  245. package/src/layout/labels.js +1 -0
  246. package/src/layout/legend.js +13 -0
  247. package/src/layout/legendGroup.js +1 -0
  248. package/src/layout/legendItems.js +59 -15
  249. package/src/layout/legendLane.js +1 -441
  250. package/src/layout/legendText.js +1 -0
  251. package/src/layout/title.js +35 -13
  252. package/src/materialization/bars/aggregate.js +11 -5
  253. package/src/materialization/bars/histogram.js +4 -1
  254. package/src/materialization/bars/ranged.js +19 -6
  255. package/src/materialization/bars/resolve.js +22 -1
  256. package/src/materialization/compositionSnapshot.js +2 -7
  257. package/src/materialization/coordinateBounds.js +21 -0
  258. package/src/materialization/dependencies.js +4 -44
  259. package/src/materialization/facetGuides/edit.js +30 -0
  260. package/src/materialization/facetGuides/layout.js +1 -0
  261. package/src/materialization/facetGuides/owner.js +125 -0
  262. package/src/materialization/facetGuides/ownerLayout.js +71 -0
  263. package/src/materialization/facetGuides/placement.js +71 -14
  264. package/src/materialization/facetGuides/preparation.js +22 -7
  265. package/src/materialization/facetHeaders.js +1 -347
  266. package/src/materialization/facets.js +1 -185
  267. package/src/materialization/graphicHierarchy.js +5 -1
  268. package/src/materialization/graphicTranslation.js +73 -0
  269. package/src/materialization/guides/layout.js +1 -57
  270. package/src/materialization/guides/resources.js +1 -123
  271. package/src/materialization/layout.js +53 -0
  272. package/src/materialization/legendBorder.js +28 -0
  273. package/src/materialization/legendClip.js +76 -0
  274. package/src/materialization/legendGroups.js +1 -0
  275. package/src/materialization/legendText.js +1 -0
  276. package/src/materialization/legends.js +2 -2
  277. package/src/materialization/marks/capabilities.js +5 -6
  278. package/src/materialization/rect.js +1 -1
  279. package/src/materialization/scaleGuideDependencies.js +14 -15
  280. package/src/materialization/scales/map.js +6 -0
  281. package/src/materialization/scales/policies/arc.js +8 -7
  282. package/src/materialization/scales/policies/bar.js +19 -7
  283. package/src/materialization/scales/policies/series.js +2 -1
  284. package/src/materialization/scales/resolve.js +7 -3
  285. package/src/materialization/selection/items/arc.js +1 -1
  286. package/src/materialization/selection/items/bar.js +7 -6
  287. package/src/materialization/selection/items/path.js +7 -6
  288. package/src/materialization/selection/items/rect.js +2 -2
  289. package/src/materialization/text.js +13 -4
  290. package/src/materialization/textLines.js +15 -0
  291. package/src/materialization/typography.js +10 -2
  292. package/src/persistence/codec.js +37 -6
  293. package/src/persistence/validation.js +220 -0
  294. package/src/persistence.js +19 -6
  295. package/src/renderers/canvas/circle.js +6 -3
  296. package/src/renderers/canvas/fill.js +7 -1
  297. package/src/renderers/canvas/index.js +22 -11
  298. package/src/renderers/canvas/isolated.js +166 -0
  299. package/src/renderers/canvas/limits.js +3 -0
  300. package/src/renderers/canvas/line.js +1 -0
  301. package/src/renderers/canvas/path.js +1 -1
  302. package/src/renderers/canvas/rect.js +11 -8
  303. package/src/renderers/canvas/stroke.js +2 -1
  304. package/src/renderers/canvas/text.js +5 -3
  305. package/src/renderers/pdf.js +2 -2
  306. package/src/renderers/png.js +2 -2
  307. package/src/renderers/svg.js +14 -4
  308. package/src/selectors/axes.js +1 -0
  309. package/src/selectors/graphicCapacity.js +38 -0
  310. package/src/selectors/layers.js +19 -0
  311. package/src/theme/defaults.js +8 -2
  312. package/src/version.js +1 -1
  313. package/types/basic.d.ts +3 -0
  314. package/types/index.d.ts +12 -0
  315. package/types/program.d.ts +536 -129
@@ -1,3 +1,4 @@
1
+ import { cartesianAxisOwners, axisTargetArgs } from "../../selectors/axes.js";
1
2
  import { closedAction } from "../../core/action.js";
2
3
  import { validateUserId } from "../../core/identifiers.js";
3
4
 
@@ -26,6 +27,7 @@ import { findDataset } from "../../selectors/datasets.js";
26
27
  import { assertPathGroupCompatible, validatePathGroupAppearance } from "../../materialization/marks/grouping.js";
27
28
  import { assertEncodingSelectionCompatibility } from "../../materialization/selection/compatibility.js";
28
29
  import { planLegendBlockTransitions } from "../guides/legends/transition.js";
30
+ import { withGuideLayoutValidation } from "../../materialization/guides/layout.js";
29
31
 
30
32
  const OPTIONS = Object.freeze(["target", "channel"]);
31
33
  const REMOVABLE_CHANNELS = Object.freeze([
@@ -40,9 +42,9 @@ const REMOVE_AXIS = Object.freeze({
40
42
  radius: "removeRadialAxis"
41
43
  });
42
44
  const SPECIALIZED_LEGEND_KIND = Object.freeze({
43
- color: Object.freeze(["gradient", "interval"]),
45
+ color: Object.freeze(["gradient", "interval", "colorSize"]),
44
46
  stroke: Object.freeze(["strokeGradient", "strokeInterval"]),
45
- size: Object.freeze(["size"]),
47
+ size: Object.freeze(["size", "colorSize"]),
46
48
  opacity: Object.freeze(["opacity"]),
47
49
  strokeWidth: Object.freeze(["strokeWidth"])
48
50
  });
@@ -143,10 +145,14 @@ function cleanupPositionGuides(program, removed) {
143
145
  ) {
144
146
  continue;
145
147
  }
146
- const axis = next.semanticSpec.guides.axis?.[definition.guideChannel];
147
- if (axis?.scale === scale) {
148
- next = next[REMOVE_AXIS[definition.guideChannel]]({
149
- scale,
148
+ const owners = ["x", "y"].includes(definition.guideChannel)
149
+ ? cartesianAxisOwners(next).filter(owner => owner.channel === definition.guideChannel)
150
+ : [{ id: definition.guideChannel, channel: definition.guideChannel,
151
+ semantic: next.semanticSpec.guides.axis?.[definition.guideChannel] }];
152
+ for (const owner of owners) {
153
+ const axis = owner.semantic;
154
+ if (axis?.scale === scale) next = next[REMOVE_AXIS[definition.guideChannel]]({
155
+ ...axisTargetArgs(owner.id, owner.channel), scale,
150
156
  ...(axis.coordinate === undefined ? {} : { coordinate: axis.coordinate })
151
157
  });
152
158
  }
@@ -208,7 +214,7 @@ export const removeEncoding = /* @__PURE__ */ closedAction(
208
214
  op: "removeEncoding",
209
215
  description: "Remove one semantic encoding and its owned materialized state."
210
216
  }, OPTIONS,
211
- function (args = {}) {
217
+ withGuideLayoutValidation(function (args = {}) {
212
218
  if (!REMOVABLE_CHANNELS.includes(args.channel)) {
213
219
  throw new Error(
214
220
  `Unsupported removable encoding channel "${args.channel}".`
@@ -259,7 +265,7 @@ export const removeEncoding = /* @__PURE__ */ closedAction(
259
265
  next = cleanupLegends(next, layer.id, channels);
260
266
  next = cleanupPositionGuides(next, removedPositions);
261
267
  return applyDetachedScaleRematerialization(rematerializeTarget(next, layer.id), [layer]);
262
- }
268
+ })
263
269
  );
264
270
 
265
271
  export function registerEncodingRemovalAction(ProgramClass) {
@@ -48,6 +48,7 @@ export const layoutSeries = /* @__PURE__ */ action({ op: "layoutSeries", descrip
48
48
  if (grain === undefined || encoding.x?.scale === undefined || encoding.y?.scale === undefined) throw new Error("Series layout requires a complete bar.");
49
49
  if (mode === "center") throw new Error("Centered bars are not supported.");
50
50
  if (grain === BAR_GRAINS.ranged && mode !== "overlay") throw new Error("Ranged bars support only overlay layout.");
51
+ if (grain === BAR_GRAINS.centered && mode !== "overlay") throw new Error("Numeric-center bars support only overlay layout.");
51
52
  if (grain === BAR_GRAINS.aggregate) deriveBarAggregates(dataset.values, updated);
52
53
  if (mode === "group" && grain === BAR_GRAINS.aggregate) {
53
54
  if (encoding.group === undefined) throw new Error("Grouped bars require a group encoding.");
@@ -1,3 +1,4 @@
1
+ import { cartesianAxisOwners } from "../../selectors/axes.js";
1
2
  import { isSourceOwnedText } from "../../grammar/text.js";
2
3
  import { validateUserId } from "../../core/identifiers.js";
3
4
  import { findDataset } from "../../selectors/datasets.js";
@@ -80,7 +81,7 @@ export function applyEncodingScale(
80
81
  for (const property of [
81
82
  "domain", "range", "nice", "zero", "clamp", "reverse",
82
83
  "base", "exponent", "constant", "paddingInner", "paddingOuter",
83
- "padding", "align", "unknown", "interpolate", "radialMapping"
84
+ "padding", "align", "unknown", "interpolate", "whitePoint", "gamma", "radialMapping"
84
85
  ]) {
85
86
  if (Object.hasOwn(options, property)) patch[property] = definition[property];
86
87
  }
@@ -102,26 +103,26 @@ export function rebindPositionGuides(
102
103
  if (definition?.guideChannel === undefined) return program;
103
104
  if (previousScale === undefined || previousScale === nextScale) return program;
104
105
 
105
- const axis = program.semanticSpec.guides.axis?.[definition.guideChannel];
106
+ const owners = ["x", "y"].includes(definition.guideChannel)
107
+ ? cartesianAxisOwners(program).filter(owner => owner.channel === definition.guideChannel)
108
+ : [{ id: definition.guideChannel, semantic: program.semanticSpec.guides.axis?.[definition.guideChannel] }];
106
109
  const direction = definition.gridDirection;
107
110
  const grid = program.semanticSpec.guides.grid?.[direction];
108
- const ownsAxis = axis?.scale === previousScale;
109
- const refreshesReboundAxis = axis?.scale === nextScale;
110
111
  const ownsGrid = grid?.scale === previousScale;
111
- if (!ownsAxis && !ownsGrid && !refreshesReboundAxis) return program;
112
-
113
- const remaining = program.semanticSpec.layers.some(layer =>
114
- layer.id !== target && !isSourceOwnedText(layer) && layer.encoding?.[channel]?.scale === previousScale
115
- );
116
- if ((ownsAxis || ownsGrid) && remaining) {
117
- throw new Error(
118
- `Cannot rebind ${channel} guides from shared scale "${previousScale}" while it has other consumers.`
119
- );
112
+ const affected = owners.filter(owner => [previousScale, nextScale].includes(owner.semantic?.scale));
113
+ if (!affected.length && !ownsGrid) return program;
114
+ const remaining = program.semanticSpec.layers.some(layer => layer.id !== target &&
115
+ !isSourceOwnedText(layer) && layer.encoding?.[channel]?.scale === previousScale);
116
+ if ((affected.some(owner => owner.semantic?.scale === previousScale) || ownsGrid) && remaining) {
117
+ throw new Error(`Cannot rebind ${channel} guides from shared scale "${previousScale}" while it has other consumers.`);
120
118
  }
121
-
122
119
  let next = program;
120
+ for (const owner of affected) {
121
+ const axisId = owner.id;
122
+ const ownsAxis = owner.semantic?.scale === previousScale;
123
+ const refreshesReboundAxis = owner.semantic?.scale === nextScale;
123
124
  if (ownsAxis || refreshesReboundAxis) {
124
- const previousAxisConfig = next.guideConfigs.axis?.[definition.guideChannel];
125
+ const previousAxisConfig = next.guideConfigs.axis?.[axisId];
125
126
  const previousTicks = previousAxisConfig?.ticks;
126
127
  const previousLabels = previousAxisConfig?.labels;
127
128
  const labelsFollowTicks = previousTicks !== undefined &&
@@ -135,13 +136,13 @@ export function rebindPositionGuides(
135
136
  ));
136
137
  if (ownsAxis) {
137
138
  next = next.editSemantic({
138
- property: `guide.axis.${definition.guideChannel}.scale`,
139
+ property: `guide.axis.${axisId}.scale`,
139
140
  value: nextScale
140
141
  });
141
142
  for (const component of ["line", "ticks", "labels", "title"]) {
142
- const config = next.guideConfigs.axis?.[definition.guideChannel]?.[component];
143
+ const config = next.guideConfigs.axis?.[axisId]?.[component];
143
144
  if (config?.scale === previousScale) {
144
- next = next._withGuideConfig(definition.guideChannel, component, {
145
+ next = next._withGuideConfig(axisId, component, {
145
146
  ...config,
146
147
  scale: nextScale
147
148
  });
@@ -151,7 +152,7 @@ export function rebindPositionGuides(
151
152
  const resolved = next.resolvedScales[nextScale] ??
152
153
  findSemanticScale(next, nextScale);
153
154
  const discrete = ["ordinal", "band", "point"].includes(resolved?.type);
154
- let ticks = next.guideConfigs.axis?.[definition.guideChannel]?.ticks;
155
+ let ticks = next.guideConfigs.axis?.[axisId]?.ticks;
155
156
  if (ticks !== undefined && discrete && ticks.mode !== "values") {
156
157
  ticks = {
157
158
  ...ticks,
@@ -160,7 +161,7 @@ export function rebindPositionGuides(
160
161
  inferredValues: true
161
162
  };
162
163
  delete ticks.count;
163
- next = next._withGuideConfig(definition.guideChannel, "ticks", ticks);
164
+ next = next._withGuideConfig(axisId, "ticks", ticks);
164
165
  } else if (
165
166
  ticks !== undefined &&
166
167
  !discrete &&
@@ -174,18 +175,18 @@ export function rebindPositionGuides(
174
175
  inferredValues: true
175
176
  };
176
177
  delete ticks.values;
177
- next = next._withGuideConfig(definition.guideChannel, "ticks", ticks);
178
+ next = next._withGuideConfig(axisId, "ticks", ticks);
178
179
  } else if (
179
180
  ticks !== undefined &&
180
181
  discrete &&
181
182
  ticks.inferredValues === true
182
183
  ) {
183
184
  ticks = { ...ticks, values: resolved.domain };
184
- next = next._withGuideConfig(definition.guideChannel, "ticks", ticks);
185
+ next = next._withGuideConfig(axisId, "ticks", ticks);
185
186
  }
186
187
  if (previousLabels !== undefined && labelsFollowTicks && ticks !== undefined) {
187
188
  const labels = {
188
- ...next.guideConfigs.axis[definition.guideChannel].labels,
189
+ ...next.guideConfigs.axis[axisId].labels,
189
190
  mode: ticks.mode,
190
191
  inferredValues: ticks.inferredValues === true,
191
192
  ...(ticks.mode === "values"
@@ -195,12 +196,13 @@ export function rebindPositionGuides(
195
196
  if (ticks.mode === "values") delete labels.count;
196
197
  else delete labels.values;
197
198
  next = next._withGuideConfig(
198
- definition.guideChannel,
199
+ axisId,
199
200
  "labels",
200
201
  labels
201
202
  );
202
203
  }
203
204
  }
205
+ }
204
206
  if (ownsGrid) {
205
207
  next = next
206
208
  .editSemantic({
@@ -1,4 +1,5 @@
1
1
  import { action } from "../../core/action.js";
2
+ import { schemaField } from "../../grammar/datasetSchema.js";
2
3
  import { formatTextValue, validateTextFormat } from "../../grammar/text.js";
3
4
  import { normalizeMarkLabelContent, resolveMarkLabelValues } from "../../grammar/markLabels.js";
4
5
  import { canMaterializeText } from "../../materialization/marks/index.js";
@@ -14,11 +15,13 @@ import { applyRequestedItemMissingPolicy } from
14
15
 
15
16
  const OPTIONS = Object.freeze(["target", "field", "value", "content", "normalizeBy", "format"]);
16
17
 
17
- function validateTextField(rows, field, format) {
18
+ function validateTextField(dataset, field, format) {
19
+ const rows = dataset.values;
18
20
  if (typeof field !== "string" || field.length === 0) {
19
21
  throw new TypeError("encodeText field must be a non-empty string.");
20
22
  }
21
- let found = false;
23
+ let found = rows.length === 0 && dataset.schema !== undefined &&
24
+ schemaField(dataset.schema, field) !== undefined;
22
25
  for (const row of rows) {
23
26
  if (!Object.hasOwn(row, field)) continue;
24
27
  found = true;
@@ -57,7 +60,7 @@ export const encodeText = /* @__PURE__ */ action(
57
60
  const content = hasContent
58
61
  ? normalizeMarkLabelContent(findLayer(this, layer.source), args)
59
62
  : undefined;
60
- if (hasField) validateTextField(dataset.values, args.field, format);
63
+ if (hasField) validateTextField(dataset, args.field, format);
61
64
  else if (hasValue && formatTextValue(args.value, format) === undefined) {
62
65
  throw new Error("encodeText value must produce non-empty text.");
63
66
  }
@@ -1,7 +1,7 @@
1
+ import { validateFillPaint } from "../../grammar/paint.js";
1
2
  import { editGraphicProperties } from "../primitives/graphicProperties.js";
2
3
  import { action, closedAction } from "../../core/action.js";
3
4
  import { isPlainObject } from "../../core/immutable.js";
4
- import { validateNonEmptyString } from "../../core/validation.js";
5
5
  import { DEFAULT_COLORS } from "../../theme/defaults.js";
6
6
  import { validateCurveInterpolation } from "../../grammar/curveCommands.js";
7
7
  import {
@@ -176,7 +176,7 @@ export const createErrorBand = /* @__PURE__ */ closedAction(
176
176
  const resolved = resolveErrorBand(this, args);
177
177
  const curve = validateCurveInterpolation(args.curve ?? "linear");
178
178
  const boundaries = resolveBoundaries(args.boundaries, curve);
179
- if (args.fill !== undefined) validateNonEmptyString(args.fill, "Error-band fill");
179
+ if (args.fill !== undefined) validateFillPaint(args.fill, "Error-band fill");
180
180
  let next = createResolvedIntervalData(this, resolved);
181
181
  next = next.createAreaMark({
182
182
  id: resolved.id,
@@ -1,3 +1,4 @@
1
+ import { validateFillPaint } from "../../grammar/paint.js";
1
2
  import { currentIntervalRoleArgs, resolveIntervalRoleScales, applyIntervalStatistics } from "../intervals/revision.js";
2
3
  import { closedAction } from "../../core/action.js";
3
4
  import { isPlainObject } from "../../core/immutable.js";
@@ -333,7 +334,7 @@ export const editErrorBand = /* @__PURE__ */ closedAction(
333
334
  if (owner.encoding?.color !== undefined) {
334
335
  throw new Error("editErrorBand fill conflicts with a color encoding; remove the color encoding first.");
335
336
  }
336
- errorBand.fill = validateNonEmptyString(args.fill, "Error-band fill");
337
+ errorBand.fill = validateFillPaint(args.fill, "Error-band fill");
337
338
  config.fill = errorBand.fill;
338
339
  }
339
340
  }