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
@@ -2,42 +2,191 @@ import { isDiscretizedColorScaleType } from "../../../grammar/scales/types.js";
2
2
  import { normalizeContinuousLegend } from "./continuous/common.js";
3
3
  import { DEFAULT_GRADIENT_SIZE } from "./continuous/gradient.js";
4
4
  import { normalizeIntervalLegend } from "./continuous/interval.js";
5
+ import {
6
+ describeLegendBlock,
7
+ legendBlockDescriptors,
8
+ resolveLegendBlock
9
+ } from "./target.js";
10
+ import { validateLegendBlockOverride } from "./blocks.js";
5
11
 
6
- const family = type => type === "sequential" ? "gradient"
7
- : isDiscretizedColorScaleType(type) ? "interval" : undefined;
12
+ const family = (channel, type) => type === "sequential"
13
+ ? channel === "stroke" ? "strokeGradient" : "gradient"
14
+ : isDiscretizedColorScaleType(type)
15
+ ? channel === "stroke" ? "strokeInterval" : "interval"
16
+ : type === "ordinal"
17
+ ? channel === "stroke" ? "stroke" : "color"
18
+ : undefined;
8
19
  const same = (a, b) => JSON.stringify(a) === JSON.stringify(b);
9
20
 
10
- export function planColorLegendTransition(program, scale, nextType) {
11
- const from = family(scale.type), to = family(nextType);
21
+ function categoricalFamilyCustom(program, kind, stored) {
22
+ const side = ["left", "right"].includes(stored.position);
23
+ const direction = side ? "vertical" : "horizontal";
24
+ const itemGap = side ? 28 : stored.position === "top" ? 24 : 20;
25
+ const order = program.semanticSpec.guides.legend?.[kind]?.order;
26
+ return stored.inferredSymbol !== true ||
27
+ stored.direction !== direction ||
28
+ (stored.columns !== undefined && !(side && stored.columns === 1)) ||
29
+ stored.itemGap !== itemGap || stored.layout !== "edge" ||
30
+ order !== undefined;
31
+ }
32
+
33
+ function planChannelLegendTransition(program, scale, nextType, channel) {
34
+ const from = family(channel, scale.type), to = family(channel, nextType);
12
35
  if (from === undefined || to === undefined || from === to) return undefined;
13
36
  const stored = program.guideConfigs.legend?.[from];
14
- if (stored?.scale !== scale.id) return undefined;
37
+ if ((stored?.scale ?? stored?.scales?.[0]) !== scale.id) return undefined;
38
+ const oldDescriptor = describeLegendBlock(program, from, stored);
39
+ const overrideKeys = Object.keys(stored.blockOverrides ?? {});
40
+ if (overrideKeys.some(key => key !== oldDescriptor.key)) {
41
+ throw new Error(`${channel} legend transition found stale legend block overrides.`);
42
+ }
43
+ const blockOverride = stored.blockOverrides?.[oldDescriptor.key];
15
44
  const side = ["left", "right"].includes(stored.position);
16
- const defaults = from === "gradient" ? normalizeContinuousLegend({ position: stored.position }, "gradient")
45
+ const categorical = ["color", "stroke"].includes(from);
46
+ const gradientFamily = from.toLowerCase().endsWith("gradient");
47
+ const defaults = gradientFamily ? normalizeContinuousLegend({ position: stored.position }, "gradient")
17
48
  : normalizeIntervalLegend({ position: stored.position });
18
- const custom = from === "gradient"
49
+ const comparableSymbol = channel === "stroke" && stored.inferredStrokeWidth === true
50
+ ? { ...stored.symbol, strokeWidth: defaults.symbol?.strokeWidth }
51
+ : stored.symbol;
52
+ const custom = categorical
53
+ ? categoricalFamilyCustom(program, from, stored)
54
+ : gradientFamily
19
55
  ? stored.count !== defaults.count || !same(stored.gradient, DEFAULT_GRADIENT_SIZE) || stored.itemGap !== defaults.itemGap
20
- : !same(stored.symbol, defaults.symbol) || stored.itemGap !== defaults.itemGap ||
56
+ : !same(comparableSymbol, defaults.symbol) || stored.itemGap !== defaults.itemGap ||
21
57
  stored.direction !== defaults.direction || (stored.columns !== undefined && !(side && stored.columns === 1));
22
58
  if (custom) {
23
- throw new Error("Color legend transition cannot discard custom family settings; remove and recreate the legend explicitly.");
59
+ throw new Error(`${channel} legend transition cannot discard custom family settings; remove and recreate the legend explicitly.`);
60
+ }
61
+ if (blockOverride?.title !== undefined) {
62
+ throw new Error(`${channel} legend transition cannot distribute a legend block title; edit the destination block explicitly.`);
63
+ }
64
+ if (blockOverride?.labelMap !== undefined) {
65
+ throw new Error(`${channel} legend transition cannot distribute a legend block labelMap; edit the destination block explicitly.`);
66
+ }
67
+ if (blockOverride?.symbol !== undefined && ["gradient", "strokeGradient"].includes(to)) {
68
+ throw new Error(`${channel} legend transition cannot apply symbol overrides to a gradient block.`);
24
69
  }
25
70
  const args = {
26
- target: stored.target, channels: ["color"], position: stored.position,
71
+ target: stored.target, channels: [channel], position: stored.position,
27
72
  labels: stored.labels, titleStyle: stored.titleStyle, border: stored.border,
28
73
  align: stored.align, offset: stored.offset, titlePosition: stored.titlePosition,
29
74
  ...(stored.inferredTitle ? {} : { title: stored.title })
30
75
  };
31
76
  try {
32
- if (to === "interval") normalizeIntervalLegend(args);
33
- else normalizeContinuousLegend(args, "gradient");
77
+ if (["interval", "strokeInterval"].includes(to)) {
78
+ normalizeIntervalLegend({ ...args, channels: undefined });
79
+ }
80
+ else if (["gradient", "strokeGradient"].includes(to)) {
81
+ normalizeContinuousLegend(args, "gradient");
82
+ }
34
83
  } catch (error) {
35
- throw new Error(`Color legend transition has incompatible layout or style: ${error.message}`);
84
+ throw new Error(`${channel} legend transition has incompatible layout or style: ${error.message}`);
36
85
  }
37
- return { args, titleVisible: stored.titleVisible !== false };
86
+ return { args, channel, titleVisible: stored.titleVisible !== false, blockOverride };
87
+ }
88
+
89
+ export function planColorLegendTransitions(program, scale, nextType) {
90
+ return ["color", "stroke"].flatMap(channel => {
91
+ const plan = planChannelLegendTransition(program, scale, nextType, channel);
92
+ return plan === undefined ? [] : [plan];
93
+ });
38
94
  }
39
95
 
40
96
  export function applyColorLegendTransition(program, plan) {
41
- const next = program.createLegend(plan.args);
42
- return plan.titleVisible ? next : next.editLegend({ target: plan.args.target, title: false });
97
+ let next = program.createLegend(plan.args);
98
+ if (!plan.titleVisible) {
99
+ next = next.editLegend({ target: plan.args.target, title: false });
100
+ }
101
+ if (plan.blockOverride === undefined) return next;
102
+ const descriptor = resolveLegendBlock(next, {
103
+ target: plan.args.target,
104
+ channel: plan.channel
105
+ }, `${plan.channel} legend transition`);
106
+ validateLegendBlockOverride(descriptor, plan.blockOverride);
107
+ next = next._withLegendConfig(descriptor.kind, {
108
+ ...descriptor.config,
109
+ blockOverrides: { [descriptor.key]: plan.blockOverride }
110
+ });
111
+ return next.rematerializeLegend();
112
+ }
113
+
114
+ function intersects(left, right) {
115
+ return left.channels.some(channel => right.channels.includes(channel));
116
+ }
117
+
118
+ function explicitOrder(program, descriptor) {
119
+ if (descriptor.family !== "categorical") return undefined;
120
+ return program.semanticSpec.guides.legend?.[descriptor.kind]?.order;
121
+ }
122
+
123
+ function sameBlockValue(left, right) {
124
+ if (Object.is(left, right)) return true;
125
+ if (Array.isArray(left) && Array.isArray(right)) {
126
+ return left.length === right.length &&
127
+ left.every((value, index) => sameBlockValue(value, right[index]));
128
+ }
129
+ if (left !== null && right !== null &&
130
+ typeof left === "object" && typeof right === "object" &&
131
+ !Array.isArray(left) && !Array.isArray(right)) {
132
+ const leftKeys = Object.keys(left).sort();
133
+ const rightKeys = Object.keys(right).sort();
134
+ return leftKeys.length === rightKeys.length &&
135
+ leftKeys.every((key, index) => key === rightKeys[index] &&
136
+ sameBlockValue(left[key], right[key]));
137
+ }
138
+ return false;
139
+ }
140
+
141
+ function transitionError(target, oldDescriptors, nextDescriptor, field) {
142
+ const oldKeys = oldDescriptors.map(item => item.key).join(", ");
143
+ throw new Error(
144
+ `Legend block transition for target "${target}" from ${oldKeys} to ${nextDescriptor.key} conflicts on ${field}.`
145
+ );
146
+ }
147
+
148
+ function withoutBlockOverrides(config) {
149
+ const { blockOverrides: _removed, ...rest } = config;
150
+ return rest;
151
+ }
152
+
153
+ export function planLegendBlockTransitions(program, target, plans) {
154
+ const oldDescriptors = legendBlockDescriptors(program, target);
155
+ const nextDescriptors = plans.map(plan =>
156
+ describeLegendBlock(program, plan.kind, plan.config));
157
+ return plans.map((plan, index) => {
158
+ const descriptor = nextDescriptors[index];
159
+ const incoming = oldDescriptors.filter(old => intersects(old, descriptor));
160
+ let override;
161
+ if (incoming.length === 1 && incoming[0].key === descriptor.key) {
162
+ override = incoming[0].config.blockOverrides?.[incoming[0].key];
163
+ } else if (incoming.length === 1) {
164
+ const old = incoming[0];
165
+ override = old.config.blockOverrides?.[old.key];
166
+ if (override?.title !== undefined) {
167
+ transitionError(target, incoming, descriptor, "title");
168
+ }
169
+ if (override?.labelMap !== undefined) {
170
+ transitionError(target, incoming, descriptor, "labelMap");
171
+ }
172
+ } else if (incoming.length > 1) {
173
+ const overrides = incoming.map(old => old.config.blockOverrides?.[old.key]);
174
+ if (!overrides.every(value => sameBlockValue(value, overrides[0]))) {
175
+ transitionError(target, incoming, descriptor, "block override");
176
+ }
177
+ const orders = incoming.map(old => explicitOrder(program, old));
178
+ if (!orders.every(value => sameBlockValue(value, orders[0]))) {
179
+ transitionError(target, incoming, descriptor, "order");
180
+ }
181
+ override = overrides[0];
182
+ }
183
+ if (override !== undefined) validateLegendBlockOverride(descriptor, override);
184
+ const config = withoutBlockOverrides(plan.config);
185
+ return {
186
+ ...plan,
187
+ config: override === undefined
188
+ ? config
189
+ : { ...config, blockOverrides: { [descriptor.key]: override } }
190
+ };
191
+ });
43
192
  }
@@ -8,7 +8,7 @@ import {
8
8
  validateEnabledAxisComponents
9
9
  } from "../../axes/components.js";
10
10
  import {
11
- LABEL_EDIT_OPTIONS,
11
+ labelEditOptions,
12
12
  LINE_EDIT_OPTIONS,
13
13
  prefix,
14
14
  resolveAngle,
@@ -54,7 +54,7 @@ export function validatePolarAxisArgs(kind, args, operation) {
54
54
  if (Object.hasOwn(args.ticksAndLabels, "labels")) {
55
55
  validateObject(
56
56
  args.ticksAndLabels.labels,
57
- LABEL_EDIT_OPTIONS.filter(key => !["count", "values"].includes(key)),
57
+ labelEditOptions(kind).filter(key => !["count", "values"].includes(key)),
58
58
  `${operation}.ticksAndLabels.labels`
59
59
  );
60
60
  }
@@ -131,7 +131,7 @@ function validateAxisEditArgs(kind, args, operation) {
131
131
  validateModeOptions(args.ticks, `${operation}.ticks`);
132
132
  }
133
133
  if (Object.hasOwn(args, "labels") && args.labels !== false) {
134
- validateObject(args.labels, LABEL_EDIT_OPTIONS, `${operation}.labels`);
134
+ validateObject(args.labels, labelEditOptions(kind), `${operation}.labels`);
135
135
  validateModeOptions(args.labels, `${operation}.labels`);
136
136
  }
137
137
  if (args.ticksAndLabels !== undefined &&
@@ -155,7 +155,7 @@ function validateAxisEditArgs(kind, args, operation) {
155
155
  if (args.ticksAndLabels.labels !== undefined) {
156
156
  validateObject(
157
157
  args.ticksAndLabels.labels,
158
- LABEL_EDIT_OPTIONS.filter(key => !["count", "values"].includes(key)),
158
+ labelEditOptions(kind).filter(key => !["count", "values"].includes(key)),
159
159
  `${operation}.ticksAndLabels.labels`
160
160
  );
161
161
  }
@@ -228,7 +228,7 @@ function makeEditAxis(kind) {
228
228
  });
229
229
  }
230
230
 
231
- export const createThetaAxis = makeCreateAxis("theta");
232
- export const createRadialAxis = makeCreateAxis("radius");
233
- export const editThetaAxis = makeEditAxis("theta");
234
- export const editRadialAxis = makeEditAxis("radius");
231
+ export const createThetaAxis = /* @__PURE__ */ makeCreateAxis("theta");
232
+ export const createRadialAxis = /* @__PURE__ */ makeCreateAxis("radius");
233
+ export const editThetaAxis = /* @__PURE__ */ makeEditAxis("theta");
234
+ export const editRadialAxis = /* @__PURE__ */ makeEditAxis("radius");
@@ -20,8 +20,8 @@ import {
20
20
  } from "../resolve.js";
21
21
  import {
22
22
  componentResources,
23
- LABEL_CREATE_OPTIONS,
24
- LABEL_EDIT_OPTIONS,
23
+ labelCreateOptions,
24
+ labelEditOptions,
25
25
  operations,
26
26
  prefix,
27
27
  resolveAngle,
@@ -30,9 +30,11 @@ import {
30
30
  validateObject,
31
31
  withAxisSemantics
32
32
  } from "./shared.js";
33
+ import { normalizeDisplayLabelMap } from
34
+ "../../../../grammar/displayLabels.js";
33
35
 
34
36
  function labelGeometry(program, kind, config, angle = resolveAngle(program, kind, {})) {
35
- const frame = resolvePolarFrameForProgram(program);
37
+ const frame = resolvePolarFrameForProgram(program, config.coordinate);
36
38
  const mapped = mapPolarGuideValues(program, config);
37
39
  const text = formatPolarGuideValues(program, config, mapped.values);
38
40
  const geometry = {
@@ -64,7 +66,7 @@ function labelGeometry(program, kind, config, angle = resolveAngle(program, kind
64
66
  textAlign: geometry.textAlign[index],
65
67
  textBaseline: geometry.textBaseline[index]
66
68
  }))
67
- });
69
+ }, program.materializationConfigs.textMetrics);
68
70
  return geometry;
69
71
  }
