ggaction 0.0.13 → 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 (359) hide show
  1. package/CHANGELOG.md +146 -0
  2. package/README.md +41 -12
  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 +39 -7
  9. package/src/BasicChartProgram.js +3 -1
  10. package/src/ChartProgram.js +2 -0
  11. package/src/accessibility.js +157 -0
  12. package/src/actions/basic.js +2 -2
  13. package/src/actions/boxPlots/components.js +20 -12
  14. package/src/actions/boxPlots/create.js +4 -5
  15. package/src/actions/boxPlots/edit.js +34 -9
  16. package/src/actions/boxPlots/materialize.js +12 -4
  17. package/src/actions/boxPlots/options.js +48 -16
  18. package/src/actions/canvas/actions.js +3 -3
  19. package/src/actions/canvas/fitting.js +1 -1
  20. package/src/actions/categoryOrder/index.js +21 -12
  21. package/src/actions/charts/area.js +6 -2
  22. package/src/actions/charts/bar.js +3 -2
  23. package/src/actions/charts/beeswarm.js +1 -1
  24. package/src/actions/charts/density.js +7 -3
  25. package/src/actions/charts/ecdf.js +6 -3
  26. package/src/actions/charts/endpoints.js +29 -7
  27. package/src/actions/charts/heatmap.js +3 -2
  28. package/src/actions/charts/histogram.js +5 -4
  29. package/src/actions/charts/horizon.js +4 -2
  30. package/src/actions/charts/interval-regression.js +7 -4
  31. package/src/actions/charts/line.js +4 -2
  32. package/src/actions/charts/parallel.js +9 -3
  33. package/src/actions/charts/pie.js +11 -3
  34. package/src/actions/charts/polar.js +17 -6
  35. package/src/actions/charts/radar.js +9 -3
  36. package/src/actions/charts/radial.js +12 -4
  37. package/src/actions/charts/raincloud.js +2 -2
  38. package/src/actions/charts/rug-strip.js +8 -4
  39. package/src/actions/charts/scatter.js +4 -2
  40. package/src/actions/composition/actions.js +29 -24
  41. package/src/actions/coordinates/actions.js +2 -2
  42. package/src/actions/coordinates/edit.js +76 -0
  43. package/src/actions/data/basicBin2d.js +4 -5
  44. package/src/actions/data/bin.js +3 -3
  45. package/src/actions/data/bin2d.js +63 -193
  46. package/src/actions/data/bin2dMaterialize.js +4 -5
  47. package/src/actions/data/box.js +4 -4
  48. package/src/actions/data/complete.js +26 -0
  49. package/src/actions/data/computed.js +4 -4
  50. package/src/actions/data/create.js +7 -14
  51. package/src/actions/data/density.js +15 -23
  52. package/src/actions/data/derived.js +57 -31
  53. package/src/actions/data/ecdf.js +2 -2
  54. package/src/actions/data/edit.js +551 -0
  55. package/src/actions/data/filter.js +28 -22
  56. package/src/actions/data/fold.js +2 -2
  57. package/src/actions/data/gradientProfile.js +2 -2
  58. package/src/actions/data/horizon.js +2 -2
  59. package/src/actions/data/impute.js +26 -0
  60. package/src/actions/data/index.js +62 -47
  61. package/src/actions/data/interval.js +2 -2
  62. package/src/actions/data/intervalEdit.js +26 -18
  63. package/src/actions/data/normalize.js +27 -0
  64. package/src/actions/data/regression.js +21 -27
  65. package/src/actions/data/revise.js +48 -0
  66. package/src/actions/data/revisionBindings.js +125 -0
  67. package/src/actions/data/shared.js +20 -4
  68. package/src/actions/data/stack.js +2 -2
  69. package/src/actions/data/summary.js +3 -3
  70. package/src/actions/data/timeUnit.js +6 -3
  71. package/src/actions/data/window.js +3 -3
  72. package/src/actions/encodings/angle.js +1 -1
  73. package/src/actions/encodings/appearance.js +4 -4
  74. package/src/actions/encodings/barWidth.js +1 -1
  75. package/src/actions/encodings/channels.js +415 -0
  76. package/src/actions/encodings/color/index.js +3 -2
  77. package/src/actions/encodings/density.js +7 -4
  78. package/src/actions/encodings/histogram.js +4 -3
  79. package/src/actions/encodings/horizon.js +6 -8
  80. package/src/actions/encodings/index.js +4 -0
  81. package/src/actions/encodings/offset.js +22 -15
  82. package/src/actions/encodings/parallel.js +4 -5
  83. package/src/actions/encodings/pathOrder.js +6 -11
  84. package/src/actions/encodings/position/apply.js +53 -7
  85. package/src/actions/encodings/position/index.js +14 -6
  86. package/src/actions/encodings/position/policies/bar.js +9 -0
  87. package/src/actions/encodings/position/resolve.js +24 -7
  88. package/src/actions/encodings/ranged.js +5 -5
  89. package/src/actions/encodings/remove.js +13 -9
  90. package/src/actions/encodings/ruleAppearance.js +2 -24
  91. package/src/actions/encodings/seriesLayout.js +2 -1
  92. package/src/actions/encodings/shared.js +82 -14
  93. package/src/actions/encodings/stroke.js +226 -0
  94. package/src/actions/encodings/strokeDash.js +2 -2
  95. package/src/actions/encodings/text.js +1 -1
  96. package/src/actions/errorBands/create.js +34 -20
  97. package/src/actions/errorBands/edit.js +34 -137
  98. package/src/actions/errorBars/create.js +43 -20
  99. package/src/actions/errorBars/edit.js +29 -125
  100. package/src/actions/facets/actions.js +267 -73
  101. package/src/actions/facets/derive.js +99 -28
  102. package/src/actions/facets/guides.js +4 -5
  103. package/src/actions/facets/replay.js +4 -5
  104. package/src/actions/gradientPlots/components.js +15 -8
  105. package/src/actions/gradientPlots/create.js +4 -5
  106. package/src/actions/gradientPlots/edit.js +18 -9
  107. package/src/actions/gradientPlots/materialize.js +5 -3
  108. package/src/actions/gradientPlots/options.js +10 -2
  109. package/src/actions/gradientPlots/rebind.js +4 -5
  110. package/src/actions/guides/applicability.js +8 -2
  111. package/src/actions/guides/axes/axes.js +23 -4
  112. package/src/actions/guides/axes/axis.js +2 -2
  113. package/src/actions/guides/axes/edit.js +2 -2
  114. package/src/actions/guides/axes/labels.js +67 -21
  115. package/src/actions/guides/axes/lines.js +15 -9
  116. package/src/actions/guides/axes/parallel/lifecycle.js +13 -13
  117. package/src/actions/guides/axes/parallel/resolve.js +6 -2
  118. package/src/actions/guides/axes/parallel.js +5 -5
  119. package/src/actions/guides/axes/remove.js +4 -4
  120. package/src/actions/guides/axes/tickGroups.js +6 -5
  121. package/src/actions/guides/axes/ticks.js +19 -6
  122. package/src/actions/guides/axes/titles.js +21 -13
  123. package/src/actions/guides/grids/grid.js +18 -29
  124. package/src/actions/guides/grids/resolve.js +7 -2
  125. package/src/actions/guides/guides.js +20 -4
  126. package/src/actions/guides/legends/blocks.js +426 -0
  127. package/src/actions/guides/legends/categorical/actions.js +138 -52
  128. package/src/actions/guides/legends/categorical/components.js +55 -45
  129. package/src/actions/guides/legends/categorical/index.js +37 -33
  130. package/src/actions/guides/legends/categorical/layout.js +98 -16
  131. package/src/actions/guides/legends/categorical/options.js +2 -2
  132. package/src/actions/guides/legends/categorical/recipes.js +111 -20
  133. package/src/actions/guides/legends/categorical/resolve.js +12 -8
  134. package/src/actions/guides/legends/categorical/symbols.js +104 -52
  135. package/src/actions/guides/legends/continuous/common.js +76 -20
  136. package/src/actions/guides/legends/continuous/gradient.js +95 -158
  137. package/src/actions/guides/legends/continuous/index.js +2 -0
  138. package/src/actions/guides/legends/continuous/interval.js +21 -16
  139. package/src/actions/guides/legends/continuous/opacity.js +37 -83
  140. package/src/actions/guides/legends/continuous/stroke.js +225 -0
  141. package/src/actions/guides/legends/creation.js +14 -1
  142. package/src/actions/guides/legends/edit.js +159 -60
  143. package/src/actions/guides/legends/focused.js +5 -5
  144. package/src/actions/guides/legends/index.js +2 -0
  145. package/src/actions/guides/legends/lane.js +59 -24
  146. package/src/actions/guides/legends/lifecycle.js +19 -8
  147. package/src/actions/guides/legends/remove.js +17 -8
  148. package/src/actions/guides/legends/sampling.js +140 -0
  149. package/src/actions/guides/legends/size.js +100 -108
  150. package/src/actions/guides/legends/strokeWidth.js +38 -92
  151. package/src/actions/guides/legends/target.js +112 -1
  152. package/src/actions/guides/legends/transition.js +165 -16
  153. package/src/actions/guides/polar/axes/facade.js +8 -8
  154. package/src/actions/guides/polar/axes/labels.js +29 -10
  155. package/src/actions/guides/polar/axes/lines.js +19 -19
  156. package/src/actions/guides/polar/axes/shared.js +16 -0
  157. package/src/actions/guides/polar/axes/ticks.js +10 -16
  158. package/src/actions/guides/polar/axes/titles.js +6 -6
  159. package/src/actions/guides/polar/grids.js +12 -14
  160. package/src/actions/guides/polar/resolve.js +12 -8
  161. package/src/actions/index.js +16 -3
  162. package/src/actions/intervals/revision.js +126 -0
  163. package/src/actions/marks/arc/actions.js +80 -22
  164. package/src/actions/marks/area/actions.js +38 -13
  165. package/src/actions/marks/area/materialize.js +17 -1
  166. package/src/actions/marks/bar/create.js +12 -3
  167. package/src/actions/marks/bar/edit.js +21 -4
  168. package/src/actions/marks/bar/materialize.js +34 -40
  169. package/src/actions/marks/index.js +10 -1
  170. package/src/actions/marks/line/actions.js +40 -17
  171. package/src/actions/marks/line/materialize.js +29 -10
  172. package/src/actions/marks/point/create.js +9 -3
  173. package/src/actions/marks/point/edit.js +19 -7
  174. package/src/actions/marks/point/jitter.js +6 -8
  175. package/src/actions/marks/point/materialize.js +48 -22
  176. package/src/actions/marks/point/packing.js +6 -8
  177. package/src/actions/marks/rect/actions.js +36 -15
  178. package/src/actions/marks/references.js +602 -33
  179. package/src/actions/marks/remove.js +67 -41
  180. package/src/actions/marks/rule/actions.js +51 -14
  181. package/src/actions/marks/shared.js +1 -1
  182. package/src/actions/marks/text/actions.js +79 -14
  183. package/src/actions/marks/text/index.js +4 -0
  184. package/src/actions/marks/text/layout.js +157 -17
  185. package/src/actions/marks/text/removal.js +173 -0
  186. package/src/actions/marks/text/selection.js +72 -0
  187. package/src/actions/marks/tick/actions.js +25 -8
  188. package/src/actions/primitives/createGraphics.js +5 -4
  189. package/src/actions/primitives/editGraphics.js +31 -4
  190. package/src/actions/primitives/graphicProperties.js +6 -0
  191. package/src/actions/primitives/semantic.js +11 -3
  192. package/src/actions/primitives/semanticAction.js +90 -14
  193. package/src/actions/primitives/semanticValidation/dataset.js +2 -4
  194. package/src/actions/primitives/semanticValidation/guide.js +1 -1
  195. package/src/actions/primitives/semanticValidation/index.js +9 -1
  196. package/src/actions/primitives/semanticValidation/layer.js +5 -0
  197. package/src/actions/primitives/semanticValidation/scale.js +28 -7
  198. package/src/actions/regression/components.js +36 -25
  199. package/src/actions/regression/create.js +13 -6
  200. package/src/actions/regression/edit.js +24 -11
  201. package/src/actions/resources/index.js +7 -0
  202. package/src/actions/resources/remove.js +173 -0
  203. package/src/actions/scales/channels.js +212 -0
  204. package/src/actions/scales/consumers/common.js +1 -1
  205. package/src/actions/scales/consumers/families.js +3 -2
  206. package/src/actions/scales/consumers/index.js +19 -2
  207. package/src/actions/scales/consumers/seriesLayout.js +28 -14
  208. package/src/actions/scales/create.js +55 -23
  209. package/src/actions/scales/definitions.js +94 -40
  210. package/src/actions/scales/edit.js +67 -12
  211. package/src/actions/scales/editPolicy.js +81 -11
  212. package/src/actions/scales/index.js +6 -0
  213. package/src/actions/scales/materialize.js +5 -4
  214. package/src/actions/scales/offset.js +48 -0
  215. package/src/actions/scales/parallel.js +71 -0
  216. package/src/actions/scales/preview.js +111 -10
  217. package/src/actions/scales/quantitativeColor.js +4 -5
  218. package/src/actions/selection/actions.js +179 -66
  219. package/src/actions/selection/index.js +3 -0
  220. package/src/actions/textMetrics/index.js +56 -0
  221. package/src/actions/theme/actions.js +70 -15
  222. package/src/actions/theme/composition.js +238 -0
  223. package/src/actions/theme/index.js +9 -2
  224. package/src/actions/theme/reconcile.js +313 -121
  225. package/src/actions/theme/state.js +160 -0
  226. package/src/actions/titles/actions.js +8 -8
  227. package/src/actions/titles/resolve.js +3 -3
  228. package/src/actions/violinPlots/create.js +6 -3
  229. package/src/actions/violinPlots/edit.js +2 -1
  230. package/src/core/action.js +117 -35
  231. package/src/core/compositionState.js +6 -1
  232. package/src/core/diagnostics.js +16 -0
  233. package/src/core/extensionRegistry.js +27 -0
  234. package/src/core/font.js +18 -0
  235. package/src/core/identifiers.js +5 -4
  236. package/src/core/immutable.js +10 -3
  237. package/src/core/optionRequirements.js +8 -0
  238. package/src/core/programState.js +21 -1
  239. package/src/core/resourceReferences.js +341 -0
  240. package/src/core/textMetricProfile.js +28 -0
  241. package/src/core/textMetrics.js +24 -3
  242. package/src/core/validation.js +22 -10
  243. package/src/core/vocabulary.js +16 -3
  244. package/src/diagnostics.js +1 -0
  245. package/src/grammar/bars/aggregate.js +4 -1
  246. package/src/grammar/bars/geometry.js +44 -0
  247. package/src/grammar/bin.js +54 -9
  248. package/src/grammar/complete.js +279 -0
  249. package/src/grammar/computed.js +265 -64
  250. package/src/grammar/coordinates.js +37 -0
  251. package/src/grammar/density.js +239 -37
  252. package/src/grammar/displayLabels.js +57 -0
  253. package/src/grammar/facets/dependencies.js +133 -1
  254. package/src/grammar/facets/guides.js +3 -0
  255. package/src/grammar/facets/index.js +7 -47
  256. package/src/grammar/facets/scales.js +15 -18
  257. package/src/grammar/impute.js +341 -0
  258. package/src/grammar/markLabelSelection.js +57 -0
  259. package/src/grammar/markLabels.js +18 -1
  260. package/src/grammar/normalize.js +366 -0
  261. package/src/grammar/pathSeries.js +26 -8
  262. package/src/grammar/pointShapes.js +13 -4
  263. package/src/grammar/polar.js +90 -8
  264. package/src/grammar/regression/index.js +1 -0
  265. package/src/grammar/regression/parameters.js +23 -0
  266. package/src/grammar/roundedRect.js +180 -0
  267. package/src/grammar/rules.js +1 -0
  268. package/src/grammar/scales/colorConsumers.js +20 -1
  269. package/src/grammar/scales/continuous.js +2 -2
  270. package/src/grammar/scales/definition.js +27 -4
  271. package/src/grammar/scales/index.js +1 -0
  272. package/src/grammar/scales/ordinal.js +12 -3
  273. package/src/grammar/scales/policies.js +2 -2
  274. package/src/grammar/scales/size.js +456 -0
  275. package/src/grammar/scales/types.js +8 -0
  276. package/src/grammar/schemas/concreteGraphic.js +14 -2
  277. package/src/grammar/schemas/graphic.js +15 -0
  278. package/src/grammar/schemas/graphicBounds.js +190 -41
  279. package/src/grammar/schemas/semanticPath.js +7 -2
  280. package/src/grammar/statisticalReference.js +103 -0
  281. package/src/grammar/strokeStyle.js +77 -0
  282. package/src/grammar/summary.js +78 -16
  283. package/src/grammar/timeUnit.js +216 -5
  284. package/src/grammar/transformTopology.js +4 -0
  285. package/src/grammar/transforms.js +394 -28
  286. package/src/grammar/weightedStatistics.js +374 -0
  287. package/src/grammar/window.js +221 -16
  288. package/src/layout/aspect.js +80 -0
  289. package/src/layout/facets.js +59 -5
  290. package/src/layout/labels.js +351 -7
  291. package/src/layout/legend.js +4 -4
  292. package/src/layout/legendItems.js +6 -6
  293. package/src/layout/text.js +10 -9
  294. package/src/layout/title.js +9 -9
  295. package/src/materialization/bars/aggregate.js +25 -2
  296. package/src/materialization/bars/histogram.js +84 -24
  297. package/src/materialization/bars/ranged.js +19 -3
  298. package/src/materialization/bars/resolve.js +7 -4
  299. package/src/materialization/composition.js +3 -1
  300. package/src/materialization/coordinateBounds.js +204 -0
  301. package/src/materialization/dependencies.js +36 -0
  302. package/src/materialization/facetGuides/legacyCategorical.js +3 -0
  303. package/src/materialization/facetGuides/placement.js +9 -3
  304. package/src/materialization/facetGuides/preparation.js +13 -8
  305. package/src/materialization/facetHeaders.js +347 -0
  306. package/src/materialization/facets.js +15 -65
  307. package/src/materialization/guides/layout.js +3 -3
  308. package/src/materialization/guides/resources.js +26 -0
  309. package/src/materialization/legends.js +1 -1
  310. package/src/materialization/marks/index.js +11 -5
  311. package/src/materialization/marks/policies.js +2 -1
  312. package/src/materialization/rect.js +25 -12
  313. package/src/materialization/rectConfig.js +5 -1
  314. package/src/materialization/scaleGuideDependencies.js +10 -0
  315. package/src/materialization/scales/map.js +5 -3
  316. package/src/materialization/scales/policies/binnedPosition.js +2 -2
  317. package/src/materialization/scales/policies/offset.js +50 -8
  318. package/src/materialization/scales/policies/series.js +4 -1
  319. package/src/materialization/scales/resolve.js +22 -6
  320. package/src/materialization/selection/items/arc.js +28 -4
  321. package/src/materialization/selection/items/bar.js +30 -3
  322. package/src/materialization/selection/items/common.js +20 -5
  323. package/src/materialization/selection/items/rect.js +28 -4
  324. package/src/materialization/selection/path.js +1 -1
  325. package/src/materialization/selection/point.js +3 -1
  326. package/src/materialization/text.js +265 -14
  327. package/src/materialization/typography.js +31 -0
  328. package/src/mcp/cli.js +5 -3
  329. package/src/persistence/codec.js +65 -0
  330. package/src/persistence/validation.js +185 -0
  331. package/src/persistence.js +74 -0
  332. package/src/renderers/canvas/circle.js +2 -3
  333. package/src/renderers/canvas/index.js +5 -4
  334. package/src/renderers/canvas/line.js +2 -3
  335. package/src/renderers/canvas/native.js +4 -4
  336. package/src/renderers/canvas/path.js +2 -3
  337. package/src/renderers/canvas/rect.js +2 -3
  338. package/src/renderers/canvas/stroke.js +11 -0
  339. package/src/renderers/nativeBackend.js +10 -0
  340. package/src/renderers/options.js +13 -0
  341. package/src/renderers/pdf.js +25 -54
  342. package/src/renderers/png.js +22 -17
  343. package/src/renderers/svg.js +29 -14
  344. package/src/renderers/text.js +1 -11
  345. package/src/selectors/coordinates.js +3 -1
  346. package/src/selectors/datasets.js +38 -5
  347. package/src/selectors/layers.js +10 -4
  348. package/src/selectors/markOwners.js +46 -0
  349. package/src/selectors/scales.js +6 -4
  350. package/src/theme/defaults.js +103 -1
  351. package/src/version.js +2 -0
  352. package/types/accessibility.d.ts +37 -0
  353. package/types/basic.d.ts +10 -2
  354. package/types/diagnostics.d.ts +15 -0
  355. package/types/index.d.ts +90 -0
  356. package/types/pdf.d.ts +9 -0
  357. package/types/persistence.d.ts +7 -0
  358. package/types/png.d.ts +9 -0
  359. package/types/program.d.ts +944 -118
