ggaction 0.0.16 → 0.0.18

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 (299) hide show
  1. package/CHANGELOG.md +66 -0
  2. package/README.md +3 -2
  3. package/knowledge/action-card.schema.json +1 -1
  4. package/knowledge/action-cards.json +1 -1
  5. package/knowledge/intent-taxonomy.json +1 -1
  6. package/knowledge/mcp-resources.json +1 -1
  7. package/knowledge/task-resolver.js +1 -1
  8. package/package.json +10 -4
  9. package/src/BasicChartProgram.js +1 -1
  10. package/src/accessibility.js +3 -2
  11. package/src/actions/boxPlots/create.js +14 -4
  12. package/src/actions/boxPlots/edit.js +39 -33
  13. package/src/actions/boxPlots/materialize.js +7 -3
  14. package/src/actions/boxPlots/options.js +37 -11
  15. package/src/actions/canvas/actions.js +70 -95
  16. package/src/actions/canvas/fitting.js +16 -1
  17. package/src/actions/canvas/index.js +3 -0
  18. package/src/actions/canvas/plotBorder.js +28 -0
  19. package/src/actions/charts/area.js +2 -2
  20. package/src/actions/charts/bar.js +34 -7
  21. package/src/actions/charts/ecdf.js +4 -18
  22. package/src/actions/charts/endpoints.js +4 -18
  23. package/src/actions/charts/heatmap.js +4 -4
  24. package/src/actions/charts/index.js +2 -0
  25. package/src/actions/charts/interval-regression.js +2 -2
  26. package/src/actions/charts/line.js +1 -1
  27. package/src/actions/charts/pie.js +3 -47
  28. package/src/actions/charts/radial.js +34 -12
  29. package/src/actions/charts/scatter.js +16 -2
  30. package/src/actions/charts/shared.js +2 -2
  31. package/src/actions/charts/text.js +35 -0
  32. package/src/actions/composition/actions.js +6 -2
  33. package/src/actions/data/bin.js +1 -1
  34. package/src/actions/data/box.js +2 -1
  35. package/src/actions/data/create.js +18 -5
  36. package/src/actions/data/density.js +1 -1
  37. package/src/actions/data/derived.js +15 -1
  38. package/src/actions/data/edit.js +20 -7
  39. package/src/actions/data/filter.js +15 -4
  40. package/src/actions/data/index.js +3 -0
  41. package/src/actions/data/interval.js +2 -0
  42. package/src/actions/data/regression.js +6 -2
  43. package/src/actions/data/revise.js +37 -5
  44. package/src/actions/data/shared.js +33 -4
  45. package/src/actions/data/sort.js +21 -0
  46. package/src/actions/data/stack.js +3 -1
  47. package/src/actions/data/summary.js +1 -1
  48. package/src/actions/encodings/angle.js +4 -1
  49. package/src/actions/encodings/appearance.js +43 -31
  50. package/src/actions/encodings/barWidth.js +36 -11
  51. package/src/actions/encodings/channels.js +0 -1
  52. package/src/actions/encodings/color/continuous.js +5 -2
  53. package/src/actions/encodings/color/index.js +5 -2
  54. package/src/actions/encodings/color/policy.js +10 -3
  55. package/src/actions/encodings/density/resolve.js +1 -6
  56. package/src/actions/encodings/offset.js +4 -1
  57. package/src/actions/encodings/position/policies/arc.js +12 -10
  58. package/src/actions/encodings/position/policies/area.js +3 -3
  59. package/src/actions/encodings/position/policies/bar.js +15 -6
  60. package/src/actions/encodings/position/policies/line.js +17 -6
  61. package/src/actions/encodings/position/resolve.js +9 -3
  62. package/src/actions/encodings/ranged.js +23 -1
  63. package/src/actions/encodings/remove.js +3 -2
  64. package/src/actions/encodings/ruleAppearance.js +4 -1
  65. package/src/actions/encodings/seriesLayout.js +1 -0
  66. package/src/actions/encodings/stroke.js +4 -1
  67. package/src/actions/encodings/strokeDash.js +6 -1
  68. package/src/actions/encodings/text.js +12 -4
  69. package/src/actions/errorBands/create.js +2 -2
  70. package/src/actions/errorBands/edit.js +2 -1
  71. package/src/actions/facets/actions.js +158 -240
  72. package/src/actions/gradientPlots/resolve.js +2 -17
  73. package/src/actions/guides/applicability.js +1 -1
  74. package/src/actions/guides/axes/axis.js +16 -4
  75. package/src/actions/guides/axes/edit.js +4 -4
  76. package/src/actions/guides/axes/labels.js +120 -46
  77. package/src/actions/guides/axes/lines.js +6 -5
  78. package/src/actions/guides/axes/parallel/lifecycle.js +1 -1
  79. package/src/actions/guides/axes/parallel/policy.js +8 -7
  80. package/src/actions/guides/axes/remove.js +3 -2
  81. package/src/actions/guides/axes/tickGroups.js +5 -2
  82. package/src/actions/guides/axes/ticks.js +6 -3
  83. package/src/actions/guides/axes/titles.js +71 -26
  84. package/src/actions/guides/basic.js +2 -0
  85. package/src/actions/guides/facadeLegend.js +10 -2
  86. package/src/actions/guides/grids/grid.js +7 -1
  87. package/src/actions/guides/grids/resolve.js +59 -12
  88. package/src/actions/guides/legends/blocks.js +3 -1
  89. package/src/actions/guides/legends/categorical/actions.js +70 -17
  90. package/src/actions/guides/legends/categorical/components.js +12 -8
  91. package/src/actions/guides/legends/categorical/index.js +6 -0
  92. package/src/actions/guides/legends/categorical/layout.js +37 -8
  93. package/src/actions/guides/legends/categorical/options.js +31 -20
  94. package/src/actions/guides/legends/categorical/resolve.js +2 -2
  95. package/src/actions/guides/legends/categorical/symbols.js +18 -12
  96. package/src/actions/guides/legends/categorical/validation.js +1 -6
  97. package/src/actions/guides/legends/continuous/colorSymbols.js +1 -0
  98. package/src/actions/guides/legends/continuous/common.js +1 -447
  99. package/src/actions/guides/legends/continuous/gradient.js +47 -34
  100. package/src/actions/guides/legends/continuous/interval.js +4 -4
  101. package/src/actions/guides/legends/continuous/opacity.js +19 -12
  102. package/src/actions/guides/legends/edit.js +1 -604
  103. package/src/actions/guides/legends/focused.js +2 -2
  104. package/src/actions/guides/legends/group.js +1 -0
  105. package/src/actions/guides/legends/lane.js +1 -516
  106. package/src/actions/guides/legends/remove.js +3 -0
  107. package/src/actions/guides/legends/sampling.js +1 -1
  108. package/src/actions/guides/legends/size.js +51 -43
  109. package/src/actions/guides/legends/strokeWidth.js +11 -29
  110. package/src/actions/guides/legends/target.js +3 -3
  111. package/src/actions/guides/legends/transition.js +21 -7
  112. package/src/actions/guides/polar/axes/labels.js +4 -2
  113. package/src/actions/guides/polar/axes/titles.js +7 -5
  114. package/src/actions/guides/polar/resolve.js +6 -14
  115. package/src/actions/index.js +16 -16
  116. package/src/actions/marks/arc/actions.js +3 -10
  117. package/src/actions/marks/area/actions.js +8 -5
  118. package/src/actions/marks/area/materialize.js +8 -9
  119. package/src/actions/marks/bar/create.js +17 -4
  120. package/src/actions/marks/bar/edit.js +18 -7
  121. package/src/actions/marks/bar/materialize.js +9 -6
  122. package/src/actions/marks/line/actions.js +11 -4
  123. package/src/actions/marks/line/materialize.js +9 -5
  124. package/src/actions/marks/point/create.js +8 -1
  125. package/src/actions/marks/point/edit.js +13 -6
  126. package/src/actions/marks/point/materialize.js +4 -2
  127. package/src/actions/marks/rect/actions.js +26 -11
  128. package/src/actions/marks/remove.js +2 -0
  129. package/src/actions/marks/rule/actions.js +31 -12
  130. package/src/actions/marks/text/actions.js +42 -11
  131. package/src/actions/marks/text/layout.js +3 -0
  132. package/src/actions/marks/tick/actions.js +23 -8
  133. package/src/actions/primitives/semanticAction.js +37 -3
  134. package/src/actions/primitives/semanticValidation/dataset.js +13 -1
  135. package/src/actions/primitives/semanticValidation/layer.js +26 -2
  136. package/src/actions/primitives/semanticValidation/scale.js +6 -0
  137. package/src/actions/regression/create.js +26 -5
  138. package/src/actions/regression/edit.js +50 -15
  139. package/src/actions/regression/follow.js +22 -0
  140. package/src/actions/regression/resolve.js +2 -6
  141. package/src/actions/scales/channels.js +20 -15
  142. package/src/actions/scales/consumers/common.js +2 -1
  143. package/src/actions/scales/consumers/families.js +16 -5
  144. package/src/actions/scales/create.js +10 -4
  145. package/src/actions/scales/definitions.js +1 -425
  146. package/src/actions/scales/edit.js +3 -3
  147. package/src/actions/scales/editPolicy.js +9 -3
  148. package/src/actions/scales/materialize.js +1 -1
  149. package/src/actions/scales/parallel.js +1 -1
  150. package/src/actions/scales/patch.js +1 -1
  151. package/src/actions/scales/preview.js +49 -2
  152. package/src/actions/scales/quantitativeColor.js +3 -3
  153. package/src/actions/selection/actions.js +1 -13
  154. package/src/actions/theme/reconcile.js +83 -27
  155. package/src/actions/theme/state.js +12 -0
  156. package/src/actions/titles/actions.js +5 -18
  157. package/src/actions/titles/resolve.js +41 -19
  158. package/src/actions/violinPlots/edit.js +3 -20
  159. package/src/core/action.js +3 -2
  160. package/src/core/compositionState.js +4 -1
  161. package/src/core/font.js +9 -2
  162. package/src/core/optionRequirements.js +1 -0
  163. package/src/core/programState.js +5 -1
  164. package/src/core/resourceReferences.js +3 -0
  165. package/src/core/textMetricProfile.js +3 -2
  166. package/src/core/textMetrics.js +41 -4
  167. package/src/core/validation.js +26 -0
  168. package/src/core/vocabulary.js +4 -0
  169. package/src/grammar/aggregate.js +4 -18
  170. package/src/grammar/arcs.js +1 -386
  171. package/src/grammar/areaPaint.js +10 -0
  172. package/src/grammar/areaSeries.js +18 -10
  173. package/src/grammar/bars/geometry.js +30 -3
  174. package/src/grammar/bars/policy.js +12 -1
  175. package/src/grammar/bin.js +41 -22
  176. package/src/grammar/bin2d.js +1 -6
  177. package/src/grammar/boxPlot.js +56 -9
  178. package/src/grammar/categoryOrder.js +1 -6
  179. package/src/grammar/complete.js +15 -19
  180. package/src/grammar/computed.js +92 -25
  181. package/src/grammar/curveCommands.js +29 -16
  182. package/src/grammar/datasetSchema.js +382 -0
  183. package/src/grammar/density.js +53 -5
  184. package/src/grammar/displayLabels.js +28 -0
  185. package/src/grammar/ecdf.js +2 -9
  186. package/src/grammar/facets/dependencies.js +6 -2
  187. package/src/grammar/facets/guides.js +5 -0
  188. package/src/grammar/facets/index.js +2 -5
  189. package/src/grammar/filter.js +133 -39
  190. package/src/grammar/fold.js +2 -12
  191. package/src/grammar/gradientProfile.js +1 -6
  192. package/src/grammar/impute.js +21 -48
  193. package/src/grammar/interval.js +34 -10
  194. package/src/grammar/itemMissing.js +59 -0
  195. package/src/grammar/legendGradient.js +18 -0
  196. package/src/grammar/legendGroups.js +1 -0
  197. package/src/grammar/legendTitleStyle.js +22 -0
  198. package/src/grammar/lineSeries.js +32 -17
  199. package/src/grammar/markLabels.js +5 -2
  200. package/src/grammar/normalize.js +4 -54
  201. package/src/grammar/numeric.js +1 -290
  202. package/src/grammar/parallelCoordinates.js +1 -6
  203. package/src/grammar/parseTime.js +41 -0
  204. package/src/grammar/pathCommands.js +11 -4
  205. package/src/grammar/polar.js +1 -184
  206. package/src/grammar/positionCompatibility.js +3 -3
  207. package/src/grammar/regression/derive.js +63 -16
  208. package/src/grammar/regression/index.js +1 -0
  209. package/src/grammar/regression/models.js +116 -59
  210. package/src/grammar/regression/parameters.js +69 -6
  211. package/src/grammar/roundedRect.js +42 -54
  212. package/src/grammar/scales/appearance.js +1 -206
  213. package/src/grammar/scales/color.js +1 -382
  214. package/src/grammar/scales/colorConsumers.js +5 -2
  215. package/src/grammar/scales/definition.js +1 -190
  216. package/src/grammar/scales/discretized.js +1 -195
  217. package/src/grammar/scales/size.js +1 -456
  218. package/src/grammar/scales/temporal.js +2 -13
  219. package/src/grammar/scales/transformed.js +1 -383
  220. package/src/grammar/scales/types.js +1 -1
  221. package/src/grammar/scales/validation.js +1 -66
  222. package/src/grammar/schemas/concreteGraphic.js +11 -0
  223. package/src/grammar/schemas/graphic.js +3 -0
  224. package/src/grammar/schemas/semanticPath.js +5 -3
  225. package/src/grammar/sort.js +88 -0
  226. package/src/grammar/stack.js +2 -10
  227. package/src/grammar/statisticalReference.js +1 -6
  228. package/src/grammar/summary.js +120 -45
  229. package/src/grammar/text.js +19 -0
  230. package/src/grammar/timeUnit.js +16 -7
  231. package/src/grammar/transformKeys.js +47 -0
  232. package/src/grammar/transformTopology.js +1 -0
  233. package/src/grammar/transforms.js +25 -12
  234. package/src/grammar/valueFormat.js +17 -5
  235. package/src/grammar/weightedStatistics.js +1 -6
  236. package/src/grammar/window.js +4 -58
  237. package/src/inspection.js +495 -0
  238. package/src/inspectionDescriptors.js +3 -0
  239. package/src/layout/canvas.js +1 -110
  240. package/src/layout/facets.js +1 -244
  241. package/src/layout/labels.js +1 -0
  242. package/src/layout/legend.js +13 -0
  243. package/src/layout/legendGroup.js +1 -0
  244. package/src/layout/legendItems.js +59 -15
  245. package/src/layout/legendLane.js +1 -441
  246. package/src/layout/legendText.js +1 -0
  247. package/src/layout/title.js +35 -13
  248. package/src/materialization/bars/aggregate.js +11 -5
  249. package/src/materialization/bars/histogram.js +4 -1
  250. package/src/materialization/bars/ranged.js +19 -6
  251. package/src/materialization/bars/resolve.js +26 -3
  252. package/src/materialization/coordinateBounds.js +8 -0
  253. package/src/materialization/dependencies.js +4 -44
  254. package/src/materialization/facetGuides/layout.js +1 -0
  255. package/src/materialization/facetGuides/placement.js +19 -8
  256. package/src/materialization/facetGuides/preparation.js +15 -7
  257. package/src/materialization/facetHeaders.js +1 -347
  258. package/src/materialization/facets.js +1 -185
  259. package/src/materialization/graphicHierarchy.js +1 -1
  260. package/src/materialization/guides/layout.js +1 -57
  261. package/src/materialization/guides/resources.js +1 -123
  262. package/src/materialization/layout.js +53 -0
  263. package/src/materialization/legendGroups.js +1 -0
  264. package/src/materialization/legendText.js +1 -0
  265. package/src/materialization/legends.js +1 -1
  266. package/src/materialization/marks/capabilities.js +5 -6
  267. package/src/materialization/rect.js +1 -1
  268. package/src/materialization/revisionIdentity.js +19 -0
  269. package/src/materialization/scaleGuideDependencies.js +1 -1
  270. package/src/materialization/scales/map.js +3 -0
  271. package/src/materialization/scales/policies/arc.js +8 -7
  272. package/src/materialization/scales/policies/bar.js +19 -7
  273. package/src/materialization/scales/policies/series.js +2 -1
  274. package/src/materialization/scales/resolve.js +72 -7
  275. package/src/materialization/selection/items/arc.js +1 -1
  276. package/src/materialization/selection/items/bar.js +7 -6
  277. package/src/materialization/selection/items/path.js +7 -6
  278. package/src/materialization/selection/items/rect.js +2 -2
  279. package/src/materialization/text.js +17 -6
  280. package/src/materialization/textLines.js +15 -0
  281. package/src/persistence/codec.js +37 -6
  282. package/src/persistence/validation.js +47 -0
  283. package/src/persistence.js +94 -8
  284. package/src/renderers/canvas/circle.js +6 -3
  285. package/src/renderers/canvas/fill.js +7 -1
  286. package/src/renderers/canvas/index.js +2 -1
  287. package/src/renderers/canvas/line.js +1 -0
  288. package/src/renderers/canvas/path.js +1 -1
  289. package/src/renderers/canvas/rect.js +11 -8
  290. package/src/renderers/canvas/stroke.js +2 -1
  291. package/src/renderers/canvas/text.js +5 -3
  292. package/src/renderers/svg.js +4 -1
  293. package/src/selectors/layers.js +19 -0
  294. package/src/theme/defaults.js +8 -2
  295. package/src/version.js +1 -1
  296. package/types/basic.d.ts +1 -0
  297. package/types/index.d.ts +7 -0
  298. package/types/inspection.d.ts +17 -0
  299. package/types/program.d.ts +494 -112