70
72
 
@@ -115,6 +117,23 @@ function resolveLabelConfig(program, kind, args, resources, previous) {
115
117
  fontWeight: args.fontWeight ?? previous?.fontWeight ??
116
118
  POLAR_AXIS_DEFAULTS.labels.fontWeight
117
119
  };
120
+ const labelScale = program.resolvedScales[resources.scale];
121
+ if (Object.hasOwn(args, "labelMap")) {
122
+ if (kind !== "theta" || !["ordinal", "band", "point"].includes(labelScale?.type)) {
123
+ throw new Error(`${prefix(kind)} axis labelMap requires a categorical theta scale.`);
124
+ }
125
+ if (args.labelMap === "auto") delete config.labelMap;
126
+ else {
127
+ config.labelMap = normalizeDisplayLabelMap(
128
+ args.labelMap,
129
+ `${prefix(kind)} axis labelMap`
130
+ );
131
+ }
132
+ }
133
+ if (config.labelMap !== undefined &&
134
+ (kind !== "theta" || !["ordinal", "band", "point"].includes(labelScale?.type))) {
135
+ throw new Error(`${prefix(kind)} axis labelMap requires a categorical theta scale.`);
136
+ }
118
137
  validatePolarTickConfig(config, `${kind}-axis labels`);