@@ -1,4 +1,5 @@
1
1
  import { action } from "../../core/action.js";
2
+ import { STROKE_STYLE_PROPERTIES } from "../../grammar/strokeStyle.js";
2
3
  import { validateNonEmptyString, validateOptionObject, validateUnitInterval } from "../../core/validation.js";
3
4
  import {
4
5
  applyFacadeGuides, normalizeAppearance, normalizeFieldEncoding, normalizeGuides,
@@ -40,7 +41,7 @@ function guideOptions(value) {
40
41
  return guides;
41
42
  }
42
43
 
43
- export const createHorizonPlot = action({
44
+ export const createHorizonPlot = /* @__PURE__ */ action({
44
45
  op: OPERATION, description: "Create a signed, folded horizon area with original-x guides."
45
46
  }, function (args = {}) {
46
47
  validateFacadeOptions(args, OPTIONS, OPERATION);
@@ -51,7 +52,8 @@ export const createHorizonPlot = action({
51
52
  const { id: requestedId, data: requestedData, coordinate, x: requestedX, y: requestedY,
52
53
  area: requestedArea, guides: requestedGuides, ...horizon } = omitUndefinedOptions(args);
53
54
  const { opacity, ...area } = omitUndefinedOptions(normalizeAppearance(requestedArea,
54
- ["opacity", "stroke", "strokeWidth", "curve"], `${OPERATION} area`));
55
+ ["opacity", "stroke", "strokeWidth", "curve", ...STROKE_STYLE_PROPERTIES],
56
+ `${OPERATION} area`));
55
57
  for (const [key, value] of Object.entries({ ...horizon, ...area })) {
56
58
  if (value === null) throw new TypeError(`${OPERATION} ${key} cannot be null.`);
57
59
  }
@@ -1,6 +1,7 @@
1
1
  import { action } from "../../core/action.js";
2
2
  import { validateNonNegativeFinite } from "../../core/validation.js";
3
3
  import { findDataset } from "../../selectors/datasets.js";
4
+ import { STROKE_STYLE_PROPERTIES } from "../../grammar/strokeStyle.js";
4
5
  import {
5
6
  applyFacadeGuides,
6
7
  normalizeAppearance,
@@ -18,10 +19,12 @@ const INTERVAL_OPTIONS = Object.freeze([
18
19
  "color", "point", "errorBar", "guides"
19
20
  ]);
20
21
  const POINT_OPTIONS = Object.freeze([
21
- "shape", "fill", "opacity", "stroke", "strokeWidth", "radius"
22
+ "shape", "fill", "opacity", "stroke", "strokeWidth", "radius",
23
+ ...STROKE_STYLE_PROPERTIES
22
24
  ]);
23
25
  const ERROR_BAR_OPTIONS = Object.freeze([
24
- "caps", "capSize", "stroke", "strokeWidth", "strokeDash", "opacity"
26
+ "caps", "capSize", "stroke", "strokeWidth", "strokeDash", "opacity",
27
+ ...STROKE_STYLE_PROPERTIES
25
28
  ]);
26
29
 
27
30
  function intervalChannel(value, operation, channel, id) {
@@ -79,7 +82,7 @@ function applyIntervalPointPositions(program, id, config) {
79
82
  return next;
80
83
  }
81
84
 
82
- export const createIntervalPlot = action(
85
+ export const createIntervalPlot = /* @__PURE__ */ action(
83
86
  {
84
87
  op: "createIntervalPlot",
85
88
  description: "Create a center point and matching statistical or explicit interval."
@@ -136,7 +139,7 @@ const REGRESSION_OPTIONS = Object.freeze([
136
139
  "interval", "band", "line", "guides"
137
140
  ]);
138
141
 
139
- export const createRegressionPlot = action(
142
+ export const createRegressionPlot = /* @__PURE__ */ action(
140
143
  {
141
144
  op: "createRegressionPlot",
142
145
  description: "Create a scatter plot with a fitted regression line and optional interval band."
@@ -1,5 +1,6 @@
1
1
  import { action } from "../../core/action.js";
2
2
  import { normalizeGroupFields } from "../../grammar/pathSeries.js";
3
+ import { STROKE_STYLE_PROPERTIES } from "../../grammar/strokeStyle.js";
3
4
  import {
4
5
  applyFacadeGuides,
5
6
  normalizeAppearance,
@@ -19,10 +20,11 @@ const OPTIONS = Object.freeze([
19
20
  "strokeDash", "line", "guides"
20
21
  ]);
21
22
  const LINE_OPTIONS = Object.freeze([
22
- "strokeWidth", "curve", "stroke", "opacity", "closed"
23
+ "strokeWidth", "curve", "stroke", "opacity", "closed",
24
+ ...STROKE_STYLE_PROPERTIES
23
25
  ]);
24
26
 
25
- export const createLinePlot = action(
27
+ export const createLinePlot = /* @__PURE__ */ action(
26
28
  {
27
29
  op: "createLinePlot",
28
30
  description: "Create a Cartesian line plot from existing chart data."
@@ -1,5 +1,6 @@
1
1
  import { action } from "../../core/action.js";
2
2
  import { resolveParallelCoordinate } from "../coordinates/parallel.js";
3
+ import { STROKE_STYLE_PROPERTIES } from "../../grammar/strokeStyle.js";
3
4
  import {
4
5
  applyFacadeGuides,
5
6
  normalizeAppearance,
@@ -17,7 +18,8 @@ const OPTIONS = Object.freeze([
17
18
  "color", "strokeDash", "line", "guides"
18
19
  ]);
19
20
  const LINE_OPTIONS = Object.freeze([
20
- "strokeWidth", "stroke", "opacity", "curve", "closed"
21
+ "strokeWidth", "stroke", "opacity", "curve", "closed",
22
+ ...STROKE_STYLE_PROPERTIES
21
23
  ]);
22
24
 
23
25
  function scopeParallelGuides(guides, coordinate) {
@@ -51,7 +53,7 @@ function scopeParallelGuides(guides, coordinate) {
51
53
  };
52
54
  }
53
55
 
54
- export const createParallelCoordinates = action(
56
+ export const createParallelCoordinates = /* @__PURE__ */ action(
55
57
  {
56
58
  op: "createParallelCoordinates",
57
59
  description: "Create a complete Parallel-coordinates chart."
@@ -105,6 +107,10 @@ export const createParallelCoordinates = action(
105
107
  if (strokeDash !== undefined) {
106
108
  next = next.encodeStrokeDash(targetArgs(strokeDash, id));
107
109
  }
108
- return applyFacadeGuides(next, guides, id);
110
+ next = applyFacadeGuides(next, guides, id);
111
+ return next._withMarkConfig(id, {
112
+ ...next.markConfigs[id],
113
+ compositionRole: "parallel"
114
+ });
109
115
  }
110
116
  );
@@ -1,4 +1,5 @@
1
1
  import { action } from "../../core/action.js";
2
+ import { STROKE_STYLE_PROPERTIES } from "../../grammar/strokeStyle.js";
2
3
  import {
3
4
  applyFacadeGuides, normalizeAppearance, normalizeCategoricalColor, normalizeCategoricalGuides,
4
5
  normalizeArcCategory, normalizeCategoryAggregate, omitUndefinedOptions,
@@ -7,7 +8,10 @@ import {
7
8
 
8
9
  const OPERATION = "createPiePlot";
9
10
  const OPTIONS = ["id", "data", "coordinate", "category", "value", "aggregate", "color", "arc", "guides"];
10
- const ARC_OPTIONS = ["innerRadius", "padAngle", "fill", "opacity", "stroke", "strokeWidth"];
11
+ const ARC_OPTIONS = [
12
+ "innerRadius", "padAngle", "fill", "opacity", "stroke", "strokeWidth",
13
+ ...STROKE_STYLE_PROPERTIES
14
+ ];
11
15
  function guideOptions(value, color) {
12
16
  const guides = normalizeCategoricalGuides(value, OPERATION, color);
13
17
  if (guides === false) return false;
@@ -19,7 +23,7 @@ function guideOptions(value, color) {
19
23
  return { ...guides, axes: false, grid: false };
20
24
  }
21
25
 
22
- export const createPiePlot = action({
26
+ export const createPiePlot = /* @__PURE__ */ action({
23
27
  op: OPERATION, description: "Create a categorical count or weighted-sum pie or donut plot."
24
28
  }, function (args = {}) {
25
29
  validateFacadeOptions(args, OPTIONS, OPERATION);
@@ -40,5 +44,9 @@ export const createPiePlot = action({
40
44
  ...(aggregate === "sum" ? { weight: args.value } : {})
41
45
  });
42
46
  if (color !== undefined) next = next.encodeColor({ ...color, target: id });
43
- return applyFacadeGuides(next, guides, id, args.guides ?? {});
47
+ next = applyFacadeGuides(next, guides, id, args.guides ?? {});
48
+ return next._withMarkConfig(id, {
49
+ ...next.markConfigs[id],
50
+ compositionRole: "pie"
51
+ });
44
52
  });
@@ -2,6 +2,7 @@ import { action } from "../../core/action.js";
2
2
  import { validateNonNegativeFinite, validateOptionObject } from
3
3
  "../../core/validation.js";
4
4
  import { normalizeGroupFields } from "../../grammar/pathSeries.js";
5
+ import { STROKE_STYLE_PROPERTIES } from "../../grammar/strokeStyle.js";
5
6
  import {
6
7
  applyFacadeGuides,
7
8
  normalizeAppearance,
@@ -20,10 +21,12 @@ const POSITION_OPTIONS = Object.freeze([
20
21
  "field", "fieldType", "temporalUnit", "scale"
21
22
  ]);
22
23
  const POINT_OPTIONS = Object.freeze([
23
- "shape", "fill", "opacity", "stroke", "strokeWidth", "radius"
24
+ "shape", "fill", "opacity", "stroke", "strokeWidth", "radius",
25
+ ...STROKE_STYLE_PROPERTIES
24
26
  ]);
25
27
  const LINE_OPTIONS = Object.freeze([
26
- "strokeWidth", "curve", "stroke", "opacity", "closed"
28
+ "strokeWidth", "curve", "stroke", "opacity", "closed",
29
+ ...STROKE_STYLE_PROPERTIES
27
30
  ]);
28
31
 
29
32
  function position(value, operation, channel) {
@@ -36,7 +39,7 @@ function position(value, operation, channel) {
36
39
  return resolved;
37
40
  }
38
41
 
39
- export const createPolarScatterPlot = action(
42
+ export const createPolarScatterPlot = /* @__PURE__ */ action(
40
43
  {
41
44
  op: "createPolarScatterPlot",
42
45
  description: "Create a Polar scatter plot with distinct radial position and glyph size."
@@ -78,11 +81,15 @@ export const createPolarScatterPlot = action(
78
81
  if (color !== undefined) next = next.encodeColor(targetArgs(color, id));
79
82
  if (size !== undefined) next = next.encodeSize(targetArgs(size, id));
80
83
  if (shape !== undefined) next = next.encodeShape(targetArgs(shape, id));
81
- return applyFacadeGuides(next, guides, id);
84
+ next = applyFacadeGuides(next, guides, id);
85
+ return next._withMarkConfig(id, {
86
+ ...next.markConfigs[id],
87
+ compositionRole: "polar-point"
88
+ });
82
89
  }
83
90
  );
84
91
 
85
- export const createPolarLinePlot = action(
92
+ export const createPolarLinePlot = /* @__PURE__ */ action(
86
93
  {
87
94
  op: "createPolarLinePlot",
88
95
  description: "Create an open or explicitly closed Polar line plot."
@@ -118,6 +125,10 @@ export const createPolarLinePlot = action(
118
125
  if (groupBy !== undefined) next = next.encodeGroup({ target: id, fields: groupBy });
119
126
  if (color !== undefined) next = next.encodeColor(targetArgs(color, id));
120
127
  if (strokeDash !== undefined) next = next.encodeStrokeDash(targetArgs(strokeDash, id));
121
- return applyFacadeGuides(next, guides, id);
128
+ next = applyFacadeGuides(next, guides, id);
129
+ return next._withMarkConfig(id, {
130
+ ...next.markConfigs[id],
131
+ compositionRole: "polar-line"
132
+ });
122
133
  }
123
134
  );
@@ -1,4 +1,5 @@
1
1
  import { action } from "../../core/action.js";
2
+ import { STROKE_STYLE_PROPERTIES } from "../../grammar/strokeStyle.js";
2
3
  import { isPlainObject } from "../../core/immutable.js";
3
4
  import { validateNonEmptyString, validateOptionObject } from
4
5
  "../../core/validation.js";
@@ -31,7 +32,8 @@ const CATEGORY_SCALE_OPTIONS = Object.freeze([
31
32
  const WIDE_OPTIONS = Object.freeze(["fields", "as"]);
32
33
  const WIDE_AS_OPTIONS = Object.freeze(["key", "value"]);
33
34
  const LINE_OPTIONS = Object.freeze([
34
- "strokeWidth", "curve", "stroke", "opacity", "closed"
35
+ "strokeWidth", "curve", "stroke", "opacity", "closed",
36
+ ...STROKE_STYLE_PROPERTIES
35
37
  ]);
36
38
 
37
39
  function normalizeCategory(value, operation) {
@@ -183,7 +185,7 @@ function scaleWithOrder(category, order, operation) {
183
185
  return { ...category, scale: { ...scale, domain: order } };
184
186
  }
185
187
 
186
- export const createRadarPlot = action(
188
+ export const createRadarPlot = /* @__PURE__ */ action(
187
189
  {
188
190
  op: "createRadarPlot",
189
191
  description: "Create a closed Radar plot from long rows or an explicit wide fold."
@@ -283,7 +285,7 @@ export const createRadarPlot = action(
283
285
  }
284
286
 
285
287
  category = scaleWithOrder(category, order, operation);
286
- return next.createPolarLinePlot({
288
+ next = next.createPolarLinePlot({
287
289
  id,
288
290
  data,
289
291
  ...(args.coordinate === undefined ? {} : { coordinate: args.coordinate }),
@@ -295,5 +297,9 @@ export const createRadarPlot = action(
295
297
  line: { ...line, closed: true },
296
298
  guides
297
299
  });
300
+ return next._withMarkConfig(id, {
301
+ ...next.markConfigs[id],
302
+ compositionRole: "radar"
303
+ });
298
304
  }
299
305
  );
@@ -1,4 +1,5 @@
1
1
  import { action } from "../../core/action.js";
2
+ import { STROKE_STYLE_PROPERTIES } from "../../grammar/strokeStyle.js";
2
3
  import {
3
4
  applyFacadeGuides, normalizeAppearance, normalizeArcCategory, normalizeCategoryAggregate,
4
5
  normalizeCategoricalColor, normalizeCategoricalGuides, omitUndefinedOptions,
@@ -6,7 +7,10 @@ import {
6
7
  } from "./shared.js";
7
8
 
8
9
  const OPTIONS = ["id", "data", "coordinate", "category", "value", "aggregate", "radiusScale", "color", "arc", "guides"];
9
- const ARC_OPTIONS = ["innerRadius", "padAngle", "fill", "opacity", "stroke", "strokeWidth"];
10
+ const ARC_OPTIONS = [
11
+ "innerRadius", "padAngle", "fill", "opacity", "stroke", "strokeWidth",
12
+ ...STROKE_STYLE_PROPERTIES
13
+ ];
10
14
  const RADIUS_OPTIONS = ["id", "type", "domain", "range", "zero", "nice", "reverse", "clamp"];
11
15
 
12
16
  function createMeasuredPlot(program, args, { operation, defaultId, mapping }) {
@@ -31,12 +35,16 @@ function createMeasuredPlot(program, args, { operation, defaultId, mapping }) {
31
35
  ...(aggregate === "sum" ? { field: args.value } : {}),
32
36
  ...(radiusScale === undefined ? {} : { scale: radiusScale }) });
33
37
  if (color !== undefined) next = next.encodeColor({ ...color, target: id });
34
- return applyFacadeGuides(next, guides, id, args.guides ?? {});
38
+ next = applyFacadeGuides(next, guides, id, args.guides ?? {});
39
+ return next._withMarkConfig(id, {
40
+ ...next.markConfigs[id],
41
+ compositionRole: "rose"
42
+ });
35
43
  }
36
44
 
37
- export const createRosePlot = action({ op: "createRosePlot", description: "Create equal-angle sectors with area proportional to category count or sum." }, function (args = {}) {
45
+ export const createRosePlot = /* @__PURE__ */ action({ op: "createRosePlot", description: "Create equal-angle sectors with area proportional to category count or sum." }, function (args = {}) {
38
46
  return createMeasuredPlot(this, args, { operation: "createRosePlot", defaultId: "rosePlot", mapping: "area" });
39
47
  });
40
- export const createRadialBarPlot = action({ op: "createRadialBarPlot", description: "Create equal-angle sectors with radial length proportional to category count or sum." }, function (args = {}) {
48
+ export const createRadialBarPlot = /* @__PURE__ */ action({ op: "createRadialBarPlot", description: "Create equal-angle sectors with radial length proportional to category count or sum." }, function (args = {}) {
41
49
  return createMeasuredPlot(this, args, { operation: "createRadialBarPlot", defaultId: "radialBarPlot", mapping: "radius-length" });
42
50
  });
@@ -376,7 +376,7 @@ function raincloudOwner(program, requested) {
376
376
  throw new Error("editRaincloudPlot target is ambiguous; provide target.");
377
377
  }
378
378
 
379
- export const createRaincloudPlot = action(
379
+ export const createRaincloudPlot = /* @__PURE__ */ action(
380
380
  { op: "createRaincloudPlot", description: "Create a half-density, summary, and raw-point distribution plot." },
381
381
  function (args = {}) {
382
382
  const operation = "createRaincloudPlot";
@@ -385,7 +385,7 @@ export const createRaincloudPlot = action(
385
385
  }
386
386
  );
387
387
 
388
- export const editRaincloudPlot = action(
388
+ export const editRaincloudPlot = /* @__PURE__ */ action(
389
389
  { op: "editRaincloudPlot", description: "Revise one Raincloud plot's shared source and statistical roles." },
390
390
  function (args = {}) {
391
391
  const operation = "editRaincloudPlot";
@@ -1,4 +1,5 @@
1
1
  import { action } from "../../core/action.js";
2
+ import { STROKE_STYLE_PROPERTIES } from "../../grammar/strokeStyle.js";
2
3
  import { isPlainObject } from "../../core/immutable.js";
3
4
  import { validateNonEmptyString, validateNonNegativeFinite, validateOptionObject } from
4
5
  "../../core/validation.js";
@@ -19,12 +20,15 @@ import {
19
20
 
20
21
  const RUG_OPTIONS = Object.freeze(["id", "data", "coordinate", "x", "y", "edge", "tick", "guides"]);
21
22
  const MEASURE_OPTIONS = Object.freeze(["field", "fieldType", "temporalUnit", "scale"]);
22
- const TICK_OPTIONS = Object.freeze(["length", "stroke", "strokeWidth", "opacity"]);
23
+ const TICK_OPTIONS = Object.freeze([
24
+ "length", "stroke", "strokeWidth", "opacity", ...STROKE_STYLE_PROPERTIES
25
+ ]);
23
26
  const STRIP_OPTIONS = Object.freeze([
24
27
  "id", "data", "coordinate", "x", "y", "color", "size", "shape", "point", "jitter", "guides"
25
28
  ]);
26
29
  const POINT_OPTIONS = Object.freeze([
27
- "radius", "shape", "fill", "opacity", "stroke", "strokeWidth"
30
+ "radius", "shape", "fill", "opacity", "stroke", "strokeWidth",
31
+ ...STROKE_STYLE_PROPERTIES
28
32
  ]);
29
33
  const JITTER_OPTIONS = Object.freeze(["maxOffset", "seed", "key"]);
30
34
 
@@ -75,7 +79,7 @@ function normalizeRugGuides(value, measure, operation) {
75
79
  return { axes, grid, legend: false };
76
80
  }
77
81
 
78
- export const createRugPlot = action(
82
+ export const createRugPlot = /* @__PURE__ */ action(
79
83
  {
80
84
  op: "createRugPlot",
81
85
  description: "Create a one-dimensional Rug plot at an explicit plot edge."
@@ -202,7 +206,7 @@ function normalizeStripGuides(value, actualChannels, hasLegend, operation) {
202
206
  return { axes, grid, legend };
203
207
  }
204
208
 
205
- export const createStripPlot = action(
209
+ export const createStripPlot = /* @__PURE__ */ action(
206
210
  {
207
211
  op: "createStripPlot",
208
212
  description: "Create a one-dimensional Strip plot with an optional categorical slot and jitter."
@@ -1,5 +1,6 @@
1
1
  import { action } from "../../core/action.js";
2
2
  import { validateNonNegativeFinite } from "../../core/validation.js";
3
+ import { STROKE_STYLE_PROPERTIES } from "../../grammar/strokeStyle.js";
3
4
  import {
4
5
  applyFacadeGuides,
5
6
  normalizeAppearance,
@@ -18,10 +19,11 @@ const OPTIONS = Object.freeze([
18
19
  "point", "guides"
19
20
  ]);
20
21
  const POINT_OPTIONS = Object.freeze([
21
- "shape", "fill", "opacity", "stroke", "strokeWidth", "radius"
22
+ "shape", "fill", "opacity", "stroke", "strokeWidth", "radius",
23
+ ...STROKE_STYLE_PROPERTIES
22
24
  ]);
23
25
 
24
- export const createScatterPlot = action(
26
+ export const createScatterPlot = /* @__PURE__ */ action(
25
27
  {
26
28
  op: "createScatterPlot",
27
29
  description: "Create a Cartesian scatter plot from existing chart data."
@@ -1,4 +1,5 @@
1
- import { action } from "../../core/action.js";
1
+ import { inheritTextMetrics } from "../textMetrics/index.js";
2
+ import { action, closedAction } from "../../core/action.js";
2
3
  import { ChartProgram as CoreChartProgram } from "../../core/ChartProgram.js";
3
4
  import { freezeOwned, isPlainObject } from "../../core/immutable.js";
4
5
  import { validateUserId } from "../../core/identifiers.js";
@@ -12,6 +13,7 @@ import { namespaceGraphicSnapshot } from "../../materialization/compositionSnaps
12
13
  import { materializeCompositionGraphics } from
13
14
  "../../materialization/composition.js";
14
15
  import { materializeFacetGraphics } from "../../materialization/facets.js";
16
+ import { replayInheritedThemeFrames } from "../theme/composition.js";
15
17
 
16
18
  const CONCAT_OPTIONS = Object.freeze([
17
19
  "id", "programs", "gap", "align", "padding"
@@ -115,7 +117,7 @@ export function applyCompositionState(program, state, tracedChildren = []) {
115
117
  return next.materializeComposition();
116
118
  }
117
119
 
118
- const useProgram = action(
120
+ const useProgram = /* @__PURE__ */ action(
119
121
  {
120
122
  op: "useProgram",
121
123
  description: "Retain one named child program in a composition.",
@@ -130,7 +132,7 @@ const useProgram = action(
130
132
  }
131
133
  );
132
134
 
133
- const materializeComposition = action(
135
+ const materializeComposition = /* @__PURE__ */ action(
134
136
  {
135
137
  op: "materializeComposition",
136
138
  description: "Materialize retained child programs into one graphic tree.",
@@ -158,17 +160,16 @@ function concatAction(direction, op) {
158
160
  );
159
161
  }
160
162
 
161
- export const hconcatAction = concatAction("horizontal", "hconcat");
162
- export const vconcatAction = concatAction("vertical", "vconcat");
163
+ export const hconcatAction = /* @__PURE__ */ concatAction("horizontal", "hconcat");
164
+ export const vconcatAction = /* @__PURE__ */ concatAction("vertical", "vconcat");
163
165
 
164
- const editCompositionLayout = action(
166
+ const editCompositionLayout = /* @__PURE__ */ closedAction(
165
167
  {
166
168
  op: "editCompositionLayout",
167
169
  description: "Edit composition layout.",
168
170
  scope: "composition"
169
- },
171
+ }, LAYOUT_EDIT_OPTIONS,
170
172
  function (args = {}) {
171
- validateOptionObject(args, LAYOUT_EDIT_OPTIONS, "editCompositionLayout");
172
173
  if (!LAYOUT_EDIT_OPTIONS.some(option => Object.hasOwn(args, option))) {
173
174
  throw new TypeError("editCompositionLayout requires at least one layout option.");
174
175
  }
@@ -226,14 +227,13 @@ const editCompositionLayout = action(
226
227
  }
227
228
  );
228
229
 
229
- const replaceCompositionChild = action(
230
+ const replaceCompositionChild = /* @__PURE__ */ closedAction(
230
231
  {
231
232
  op: "replaceCompositionChild",
232
233
  description: "Replace one composition child without changing its slot.",
233
234
  scope: "composition"
234
- },
235
+ }, REPLACEMENT_OPTIONS,
235
236
  function (args = {}) {
236
- validateOptionObject(args, REPLACEMENT_OPTIONS, "replaceCompositionChild");
237
237
  this._assertCompositionProgram("replaceCompositionChild");
238
238
  if (this.compositionSpec.type === "facet") {
239
239
  throw new Error("replaceCompositionChild is not available on a facet composition.");
@@ -245,10 +245,14 @@ const replaceCompositionChild = action(
245
245
  if (!(args.program instanceof CoreChartProgram)) {
246
246
  throw new TypeError("replaceCompositionChild program must be a ChartProgram.");
247
247
  }
248
- childDescriptor({ id: target, program: args.program });
248
+ const replacement = inheritTextMetrics(this, replayInheritedThemeFrames(
249
+ args.program,
250
+ this.materializationConfigs.theme
251
+ ));
252
+ childDescriptor({ id: target, program: replacement });
249
253
  const children = freezeOwned({
250
254
  ...this.children,
251
- [target]: args.program
255
+ [target]: replacement
252
256
  });
253
257
  return applyCompositionState(this, {
254
258
  children,
@@ -264,14 +268,13 @@ function requireConcat(program, operation) {
264
268
  }
265
269
  }
266
270
 
267
- const insertCompositionChild = action(
271
+ const insertCompositionChild = /* @__PURE__ */ closedAction(
268
272
  {
269
273
  op: "insertCompositionChild",
270
274
  description: "Insert one named child into a concat composition.",
271
275
  scope: "composition"
272
- },
276
+ }, INSERTION_OPTIONS,
273
277
  function (args = {}) {
274
- validateOptionObject(args, INSERTION_OPTIONS, "insertCompositionChild");
275
278
  requireConcat(this, "insertCompositionChild");
276
279
  const id = validateUserId(args.id, "Composition child ID");
277
280
  if (Object.hasOwn(this.children, id)) {
@@ -283,7 +286,11 @@ const insertCompositionChild = action(
283
286
  if (args.before !== undefined && args.after !== undefined) {
284
287
  throw new Error("insertCompositionChild before and after are mutually exclusive.");
285
288
  }
286
- childDescriptor({ id, program: args.program });
289
+ const inserted = inheritTextMetrics(this, replayInheritedThemeFrames(
290
+ args.program,
291
+ this.materializationConfigs.theme
292
+ ));
293
+ childDescriptor({ id, program: inserted });
287
294
  const order = [...this.compositionSpec.children];
288
295
  if (args.before !== undefined || args.after !== undefined) {
289
296
  const property = args.before !== undefined ? "before" : "after";
@@ -295,20 +302,19 @@ const insertCompositionChild = action(
295
302
  order.push(id);
296
303
  }
297
304
  return applyCompositionState(this, {
298
- children: freezeOwned({ ...this.children, [id]: args.program }),
305
+ children: freezeOwned({ ...this.children, [id]: inserted }),
299
306
  compositionSpec: { ...this.compositionSpec, children: order }
300
307
  }, [id]);
301
308
  }
302
309
  );
303
310
 
304
- const removeCompositionChild = action(
311
+ const removeCompositionChild = /* @__PURE__ */ closedAction(
305
312
  {
306
313
  op: "removeCompositionChild",
307
314
  description: "Remove one named child from a concat composition.",
308
315
  scope: "composition"
309
- },
316
+ }, REMOVAL_OPTIONS,
310
317
  function (args = {}) {
311
- validateOptionObject(args, REMOVAL_OPTIONS, "removeCompositionChild");
312
318
  requireConcat(this, "removeCompositionChild");
313
319
  const target = validateUserId(args.target, "Composition child target");
314
320
  if (!Object.hasOwn(this.children, target)) {
@@ -329,14 +335,13 @@ const removeCompositionChild = action(
329
335
  }
330
336
  );
331
337
 
332
- const reorderCompositionChildren = action(
338
+ const reorderCompositionChildren = /* @__PURE__ */ closedAction(
333
339
  {
334
340
  op: "reorderCompositionChildren",
335
341
  description: "Reorder every named child in a concat composition.",
336
342
  scope: "composition"
337
- },
343
+ }, REORDER_OPTIONS,
338
344
  function (args = {}) {
339
- validateOptionObject(args, REORDER_OPTIONS, "reorderCompositionChildren");
340
345
  requireConcat(this, "reorderCompositionChildren");
341
346
  if (!Array.isArray(args.order) || args.order.length === 0 ||
342
347
  args.order.some(id => typeof id !== "string" || id.length === 0)) {
@@ -31,7 +31,7 @@ function validateLayers(program, layers) {
31
31
  return ids;
32
32
  }
33
33
 
34
- export const createCoordinate = action(
34
+ export const createCoordinate = /* @__PURE__ */ action(
35
35
  {
36
36
  op: "createCoordinate",
37
37
  description: "Create a semantic coordinate and attach layers to it."
@@ -81,6 +81,6 @@ export const createCoordinate = action(
81
81
  }
82
82
  );
83
83
 
84
- export function registerCoordinateActions(ProgramClass) {
84
+ export function registerBasicCoordinateActions(ProgramClass) {
85
85
  ProgramClass.prototype.createCoordinate = createCoordinate;
86
86
  }
@@ -0,0 +1,76 @@
1
+ import { action } from "../../core/action.js";
2
+ import { validateUserId } from "../../core/identifiers.js";
3
+ import { validateOptionObject } from "../../core/validation.js";
4
+ import { normalizeCoordinateAspect } from "../../grammar/coordinates.js";
5
+ import { normalizePolarFrameOptions } from "../../grammar/polar.js";
6
+ import {
7
+ applyMaterializationPlan,
8
+ planCoordinateRematerialization
9
+ } from "../../materialization/dependencies.js";
10
+ import { requireCoordinate } from "../../selectors/coordinates.js";
11
+
12
+ const EDIT_COORDINATE_OPTIONS = Object.freeze(["target", "aspect", "polarFrame"]);
13
+
14
+ function applyCoordinatePatch(program, target, property, value) {
15
+ const coordinate = requireCoordinate(program, target);
16
+ if (value === "auto") {
17
+ return coordinate[property] === undefined
18
+ ? program
19
+ : program.editSemantic({
20
+ property: `coordinate[${target}].${property}`,
21
+ remove: true
22
+ });
23
+ }
24
+ return program.editSemantic({
25
+ property: `coordinate[${target}].${property}`,
26
+ value
27
+ });
28
+ }
29
+
30
+ export const editCoordinate = /* @__PURE__ */ action(
31
+ {
32
+ op: "editCoordinate",
33
+ description: "Edit coordinate layout constraints and rematerialize its consumers."
34
+ },
35
+ function (args = {}) {
36
+ validateOptionObject(args, EDIT_COORDINATE_OPTIONS, "editCoordinate", {
37
+ allowEmpty: false,
38
+ emptyMessage: "editCoordinate requires aspect or polarFrame changes.",
39
+ emptyError: Error
40
+ });
41
+ const target = validateUserId(args.target, "Coordinate id");
42
+ const coordinate = requireCoordinate(this, target);
43
+ const hasAspect = Object.hasOwn(args, "aspect");
44
+ const hasPolarFrame = Object.hasOwn(args, "polarFrame");
45
+ if (!hasAspect && !hasPolarFrame) {
46
+ throw new Error("editCoordinate requires aspect or polarFrame changes.");
47
+ }
48
+ const aspect = hasAspect ? normalizeCoordinateAspect(args.aspect) : undefined;
49
+ if (hasPolarFrame && coordinate.type !== "polar") {
50
+ throw new Error("editCoordinate polarFrame requires a Polar coordinate.");
51
+ }
52
+ const polarFrame = hasPolarFrame
53
+ ? normalizePolarFrameOptions(args.polarFrame)
54
+ : undefined;
55
+ let proposed = this;
56
+ if (hasAspect) {
57
+ proposed = applyCoordinatePatch(proposed, target, "aspect", aspect);
58
+ }
59
+ if (hasPolarFrame) {
60
+ proposed = applyCoordinatePatch(
61
+ proposed,
62
+ target,
63
+ "polarFrame",
64
+ polarFrame
65
+ );
66
+ }
67
+ const plan = planCoordinateRematerialization(proposed, target);
68
+ // Validate the complete dependent geometry on a discarded immutable branch.
69
+ applyMaterializationPlan(proposed, plan);
70
+ return applyMaterializationPlan(proposed, plan);
71
+ }
72
+ );
73
+
74
+ export function registerCoordinateEditActions(ProgramClass) {
75
+ ProgramClass.prototype.editCoordinate = editCoordinate;
76
+ }
@@ -1,6 +1,6 @@
1
- import { action } from "../../core/action.js";
1
+ import { closedAction } from "../../core/action.js";
2
2
  import { validateUserId } from "../../core/identifiers.js";
3
- import { validateKeys } from "../../core/validation.js";
3
+
4
4
  import {
5
5
  deriveBin2DRows,
6
6
  normalizeBin2DTransform
@@ -11,13 +11,12 @@ const OPTIONS = Object.freeze([
11
11
  "id", "source", "x", "y", "bins", "extent", "includeEmpty", "members", "as"
12
12
  ]);
13
13
 
14
- export const createBasicBin2DData = action(
14
+ export const createBasicBin2DData = /* @__PURE__ */ closedAction(
15
15
  {
16
16
  op: "createBin2DData",
17
17
  description: "Create immutable rectangular 2D-bin values."
18
- },
18
+ }, OPTIONS,
19
19
  function (args = {}) {
20
- validateKeys(args, OPTIONS, "createBin2DData");
21
20
  const owner = validateUserId(args.id, "2D bin dataset id");
22
21
  if (this.materializationConfigs.data?.bin2d?.[owner] !== undefined) {
23
22
  throw new Error(`2D bin owner "${owner}" already exists.`);