ggaction 0.0.13 → 0.0.15

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 +78 -0
  2. package/README.md +20 -11
  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/package.json +8 -3
  7. package/src/actions/basic.js +2 -2
  8. package/src/actions/boxPlots/components.js +14 -4
  9. package/src/actions/boxPlots/edit.js +31 -5
  10. package/src/actions/boxPlots/materialize.js +11 -3
  11. package/src/actions/boxPlots/options.js +48 -16
  12. package/src/actions/categoryOrder/index.js +15 -4
  13. package/src/actions/charts/area.js +5 -1
  14. package/src/actions/charts/bar.js +2 -1
  15. package/src/actions/charts/density.js +6 -2
  16. package/src/actions/charts/ecdf.js +4 -1
  17. package/src/actions/charts/endpoints.js +25 -3
  18. package/src/actions/charts/heatmap.js +2 -1
  19. package/src/actions/charts/histogram.js +4 -3
  20. package/src/actions/charts/horizon.js +3 -1
  21. package/src/actions/charts/interval-regression.js +5 -2
  22. package/src/actions/charts/line.js +3 -1
  23. package/src/actions/charts/parallel.js +8 -2
  24. package/src/actions/charts/pie.js +10 -2
  25. package/src/actions/charts/polar.js +15 -4
  26. package/src/actions/charts/radar.js +8 -2
  27. package/src/actions/charts/radial.js +10 -2
  28. package/src/actions/charts/rug-strip.js +6 -2
  29. package/src/actions/charts/scatter.js +3 -1
  30. package/src/actions/composition/actions.js +13 -4
  31. package/src/actions/coordinates/actions.js +1 -1
  32. package/src/actions/coordinates/edit.js +76 -0
  33. package/src/actions/data/bin.js +1 -1
  34. package/src/actions/data/bin2d.js +57 -185
  35. package/src/actions/data/complete.js +26 -0
  36. package/src/actions/data/computed.js +2 -2
  37. package/src/actions/data/create.js +2 -2
  38. package/src/actions/data/density.js +12 -20
  39. package/src/actions/data/derived.js +47 -17
  40. package/src/actions/data/edit.js +539 -0
  41. package/src/actions/data/filter.js +14 -2
  42. package/src/actions/data/impute.js +26 -0
  43. package/src/actions/data/index.js +14 -0
  44. package/src/actions/data/normalize.js +27 -0
  45. package/src/actions/data/regression.js +16 -21
  46. package/src/actions/data/revisionBindings.js +145 -0
  47. package/src/actions/data/shared.js +20 -4
  48. package/src/actions/data/summary.js +1 -1
  49. package/src/actions/data/timeUnit.js +4 -1
  50. package/src/actions/data/window.js +1 -1
  51. package/src/actions/encodings/channels.js +415 -0
  52. package/src/actions/encodings/color/index.js +2 -1
  53. package/src/actions/encodings/density.js +5 -2
  54. package/src/actions/encodings/histogram.js +3 -2
  55. package/src/actions/encodings/index.js +4 -0
  56. package/src/actions/encodings/offset.js +20 -13
  57. package/src/actions/encodings/position/apply.js +53 -7
  58. package/src/actions/encodings/position/index.js +10 -2
  59. package/src/actions/encodings/position/policies/bar.js +9 -0
  60. package/src/actions/encodings/position/resolve.js +24 -7
  61. package/src/actions/encodings/remove.js +9 -4
  62. package/src/actions/encodings/ruleAppearance.js +1 -23
  63. package/src/actions/encodings/seriesLayout.js +1 -0
  64. package/src/actions/encodings/shared.js +82 -14
  65. package/src/actions/encodings/stroke.js +226 -0
  66. package/src/actions/errorBands/create.js +23 -3
  67. package/src/actions/errorBands/edit.js +21 -6
  68. package/src/actions/errorBars/create.js +35 -7
  69. package/src/actions/errorBars/edit.js +19 -4
  70. package/src/actions/facets/actions.js +237 -57
  71. package/src/actions/facets/derive.js +91 -26
  72. package/src/actions/gradientPlots/components.js +10 -2
  73. package/src/actions/gradientPlots/edit.js +14 -4
  74. package/src/actions/gradientPlots/materialize.js +3 -1
  75. package/src/actions/gradientPlots/options.js +10 -2
  76. package/src/actions/guides/applicability.js +8 -2
  77. package/src/actions/guides/axes/labels.js +58 -12
  78. package/src/actions/guides/axes/lines.js +6 -2
  79. package/src/actions/guides/axes/parallel/resolve.js +6 -2
  80. package/src/actions/guides/axes/tickGroups.js +2 -1
  81. package/src/actions/guides/axes/ticks.js +6 -2
  82. package/src/actions/guides/axes/titles.js +11 -3
  83. package/src/actions/guides/grids/resolve.js +7 -2
  84. package/src/actions/guides/guides.js +19 -3
  85. package/src/actions/guides/legends/blocks.js +426 -0
  86. package/src/actions/guides/legends/categorical/actions.js +134 -48
  87. package/src/actions/guides/legends/categorical/components.js +17 -12
  88. package/src/actions/guides/legends/categorical/index.js +37 -33
  89. package/src/actions/guides/legends/categorical/layout.js +97 -15
  90. package/src/actions/guides/legends/categorical/options.js +2 -2
  91. package/src/actions/guides/legends/categorical/recipes.js +111 -20
  92. package/src/actions/guides/legends/categorical/resolve.js +12 -8
  93. package/src/actions/guides/legends/categorical/symbols.js +85 -30
  94. package/src/actions/guides/legends/continuous/common.js +30 -12
  95. package/src/actions/guides/legends/continuous/gradient.js +10 -7
  96. package/src/actions/guides/legends/continuous/index.js +2 -0
  97. package/src/actions/guides/legends/continuous/interval.js +8 -3
  98. package/src/actions/guides/legends/continuous/opacity.js +8 -5
  99. package/src/actions/guides/legends/continuous/stroke.js +525 -0
  100. package/src/actions/guides/legends/creation.js +14 -1
  101. package/src/actions/guides/legends/edit.js +158 -59
  102. package/src/actions/guides/legends/index.js +2 -0
  103. package/src/actions/guides/legends/lane.js +54 -19
  104. package/src/actions/guides/legends/lifecycle.js +19 -8
  105. package/src/actions/guides/legends/remove.js +13 -3
  106. package/src/actions/guides/legends/sampling.js +140 -0
  107. package/src/actions/guides/legends/size.js +93 -40
  108. package/src/actions/guides/legends/strokeWidth.js +34 -28
  109. package/src/actions/guides/legends/target.js +112 -1
  110. package/src/actions/guides/legends/transition.js +165 -16
  111. package/src/actions/guides/polar/axes/facade.js +4 -4
  112. package/src/actions/guides/polar/axes/labels.js +24 -5
  113. package/src/actions/guides/polar/axes/lines.js +10 -4
  114. package/src/actions/guides/polar/axes/shared.js +16 -0
  115. package/src/actions/guides/polar/axes/ticks.js +1 -1
  116. package/src/actions/guides/polar/axes/titles.js +1 -1
  117. package/src/actions/guides/polar/grids.js +1 -1
  118. package/src/actions/guides/polar/resolve.js +12 -8
  119. package/src/actions/index.js +14 -3
  120. package/src/actions/marks/arc/actions.js +77 -19
  121. package/src/actions/marks/area/actions.js +34 -9
  122. package/src/actions/marks/area/materialize.js +17 -1
  123. package/src/actions/marks/bar/create.js +11 -2
  124. package/src/actions/marks/bar/edit.js +20 -3
  125. package/src/actions/marks/bar/materialize.js +22 -2
  126. package/src/actions/marks/index.js +10 -1
  127. package/src/actions/marks/line/actions.js +37 -14
  128. package/src/actions/marks/line/materialize.js +29 -10
  129. package/src/actions/marks/point/create.js +8 -2
  130. package/src/actions/marks/point/edit.js +18 -6
  131. package/src/actions/marks/point/materialize.js +49 -15
  132. package/src/actions/marks/rect/actions.js +33 -12
  133. package/src/actions/marks/references.js +601 -30
  134. package/src/actions/marks/remove.js +71 -1
  135. package/src/actions/marks/rule/actions.js +47 -10
  136. package/src/actions/marks/shared.js +1 -1
  137. package/src/actions/marks/text/actions.js +74 -9
  138. package/src/actions/marks/text/index.js +4 -0
  139. package/src/actions/marks/text/layout.js +154 -6
  140. package/src/actions/marks/text/removal.js +173 -0
  141. package/src/actions/marks/text/selection.js +73 -0
  142. package/src/actions/marks/tick/actions.js +22 -5
  143. package/src/actions/primitives/editGraphics.js +26 -0
  144. package/src/actions/primitives/semantic.js +2 -1
  145. package/src/actions/primitives/semanticAction.js +83 -10
  146. package/src/actions/primitives/semanticValidation/guide.js +1 -1
  147. package/src/actions/primitives/semanticValidation/index.js +9 -1
  148. package/src/actions/primitives/semanticValidation/layer.js +5 -0
  149. package/src/actions/primitives/semanticValidation/scale.js +28 -7
  150. package/src/actions/regression/components.js +26 -11
  151. package/src/actions/regression/create.js +10 -2
  152. package/src/actions/regression/edit.js +21 -7
  153. package/src/actions/resources/index.js +7 -0
  154. package/src/actions/resources/remove.js +172 -0
  155. package/src/actions/scales/channels.js +212 -0
  156. package/src/actions/scales/consumers/common.js +1 -1
  157. package/src/actions/scales/consumers/families.js +3 -2
  158. package/src/actions/scales/consumers/index.js +19 -2
  159. package/src/actions/scales/consumers/seriesLayout.js +28 -14
  160. package/src/actions/scales/create.js +54 -22
  161. package/src/actions/scales/definitions.js +94 -40
  162. package/src/actions/scales/edit.js +66 -11
  163. package/src/actions/scales/editPolicy.js +81 -11
  164. package/src/actions/scales/index.js +6 -0
  165. package/src/actions/scales/materialize.js +4 -3
  166. package/src/actions/scales/offset.js +48 -0
  167. package/src/actions/scales/parallel.js +71 -0
  168. package/src/actions/scales/preview.js +111 -10
  169. package/src/actions/selection/actions.js +154 -30
  170. package/src/actions/selection/index.js +3 -0
  171. package/src/actions/theme/actions.js +68 -13
  172. package/src/actions/theme/composition.js +238 -0
  173. package/src/actions/theme/index.js +9 -2
  174. package/src/actions/theme/reconcile.js +315 -67
  175. package/src/actions/theme/state.js +160 -0
  176. package/src/actions/violinPlots/create.js +5 -2
  177. package/src/actions/violinPlots/edit.js +1 -0
  178. package/src/core/action.js +10 -0
  179. package/src/core/compositionState.js +6 -1
  180. package/src/core/programState.js +20 -0
  181. package/src/core/resourceReferences.js +332 -0
  182. package/src/core/vocabulary.js +16 -3
  183. package/src/grammar/bars/aggregate.js +4 -1
  184. package/src/grammar/bars/geometry.js +44 -0
  185. package/src/grammar/bin.js +54 -9
  186. package/src/grammar/complete.js +279 -0
  187. package/src/grammar/computed.js +265 -64
  188. package/src/grammar/coordinates.js +37 -0
  189. package/src/grammar/density.js +239 -37
  190. package/src/grammar/displayLabels.js +57 -0
  191. package/src/grammar/facets/dependencies.js +133 -1
  192. package/src/grammar/facets/guides.js +3 -0
  193. package/src/grammar/facets/index.js +7 -47
  194. package/src/grammar/facets/scales.js +15 -18
  195. package/src/grammar/impute.js +340 -0
  196. package/src/grammar/markLabelSelection.js +57 -0
  197. package/src/grammar/markLabels.js +18 -1
  198. package/src/grammar/normalize.js +366 -0
  199. package/src/grammar/pathSeries.js +26 -8
  200. package/src/grammar/pointShapes.js +13 -4
  201. package/src/grammar/polar.js +90 -8
  202. package/src/grammar/regression/index.js +1 -0
  203. package/src/grammar/regression/parameters.js +23 -0
  204. package/src/grammar/roundedRect.js +180 -0
  205. package/src/grammar/rules.js +1 -0
  206. package/src/grammar/scales/colorConsumers.js +20 -1
  207. package/src/grammar/scales/continuous.js +2 -2
  208. package/src/grammar/scales/definition.js +27 -4
  209. package/src/grammar/scales/index.js +1 -0
  210. package/src/grammar/scales/ordinal.js +12 -3
  211. package/src/grammar/scales/policies.js +2 -2
  212. package/src/grammar/scales/size.js +456 -0
  213. package/src/grammar/schemas/concreteGraphic.js +14 -2
  214. package/src/grammar/schemas/graphic.js +15 -0
  215. package/src/grammar/schemas/graphicBounds.js +179 -30
  216. package/src/grammar/schemas/semanticPath.js +7 -2
  217. package/src/grammar/statisticalReference.js +103 -0
  218. package/src/grammar/strokeStyle.js +77 -0
  219. package/src/grammar/summary.js +78 -16
  220. package/src/grammar/timeUnit.js +216 -5
  221. package/src/grammar/transformTopology.js +4 -0
  222. package/src/grammar/transforms.js +394 -28
  223. package/src/grammar/weightedStatistics.js +374 -0
  224. package/src/grammar/window.js +221 -16
  225. package/src/layout/aspect.js +80 -0
  226. package/src/layout/facets.js +59 -5
  227. package/src/layout/labels.js +343 -0
  228. package/src/materialization/bars/aggregate.js +25 -2
  229. package/src/materialization/bars/histogram.js +84 -24
  230. package/src/materialization/bars/ranged.js +19 -3
  231. package/src/materialization/bars/resolve.js +7 -4
  232. package/src/materialization/composition.js +3 -1
  233. package/src/materialization/coordinateBounds.js +204 -0
  234. package/src/materialization/dependencies.js +36 -0
  235. package/src/materialization/facetGuides/legacyCategorical.js +3 -0
  236. package/src/materialization/facetGuides/placement.js +8 -2
  237. package/src/materialization/facetGuides/preparation.js +12 -7
  238. package/src/materialization/facetHeaders.js +346 -0
  239. package/src/materialization/facets.js +15 -65
  240. package/src/materialization/guides/resources.js +26 -0
  241. package/src/materialization/legends.js +1 -1
  242. package/src/materialization/marks/index.js +11 -5
  243. package/src/materialization/marks/policies.js +2 -1
  244. package/src/materialization/rect.js +25 -12
  245. package/src/materialization/rectConfig.js +5 -1
  246. package/src/materialization/scales/map.js +5 -3
  247. package/src/materialization/scales/policies/binnedPosition.js +2 -2
  248. package/src/materialization/scales/policies/offset.js +50 -8
  249. package/src/materialization/scales/policies/series.js +4 -1
  250. package/src/materialization/scales/resolve.js +22 -6
  251. package/src/materialization/selection/items/arc.js +28 -4
  252. package/src/materialization/selection/items/bar.js +30 -3
  253. package/src/materialization/selection/items/common.js +19 -4
  254. package/src/materialization/selection/items/rect.js +28 -4
  255. package/src/materialization/selection/path.js +1 -1
  256. package/src/materialization/selection/point.js +3 -1
  257. package/src/materialization/text.js +265 -14
  258. package/src/renderers/canvas/circle.js +2 -3
  259. package/src/renderers/canvas/line.js +2 -3
  260. package/src/renderers/canvas/native.js +4 -4
  261. package/src/renderers/canvas/path.js +2 -3
  262. package/src/renderers/canvas/rect.js +2 -3
  263. package/src/renderers/canvas/stroke.js +11 -0
  264. package/src/renderers/svg.js +19 -0
  265. package/src/selectors/datasets.js +32 -1
  266. package/src/selectors/layers.js +4 -0
  267. package/src/theme/defaults.js +101 -0
  268. package/types/basic.d.ts +6 -0
  269. package/types/index.d.ts +85 -0
  270. package/types/program.d.ts +910 -117
