ggaction 0.0.15 → 0.0.16

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (236) hide show
  1. package/CHANGELOG.md +68 -0
  2. package/README.md +22 -2
  3. package/knowledge/action-cards.json +1 -1
  4. package/knowledge/intent-taxonomy.json +1 -1
  5. package/knowledge/mcp-resources.json +1 -1
  6. package/knowledge/task-packet.schema.json +1 -1
  7. package/knowledge/task-resolver.js +1 -1
  8. package/package.json +33 -6
  9. package/src/BasicChartProgram.js +3 -1
  10. package/src/ChartProgram.js +2 -0
  11. package/src/accessibility.js +157 -0
  12. package/src/actions/boxPlots/components.js +6 -8
  13. package/src/actions/boxPlots/create.js +4 -5
  14. package/src/actions/boxPlots/edit.js +3 -4
  15. package/src/actions/boxPlots/materialize.js +1 -1
  16. package/src/actions/canvas/actions.js +3 -3
  17. package/src/actions/canvas/fitting.js +1 -1
  18. package/src/actions/categoryOrder/index.js +6 -8
  19. package/src/actions/charts/area.js +1 -1
  20. package/src/actions/charts/bar.js +1 -1
  21. package/src/actions/charts/beeswarm.js +1 -1
  22. package/src/actions/charts/density.js +1 -1
  23. package/src/actions/charts/ecdf.js +2 -2
  24. package/src/actions/charts/endpoints.js +4 -4
  25. package/src/actions/charts/heatmap.js +1 -1
  26. package/src/actions/charts/histogram.js +1 -1
  27. package/src/actions/charts/horizon.js +1 -1
  28. package/src/actions/charts/interval-regression.js +2 -2
  29. package/src/actions/charts/line.js +1 -1
  30. package/src/actions/charts/parallel.js +1 -1
  31. package/src/actions/charts/pie.js +1 -1
  32. package/src/actions/charts/polar.js +2 -2
  33. package/src/actions/charts/radar.js +1 -1
  34. package/src/actions/charts/radial.js +2 -2
  35. package/src/actions/charts/raincloud.js +2 -2
  36. package/src/actions/charts/rug-strip.js +2 -2
  37. package/src/actions/charts/scatter.js +1 -1
  38. package/src/actions/composition/actions.js +20 -24
  39. package/src/actions/coordinates/actions.js +1 -1
  40. package/src/actions/coordinates/edit.js +1 -1
  41. package/src/actions/data/basicBin2d.js +4 -5
  42. package/src/actions/data/bin.js +2 -2
  43. package/src/actions/data/bin2d.js +6 -8
  44. package/src/actions/data/bin2dMaterialize.js +4 -5
  45. package/src/actions/data/box.js +4 -4
  46. package/src/actions/data/complete.js +2 -2
  47. package/src/actions/data/computed.js +2 -2
  48. package/src/actions/data/create.js +5 -12
  49. package/src/actions/data/density.js +3 -3
  50. package/src/actions/data/derived.js +10 -14
  51. package/src/actions/data/ecdf.js +2 -2
  52. package/src/actions/data/edit.js +35 -23
  53. package/src/actions/data/filter.js +14 -20
  54. package/src/actions/data/fold.js +2 -2
  55. package/src/actions/data/gradientProfile.js +2 -2
  56. package/src/actions/data/horizon.js +2 -2
  57. package/src/actions/data/impute.js +2 -2
  58. package/src/actions/data/index.js +55 -54
  59. package/src/actions/data/interval.js +2 -2
  60. package/src/actions/data/intervalEdit.js +26 -18
  61. package/src/actions/data/normalize.js +2 -2
  62. package/src/actions/data/regression.js +5 -6
  63. package/src/actions/data/revise.js +48 -0
  64. package/src/actions/data/revisionBindings.js +13 -33
  65. package/src/actions/data/stack.js +2 -2
  66. package/src/actions/data/summary.js +2 -2
  67. package/src/actions/data/timeUnit.js +2 -2
  68. package/src/actions/data/window.js +2 -2
  69. package/src/actions/encodings/angle.js +1 -1
  70. package/src/actions/encodings/appearance.js +4 -4
  71. package/src/actions/encodings/barWidth.js +1 -1
  72. package/src/actions/encodings/channels.js +2 -2
  73. package/src/actions/encodings/color/index.js +1 -1
  74. package/src/actions/encodings/density.js +2 -2
  75. package/src/actions/encodings/histogram.js +1 -1
  76. package/src/actions/encodings/horizon.js +6 -8
  77. package/src/actions/encodings/offset.js +2 -2
  78. package/src/actions/encodings/parallel.js +4 -5
  79. package/src/actions/encodings/pathOrder.js +6 -11
  80. package/src/actions/encodings/position/index.js +4 -4
  81. package/src/actions/encodings/ranged.js +5 -5
  82. package/src/actions/encodings/remove.js +4 -5
  83. package/src/actions/encodings/ruleAppearance.js +1 -1
  84. package/src/actions/encodings/seriesLayout.js +1 -1
  85. package/src/actions/encodings/stroke.js +1 -1
  86. package/src/actions/encodings/strokeDash.js +2 -2
  87. package/src/actions/encodings/text.js +1 -1
  88. package/src/actions/errorBands/create.js +11 -17
  89. package/src/actions/errorBands/edit.js +13 -131
  90. package/src/actions/errorBars/create.js +8 -13
  91. package/src/actions/errorBars/edit.js +10 -121
  92. package/src/actions/facets/actions.js +30 -16
  93. package/src/actions/facets/derive.js +8 -2
  94. package/src/actions/facets/guides.js +4 -5
  95. package/src/actions/facets/replay.js +4 -5
  96. package/src/actions/gradientPlots/components.js +5 -6
  97. package/src/actions/gradientPlots/create.js +4 -5
  98. package/src/actions/gradientPlots/edit.js +4 -5
  99. package/src/actions/gradientPlots/materialize.js +2 -2
  100. package/src/actions/gradientPlots/rebind.js +4 -5
  101. package/src/actions/guides/axes/axes.js +23 -4
  102. package/src/actions/guides/axes/axis.js +2 -2
  103. package/src/actions/guides/axes/edit.js +2 -2
  104. package/src/actions/guides/axes/labels.js +9 -9
  105. package/src/actions/guides/axes/lines.js +9 -7
  106. package/src/actions/guides/axes/parallel/lifecycle.js +13 -13
  107. package/src/actions/guides/axes/parallel.js +5 -5
  108. package/src/actions/guides/axes/remove.js +4 -4
  109. package/src/actions/guides/axes/tickGroups.js +4 -4
  110. package/src/actions/guides/axes/ticks.js +13 -4
  111. package/src/actions/guides/axes/titles.js +10 -10
  112. package/src/actions/guides/grids/grid.js +18 -29
  113. package/src/actions/guides/guides.js +1 -1
  114. package/src/actions/guides/legends/blocks.js +1 -1
  115. package/src/actions/guides/legends/categorical/actions.js +4 -4
  116. package/src/actions/guides/legends/categorical/components.js +38 -33
  117. package/src/actions/guides/legends/categorical/layout.js +1 -1
  118. package/src/actions/guides/legends/categorical/symbols.js +27 -30
  119. package/src/actions/guides/legends/continuous/common.js +46 -8
  120. package/src/actions/guides/legends/continuous/gradient.js +89 -155
  121. package/src/actions/guides/legends/continuous/interval.js +13 -13
  122. package/src/actions/guides/legends/continuous/opacity.js +30 -79
  123. package/src/actions/guides/legends/continuous/stroke.js +22 -322
  124. package/src/actions/guides/legends/edit.js +1 -1
  125. package/src/actions/guides/legends/focused.js +5 -5
  126. package/src/actions/guides/legends/lane.js +6 -6
  127. package/src/actions/guides/legends/remove.js +4 -5
  128. package/src/actions/guides/legends/size.js +21 -82
  129. package/src/actions/guides/legends/strokeWidth.js +17 -77
  130. package/src/actions/guides/polar/axes/facade.js +4 -4
  131. package/src/actions/guides/polar/axes/labels.js +5 -5
  132. package/src/actions/guides/polar/axes/lines.js +9 -15
  133. package/src/actions/guides/polar/axes/ticks.js +9 -15
  134. package/src/actions/guides/polar/axes/titles.js +5 -5
  135. package/src/actions/guides/polar/grids.js +11 -13
  136. package/src/actions/index.js +2 -0
  137. package/src/actions/intervals/revision.js +126 -0
  138. package/src/actions/marks/arc/actions.js +3 -3
  139. package/src/actions/marks/area/actions.js +4 -4
  140. package/src/actions/marks/bar/create.js +1 -1
  141. package/src/actions/marks/bar/edit.js +1 -1
  142. package/src/actions/marks/bar/materialize.js +12 -38
  143. package/src/actions/marks/line/actions.js +3 -3
  144. package/src/actions/marks/point/create.js +1 -1
  145. package/src/actions/marks/point/edit.js +1 -1
  146. package/src/actions/marks/point/jitter.js +6 -8
  147. package/src/actions/marks/point/materialize.js +16 -24
  148. package/src/actions/marks/point/packing.js +6 -8
  149. package/src/actions/marks/rect/actions.js +3 -3
  150. package/src/actions/marks/references.js +8 -10
  151. package/src/actions/marks/remove.js +5 -49
  152. package/src/actions/marks/rule/actions.js +4 -4
  153. package/src/actions/marks/text/actions.js +5 -5
  154. package/src/actions/marks/text/layout.js +12 -20
  155. package/src/actions/marks/text/removal.js +1 -1
  156. package/src/actions/marks/text/selection.js +4 -5
  157. package/src/actions/marks/tick/actions.js +3 -3
  158. package/src/actions/primitives/createGraphics.js +5 -4
  159. package/src/actions/primitives/editGraphics.js +5 -4
  160. package/src/actions/primitives/graphicProperties.js +6 -0
  161. package/src/actions/primitives/semantic.js +10 -3
  162. package/src/actions/primitives/semanticAction.js +7 -4
  163. package/src/actions/primitives/semanticValidation/dataset.js +2 -4
  164. package/src/actions/regression/components.js +10 -14
  165. package/src/actions/regression/create.js +3 -4
  166. package/src/actions/regression/edit.js +3 -4
  167. package/src/actions/resources/remove.js +12 -11
  168. package/src/actions/scales/create.js +1 -1
  169. package/src/actions/scales/edit.js +1 -1
  170. package/src/actions/scales/materialize.js +1 -1
  171. package/src/actions/scales/offset.js +2 -2
  172. package/src/actions/scales/parallel.js +1 -1
  173. package/src/actions/scales/quantitativeColor.js +4 -5
  174. package/src/actions/selection/actions.js +25 -36
  175. package/src/actions/textMetrics/index.js +56 -0
  176. package/src/actions/theme/actions.js +2 -2
  177. package/src/actions/theme/reconcile.js +65 -121
  178. package/src/actions/titles/actions.js +8 -8
  179. package/src/actions/titles/resolve.js +3 -3
  180. package/src/actions/violinPlots/create.js +1 -1
  181. package/src/actions/violinPlots/edit.js +1 -1
  182. package/src/core/action.js +107 -35
  183. package/src/core/diagnostics.js +16 -0
  184. package/src/core/extensionRegistry.js +27 -0
  185. package/src/core/font.js +18 -0
  186. package/src/core/identifiers.js +5 -4
  187. package/src/core/immutable.js +10 -3
  188. package/src/core/optionRequirements.js +8 -0
  189. package/src/core/programState.js +1 -1
  190. package/src/core/resourceReferences.js +15 -6
  191. package/src/core/textMetricProfile.js +28 -0
  192. package/src/core/textMetrics.js +24 -3
  193. package/src/core/validation.js +22 -10
  194. package/src/diagnostics.js +1 -0
  195. package/src/grammar/impute.js +3 -2
  196. package/src/grammar/scales/types.js +8 -0
  197. package/src/grammar/schemas/graphicBounds.js +11 -11
  198. package/src/layout/labels.js +11 -10
  199. package/src/layout/legend.js +4 -4
  200. package/src/layout/legendItems.js +6 -6
  201. package/src/layout/text.js +10 -9
  202. package/src/layout/title.js +9 -9
  203. package/src/materialization/facetGuides/placement.js +1 -1
  204. package/src/materialization/facetGuides/preparation.js +1 -1
  205. package/src/materialization/facetHeaders.js +11 -10
  206. package/src/materialization/guides/layout.js +3 -3
  207. package/src/materialization/scaleGuideDependencies.js +10 -0
  208. package/src/materialization/selection/items/common.js +1 -1
  209. package/src/materialization/text.js +2 -2
  210. package/src/materialization/typography.js +31 -0
  211. package/src/mcp/cli.js +5 -3
  212. package/src/persistence/codec.js +65 -0
  213. package/src/persistence/validation.js +185 -0
  214. package/src/persistence.js +74 -0
  215. package/src/renderers/canvas/index.js +5 -4
  216. package/src/renderers/nativeBackend.js +10 -0
  217. package/src/renderers/options.js +13 -0
  218. package/src/renderers/pdf.js +25 -54
  219. package/src/renderers/png.js +22 -17
  220. package/src/renderers/svg.js +10 -14
  221. package/src/renderers/text.js +1 -11
  222. package/src/selectors/coordinates.js +3 -1
  223. package/src/selectors/datasets.js +8 -6
  224. package/src/selectors/layers.js +6 -4
  225. package/src/selectors/markOwners.js +46 -0
  226. package/src/selectors/scales.js +6 -4
  227. package/src/theme/defaults.js +2 -1
  228. package/src/version.js +2 -0
  229. package/types/accessibility.d.ts +37 -0
  230. package/types/basic.d.ts +4 -2
  231. package/types/diagnostics.d.ts +15 -0
  232. package/types/index.d.ts +5 -0
  233. package/types/pdf.d.ts +9 -0
  234. package/types/persistence.d.ts +7 -0
  235. package/types/png.d.ts +9 -0
  236. package/types/program.d.ts +34 -1