@@ -0,0 +1,22 @@
1
+ export function reconcileFollowingRegressions(program) {
2
+ let next = program;
3
+ for (const layer of program.semanticSpec.layers) {
4
+ if (layer.derivedBindings?.regression?.mode !== "follow") continue;
5
+ const config = next.markConfigs[layer.id]?.regression;
6
+ if (config === undefined) continue;
7
+ const x = layer.encoding?.x;
8
+ const y = layer.encoding?.y;
9
+ if (typeof layer.data !== "string" || x?.fieldType !== "quantitative" || y?.fieldType !== "quantitative" ||
10
+ typeof x.field !== "string" || typeof y.field !== "string") {
11
+ throw new Error(`Following regression source "${layer.id}" requires quantitative x/y fields and data.`);
12
+ }
13
+ if (config.source === layer.data && config.x === x.field && config.y === y.field) continue;
14
+ next = next.editRegression({
15
+ target: layer.id,
16
+ data: layer.data,
17
+ x: x.field,
18
+ y: y.field
19
+ });
20
+ }
21
+ return next;
22
+ }
@@ -1,3 +1,5 @@
1
+ import { requireStringValue as requireRegressionField } from "../../core/validation.js";
2
+ export { requireStringValue as requireRegressionField } from "../../core/validation.js";
1
3
  import { isPlainObject } from "../../core/immutable.js";
