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
@@ -0,0 +1,126 @@
1
+ import { findSemanticScale } from "../../selectors/scales.js";
2
+ import {
3
+ findIntervalTransform,
4
+ mergeIntervalStatistics,
5
+ validateIntervalStatistics
6
+ } from "../data/intervalEdit.js";
7
+ import { resolveDistributionScalePlan } from "../distributions/revision.js";
8
+ import { resolveIntervalComposite } from "./resolve.js";
9
+
10
+ export function currentIntervalRoleArgs(program, owner, current, bar) {
11
+ const transform = findIntervalTransform(program, current.data);
12
+ const intervalChannel = current.orientation === "vertical" ? "y" : "x";
13
+ const positionChannel = intervalChannel === "x" ? "y" : "x";
14
+ const storedPosition = bar
15
+ ? {
16
+ field: current.positionField,
17
+ fieldType: current.positionFieldType,
18
+ temporalUnit: current.positionTemporalUnit
19
+ }
20
+ : current.position;
21
+ const position = {
22
+ field: storedPosition.field,
23
+ fieldType: storedPosition.fieldType,
24
+ ...(storedPosition.temporalUnit === undefined
25
+ ? {}
26
+ : { temporalUnit: storedPosition.temporalUnit }),
27
+ scale: { id: current.positionScale }
28
+ };
29
+ const interval = transform === undefined
30
+ ? {
31
+ center: current.centerField ?? owner.encoding[intervalChannel].title,
32
+ lower: current.lowerField,
33
+ upper: current.upperField,
34
+ scale: { id: current.intervalScale }
35
+ }
36
+ : {
37
+ field: transform.field,
38
+ center: transform.center,
39
+ extent: transform.extent,
40
+ ...(transform.method === undefined ? {} : { method: transform.method }),
41
+ ...(transform.level === undefined ? {} : { level: transform.level }),
42
+ scale: { id: current.intervalScale }
43
+ };
44
+ return {
45
+ source: current.source ?? transform?.source ?? current.data,
46
+ x: positionChannel === "x" ? position : interval,
47
+ y: positionChannel === "y" ? position : interval,
48
+ groupBy: bar ? current.groupField ?? transform?.groupBy?.find(
49
+ field => field !== current.positionField
50
+ ) : current.groupBy
51
+ };
52
+ }
53
+
54
+ export function resolveIntervalRoleScales(program, resolved, current, policy, owner, previous) {
55
+ const positionRole = {
56
+ field: resolved.position.field,
57
+ fieldType: resolved.position.fieldType,
58
+ scale: resolved.position.scale
59
+ };
60
+ const intervalTitle = resolved.interval.mode === "statistical"
61
+ ? resolved.interval.field
62
+ : resolved.interval.title;
63
+ const intervalRole = {
64
+ field: intervalTitle,
65
+ fieldType: "quantitative",
66
+ scale: resolved.interval.scale
67
+ };
68
+ const x = resolved.position.channel === "x" ? positionRole : intervalRole;
69
+ const y = resolved.position.channel === "y" ? positionRole : intervalRole;
70
+ const plan = (channel, role) => {
71
+ const fallback = role === intervalRole
72
+ ? current.intervalScale
73
+ : current.positionScale;
74
+ const stored = findSemanticScale(program, fallback);
75
+ const compatible = role.fieldType === "temporal"
76
+ ? stored?.type === "time"
77
+ : ["nominal", "ordinal"].includes(role.fieldType)
78
+ ? ["band", "point"].includes(stored?.type)
79
+ : ["linear", "log", "pow", "sqrt", "symlog"].includes(stored?.type);
80
+ const defaultType = role.fieldType === "temporal"
81
+ ? "time"
82
+ : ["nominal", "ordinal"].includes(role.fieldType) ? "band" : "linear";
83
+ const requested = role.scale.type !== undefined || compatible
84
+ ? role.scale
85
+ : { ...role.scale, type: defaultType };
86
+ return resolveDistributionScalePlan(program, {
87
+ channel,
88
+ fieldType: role.fieldType,
89
+ requested,
90
+ fallback,
91
+ defaults: role === intervalRole
92
+ ? policy.intervalScaleDefaults
93
+ : policy.scaleDefaults(role.fieldType)
94
+ });
95
+ };
96
+ const xScale = plan("x", x);
97
+ const yScale = plan("y", y);
98
+ return {
99
+ x: { ...x, scale: xScale.id },
100
+ y: { ...y, scale: yScale.id },
101
+ xScale,
102
+ yScale,
103
+ category: resolved.position.field,
104
+ categoryType: resolved.position.fieldType,
105
+ measure: intervalTitle,
106
+ previous: {
107
+ x: { field: previous.x.center ?? previous.x.field,
108
+ fieldType: owner.encoding.x.fieldType, scale: owner.encoding.x.scale },
109
+ y: { field: previous.y.center ?? previous.y.field,
110
+ fieldType: owner.encoding.y.fieldType, scale: owner.encoding.y.scale }
111
+ }
112
+ };
113
+ }
114
+
115
+ export function applyIntervalStatistics(program, full, policy, args, resolved) {
116
+ if (Object.hasOwn(args, "statistics")) {
117
+ validateIntervalStatistics(args.statistics, policy.operation);
118
+ const { method, level, ...interval } = full[resolved.interval.channel];
119
+ full[resolved.interval.channel] = {
120
+ ...interval,
121
+ ...mergeIntervalStatistics(resolved.interval, args.statistics)
122
+ };
123
+ resolved = resolveIntervalComposite(program, full, policy);
124
+ }
125
+ return resolved;
126
+ }
@@ -7,9 +7,12 @@ import {
7
7
  } from "../../../core/validation.js";