119
138
  validateNonNegativeFinite(config.offset, "Polar axis label offset");
120
139
  validatePolarLabelFormat(config.format);
@@ -128,7 +147,7 @@ function makeEditLabels(kind) {
128
147
  op: operation.edit,
129
148
  description: `Edit the Polar ${kind}-axis labels.`
130
149
  }, function (args = {}) {
131
- validateObject(args, LABEL_EDIT_OPTIONS, operation.edit);
150
+ validateObject(args, labelEditOptions(kind), operation.edit);
132
151
  validateModeOptions(args, operation.edit);
133
152
  const names = polarGuideNames(kind);
134
153
  const previous = this.guideConfigs.axis?.[kind]?.labels;
@@ -172,7 +191,7 @@ function makeCreateLabels(kind) {
172
191
  op: operation.create,
173
192
  description: `Create the Polar ${kind}-axis labels.`
174
193
  }, function (args = {}) {
175
- validateComponentCreateArgs(kind, args, LABEL_CREATE_OPTIONS, operation.create);
194
+ validateComponentCreateArgs(kind, args, labelCreateOptions(kind), operation.create);
176
195
  validateModeOptions(args, operation.create);
177
196
  const names = polarGuideNames(kind);
178
197
  if (this.graphicSpec.objects[names.labels] !== undefined) {
@@ -199,7 +218,7 @@ function makeCreateLabels(kind) {
199
218
  });
200
219
  }
201
220
 
202
- export const createThetaAxisLabels = makeCreateLabels("theta");
203
- export const createRadialAxisLabels = makeCreateLabels("radius");
204
- export const editThetaAxisLabels = makeEditLabels("theta");
205
- export const editRadialAxisLabels = makeEditLabels("radius");
221
+ export const createThetaAxisLabels = /* @__PURE__ */ makeCreateLabels("theta");
222
+ export const createRadialAxisLabels = /* @__PURE__ */ makeCreateLabels("radius");
223
+ export const editThetaAxisLabels = /* @__PURE__ */ makeEditLabels("theta");
224
+ export const editRadialAxisLabels = /* @__PURE__ */ makeEditLabels("radius");
@@ -1,3 +1,4 @@
1
+ import { editGraphicProperties } from "../../../primitives/graphicProperties.js";
1
2
  import { action } from "../../../../core/action.js";
2
3
  import {
3
4
  buildPolarCircleCommands,
@@ -23,8 +24,8 @@ import {
23
24
  withAxisSemantics
24
25
  } from "./shared.js";
25
26
 
26
- function lineGeometry(program, kind, angle, scale) {
27
- const frame = resolvePolarFrameForProgram(program);
27
+ function lineGeometry(program, kind, angle, scale, coordinate) {
28
+ const frame = resolvePolarFrameForProgram(program, coordinate);
28
29
  if (kind === "theta") {
29
30
  return { commands: buildPolarCircleCommands(frame, frame.availableRadius) };
30
31
  }
@@ -52,22 +53,21 @@ function makeEditLine(kind) {
52
53
  const config = { ...previous, ...args };
53
54
  validatePolarLineStyle(config, `${prefix(kind)} axis line`);
54
55
  const angle = resolveAngle(this, kind, {});
55
- const geometry = lineGeometry(this, kind, angle, previous.scale);
56
+ const geometry = lineGeometry(
57
+ this,
58
+ kind,
59
+ angle,
60
+ previous.scale,
61
+ previous.coordinate
62
+ );
56
63
  let next = this._withGuideConfig(kind, "line", config);
57
64
  for (const [property, value] of Object.entries(geometry)) {
58
65
  next = next.editGraphics({ target: names.line, property, value });
59
66
  }
60
- return next
61
- .editGraphics({
62
- target: names.line,
63
- property: "stroke",
64
- value: config.color
65
- })
66
- .editGraphics({
67
- target: names.line,
68
- property: "strokeWidth",
69
- value: config.lineWidth
70
- });
67
+ return editGraphicProperties(next, names.line, {
68
+ stroke: config.color,
69
+ strokeWidth: config.lineWidth
70
+ });
71
71
  });
72
72
  }
73
73
 
@@ -91,7 +91,7 @@ function makeCreateLine(kind) {
91
91
  lineWidth: args.lineWidth ?? POLAR_AXIS_DEFAULTS.line.lineWidth
92
92
  };
93
93
  validatePolarLineStyle(config, `${prefix(kind)} axis line`);
94
- lineGeometry(this, kind, angle, resources.scale);
94
+ lineGeometry(this, kind, angle, resources.scale, resources.coordinate);
95
95
  let next = withAxisSemantics(this, kind, resources);
96
96
  if (kind === "radius" &&
97
97
  next.guideConfigs.axis?.radius?.layout === undefined) {
@@ -108,7 +108,7 @@ function makeCreateLine(kind) {
108
108
  });
109
109
  }
110
110
 
111
- export const createThetaAxisLine = makeCreateLine("theta");
112
- export const createRadialAxisLine = makeCreateLine("radius");
113
- export const editThetaAxisLine = makeEditLine("theta");
114
- export const editRadialAxisLine = makeEditLine("radius");
111
+ export const createThetaAxisLine = /* @__PURE__ */ makeCreateLine("theta");
112
+ export const createRadialAxisLine = /* @__PURE__ */ makeCreateLine("radius");
113
+ export const editThetaAxisLine = /* @__PURE__ */ makeEditLine("theta");
114
+ export const editRadialAxisLine = /* @__PURE__ */ makeEditLine("radius");
@@ -26,6 +26,22 @@ export const LABEL_EDIT_OPTIONS = Object.freeze([
26
26
  "count", "values", "offset", "format", "color", "fontSize",
27
27
  "fontFamily", "fontWeight"
28
28
  ]);
29
+ const THETA_LABEL_CREATE_OPTIONS = Object.freeze([
30
+ ...LABEL_CREATE_OPTIONS,
31
+ "labelMap"
32
+ ]);
33
+ const THETA_LABEL_EDIT_OPTIONS = Object.freeze([
34
+ ...LABEL_EDIT_OPTIONS,
35
+ "labelMap"
36
+ ]);
37
+
38
+ export function labelCreateOptions(kind) {
39
+ return kind === "theta" ? THETA_LABEL_CREATE_OPTIONS : LABEL_CREATE_OPTIONS;
40
+ }
41
+
42
+ export function labelEditOptions(kind) {
43
+ return kind === "theta" ? THETA_LABEL_EDIT_OPTIONS : LABEL_EDIT_OPTIONS;
44
+ }
29
45
  export const TITLE_CREATE_OPTIONS = Object.freeze([
30
46
  "scale", "coordinate", "angle", "text", "offset", "color", "fontSize",
31
47
  "fontFamily", "fontWeight", "position"
@@ -1,3 +1,4 @@
1
+ import { editGraphicProperties } from "../../../primitives/graphicProperties.js";
1
2
  import { action } from "../../../../core/action.js";
2
3
  import { validateNonNegativeFinite } from "../../../../core/validation.js";
3
4
  import {
@@ -29,7 +30,7 @@ import {
29
30
  } from "./shared.js";
30
31
 
31
32
  function tickGeometry(program, kind, config, angle = resolveAngle(program, kind, {})) {
32
- const frame = resolvePolarFrameForProgram(program);
33
+ const frame = resolvePolarFrameForProgram(program, config.coordinate);
33
34
  const mapped = mapPolarGuideValues(program, config);
34
35
  return {
35
36
  values: mapped.values,
@@ -112,17 +113,10 @@ function makeEditTicks(kind) {
112
113
  value: geometry[property]
113
114
  });
114
115
  }
115
- return next
116
- .editGraphics({
117
- target: names.ticks,
118
- property: "stroke",
119
- value: config.color
120
- })
121
- .editGraphics({
122
- target: names.ticks,
123
- property: "strokeWidth",
124
- value: config.lineWidth
125
- });
116
+ return editGraphicProperties(next, names.ticks, {
117
+ stroke: config.color,
118
+ strokeWidth: config.lineWidth
119
+ });
126
120
  });
127
121
  }
128
122
 
@@ -159,7 +153,7 @@ function makeCreateTicks(kind) {
159
153
  });