@@ -25,9 +25,11 @@ import { findLayer } from "../../../../selectors/layers.js";
25
25
  import { isOpacityLegendLayer } from "../../../../materialization/legends.js";
26
26
  import { findCanvasGraphic } from
27
27
  "../../../../materialization/graphicHierarchy.js";
28
+ import { normalizeLegendSampling } from "../sampling.js";
28
29
 
29
30
  const OPTIONS = [
30
31
  "target", "channels", "position", "align", "offset", "title", "count",
32
+ "values",
31
33
  "gradient", "symbol", "labels", "titleStyle", "itemGap", "border",
32
34
  "direction", "columns", "titlePosition"
33
35
  ];
@@ -129,13 +131,24 @@ export function normalizeContinuousLegend(args, kind) {
129
131
  if (["left", "right"].includes(position) && align !== "center") {
130
132
  throw new Error("Side continuous legends require center alignment.");
131
133
  }
132
- const count = args.count ?? 5;
133
- if (!Number.isInteger(count) || count < 2) {
134
- throw new RangeError(
135
- "Continuous legend count must be an integer of at least 2."
136
- );
134
+ if (kind === "gradient" && Object.hasOwn(args, "values")) {
135
+ throw new Error("Gradient legends do not support exact sample values.");
136
+ }
137
+ const sampling = kind === "opacity"
138
+ ? normalizeLegendSampling(args, {
139
+ operation: "create",
140
+ label: "Opacity legend"
141
+ })
142
+ : undefined;
143
+ const count = kind === "gradient" ? args.count ?? 5 : undefined;
144
+ if (kind === "gradient") {
145
+ if (!Number.isInteger(count) || count < 2) {
146
+ throw new RangeError(
147
+ "Continuous legend count must be an integer of at least 2."
148
+ );
149
+ }
150
+ validateGeneratedItemLimit(count, "Continuous legend count");
137
151
  }
138
- validateGeneratedItemLimit(count, "Continuous legend count");
139
152
  const offset = args.offset ?? 30;
140
153
  validateNonNegative(offset, "Legend offset");
141
154
  const titlePosition = args.titlePosition ?? "top";
@@ -171,7 +184,7 @@ export function normalizeContinuousLegend(args, kind) {
171
184
  position,
172
185
  align,
173
186
  offset,
174
- count,
187
+ ...(kind === "gradient" ? { count } : { sampling }),
175
188
  title: args.title,
176
189
  inferredTitle: args.title === undefined,
177
190
  labels: normalizeLegendTextOptions(
@@ -218,18 +231,23 @@ export function resolveContinuousLegendLayer(program, requested, channel) {
218
231
  return layer;
219
232
  }
220
233
 
221
- export function resolveContinuousColorLayer(program, requested) {
234
+ export function resolveContinuousColorLayer(program, requested, channel = "color") {
222
235
  const layer = selectLegendLayer(
223
236
  program,
224
237
  requested,
225
- candidate => ["point", "bar", "rect"].includes(candidate.mark?.type) &&
226
- candidate.encoding?.color?.scale !== undefined
238
+ candidate => (channel === "stroke"
239
+ ? ["point", "line", "area", "bar", "rect", "arc", "rule", "tick"]
240
+ : ["point", "bar", "rect"]
241
+ ).includes(candidate.mark?.type) &&
242
+ candidate.encoding?.[channel]?.scale !== undefined
227
243
  );
228
244
  if (layer === undefined) {
229
245
  throw new Error(
230
246
  requested === undefined
231
- ? "color legend requires one eligible point, bar, or rect mark."
232
- : `Unknown color legend target "${requested}".`
247
+ ? channel === "color"
248
+ ? "color legend requires one eligible point, bar, or rect mark."
249
+ : "stroke legend requires one eligible mark."
250
+ : `Unknown ${channel} legend target "${requested}".`
233
251
  );
234
252
  }
235
253
  return layer;
@@ -20,24 +20,26 @@ import {
20
20
  } from "./common.js";
21
21
  import { resolveLegendGraphicPlacement } from
22
22
  "../../../../materialization/graphicHierarchy.js";
23
+ import { resolveEffectiveLegendBlockConfig } from "../blocks.js";
23
24
 
24
25
  export const DEFAULT_GRADIENT_SIZE = Object.freeze({ length: 120, thickness: 12 });
25
26
 
26
27
  const GRADIENT_OPTIONS = Object.freeze(["length", "thickness"]);
27
28
 
28
- function resolveGradientLayout(program, config, scale) {
29
+ export function resolveGradientLayout(program, config, scale) {
29
30
  const { plot, canvas } = resolveContinuousBounds(program);
30
31
  const vertical = ["right", "left"].includes(config.position);
31
32
  const length = config.gradient.length;
32
33
  const thickness = config.gradient.thickness;
34
+ const titleGap = config.blockGap ?? 12;
33
35
  let x;
34
36
  let y;
35
37
  if (config.position === "right") {
36
38
  x = plot.x + plot.width + config.offset;
37
- y = plot.y + 46;
39
+ y = plot.y + 46 + titleGap - 12;
38
40
  } else if (config.position === "left") {
39
41
  x = plot.x - config.offset - thickness;
40
- y = plot.y + 46;
42
+ y = plot.y + 46 + titleGap - 12;
41
43
  } else {
42
44
  x = config.align === "left" ? plot.x
43
45
  : config.align === "right" ? plot.x + plot.width - length
@@ -46,13 +48,13 @@ function resolveGradientLayout(program, config, scale) {
46
48
  ? plot.y - config.offset - thickness - config.labels.offset -
47
49
  config.labels.fontSize
48
50
  : plot.y + plot.height + config.offset +
49
- (config.titleVisible === false ? 0 : config.titleStyle.fontSize + 12);
51
+ (config.titleVisible === false ? 0 : config.titleStyle.fontSize + titleGap);
50
52
  }
51
53
  const title = vertical
52
54
  ? { x, y: plot.y + 20, align: "left" }
53
55
  : {
54
56
  x: x + length / 2,
55
- y: y - 12 - config.titleStyle.fontSize / 2,
57
+ y: y - titleGap - config.titleStyle.fontSize / 2,
56
58
  align: "center"
57
59
  };
58
60
  const values = [...sampleContinuousValues(scale.domain, config.count)];
@@ -172,7 +174,8 @@ export const rematerializeGradientLegend = action(
172
174
  if (stored === undefined) {
173
175
  throw new Error("Gradient legend requires stored configuration.");
174
176
  }
175
- const { scale, encoding, config } = resolveGradientConfig(this, stored);
177
+ const { scale, encoding, config: currentConfig } = resolveGradientConfig(this, stored);
178
+ const config = resolveEffectiveLegendBlockConfig(this, "gradient", currentConfig);
176
179
  const layout = resolveGradientLayout(this, config, scale);
177
180
  const stripCount = 60;
178
181
  const stripSize = layout.length / stripCount;
@@ -202,7 +205,7 @@ export const rematerializeGradientLegend = action(
202
205
  property: "guide.legend.color.title",
203
206
  value: config.title
204
207
  })
205
- ._withLegendConfig("gradient", config)
208
+ ._withLegendConfig("gradient", currentConfig)
206
209
  .editGraphics({
207
210
  target: "colorGradientStrips",
208
211
  property: "length",
@@ -5,6 +5,7 @@ import {
5
5
  removeOpacityLegend
6
6
  } from "./opacity.js";
7
7
  import { createIntervalLegend, rematerializeIntervalLegend } from "./interval.js";
8
+ import { registerStrokeColorLegendActions } from "./stroke.js";
8
9
 
9
10
  export { createGradientLegend, rematerializeGradientLegend } from "./gradient.js";
10
11
  export {
@@ -20,6 +21,7 @@ export function registerContinuousLegendActions(ProgramClass) {
20
21
  ProgramClass.prototype.rematerializeOpacityLegend = rematerializeOpacityLegend;
21
22
  ProgramClass.prototype.removeOpacityLegend = removeOpacityLegend;
22
23
  registerIntervalLegendActions(ProgramClass);
24
+ registerStrokeColorLegendActions(ProgramClass);
23
25
  }
24
26
 
25
27
  export function registerGradientLegendActions(ProgramClass) {
@@ -26,6 +26,7 @@ import {
26
26
  } from "./common.js";
27
27
  import { resolveLegendGraphicPlacement } from
28
28
  "../../../../materialization/graphicHierarchy.js";
29
+ import { resolveEffectiveLegendBlockConfig } from "../blocks.js";
29
30
 
30
31
  const OPTIONS = [
31
32
  "target", "channels", "position", "align", "offset", "title",
@@ -133,12 +134,13 @@ export const rematerializeIntervalLegend = /* @__PURE__ */ action(
133
134
  if (stored === undefined) {
134
135
  throw new Error("Interval legend requires stored configuration.");
135
136
  }
136
- const { encoding, scale, config } = resolveIntervalConfig(this, stored);
137
+ const { encoding, scale, config: currentConfig } = resolveIntervalConfig(this, stored);
138
+ const config = resolveEffectiveLegendBlockConfig(this, "interval", currentConfig);
137
139
  const layout = resolveIntervalLayout(this, config, scale);
138
140
  let next = editGraphicProperties(this
139
141
  .editSemantic({ property: "guide.legend.color.scale", value: encoding.scale })
140
142
  .editSemantic({ property: "guide.legend.color.title", value: config.title })
141
- ._withLegendConfig("interval", config), "colorLegendSymbols", {
143
+ ._withLegendConfig("interval", currentConfig), "colorLegendSymbols", {
142
144
  length: scale.range.length,
143
145
  x: layout.symbolX,
144
146
  y: layout.itemY.map(value => value - config.symbol.height / 2),
@@ -146,7 +148,10 @@ export const rematerializeIntervalLegend = /* @__PURE__ */ action(
146
148
  height: config.symbol.height,
147
149
  fill: scale.range,
148
150
  stroke: config.symbol.stroke,
149
- strokeWidth: config.symbol.strokeWidth
151
+ strokeWidth: config.symbol.strokeWidth,
152
+ ...(config.blockSymbol?.opacity === undefined
153
+ ? {}
154
+ : { opacity: config.blockSymbol.opacity })
150
155
  });
151
156
  next = editGraphicProperties(next, "colorLegendLabels", {
152
157
  length: layout.labels.length,
@@ -14,13 +14,14 @@ import {
14
14
  resolveContinuousLegendLayer,
15
15
  resolveLegendBackgroundFromBounds,
16
16
  resolveLegendTextBounds,
17
- sampleContinuousValues,
18
17
  styleContinuousText,
19
18
  validateNonNegative,
20
19
  validatePositive
21
20
  } from "./common.js";
22
21
  import { resolveLegendGraphicPlacement } from
23
22
  "../../../../materialization/graphicHierarchy.js";
23
+ import { resolveLegendSampleValues } from "../sampling.js";
24
+ import { resolveEffectiveLegendBlockConfig } from "../blocks.js";
24
25
 
25
26
  const SYMBOL_OPTIONS = Object.freeze([
26
27
  "type", "radius", "fill", "stroke", "strokeWidth"
@@ -85,7 +86,7 @@ function resolveOpacityConfig(program, config) {
85
86
  function resolveOpacityLayout(program, config, scale) {
86
87
  const { plot, canvas } = resolveContinuousBounds(program);
87
88
  const vertical = ["right", "left"].includes(config.position);
88
- const values = sampleContinuousValues(scale.domain, config.count);
89
+ const values = resolveLegendSampleValues(config, scale, "Opacity legend");
89
90
  const texts = formatContinuousValues(
90
91
  values,
91
92
  scale.domain,
@@ -166,8 +167,9 @@ function resolveOpacityLayout(program, config, scale) {
166
167
  config.labels.offset - symbolExtent
167
168
  : plot.y + plot.height + config.offset +
168
169
  (config.titleVisible === false ? 0 : config.titleStyle.fontSize + 12) + symbolExtent;
170
+ const samplePitch = values.length === 1 ? 0 : width / (values.length - 1);
169
171
  symbols = values.map((_, index) => ({
170
- x: startX + index * width / (values.length - 1),
172
+ x: startX + index * samplePitch,
171
173
  y
172
174
  }));
173
175
  labels = symbols.map(symbol => ({
@@ -221,7 +223,8 @@ export const rematerializeOpacityLegend = /* @__PURE__ */ action(
221
223
  if (stored === undefined) {
222
224
  throw new Error("Opacity legend requires stored configuration.");
223
225
  }
224
- const { encoding, scale, config } = resolveOpacityConfig(this, stored);
226
+ const { encoding, scale, config: currentConfig } = resolveOpacityConfig(this, stored);
227
+ const config = resolveEffectiveLegendBlockConfig(this, "opacity", currentConfig);
225
228
  const layout = resolveOpacityLayout(this, config, scale);
226
229
  const opacities = mapLinearValues(layout.values, scale.domain, scale.range, {
227
230
  clamp: scale.clamp ?? false
@@ -235,7 +238,7 @@ export const rematerializeOpacityLegend = /* @__PURE__ */ action(
235
238
  property: "guide.legend.opacity.title",
236
239
  value: config.title
237
240
  })
238
- ._withLegendConfig("opacity", config)
241
+ ._withLegendConfig("opacity", currentConfig)
239
242
  .editGraphics({
240
243
  target: "opacityLegendSymbols",
241
244
  property: "length",