8
8
  import { deriveArcSectors } from "../../../grammar/arcs.js";
9
9
  import { buildAnnularSectorCommands } from "../../../grammar/polarPaths.js";
10
- import { resolvePolarFrame } from "../../../grammar/polar.js";
11
- import { mapOrdinalValues } from "../../../grammar/scales/index.js";
12
- import { resolveGraphicBounds } from "../../../layout/canvas.js";
10
+ import {
11
+ mapOrdinalValues,
12
+ readScaleField
13
+ } from "../../../grammar/scales/index.js";
14
+ import { resolveCoordinatePolarFrame } from
15
+ "../../../materialization/coordinateBounds.js";
13
16
  import {
14
17
  canMaterializeArc,
15
18
  getSourceDependentMarkSteps
@@ -19,7 +22,10 @@ import { findLayer, resolveEligibleLayer } from "../../../selectors/layers.js";
19
22
  import { DEFAULT_COLORS } from "../../../theme/defaults.js";
20
23
  import { resolveMarkGraphicPlacement } from
21
24
  "../../../materialization/graphicHierarchy.js";
25
+ import { rematerializeExistingLegend } from "../../encodings/shared.js";
22
26
  import { rematerializeHighlightBaseline } from "../lifecycle.js";
27
+ import { mapScaleConsumerValues } from
28
+ "../../../materialization/scales/map.js";
23
29
  import {
24
30
  assertMarkAvailable,
25
31
  applyLayeredMarkInheritance,
@@ -30,13 +36,18 @@ import {
30
36
  resolveMarkId,
31
37
  validateMarkOptions
32
38
  } from "../shared.js";
39
+ import {
40
+ requestedStrokeDetails,
41
+ STROKE_STYLE_PROPERTIES
42
+ } from "../../../grammar/strokeStyle.js";
33
43
 
34
44
  const ARC_OPTIONS = Object.freeze([
35
- "innerRadius", "padAngle", "fill", "opacity", "stroke", "strokeWidth"
45
+ "innerRadius", "padAngle", "fill", "opacity", "stroke", "strokeWidth",
46
+ ...STROKE_STYLE_PROPERTIES
36
47
  ]);
37
48
  const CREATE_OPTIONS = Object.freeze(["id", "data", ...ARC_OPTIONS]);
38
49
  const EDIT_OPTIONS = Object.freeze(["target", ...ARC_OPTIONS]);
39
- const REMATERIALIZE_OPTIONS = Object.freeze(["id"]);
50
+ const REMATERIALIZE_OPTIONS = Object.freeze(["id", "scales"]);
40
51
 
41
52
  function validateInnerRadius(value) {
42
53
  if (!Number.isFinite(value) || value < 0 || value >= 1) {
@@ -47,9 +58,14 @@ function validateInnerRadius(value) {
47
58
  return value;
48
59
  }
49
60
 
50
- function normalizeConfig(args, previous = {}, { allowStrokeRemoval = false } = {}) {
61
+ function normalizeConfig(
62
+ args,
63
+ previous = {},
64
+ { allowStrokeRemoval = false, strokeDetails = {} } = {}
65
+ ) {
51
66
  let config = {
52
67
  ...previous,
68
+ ...strokeDetails,
53
69
  ...(Object.hasOwn(args, "innerRadius")
54
70
  ? { innerRadius: validateInnerRadius(args.innerRadius), innerRadiusExplicit: true }
55
71
  : {}),
@@ -86,13 +102,14 @@ function normalizeConfig(args, previous = {}, { allowStrokeRemoval = false } = {
86
102
  return config;
87
103
  }
88
104
 
89
- const createArcMark = action(
105
+ const createArcMark = /* @__PURE__ */ action(
90
106
  {
91
107
  op: "createArcMark",
92
108
  description: "Create a semantic arc mark and empty path collection."
93
109
  },
94
110
  function (args = {}) {
95
111
  validateMarkOptions(args, CREATE_OPTIONS, "createArcMark");
112
+ const strokeDetails = requestedStrokeDetails(args, "createArcMark");
96
113
  const id = resolveMarkId(this, args.id, {
97
114
  defaultId: "arc",
98
115
  label: "Arc mark id",
@@ -112,7 +129,7 @@ const createArcMark = action(
112
129
  opacity: 1,
113
130
  stroke: "#ffffff",
114
131
  strokeWidth: 1
115
- });
132
+ }, { strokeDetails });
116
133
  let created = this
117
134
  .editSemantic({ property: `layer[${id}].mark.type`, value: "arc" })
118
135
  .editSemantic({ property: `layer[${id}].data`, value: data });
@@ -141,13 +158,16 @@ function requireArc(program, id) {
141
158
  return { layer, dataset };
142
159
  }
143
160
 
144
- const rematerializeArcMark = action(
161
+ const rematerializeArcMark = /* @__PURE__ */ action(
145
162
  {
146
163
  op: "rematerializeArcMark",
147
164
  description: "Recompute concrete annular-sector paths."
148
165
  },
149
166
  function (args = {}) {
150
167
  validateMarkOptions(args, REMATERIALIZE_OPTIONS, "rematerializeArcMark");
168
+ if (args.scales !== undefined && typeof args.scales !== "boolean") {
169
+ throw new TypeError("rematerializeArcMark scales must be a boolean.");
170
+ }
151
171
  const id = validateUserId(args.id, "Arc mark id");
152
172
  const highlighted = rematerializeHighlightBaseline(this, {
153
173
  target: id,
@@ -163,15 +183,21 @@ const rematerializeArcMark = action(
163
183
  const thetaScaleId = layer.encoding.theta.scale;
164
184
  const radiusScaleId = layer.encoding?.radius?.scale;
165
185
  const colorScaleId = layer.encoding?.color?.scale;
166
- let resolved = this.rematerializeScale({ id: thetaScaleId });
167
- if (radiusScaleId !== undefined) {
186
+ const strokeScaleId = layer.encoding?.stroke?.scale;
187
+ let resolved = args.scales === false
188
+ ? this
189
+ : this.rematerializeScale({ id: thetaScaleId });
190
+ if (radiusScaleId !== undefined && args.scales !== false) {
168
191
  resolved = resolved.rematerializeScale({ id: radiusScaleId });
169
192
  }
170
- if (colorScaleId !== undefined) {
193
+ if (colorScaleId !== undefined && args.scales !== false) {
171
194
  resolved = resolved.rematerializeScale({ id: colorScaleId });
172
195
  }
196
+ if (strokeScaleId !== undefined && args.scales !== false) {
197
+ resolved = resolved.rematerializeScale({ id: strokeScaleId });
198
+ }
173
199
  const config = resolved.markConfigs[id] ?? {};
174
- const frame = resolvePolarFrame(resolveGraphicBounds(resolved));
200
+ const frame = resolveCoordinatePolarFrame(resolved, layer.coordinate);
175
201
  const derived = deriveArcSectors(dataset.values, layer, {
176
202
  thetaScale: resolved.resolvedScales[thetaScaleId],
177
203
  ...(radiusScaleId === undefined
@@ -195,25 +221,49 @@ const rematerializeArcMark = action(
195
221
  resolved.resolvedScales[colorScaleId].domain,
196
222
  resolved.resolvedScales[colorScaleId].range
197
223
  );
224
+ const strokeEncoding = layer.encoding?.stroke;
225
+ const strokeValues = strokeEncoding === undefined ? undefined : derived.sectors.map(
226
+ sector => {
227
+ const values = readScaleField(
228
+ sector.sourceIndices.map(index => dataset.values[index]),
229
+ strokeEncoding.field,
230
+ strokeEncoding.fieldType,
231
+ { temporalUnit: strokeEncoding.temporalUnit }
232
+ );
233
+ if (new Set(values).size !== 1) {
234
+ throw new Error("Arc stroke requires one value within each sector.");
235
+ }
236
+ return values[0];
237
+ }
238
+ );
239
+ const strokes = strokeValues === undefined ? undefined : mapScaleConsumerValues(
240
+ strokeValues,
241
+ resolved.resolvedScales[strokeScaleId],
242
+ "stroke"
243
+ );
198
244
  return editMarkGraphic(resolved, id, {
199
245
  length: commands.length,
200
246
  commands,
201
247
  fill: fills,
202
248
  opacity: config.opacity ?? 1,
203
- stroke: config.stroke === false ? "transparent" : config.stroke ?? "#ffffff",
249
+ stroke: strokes ?? (
250
+ config.stroke === false ? "transparent" : config.stroke ?? "#ffffff"
251
+ ),
204
252
  strokeWidth: config.stroke === false ? 0 : config.strokeWidth ?? 1,
205
- strokeDash: commands.map(() => [])
253
+ strokeDash: commands.map(() => []),
254
+ ...requestedStrokeDetails(config, "Arc mark")
206
255
  });
207
256
  }
208
257
  );
209
258
 
210
- const editArcMark = action(
259
+ const editArcMark = /* @__PURE__ */ action(
211
260
  {
212
261
  op: "editArcMark",
213
262
  description: "Edit arc geometry and appearance."
214
263
  },
215
264
  function (args = {}) {
216
265
  validateMarkOptions(args, EDIT_OPTIONS, "editArcMark");
266
+ const strokeDetails = requestedStrokeDetails(args, "editArcMark");
217
267
  if (Object.keys(args).every(key => key === "target")) {
218
268
  throw new Error(
219
269
  "editArcMark requires innerRadius, padAngle, fill, opacity, stroke, or strokeWidth."
@@ -230,6 +280,11 @@ const editArcMark = action(
230
280
  if (Object.hasOwn(args, "fill") && layer.encoding?.color !== undefined) {
231
281
  throw new Error("editArcMark fill cannot be combined with a color encoding.");
232
282
  }
283
+ if (Object.hasOwn(args, "stroke") && layer.encoding?.stroke !== undefined) {
284
+ throw new Error(
285
+ "editArcMark stroke conflicts with a field encoding; use encodeStroke with value to replace it."
286
+ );
287
+ }
233
288
  if (args.stroke === false && Object.hasOwn(args, "strokeWidth")) {
234
289
  throw new Error(
235
290
  "editArcMark cannot set strokeWidth while removing stroke."
@@ -245,15 +300,18 @@ const editArcMark = action(
245
300
  const next = this._withMarkConfig(
246
301
  layer.id,
247
302
  normalizeConfig(args, this.markConfigs[layer.id], {
248
- allowStrokeRemoval: true
303
+ allowStrokeRemoval: true,
304
+ strokeDetails
249
305
  })
250
306
  );
251
- if (!canMaterializeArc(next, layer)) return next;
252
- let rematerialized = next.rematerializeArcMark({ id: layer.id });
253
- for (const step of getSourceDependentMarkSteps(rematerialized, layer.id)) {
254
- rematerialized = rematerialized[step.op](step.args);
307
+ let materialized = next;
308
+ if (canMaterializeArc(next, layer)) {
309
+ materialized = next.rematerializeArcMark({ id: layer.id });
310
+ for (const step of getSourceDependentMarkSteps(materialized, layer.id)) {
311
+ materialized = materialized[step.op](step.args);
312
+ }
255
313
  }
256
- return rematerialized;
314
+ return rematerializeExistingLegend(materialized);
257
315
  }
258
316
  );
259
317
 
@@ -22,14 +22,20 @@ import { findLayer } from "../../../selectors/layers.js";
22
22
  import { validateCurveInterpolation } from "../../../grammar/curveCommands.js";
23
23
  import { resolveEligibleLayer } from "../../../selectors/layers.js";
24
24
  import { canMaterializeArea } from "../../../materialization/marks/index.js";
25
+ import { rematerializeExistingLegend } from "../../encodings/shared.js";
25
26
  import { findUpstreamTransform } from "../../../materialization/dataProvenance.js";
26
27
  import { resolveMarkGraphicPlacement } from
27
28
  "../../../materialization/graphicHierarchy.js";
28
29
  import { rematerializeHighlightBaseline } from "../lifecycle.js";
29
30
  import { resolveAreaMaterialization } from "./materialize.js";
31
+ import {
32
+ requestedStrokeDetails,
33
+ STROKE_STYLE_PROPERTIES
34
+ } from "../../../grammar/strokeStyle.js";
30
35
 
31
36
  const AREA_OPTIONS = Object.freeze([
32
- "fill", "opacity", "stroke", "strokeWidth", "curve"
37
+ "fill", "opacity", "stroke", "strokeWidth", "curve",
38
+ ...STROKE_STYLE_PROPERTIES
33
39
  ]);
34
40
  const CREATE_OPTIONS = Object.freeze(["id", "data", "missing", ...AREA_OPTIONS]);
35
41
  const EDIT_OPTIONS = Object.freeze(["target", "missing", ...AREA_OPTIONS]);
@@ -51,13 +57,14 @@ export function validateAreaCreateOutline(args, operation = "createAreaMark") {
51
57
  };
52
58
  }
53
59
 
54
- const createAreaMark = action(
60
+ const createAreaMark = /* @__PURE__ */ action(
55
61
  {
56
62
  op: "createAreaMark",
57
63
  description: "Create a semantic area mark and empty path collection."
58
64
  },
59
65
  function (args = {}) {
60
66
  validateMarkOptions(args, CREATE_OPTIONS, "createAreaMark");
67
+ const strokeDetails = requestedStrokeDetails(args, "createAreaMark");
61
68
  const id = resolveMarkId(this, args.id, {
62
69
  defaultId: "area",
63
70
  label: "Area mark id",
@@ -95,13 +102,14 @@ const createAreaMark = action(
95
102
  fill,
96
103
  opacity,
97
104
  ...(Object.hasOwn(args, "curve") ? { curve } : {}),
98
- ...(stroke === undefined ? {} : { stroke, strokeWidth })
105
+ ...(stroke === undefined ? {} : { stroke, strokeWidth }),
106
+ ...strokeDetails
99
107
  });
100
108
  return materializeInheritedMark(created, id);
101
109
  }
102
110
  );
103
111
 
104
- const configureAreaStrokeFromFill = action(
112
+ const configureAreaStrokeFromFill = /* @__PURE__ */ action(
105
113
  {
106
114
  op: "configureAreaStrokeFromFill",
107
115
  description: "Use each area path fill as its outline color."
@@ -130,7 +138,7 @@ const configureAreaStrokeFromFill = action(
130
138
  }
131
139
  );
132
140
 
133
- const rematerializeAreaMark = action(
141
+ const rematerializeAreaMark = /* @__PURE__ */ action(
134
142
  {
135
143
  op: "rematerializeAreaMark",
136
144
  description: "Recompute grouped closed area paths."
@@ -179,6 +187,7 @@ const rematerializeAreaMark = action(
179
187
  );
180
188
  }
181
189
  const colorEncoding = layer.encoding?.color;
190
+ const strokeEncoding = layer.encoding?.stroke;
182
191
  let resolved = args.scales === false
183
192
  ? this
184
193
  : this
@@ -187,8 +196,11 @@ const rematerializeAreaMark = action(
187
196
  if (args.scales !== false && colorEncoding?.scale !== undefined) {
188
197
  resolved = resolved.rematerializeScale({ id: colorEncoding.scale });
189
198
  }
199
+ if (args.scales !== false && strokeEncoding?.scale !== undefined) {
200
+ resolved = resolved.rematerializeScale({ id: strokeEncoding.scale });
201
+ }
190
202
  const config = this.markConfigs[id];
191
- const { paths, fills } = resolveAreaMaterialization({
203
+ const { paths, fills, strokes } = resolveAreaMaterialization({
192
204
  rows: dataset.values,
193
205
  layer,
194
206
  densityTransform,
@@ -196,7 +208,8 @@ const rematerializeAreaMark = action(
196
208
  config
197
209
  });
198
210
  const existingChildren = resolved.graphicSpec.objects[id].items ?? [];
199
- const hasOutline = config.stroke !== undefined || config.strokeFromFill === true;
211
+ const hasOutline = strokes !== undefined || config.stroke !== undefined ||
212
+ config.strokeFromFill === true;
200
213
  const removesOutline = !hasOutline && existingChildren.some(
201
214
  child => child.properties.stroke !== undefined
202
215
  );
@@ -210,21 +223,26 @@ const rematerializeAreaMark = action(
210
223
  fill: fills,
211
224
  opacity: config.opacity,
212
225
  ...(hasOutline ? {
213
- stroke: config.strokeFromFill === true ? fills : config.stroke,
214
- strokeWidth: config.strokeWidth
215
- } : {})
226
+ stroke: strokes ?? (config.strokeFromFill === true ? fills : config.stroke),
227
+ strokeWidth: config.strokeWidth ?? (strokes === undefined ? undefined : 1)
228
+ } : {}),
229
+ ...requestedStrokeDetails(config, "Area mark")
216
230
  });
217
231
  }
218
232
  );
219
233
 
220
- const editAreaMark = action(
234
+ const editAreaMark = /* @__PURE__ */ action(
221
235
  {
222
236
  op: "editAreaMark",
223
237
  description: "Edit area curve and constant appearance."
224
238
  },
225
239
  function (args = {}) {
226
240
  validateMarkOptions(args, EDIT_OPTIONS, "editAreaMark");
227
- const changes = ["fill", "opacity", "stroke", "strokeWidth", "curve", "missing"];
241
+ const strokeDetails = requestedStrokeDetails(args, "editAreaMark");
242
+ const changes = [
243
+ "fill", "opacity", "stroke", "strokeWidth", "curve", "missing",
244
+ ...STROKE_STYLE_PROPERTIES
245
+ ];
228
246
  if (!changes.some(key => Object.hasOwn(args, key))) {
229
247
  throw new Error(
230
248
  "editAreaMark requires fill, opacity, stroke, strokeWidth, or curve."
@@ -243,11 +261,17 @@ const editAreaMark = action(
243
261
  "editAreaMark fill cannot be combined with a color encoding."
244
262
  );
245
263
  }
264
+ if (Object.hasOwn(args, "stroke") && layer.encoding?.stroke !== undefined) {
265
+ throw new Error(
266
+ "editAreaMark stroke conflicts with a field encoding; use encodeStroke with value to replace it."
267
+ );
268
+ }
246
269
  if (args.stroke === false && Object.hasOwn(args, "strokeWidth")) {
247
270
  throw new Error("editAreaMark cannot set strokeWidth while removing stroke.");
248
271
  }
249
272
 
250
273
  let config = { ...this.markConfigs[layer.id] };
274
+ Object.assign(config, strokeDetails);
251
275
  if (Object.hasOwn(args, "fill")) {
252
276
  config.fill = validateNonEmptyString(args.fill, "Area fill");
253
277
  if (config.errorBand !== undefined) config.errorBand = { ...config.errorBand, fill: config.fill };
@@ -298,9 +322,10 @@ const editAreaMark = action(
298
322
  }
299
323
  next = next.editSemantic({ property: `layer[${layer.id}].mark.missing`, value: missing });
300
324
  }
301
- return canMaterializeArea(next, layer)
325
+ const materialized = canMaterializeArea(next, layer)
302
326
  ? next.rematerializeAreaMark({ id: layer.id })
303
327
  : next;
328
+ return rematerializeExistingLegend(materialized);
304
329
  }
305
330
  );
306
331
 
@@ -8,6 +8,8 @@ import {
8
8
  mapContinuousScaleValues,
9
9
  mapOrdinalValues
10
10
  } from "../../../grammar/scales/index.js";
11
+ import { mapScaleConsumerValues } from
12
+ "../../../materialization/scales/map.js";
11
13
  import { buildAreaCurvePathCommands } from
12
14
  "../../../grammar/curveCommands.js";
13
15
  import { buildLinearPathCommands } from
@@ -171,5 +173,19 @@ export function resolveAreaMaterialization({
171
173
  resolvedScales[colorEncoding.scale].domain,
172
174
  resolvedScales[colorEncoding.scale].range
173
175
  );
174
- return { paths, fills };
176
+ const strokeEncoding = layer.encoding?.stroke;
177
+ const strokes = strokeEncoding?.scale === undefined
178
+ ? undefined
179
+ : mapScaleConsumerValues(
180
+ derivePathSeriesFieldValues(
181
+ rows,
182
+ derived.series,
183
+ strokeEncoding.field,
184
+ "stroke",
185
+ strokeEncoding
186
+ ),
187
+ resolvedScales[strokeEncoding.scale],
188
+ "stroke"
189
+ );
190
+ return { paths, fills, strokes };
175
191
  }
@@ -10,18 +10,24 @@ import {
10
10
  } from "../shared.js";
11
11
  import { resolveMarkGraphicPlacement } from
12
12
  "../../../materialization/graphicHierarchy.js";
13
+ import { requestedRectStyleDetails } from
14
+ "../../../grammar/roundedRect.js";
15
+ import { STROKE_STYLE_PROPERTIES } from
16
+ "../../../grammar/strokeStyle.js";
13
17
 
14
18
  const CREATE_OPTIONS = Object.freeze([
15
- "id", "data", "fill", "opacity", "stroke", "strokeWidth"
19
+ "id", "data", "fill", "opacity", "stroke", "strokeWidth",
20
+ "cornerRadius", ...STROKE_STYLE_PROPERTIES
16
21
  ]);
17
22
 
18
- export const createBarMark = action(
23
+ export const createBarMark = /* @__PURE__ */ action(
19
24
  {
20
25
  op: "createBarMark",
21
26
  description: "Create a semantic bar mark and empty rect collection."
22
27
  },
23
28
  function (args = {}) {
24
29
  validateMarkOptions(args, CREATE_OPTIONS, "createBarMark");
30
+ requestedRectStyleDetails(args, "createBarMark");
25
31
  const id = resolveMarkId(this, args.id, {
26
32
  defaultId: "bar",
27
33
  label: "Bar mark id",
@@ -56,7 +62,10 @@ export const createBarMark = action(
56
62
  });
57
63
  created = materializeInheritedMark(created, id);
58
64
  const appearance = Object.fromEntries(
59
- ["fill", "opacity", "stroke", "strokeWidth"]
65
+ [
66
+ "fill", "opacity", "stroke", "strokeWidth", "cornerRadius",
67
+ ...STROKE_STYLE_PROPERTIES
68
+ ]
60
69
  .filter(property => Object.hasOwn(args, property))
61
70
  .map(property => [property, args[property]])
62
71
  );
@@ -9,19 +9,29 @@ import { canMaterializeBar } from "../../../materialization/marks/index.js";
9
9
  import { DEFAULT_BAR_STROKE_WIDTH } from "../../../materialization/bars/resolve.js";
10
10
  import { resolveEligibleLayer } from "../../../selectors/layers.js";
11
11
  import { validateMarkOptions } from "../shared.js";
12
+ import { requestedRectStyleDetails } from
13
+ "../../../grammar/roundedRect.js";
14
+ import { STROKE_STYLE_PROPERTIES } from
15
+ "../../../grammar/strokeStyle.js";
16
+ import { rematerializeExistingLegend } from "../../encodings/shared.js";
12
17
 
13
18
  const EDIT_OPTIONS = Object.freeze([
14
- "target", "fill", "opacity", "stroke", "strokeWidth"
19
+ "target", "fill", "opacity", "stroke", "strokeWidth", "cornerRadius",
20
+ ...STROKE_STYLE_PROPERTIES
15
21
  ]);
16
22
 
17
- export const editBarMark = action(
23
+ export const editBarMark = /* @__PURE__ */ action(
18
24
  {
19
25
  op: "editBarMark",
20
26
  description: "Edit whole-bar fill, opacity, and outline appearance."
21
27
  },
22
28
  function (args = {}) {
23
29
  validateMarkOptions(args, EDIT_OPTIONS, "editBarMark");
24
- const changes = ["fill", "opacity", "stroke", "strokeWidth"];
30
+ const styleDetails = requestedRectStyleDetails(args, "editBarMark");
31
+ const changes = [
32
+ "fill", "opacity", "stroke", "strokeWidth", "cornerRadius",
33
+ ...STROKE_STYLE_PROPERTIES
34
+ ];
25
35
  if (!changes.some(key => Object.hasOwn(args, key))) {
26
36
  throw new Error(
27
37
  "editBarMark requires fill, opacity, stroke, or strokeWidth."
@@ -40,6 +50,11 @@ export const editBarMark = action(
40
50
  "editBarMark fill cannot be combined with a color encoding."
41
51
  );
42
52
  }
53
+ if (Object.hasOwn(args, "stroke") && layer.encoding?.stroke !== undefined) {
54
+ throw new Error(
55
+ "editBarMark stroke conflicts with a field encoding; use encodeStroke with value to replace it."
56
+ );
57
+ }
43
58
  if (args.stroke === false && Object.hasOwn(args, "strokeWidth")) {
44
59
  throw new Error(
45
60
  "editBarMark cannot set strokeWidth while removing stroke."
@@ -48,6 +63,7 @@ export const editBarMark = action(
48
63
 
49
64
  const config = { ...this.markConfigs[layer.id] };
50
65
  const appearance = { ...config.barAppearance };
66
+ Object.assign(appearance, styleDetails);
51
67
  if (Object.hasOwn(args, "fill")) {
52
68
  appearance.fill = validateNonEmptyString(args.fill, "Bar fill");
53
69
  }
@@ -83,8 +99,9 @@ export const editBarMark = action(
83
99
  ...config,
84
100
  barAppearance: appearance
85
101
  });
86
- return canMaterializeBar(next, layer)
102
+ const materialized = canMaterializeBar(next, layer)
87
103
  ? next.rematerializeBarMark({ id: layer.id })
88
104
  : next;
105
+ return rematerializeExistingLegend(materialized);
89
106
  }
90
107
  );