160
154
  }
161
155
 
162
- export const createThetaAxisTicks = makeCreateTicks("theta");
163
- export const createRadialAxisTicks = makeCreateTicks("radius");
164
- export const editThetaAxisTicks = makeEditTicks("theta");
165
- export const editRadialAxisTicks = makeEditTicks("radius");
156
+ export const createThetaAxisTicks = /* @__PURE__ */ makeCreateTicks("theta");
157
+ export const createRadialAxisTicks = /* @__PURE__ */ makeCreateTicks("radius");
158
+ export const editThetaAxisTicks = /* @__PURE__ */ makeEditTicks("theta");
159
+ export const editRadialAxisTicks = /* @__PURE__ */ makeEditTicks("radius");
@@ -30,7 +30,7 @@ import {
30
30
  } from "./shared.js";
31
31
 
32
32
  function titleGeometry(program, kind, config, angle = resolveAngle(program, kind, {})) {
33
- const frame = resolvePolarFrameForProgram(program);
33
+ const frame = resolvePolarFrameForProgram(program, config.coordinate);
34
34
  return kind === "theta"
35
35
  ? resolveThetaAxisTitle({ frame, offset: config.offset })
36
36
  : resolveRadialAxisTitle({
@@ -52,7 +52,7 @@ function validateTitleGeometry(program, kind, config, geometry, text) {
52
52
  fontFamily: config.fontFamily,
53
53
  fontWeight: config.fontWeight
54
54
  }]
55
- });
55
+ }, program.materializationConfigs.textMetrics);
56
56
  }