@@ -1,10 +1,7 @@
1
- import { action } from "../../../core/action.js";
1
+ import { editGraphicProperties } from "../../primitives/graphicProperties.js";
2
+ import { action, closedAction } from "../../../core/action.js";
2
3
  import { isPlainObject } from "../../../core/immutable.js";
3
- import {
4
- noOptions,
5
- validateKeys,
6
- validateOptionObject
7
- } from "../../../core/validation.js";
4
+ import { noOptions, validateOptionObject } from "../../../core/validation.js";
8
5
  import {
9
6
  gridNames,
10
7
  editGridConfig,
@@ -75,17 +72,10 @@ function makeRematerialize(direction) {
75
72
  value: geometry[property]
76
73
  });
77
74
  }
78
- return next
79
- .editGraphics({
80
- target: operation.graphic,
81
- property: "stroke",
82
- value: config.color
83
- })
84
- .editGraphics({
85
- target: operation.graphic,
86
- property: "strokeWidth",
87
- value: config.lineWidth
88
- })
75
+ return editGraphicProperties(next, operation.graphic, {
76
+ stroke: config.color,
77
+ strokeWidth: config.lineWidth
78
+ })
89
79
  .editGraphics({
90
80
  target: operation.graphic,
91
81
  property: "strokeDash",
@@ -176,14 +166,14 @@ function normalizeDirection(value, direction) {
176
166
  return value;
177
167
  }
178
168
 
179
- const rematerializeHorizontalGrid = makeRematerialize("horizontal");
180
- const rematerializeVerticalGrid = makeRematerialize("vertical");
181
- const createHorizontalGrid = makeCreate("horizontal");
182
- const createVerticalGrid = makeCreate("vertical");
183
- const editHorizontalGrid = makeEdit("horizontal");
184
- const editVerticalGrid = makeEdit("vertical");
169
+ const rematerializeHorizontalGrid = /* @__PURE__ */ makeRematerialize("horizontal");
170
+ const rematerializeVerticalGrid = /* @__PURE__ */ makeRematerialize("vertical");
171
+ const createHorizontalGrid = /* @__PURE__ */ makeCreate("horizontal");
172
+ const createVerticalGrid = /* @__PURE__ */ makeCreate("vertical");
173
+ const editHorizontalGrid = /* @__PURE__ */ makeEdit("horizontal");
174
+ const editVerticalGrid = /* @__PURE__ */ makeEdit("vertical");
185
175
 
186
- const editGrid = action(
176
+ const editGrid = /* @__PURE__ */ action(
187
177
  {
188
178
  op: "editGrid",
189
179
  description: "Edit selected existing Cartesian grid directions."
@@ -253,7 +243,7 @@ export function resolveGridOptions(program, args = {}, layers = program.semantic
253
243
  return { horizontal, vertical, theta, radial };
254
244
  }
255
245
 
256
- const createGrid = action(
246
+ const createGrid = /* @__PURE__ */ action(
257
247
  {
258
248
  op: "createGrid",
259
249
  description: "Create selected Cartesian grid directions."
@@ -273,7 +263,7 @@ const createGrid = action(
273
263
  }
274
264
  );
275
265
 
276
- const rematerializeGrid = action(
266
+ const rematerializeGrid = /* @__PURE__ */ action(
277
267
  {
278
268
  op: "rematerializeGrid",
279
269
  description: "Recompute every existing grid direction."
@@ -305,13 +295,12 @@ const rematerializeGrid = action(
305
295
  }
306
296
  );
307
297
 
308
- const removeGrid = action(
298
+ const removeGrid = /* @__PURE__ */ closedAction(
309
299
  {
310
300
  op: "removeGrid",
311
301
  description: "Remove selected Cartesian grid directions."
312
- },
302
+ }, AGGREGATE_OPTIONS,
313
303
  function (args = {}) {
314
- validateOptionObject(args, AGGREGATE_OPTIONS, "removeGrid");
315
304
  for (const direction of AGGREGATE_OPTIONS) {
316
305
  if (
317
306
  Object.hasOwn(args, direction) &&
@@ -123,7 +123,7 @@ export function resolveGuideOptions(program, args = {}, layers = program.semanti
123
123
  return { axes, grid, legend };
124
124
  }
125
125
 
126
- const createGuides = action(
126
+ const createGuides = /* @__PURE__ */ action(
127
127
  {
128
128
  op: "createGuides",
129
129
  description: "Create applicable axes, grid, and legend."
@@ -353,7 +353,7 @@ function normalizeBlockPatch(args, descriptor) {
353
353
  return patch;
354
354
  }
355
355
 
356
- export const editLegendBlock = action(
356
+ export const editLegendBlock = /* @__PURE__ */ action(
357
357
  {
358
358
  op: "editLegendBlock",
359
359
  description: "Edit one logical legend block selected by channel."
@@ -50,7 +50,7 @@ function resolveStandaloneLegendStep(args, kind) {
50
50
  return { op: kind === "size" ? "createSizeLegend" : "createStrokeWidthLegend", args: options };
51
51
  }
52
52
 
53
- export const rematerializeLegend = action(
53
+ export const rematerializeLegend = /* @__PURE__ */ action(
54
54
  { op: "rematerializeLegend", description: "Rematerialize every existing legend component." },
55
55
  withGuideLayoutValidation(function (args = {}) {
56
56
  noOptions(args, "rematerializeLegend");
@@ -213,7 +213,7 @@ export function resolveCategoricalLegendConfig(program, args = {}) {
213
213
  return config;
214
214
  }
215
215
 
216
- export const createCategoricalLegend = action(
216
+ export const createCategoricalLegend = /* @__PURE__ */ action(
217
217
  { op: "createCategoricalLegend", description: "Create one categorical legend block." },
218
218
  withGuideLayoutValidation(function (args = {}) {
219
219
  const config = resolveCategoricalLegendConfig(this, args);
@@ -403,14 +403,14 @@ export function applyLegendCreationPlan(program, plan) {
403
403
  : plan.finish === "auto" ? finishLegend(next) : next;
404
404
  }
405
405
 
406
- export const createLegend = action(
406
+ export const createLegend = /* @__PURE__ */ action(
407
407
  { op: "createLegend", description: "Create an inferred legend for selected channels." },
408
408
  withGuideLayoutValidation(function (args = {}) {
409
409
  return applyLegendCreationPlan(this, resolveLegendCreationPlan(this, args));
410
410
  })
411
411
  );
412
412
 
413
- export const removeCategoricalLegend = action(
413
+ export const removeCategoricalLegend = /* @__PURE__ */ action(
414
414
  {
415
415
  op: "removeCategoricalLegend",
416
416
  description: "Remove the active categorical legend and its concrete components."
@@ -1,3 +1,4 @@
1
+ import { editGraphicProperties } from "../../../primitives/graphicProperties.js";
1
2
  import { action } from "../../../../core/action.js";
2
3
  import {
3
4
  activeConfig,
@@ -8,7 +9,7 @@ import {
8
9
  } from "./layout.js";
9
10
  import { resolveCategoricalLegendPlacement } from "../lifecycle.js";
10
11
 
11
- export const rematerializeLegendLabels = action(
12
+ export const rematerializeLegendLabels = /* @__PURE__ */ action(
12
13
  { op: "rematerializeLegendLabels", description: "Rematerialize categorical legend labels." },
13
14
  function (args = {}) {
14
15
  noOptions(args, "rematerializeLegendLabels");
@@ -18,25 +19,27 @@ export const rematerializeLegendLabels = action(
18
19
  throw new Error("rematerializeLegendLabels requires existing legend labels.");
19
20
  }
20
21
  const layout = resolveLayout(this, config);
21
- return this
22
- .editGraphics({ target: id, property: "length", value: config.domain.length })
23
- .editGraphics({ target: id, property: "x", value: layout.labelX })
24
- .editGraphics({ target: id, property: "y", value: layout.itemY })
22
+ return editGraphicProperties(editGraphicProperties(this, id, {
23
+ length: config.domain.length,
24
+ x: layout.labelX,
25
+ y: layout.itemY
26
+ })
25
27
  .editGraphics({
26
28
  target: id,
27
29
  property: "text",
28
30
  value: categoricalLegendLabels(config)
29
- })
30
- .editGraphics({ target: id, property: "fill", value: config.labels.color })
31
- .editGraphics({ target: id, property: "fontSize", value: config.labels.fontSize })
32
- .editGraphics({ target: id, property: "fontFamily", value: config.labels.fontFamily })
33
- .editGraphics({ target: id, property: "fontWeight", value: config.labels.fontWeight })
34
- .editGraphics({ target: id, property: "textAlign", value: "left" })
35
- .editGraphics({ target: id, property: "textBaseline", value: "middle" });
31
+ }), id, {
32
+ fill: config.labels.color,
33
+ fontSize: config.labels.fontSize,
34
+ fontFamily: config.labels.fontFamily,
35
+ fontWeight: config.labels.fontWeight,
36
+ textAlign: "left",
37
+ textBaseline: "middle"
38
+ });
36
39
  }
37
40
  );
38
41
 
39
- export const createLegendLabels = action(
42
+ export const createLegendLabels = /* @__PURE__ */ action(
40
43
  { op: "createLegendLabels", description: "Create categorical legend labels." },
41
44
  function (args = {}) {
42
45
  noOptions(args, "createLegendLabels");
@@ -56,7 +59,7 @@ export const createLegendLabels = action(
56
59
  }
57
60
  );
58
61
 
59
- export const rematerializeLegendTitle = action(
62
+ export const rematerializeLegendTitle = /* @__PURE__ */ action(
60
63
  { op: "rematerializeLegendTitle", description: "Rematerialize the categorical legend title." },
61
64
  function (args = {}) {
62
65
  noOptions(args, "rematerializeLegendTitle");
@@ -66,14 +69,15 @@ export const rematerializeLegendTitle = action(
66
69
  throw new Error("rematerializeLegendTitle requires an existing legend title.");
67
70
  }
68
71
  const layout = resolveLayout(this, config);
69
- return this
70
- .editGraphics({ target: id, property: "x", value: layout.titleX })
71
- .editGraphics({ target: id, property: "y", value: layout.titleY })
72
- .editGraphics({ target: id, property: "text", value: config.title })
73
- .editGraphics({ target: id, property: "fill", value: config.titleStyle.color })
74
- .editGraphics({ target: id, property: "fontSize", value: config.titleStyle.fontSize })
75
- .editGraphics({ target: id, property: "fontFamily", value: config.titleStyle.fontFamily })
76
- .editGraphics({ target: id, property: "fontWeight", value: config.titleStyle.fontWeight })
72
+ return editGraphicProperties(this, id, {
73
+ x: layout.titleX,
74
+ y: layout.titleY,
75
+ text: config.title,
76
+ fill: config.titleStyle.color,
77
+ fontSize: config.titleStyle.fontSize,
78
+ fontFamily: config.titleStyle.fontFamily,
79
+ fontWeight: config.titleStyle.fontWeight
80
+ })
77
81
  .editGraphics({
78
82
  target: id,
79
83
  property: "textAlign",
@@ -86,7 +90,7 @@ export const rematerializeLegendTitle = action(
86
90
  }
87
91
  );
88
92
 
89
- export const createLegendTitle = action(
93
+ export const createLegendTitle = /* @__PURE__ */ action(
90
94
  { op: "createLegendTitle", description: "Create the categorical legend title." },
91
95
  function (args = {}) {
92
96
  noOptions(args, "createLegendTitle");
@@ -105,7 +109,7 @@ export const createLegendTitle = action(
105
109
  }
106
110
  );
107
111
 
108
- export const rematerializeLegendBackground = action(
112
+ export const rematerializeLegendBackground = /* @__PURE__ */ action(
109
113
  { op: "rematerializeLegendBackground", description: "Rematerialize the legend background." },
110
114
  function (args = {}) {
111
115
  noOptions(args, "rematerializeLegendBackground");
@@ -118,18 +122,19 @@ export const rematerializeLegendBackground = action(
118
122
  throw new Error("rematerializeLegendBackground requires an existing background.");
119
123
  }
120
124
  const layout = resolveLayout(this, config).background;
121
- return this
122
- .editGraphics({ target: id, property: "x", value: layout.x })
123
- .editGraphics({ target: id, property: "y", value: layout.y })
124
- .editGraphics({ target: id, property: "width", value: layout.width })
125
- .editGraphics({ target: id, property: "height", value: layout.height })
126
- .editGraphics({ target: id, property: "fill", value: config.border.background })
127
- .editGraphics({ target: id, property: "stroke", value: config.border.color })
128
- .editGraphics({ target: id, property: "strokeWidth", value: config.border.lineWidth });
125
+ return editGraphicProperties(this, id, {
126
+ x: layout.x,
127
+ y: layout.y,
128
+ width: layout.width,
129
+ height: layout.height,
130
+ fill: config.border.background,
131
+ stroke: config.border.color,
132
+ strokeWidth: config.border.lineWidth
133
+ });
129
134
  }
130
135
  );
131
136
 
132
- export const createLegendBackground = action(
137
+ export const createLegendBackground = /* @__PURE__ */ action(
133
138
  { op: "createLegendBackground", description: "Create the legend background rect." },
134
139
  function (args = {}) {
135
140
  noOptions(args, "createLegendBackground");
@@ -152,7 +152,7 @@ export function resolveLayout(program, config) {
152
152
  const width = symbolWidth(config);
153
153
  const layout = resolveLegendItemLayout(plot, config, categoricalLegendLabels(config), {
154
154
  width, height: 0, itemBounds: resolveSampleBounds(program, config, width)
155
- }, canvas);
155
+ }, canvas, program.materializationConfigs.textMetrics);
156
156
  assertLegendBoundsInsideCanvas(layout.bounds, canvas, "Categorical legend layout", config);
157
157
  const background = resolveLegendBackgroundFromBounds(layout.bounds, config.border, canvas,
158
158
  "Categorical legend", config);
@@ -1,3 +1,4 @@
1
+ import { editGraphicProperties } from "../../../primitives/graphicProperties.js";
1
2
  import { action } from "../../../../core/action.js";
2
3
  import {
3
4
  activeConfig,
@@ -58,24 +59,23 @@ function makeEditSymbol(type) {
58
59
  const x1 = layout.symbolX.map(
59
60
  value => value + (symbolWidth(config) - layer.length) / 2
60
61
  );
61
- next = next
62
- .editGraphics({ target: id, property: "x1", value: x1 })
63
- .editGraphics({ target: id, property: "y1", value: layout.itemY })
64
- .editGraphics({
65
- target: id,
66
- property: "x2",
67
- value: x1.map(value => value + layer.length)
68
- })
69
- .editGraphics({ target: id, property: "y2", value: layout.itemY })
62
+ next = editGraphicProperties(editGraphicProperties(editGraphicProperties(next, id, {
63
+ x1: x1,
64
+ y1: layout.itemY
65
+ }), id, {
66
+ x2: x1.map(value => value + layer.length),
67
+ y2: layout.itemY
68
+ })
70
69
  .editGraphics({
71
70
  target: id,
72
71
  property: "stroke",
73
72
  value: layer.stroke ?? (config.channels.includes("stroke")
74
73
  ? appearance.strokes
75
74
  : appearance.colors)
76
- })
77
- .editGraphics({ target: id, property: "strokeWidth", value: layer.lineWidth })
78
- .editGraphics({ target: id, property: "strokeDash", value: appearance.dashes });
75
+ }), id, {
76
+ strokeWidth: layer.lineWidth,
77
+ strokeDash: appearance.dashes
78
+ });
79
79
  for (const [property, value] of Object.entries(
80
80
  requestedStrokeDetails(layer, "Legend line symbol")
81
81
  )) {
@@ -108,15 +108,12 @@ function makeEditSymbol(type) {
108
108
  value: items
109
109
  });
110
110
  }
111
- next = next
112
- .editGraphics({ target: id, property: "x", value: x })
113
- .editGraphics({ target: id, property: "y", value: layout.itemY })
114
- .editGraphics({ target: id, property: "radius", value: layer.size })
115
- .editGraphics({
116
- target: id,
117
- property: "fill",
118
- value: layer.fill ?? appearance.colors
119
- })
111
+ next = editGraphicProperties(next, id, {
112
+ x: x,
113
+ y: layout.itemY,
114
+ radius: layer.size,
115
+ fill: layer.fill ?? appearance.colors
116
+ })
120
117
  .editGraphics({
121
118
  target: id,
122
119
  property: "stroke",
@@ -196,23 +193,23 @@ function makeCreateSymbol(type, edit) {
196
193
  );
197
194
  }
198
195
 
199
- export const rematerializeLegendSymbolLines = makeEditSymbol("line");
200
- export const rematerializeLegendSymbolPoints = makeEditSymbol("point");
201
- export const rematerializeLegendSymbolSwatches = makeEditSymbol("swatch");
202
- export const createLegendSymbolLines = makeCreateSymbol(
196
+ export const rematerializeLegendSymbolLines = /* @__PURE__ */ makeEditSymbol("line");
197
+ export const rematerializeLegendSymbolPoints = /* @__PURE__ */ makeEditSymbol("point");
198
+ export const rematerializeLegendSymbolSwatches = /* @__PURE__ */ makeEditSymbol("swatch");
199
+ export const createLegendSymbolLines = /* @__PURE__ */ makeCreateSymbol(
203
200
  "line",
204
201
  "rematerializeLegendSymbolLines"
205
202
  );
206
- export const createLegendSymbolPoints = makeCreateSymbol(
203
+ export const createLegendSymbolPoints = /* @__PURE__ */ makeCreateSymbol(
207
204
  "point",
208
205
  "rematerializeLegendSymbolPoints"
209
206
  );
210
- export const createLegendSymbolSwatches = makeCreateSymbol(
207
+ export const createLegendSymbolSwatches = /* @__PURE__ */ makeCreateSymbol(
211
208
  "swatch",
212
209
  "rematerializeLegendSymbolSwatches"
213
210
  );
214
211
 
215
- export const createLegendSymbols = action(
212
+ export const createLegendSymbols = /* @__PURE__ */ action(
216
213
  { op: "createLegendSymbols", description: "Create layered legend symbols." },
217
214
  function (args = {}) {
218
215
  noOptions(args, "createLegendSymbols");
@@ -230,7 +227,7 @@ export const createLegendSymbols = action(
230
227
  }
231
228
  );
232
229
 
233
- export const rematerializeLegendSymbols = action(
230
+ export const rematerializeLegendSymbols = /* @__PURE__ */ action(
234
231
  { op: "rematerializeLegendSymbols", description: "Rematerialize layered legend symbols." },
235
232
  function (args = {}) {
236
233
  noOptions(args, "rematerializeLegendSymbols");
@@ -248,7 +245,7 @@ export const rematerializeLegendSymbols = action(
248
245
  }
249
246
  );
250
247
 
251
- export const rematerializeBasicLegendHighlights = action(
248
+ export const rematerializeBasicLegendHighlights = /* @__PURE__ */ action(
252
249
  {
253
250
  op: "rematerializeLegendHighlights",
254
251
  description: "Reflect exact categorical mark highlights in legend symbols."
@@ -26,6 +26,7 @@ import { isOpacityLegendLayer } from "../../../../materialization/legends.js";
26
26
  import { findCanvasGraphic } from
27
27
  "../../../../materialization/graphicHierarchy.js";
28
28
  import { normalizeLegendSampling } from "../sampling.js";
29
+ import { editGraphicProperties } from "../../../primitives/graphicProperties.js";
29
30
 
30
31
  const OPTIONS = [
31
32
  "target", "channels", "position", "align", "offset", "title", "count",
@@ -63,12 +64,7 @@ const DEFAULT_BORDER = {
63
64
  export const validatePositive = validatePositiveFinite;
64
65
  export const validateNonNegative = validateNonNegativeFinite;
65
66
 
66
- export function editGraphicProperties(program, target, properties) {
67
- for (const [property, value] of Object.entries(properties)) {
68
- program = program.editGraphics({ target, property, value });
69
- }
70
- return program;
71
- }
67
+ export { editGraphicProperties };
72
68
 
73
69
  export function normalizeLegendTextOptions(value, label, defaults) {
74
70
  if (value === undefined) return { ...defaults };
@@ -318,7 +314,7 @@ export function styleContinuousText(
318
314
  });
319
315
  }
320
316
 
321
- export function resolveLegendTextBounds(position, text, style) {
317
+ export function resolveLegendTextBounds(position, text, style, profile) {
322
318
  return resolveTextBounds({
323
319
  x: position.x,
324
320
  y: position.y,
@@ -326,7 +322,7 @@ export function resolveLegendTextBounds(position, text, style) {
326
322
  ...style,
327
323
  textAlign: position.align ?? "left",
328
324
  textBaseline: "middle"
329
- });
325
+ }, profile);
330
326
  }
331
327
 
332
328
  export function assertLegendBoundsInsideCanvas(bounds, canvas, label, config) {
@@ -407,3 +403,45 @@ export function normalizeItemLegendLayout(args) {
407
403
  validatePositive(itemGap, "Legend itemGap");
408
404
  return { position, layout, align, direction, columns, titlePosition, offset, itemGap };
409
405
  }
406
+
407
+ export function materializeItemLegend(program, kind, config, layout, {
408
+ symbols, optional = {}, text = layout.labels,
409
+ labels = layout.config.labels, titleStyle = layout.config.titleStyle
410
+ }) {
411
+ const prefix = `${kind}Legend`;
412
+ let next = program
413
+ .editSemantic({ property: `guide.legend.${kind}.scale`, value: config.scale })
414
+ .editSemantic({ property: `guide.legend.${kind}.title`, value: config.title })
415
+ ._withLegendConfig(kind, config);
416
+ next = editGraphicProperties(next, `${prefix}Symbols`, {
417
+ length: text.length,
418
+ ...symbols
419
+ });
420
+ next = editGraphicProperties(next, `${prefix}Labels`, {
421
+ length: text.length, x: layout.labelX, y: layout.itemY, text
422
+ });
423
+ next = editLegendBackground(next, `${prefix}Background`, layout.background, config.border);
424
+ next = editGraphicProperties(next, `${prefix}Symbols`, Object.fromEntries(
425
+ Object.entries(optional).filter(([, value]) => value !== undefined)
426
+ ));
427
+ next = styleContinuousText(next, `${prefix}Labels`, labels);
428
+ const effective = layout.config;
429
+ if (effective.titleVisible === false) return next;
430
+ next = editGraphicProperties(next, `${prefix}Title`, {
431
+ x: layout.title.x, y: layout.title.y, text: effective.title
432
+ });
433
+ return styleContinuousText(next, `${prefix}Title`, titleStyle, { align: layout.title.align });
434
+ }
435
+
436
+ export function createItemLegendGraphics(program, kind, config, count, type, placement) {
437
+ const prefix = `${kind}Legend`;
438
+ let next = program
439
+ .editSemantic({ property: `guide.legend.${kind}.scale`, value: config.scale })
440
+ .editSemantic({ property: `guide.legend.${kind}.title`, value: config.title })
441
+ ._withLegendConfig(kind, config);
442
+ if (config.border !== false) next = next.createGraphics({ id: `${prefix}Background`, type: "rect", ...placement });
443
+ next = next.createGraphics({ id: `${prefix}Symbols`, type, length: count, ...placement })
444
+ .createGraphics({ id: `${prefix}Labels`, type: "text", length: count, ...placement });
445
+ if (config.titleVisible !== false) next = next.createGraphics({ id: `${prefix}Title`, type: "text", ...placement });
446
+ return next;
447
+ }