2
4
  import { findLayer } from "../../selectors/layers.js";
3
5
 
@@ -8,12 +10,6 @@ export function requireRegressionObject(value, label) {
8
10
  return value;
9
11
  }
10
12
 
11
- export function requireRegressionField(value, label) {
12
- if (typeof value !== "string" || value.length === 0) {
13
- throw new TypeError(`${label} must be a non-empty string.`);
14
- }
15
- return value;
16
- }
17
13
 
18
14
  export function findRegressionPoint(program, requested) {
19
15
  const eligible = program.semanticSpec.layers.filter(layer =>
@@ -5,12 +5,13 @@ import { normalizePositionScaleChannel } from "../../core/vocabulary.js";
5
5
  import { findLayer } from "../../selectors/layers.js";
6
6
  import { requireSemanticScale } from "../../selectors/scales.js";
7
7
  import { findScaleConsumers } from "./consumers/index.js";
8
+ import { axisScaleBindings } from "../../materialization/coordinateBounds.js";
8
9
 
9
10
  const DEFINITIONS = Object.freeze({
10
11
  editXScale: Object.freeze({
11
12
  channel: "x",
12
13
  options: Object.freeze([
13
- "type", "domain", "range", "nice", "zero", "clamp", "reverse",
14
+ "type", "domain", "range", "emptyDomain", "nice", "zero", "clamp", "reverse",
14
15
  "base", "exponent", "constant", "paddingInner", "paddingOuter",
15
16
  "padding", "align", "unknown"
16
17
  ])
@@ -18,7 +19,7 @@ const DEFINITIONS = Object.freeze({
18
19
  editYScale: Object.freeze({
19
20
  channel: "y",
20
21
  options: Object.freeze([
21
- "type", "domain", "range", "nice", "zero", "clamp", "reverse",
22
+ "type", "domain", "range", "emptyDomain", "nice", "zero", "clamp", "reverse",
22
23
  "base", "exponent", "constant", "paddingInner", "paddingOuter",
23
24
  "padding", "align", "unknown"
24
25
  ])
@@ -26,59 +27,59 @@ const DEFINITIONS = Object.freeze({
26
27
  editThetaScale: Object.freeze({
27
28
  channel: "theta",
28
29
  options: Object.freeze([
29
- "type", "domain", "range", "nice", "zero", "clamp", "reverse",
30
+ "type", "domain", "range", "emptyDomain", "nice", "zero", "clamp", "reverse",
30
31
  "paddingInner", "paddingOuter", "padding", "align"
31
32
  ])
32
33
  }),
33
34
  editRScale: Object.freeze({
34
35
  channel: "radius",
35
36
  options: Object.freeze([
36
- "type", "domain", "range", "nice", "zero", "clamp", "reverse",
37
+ "type", "domain", "range", "emptyDomain", "nice", "zero", "clamp", "reverse",
37
38
  "base", "exponent", "constant", "radialMapping"
38
39
  ])
39
40
  }),
40
41
  editColorScale: Object.freeze({
41
42
  channel: "color",
42
43
  options: Object.freeze([
43
- "type", "domain", "range", "clamp", "reverse", "palette",
44
- "interpolate", "midpoint", "unknown"
44
+ "type", "domain", "range", "emptyDomain", "clamp", "reverse", "palette",
45
+ "interpolate", "midpoint", "base", "constant", "unknown"
45
46
  ])
46
47
  }),
47
48
  editStrokeScale: Object.freeze({
48
49
  channel: "stroke",
49
50
  targetOnly: true,
50
51
  options: Object.freeze([
51
- "type", "domain", "range", "clamp", "reverse", "palette",
52
- "interpolate", "midpoint", "unknown"
52
+ "type", "domain", "range", "emptyDomain", "clamp", "reverse", "palette",
53
+ "interpolate", "midpoint", "base", "constant", "unknown"
53
54
  ])
54
55
  }),
55
56
  editSizeScale: Object.freeze({
56
57
  channel: "size",
57
58
  options: Object.freeze([
58
- "type", "domain", "range", "unknown", "clamp", "reverse", "base",
59
+ "type", "domain", "range", "emptyDomain", "unknown", "clamp", "reverse", "base",
59
60
  "exponent"
60
61
  ])
61
62
  }),
62
63
  editOpacityScale: Object.freeze({
63
64
  channel: "opacity",
64
65
  options: Object.freeze([
65
- "type", "domain", "range", "nice", "zero", "clamp", "reverse", "unknown"
66
+ "type", "domain", "range", "emptyDomain", "nice", "zero", "clamp", "reverse", "unknown"
66
67
  ])
67
68
  }),
68
69
  editShapeScale: Object.freeze({
69
70
  channel: "shape",
70
- options: Object.freeze(["type", "domain", "range", "unknown"])
71
+ options: Object.freeze(["type", "domain", "range", "emptyDomain", "unknown"])
71
72
  }),
72
73
  editStrokeWidthScale: Object.freeze({
73
74
  channel: "strokeWidth",
74
75
  options: Object.freeze([
75
- "type", "domain", "range", "nice", "zero", "clamp", "reverse",
76
+ "type", "domain", "range", "emptyDomain", "nice", "zero", "clamp", "reverse",
76
77
  "base", "exponent", "constant"
77
78
  ])
78
79
  }),
79
80
  editStrokeDashScale: Object.freeze({
80
81
  channel: "strokeDash",
81
- options: Object.freeze(["type", "domain", "range"])
82
+ options: Object.freeze(["type", "domain", "range", "emptyDomain"])
82
83
  })
83
84
  });
84
85
 
@@ -99,9 +100,11 @@ function allConsumers(program) {
99
100
  }
100
101
 
101
102
  function channelScaleIds(program, channel) {
102
- return [...new Set(allConsumers(program)
103
+ return [...new Set([...allConsumers(program)
103
104
  .filter(consumer => normalizePositionScaleChannel(consumer.channel) === channel)
104
- .map(consumer => consumer.encoding.scale))];
105
+ .map(consumer => consumer.encoding.scale),
106
+ ...program.semanticSpec.scales.filter(scale => axisScaleBindings(program, scale.id)
107
+ .some(binding => binding.channel === channel)).map(scale => scale.id)])];
105
108
  }
106
109
 
107
110
  function requireSingleScale(ids, operation, scope) {
@@ -115,6 +118,8 @@ function requireSingleScale(ids, operation, scope) {
115
118
  function validateScaleChannel(program, id, channel, operation) {
116
119
  requireSemanticScale(program, id);
117
120
  const consumers = findScaleConsumers(program, id);
121
+ const axes = axisScaleBindings(program, id);
122
+ if (consumers.length === 0 && axes.length === 1 && axes[0].channel === channel) return id;
118
123
  if (consumers.length === 0) {
119
124
  throw new Error(`${operation} requires a scale bound to the ${channel} channel.`);
120
125
  }
@@ -5,6 +5,7 @@ import { readScaleField } from "../../../grammar/scales/index.js";
5
5
  import { findDataset } from "../../../selectors/datasets.js";
6
6
  import { requireSemanticScale } from "../../../selectors/scales.js";
7
7
  import { SCALED_ENCODING_CHANNELS } from "../../../core/vocabulary.js";
8
+ import { applyItemMissingPolicy } from "../../../grammar/itemMissing.js";
8
9
 
9
10
  export function findScale(program, id) {
10
11
  return requireSemanticScale(program, id);
@@ -39,7 +40,7 @@ export function requireConsumerDataset(program, consumer) {
39
40
  `Mark "${consumer.layer.id}" references unknown dataset "${consumer.layer.data}".`
40
41
  );
41
42
  }
42
- return dataset;
43
+ return applyItemMissingPolicy(consumer.layer, dataset);
43
44
  }
44
45
 
45
46
  export function isDirectCategoricalConsumer(consumer) {
@@ -1,8 +1,9 @@
1
1
  import { isPendingMeasuredRadiusConsumer } from "../../../materialization/scales/policies/arc.js";
2
- import { deriveMeasuredArcValues } from "../../../grammar/arcs.js";
2
+ import { deriveMeasuredArcValues, deriveProportionalArcRadiusValues } from "../../../grammar/arcs.js";
3
3
  import { deriveBarAggregates } from "../../../grammar/bars/aggregate.js";
4
4
  import {
5
5
  BAR_GRAINS,
6
+ resolveBarChannels,
6
7
  resolveBarGrain
7
8
  } from "../../../grammar/bars/policy.js";
8
9
  import {
@@ -28,9 +29,15 @@ function lineDerivationOptions(program, consumer, dataset) {
28
29
  }
29
30
 
30
31
  export function resolveMarkFamilyConsumerValues(program, consumer, dataset) {
31
- if (consumer.layer.mark?.type === "arc" && consumer.channel === "radius" &&
32
- findScale(program, consumer.encoding.scale).radialMapping !== undefined) {
33
- return { matched: true, values: isPendingMeasuredRadiusConsumer(consumer) ? [] : deriveMeasuredArcValues(dataset.values, consumer.layer).map(item => item.radius) };
32
+ if (consumer.layer.mark?.type === "arc" && consumer.channel === "radius") {
33
+ let derive;
34
+ if (findScale(program, consumer.encoding.scale).radialMapping !== undefined) derive = deriveMeasuredArcValues;
35
+ else if (consumer.layer.encoding?.theta?.fieldType === "quantitative" ||
36
+ consumer.layer.encoding?.theta?.aggregate !== undefined || consumer.encoding.aggregate !== undefined) {
37
+ derive = deriveProportionalArcRadiusValues;
38
+ }
39
+ if (derive !== undefined) return { matched: true, values: isPendingMeasuredRadiusConsumer(consumer)
40
+ ? [] : derive(dataset.values, consumer.layer).map(item => item.radius) };
34
41
  }
35
42
 
36
43
  if (consumer.layer.mark?.type === "rect") {
@@ -44,6 +51,10 @@ export function resolveMarkFamilyConsumerValues(program, consumer, dataset) {
44
51
  };
45
52
  }
46
53
  const { layer, channel } = consumer;
54
+ if (resolveBarGrain(layer) === BAR_GRAINS.centered &&
55
+ channel === resolveBarChannels(layer).measure && layer.encoding[`${channel}2`] === undefined) {
56
+ return { matched: true, values: [0, ...dataset.values.map(row => row[consumer.encoding.field])] };
57
+ }
47
58
  const encoding = layer.encoding ?? {};
48
59
  const appearance = ["stroke", "strokeWidth", "opacity"].includes(channel);
49
60
  if (
@@ -75,7 +86,7 @@ export function resolveMarkFamilyConsumerValues(program, consumer, dataset) {
75
86
  : channel === "x" ? derived.xValues : derived.yValues
76
87
  };
77
88
  }
78
- if (resolveBarGrain(consumer.layer) === BAR_GRAINS.aggregate) {
89
+ if (resolveBarGrain(consumer.layer) === BAR_GRAINS.aggregate && ["x", "y", "color"].includes(consumer.channel)) {
79
90
  const derived = deriveBarAggregates(dataset.values, consumer.layer);
80
91
  if (consumer.channel === "color") {
81
92
  return {
@@ -24,6 +24,7 @@ const CREATE_SCALE_OPTIONS = Object.freeze([
24
24
  "id",
25
25
  "type",
26
26
  "domain",
27
+ "emptyDomain",
27
28
  "range",
28
29
  "nice",
29
30
  "zero",
@@ -86,14 +87,18 @@ export const createScale = /* @__PURE__ */ action(
86
87
  validateOptions(args);
87
88
  const id = validateUserId(args.id, "Scale id");
88
89
  const type = validateScaleType(args.type ?? "linear");
89
- const colorType = isColorScaleType(type);
90
+ const colorType = isColorScaleType(type) && (
91
+ !["log", "sqrt", "symlog"].includes(type) || args.palette !== undefined ||
92
+ args.interpolate !== undefined || (Array.isArray(args.range) && typeof args.range[0] === "string") ||
93
+ args.range?.palette !== undefined
94
+ );
90
95
  if (args.palette !== undefined && args.range !== undefined) {
91
96
  throw new Error("Color scale cannot specify both palette and range.");
92
97
  }
93
98
  if (args.palette !== undefined && !colorType) {
94
99
  throw new Error(`Scale type "${type}" does not support palette.`);
95
100
  }
96
- if (args.interpolate !== undefined && type !== "sequential") {
101
+ if (args.interpolate !== undefined && !colorType) {
97
102
  throw new Error(`Scale type "${type}" does not support interpolate.`);
98
103
  }
99
104
  const requestedRange = args.palette === undefined
@@ -128,6 +133,7 @@ export const createScale = /* @__PURE__ */ action(
128
133
  })
129
134
  : normalizeScaleDefinition({
130
135
  type,
136
+ color: colorType,
131
137
  patch: {
132
138
  ...args,
133
139
  ...(requestedRange === undefined ? {} : { range: requestedRange })
@@ -142,7 +148,7 @@ export const createScale = /* @__PURE__ */ action(
142
148
  validateRange: (scaleType, value) =>
143
149
  isDiscretizedColorScaleType(scaleType)
144
150
  ? validateDiscretizedColorRange(value)
145
- : isContinuousColorScaleType(scaleType)
151
+ : colorType && isContinuousColorScaleType(scaleType)
146
152
  ? validateSequentialColorRange(value)
147
153
  : scaleType === "ordinal"
148
154
  ? validateOrdinalRange(value)
@@ -164,7 +170,7 @@ export const createScale = /* @__PURE__ */ action(
164
170
  .editSemantic({ property: `scale[${id}].range`, value: definition.range });
165
171
 
166
172
  for (const property of [
167
- "nice", "zero", "clamp", "reverse", "base", "exponent", "constant",
173
+ "emptyDomain", "nice", "zero", "clamp", "reverse", "base", "exponent", "constant",
168
174
  "paddingInner", "paddingOuter", "padding", "align", "interpolate", "midpoint",
169
175
  "radialMapping", "unknown"
170
176
  ]) {