57
57
 
58
58
  function resolveTitleConfig(kind, args, resources, previous) {
@@ -177,7 +177,7 @@ function makeCreateTitle(kind) {
177
177
  });
178
178
  }
179
179
 
180
- export const createThetaAxisTitle = makeCreateTitle("theta");
181
- export const createRadialAxisTitle = makeCreateTitle("radius");
182
- export const editThetaAxisTitle = makeEditTitle("theta");
183
- export const editRadialAxisTitle = makeEditTitle("radius");
180
+ export const createThetaAxisTitle = /* @__PURE__ */ makeCreateTitle("theta");
181
+ export const createRadialAxisTitle = /* @__PURE__ */ makeCreateTitle("radius");
182
+ export const editThetaAxisTitle = /* @__PURE__ */ makeEditTitle("theta");
183
+ export const editRadialAxisTitle = /* @__PURE__ */ makeEditTitle("radius");
@@ -1,3 +1,4 @@
1
+ import { editGraphicProperties } from "../../primitives/graphicProperties.js";
1
2
  import { action } from "../../../core/action.js";
2
3
  import {
3
4
  noOptions,
@@ -103,7 +104,7 @@ function resolveConfig(program, kind, args, resources, previous) {
103
104
  }
104
105
 
105
106
  function resolveGeometry(program, kind, config) {
106
- const frame = resolvePolarFrameForProgram(program);
107
+ const frame = resolvePolarFrameForProgram(program, config.coordinate);
107
108
  const mapped = mapPolarGuideValues(program, config);
108
109
  if (kind === "theta") {
109
110
  return { values: mapped.values, ...resolveThetaSpokes({
@@ -139,13 +140,10 @@ function editConcrete(program, kind, config, geometry) {
139
140
  for (const [property, value] of Object.entries(properties)) {
140
141
  next = next.editGraphics({ target: graphic, property, value });
141
142
  }
142
- return next
143
- .editGraphics({ target: graphic, property: "stroke", value: config.color })
144
- .editGraphics({
145
- target: graphic,
146
- property: "strokeWidth",
147
- value: config.lineWidth
148
- })
143
+ return editGraphicProperties(next, graphic, {
144
+ stroke: config.color,
145
+ strokeWidth: config.lineWidth
146
+ })
149
147
  .editGraphics({
150
148
  target: graphic,
151
149
  property: "strokeDash",
@@ -239,12 +237,12 @@ function makeEdit(kind) {
239
237
  });
240
238
  }
241
239
 
242
- const createThetaGrid = makeCreate("theta");
243
- const createRadialGrid = makeCreate("radial");
244
- const editThetaGrid = makeEdit("theta");
245
- const editRadialGrid = makeEdit("radial");
246
- const rematerializeThetaGrid = makeRematerialize("theta");
247
- const rematerializeRadialGrid = makeRematerialize("radial");
240
+ const createThetaGrid = /* @__PURE__ */ makeCreate("theta");
241
+ const createRadialGrid = /* @__PURE__ */ makeCreate("radial");
242
+ const editThetaGrid = /* @__PURE__ */ makeEdit("theta");
243
+ const editRadialGrid = /* @__PURE__ */ makeEdit("radial");
244
+ const rematerializeThetaGrid = /* @__PURE__ */ makeRematerialize("theta");
245
+ const rematerializeRadialGrid = /* @__PURE__ */ makeRematerialize("radial");
248
246
 
249
247
  export function registerPolarGridActions(ProgramClass) {
250
248
  ProgramClass.prototype.createThetaGrid = createThetaGrid;
@@ -5,7 +5,6 @@ import {
5
5
  validateNonNegativeFinite,
6
6
  validatePositiveFinite
7
7
  } from "../../../core/validation.js";
8
- import { resolvePolarFrame } from "../../../grammar/polar.js";
9
8
  import {
10
9
  formatTransformedTick,
11
10
  isTransformedScaleType,
@@ -13,7 +12,8 @@ import {
13
12
  mapOrdinalPositionValues
14
13
  } from "../../../grammar/scales/index.js";
15
14
  import { formatTimeTick, formatTimeTicks } from "../../../grammar/ticks.js";
16
- import { resolveGraphicBounds } from "../../../layout/canvas.js";
15
+ import { resolveCoordinatePolarFrame } from
16
+ "../../../materialization/coordinateBounds.js";
17
17
  import { findCoordinate } from "../../../selectors/coordinates.js";
18
18
  import { DEFAULT_COLORS, DEFAULT_FONT_FAMILY } from
19
19
  "../../../theme/defaults.js";
@@ -23,6 +23,7 @@ import {
23
23
  } from "../../../grammar/schemas/graphicTree.js";
24
24
  import { valuesFromTickConfig } from "../tickValues.js";
25
25
  import { formatAxisValue, validateAxisFormat } from "../axes/policy.js";
26
+ import { resolveDisplayLabel } from "../../../grammar/displayLabels.js";
26
27
 
27
28
  export const POLAR_AXIS_DEFAULTS = Object.freeze({
28
29
  angle: 90,
@@ -160,12 +161,8 @@ export function resolvePolarGuideResources(program, kind, args, operation) {
160
161
  });
161
162
  }
162
163
 
163
- export function resolvePolarFrameForProgram(program) {
164
- const bounds = resolveGraphicBounds(program);
165
- if (bounds === undefined) {
166
- throw new Error("Polar guides require graphical Canvas bounds.");
167
- }
168
- return resolvePolarFrame(bounds);
164
+ export function resolvePolarFrameForProgram(program, coordinate) {
165
+ return resolveCoordinatePolarFrame(program, coordinate);
169
166
  }
170
167
 
171
168
  export function resolvePolarTickValues(program, config) {
@@ -203,6 +200,13 @@ export function mapPolarGuideValues(program, config) {
203
200
 
204
201
  export function formatPolarGuideValues(program, config, values) {
205
202
  const scale = program.resolvedScales[config.scale];
203
+ if (["ordinal", "band", "point"].includes(scale.type)) {
204
+ return values.map(value => resolveDisplayLabel(
205
+ value,
206
+ config.labelMap,
207
+ String
208
+ ));
209
+ }
206
210
  if (scale.type === "time" && config.format === "auto") {
207
211
  return formatTimeTicks(values, scale.domain);
208
212
  }
@@ -1,3 +1,4 @@
1
+ import { registerTextMetricActions } from "./textMetrics/index.js";
1
2
  import { registerPrimitiveActions } from "./primitives/index.js";
2
3
  import { registerSelectionActions } from "./selection/index.js";
3
4
  import { registerDataActions } from "./data/index.js";
@@ -5,7 +6,8 @@ import { registerCategoryOrderActions } from "./categoryOrder/index.js";
5
6
  import { registerEncodingActions } from "./encodings/index.js";
6
7
  import { registerScaleActions } from "./scales/index.js";
7
8
  import { registerMarkActions } from "./marks/index.js";
8
- import { registerCoordinateActions } from "./coordinates/actions.js";
9
+ import { registerBasicCoordinateActions } from "./coordinates/actions.js";
10
+ import { registerCoordinateEditActions } from "./coordinates/edit.js";
9
11
  import { registerFacetActions } from "./facets/index.js";
10
12
  import { registerCompositionActions } from "./composition/index.js";
11
13
  import { registerTitleActions } from "./titles/index.js";
@@ -19,9 +21,17 @@ import { registerViolinPlotActions } from "./violinPlots/index.js";
19
21
  import { registerErrorBandActions } from "./errorBands/index.js";
20
22
  import { registerChartActions } from "./charts/index.js";
21
23
  import { registerThemeActions } from "./theme/index.js";
24
+ import { registerResourceActions } from "./resources/index.js";
25
+ import {
26
+ applyCompositionTheme,
27
+ removeCompositionTheme
28
+ } from "./theme/composition.js";
22
29
 
23
30
  export function registerActions(ProgramClass) {
24
- registerThemeActions(ProgramClass);
31
+ registerThemeActions(ProgramClass, {
32
+ apply: applyCompositionTheme,
33
+ remove: removeCompositionTheme
34
+ });
25
35
  registerPrimitiveActions(ProgramClass);
26
36
  registerCompositionActions(ProgramClass);
27
37
  registerFacetActions(ProgramClass);
@@ -30,7 +40,8 @@ export function registerActions(ProgramClass) {
30
40
  registerMarkActions(ProgramClass);
31
41
  registerScaleActions(ProgramClass);
32
42
  registerEncodingActions(ProgramClass);
33
- registerCoordinateActions(ProgramClass);
43
+ registerBasicCoordinateActions(ProgramClass);
44
+ registerCoordinateEditActions(ProgramClass);
34
45
  registerGuideActions(ProgramClass);
35
46
  registerTitleActions(ProgramClass);
36
47
  registerRegressionActions(ProgramClass);
@@ -42,4 +53,6 @@ export function registerActions(ProgramClass) {
42
53
  registerChartActions(ProgramClass);
43
54
  registerCategoryOrderActions(ProgramClass);
44
55
  registerSelectionActions(ProgramClass);
56
+ registerResourceActions(ProgramClass);
57
+ registerTextMetricActions(ProgramClass);
45
58
  }