ggaction 0.0.2 → 0.0.4

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 (242) hide show
  1. package/CHANGELOG.md +55 -2
  2. package/README.md +95 -72
  3. package/package.json +15 -5
  4. package/src/actions/boxPlots/components.js +3 -3
  5. package/src/actions/boxPlots/edit.js +277 -0
  6. package/src/actions/boxPlots/index.js +2 -0
  7. package/src/actions/boxPlots/materialize.js +12 -1
  8. package/src/actions/boxPlots/options.js +25 -14
  9. package/src/actions/canvas/actions.js +21 -17
  10. package/src/actions/composition/actions.js +247 -0
  11. package/src/actions/composition/index.js +1 -0
  12. package/src/actions/coordinates/actions.js +2 -5
  13. package/src/actions/data/density.js +7 -1
  14. package/src/actions/data/filter.js +3 -1
  15. package/src/actions/data/regression.js +1 -1
  16. package/src/actions/encodings/appearance.js +12 -1
  17. package/src/actions/encodings/barWidth.js +5 -3
  18. package/src/actions/encodings/color/continuous.js +137 -0
  19. package/src/actions/encodings/color/index.js +151 -0
  20. package/src/actions/encodings/color/layout.js +91 -0
  21. package/src/actions/encodings/color/policy.js +88 -0
  22. package/src/actions/encodings/index.js +4 -2
  23. package/src/actions/encodings/offset.js +91 -73
  24. package/src/actions/encodings/position/apply.js +66 -0
  25. package/src/actions/encodings/position/index.js +130 -0
  26. package/src/actions/encodings/position/policies/arc.js +26 -0
  27. package/src/actions/encodings/position/policies/bar.js +9 -5
  28. package/src/actions/encodings/position/policies/index.js +5 -1
  29. package/src/actions/encodings/position/policies/line.js +20 -3
  30. package/src/actions/encodings/position/resolve.js +58 -9
  31. package/src/actions/encodings/ranged.js +30 -8
  32. package/src/actions/encodings/shared.js +17 -21
  33. package/src/actions/encodings/strokeDash.js +1 -1
  34. package/src/actions/encodings/text.js +73 -0
  35. package/src/actions/errorBands/create.js +37 -29
  36. package/src/actions/errorBands/edit.js +206 -0
  37. package/src/actions/errorBands/index.js +9 -0
  38. package/src/actions/errorBands/options.js +39 -0
  39. package/src/actions/errorBars/create.js +50 -43
  40. package/src/actions/errorBars/edit.js +130 -0
  41. package/src/actions/errorBars/index.js +3 -0
  42. package/src/actions/errorBars/options.js +52 -0
  43. package/src/actions/facets/actions.js +162 -0
  44. package/src/actions/facets/derive.js +200 -0
  45. package/src/actions/facets/guides.js +16 -0
  46. package/src/actions/facets/index.js +1 -0
  47. package/src/actions/facets/replay.js +69 -0
  48. package/src/actions/guides/applicability.js +113 -0
  49. package/src/actions/guides/axes/axes.js +70 -16
  50. package/src/actions/guides/axes/edit.js +126 -0
  51. package/src/actions/guides/axes/index.js +12 -0
  52. package/src/actions/guides/axes/labels.js +22 -19
  53. package/src/actions/guides/axes/remove.js +60 -0
  54. package/src/actions/guides/axes/tickGroups.js +7 -5
  55. package/src/actions/guides/axes/ticks.js +10 -5
  56. package/src/actions/guides/axes/titles.js +8 -6
  57. package/src/actions/guides/grids/grid.js +144 -15
  58. package/src/actions/guides/grids/resolve.js +6 -14
  59. package/src/actions/guides/guides.js +17 -75
  60. package/src/actions/guides/index.js +6 -0
  61. package/src/actions/guides/legends/categorical/actions.js +48 -9
  62. package/src/actions/guides/legends/categorical/components.js +16 -16
  63. package/src/actions/guides/legends/categorical/index.js +14 -14
  64. package/src/actions/guides/legends/categorical/layout.js +7 -3
  65. package/src/actions/guides/legends/categorical/options.js +2 -5
  66. package/src/actions/guides/legends/categorical/resolve.js +2 -2
  67. package/src/actions/guides/legends/categorical/symbols.js +14 -14
  68. package/src/actions/guides/legends/continuous/common.js +7 -7
  69. package/src/actions/guides/legends/continuous/interval.js +6 -6
  70. package/src/actions/guides/legends/continuous/opacity.js +1 -1
  71. package/src/actions/guides/legends/edit.js +4 -26
  72. package/src/actions/guides/legends/focused.js +63 -0
  73. package/src/actions/guides/legends/index.js +4 -0
  74. package/src/actions/guides/legends/remove.js +46 -0
  75. package/src/actions/guides/legends/size.js +13 -15
  76. package/src/actions/guides/legends/target.js +25 -0
  77. package/src/actions/guides/polar/axes/facade.js +219 -0
  78. package/src/actions/guides/polar/axes/index.js +55 -0
  79. package/src/actions/guides/polar/axes/labels.js +188 -0
  80. package/src/actions/guides/polar/axes/lines.js +113 -0
  81. package/src/actions/guides/polar/axes/shared.js +112 -0
  82. package/src/actions/guides/polar/axes/ticks.js +164 -0
  83. package/src/actions/guides/polar/axes/titles.js +165 -0
  84. package/src/actions/guides/polar/grids.js +252 -0
  85. package/src/actions/guides/polar/index.js +2 -0
  86. package/src/actions/guides/polar/resolve.js +269 -0
  87. package/src/actions/guides/tickValues.js +1 -1
  88. package/src/actions/index.js +4 -0
  89. package/src/actions/intervals/resolve.js +1 -1
  90. package/src/actions/marks/arc/actions.js +239 -0
  91. package/src/actions/marks/arc/index.js +1 -0
  92. package/src/actions/marks/{area.js → area/actions.js} +51 -38
  93. package/src/actions/marks/area/index.js +4 -0
  94. package/src/actions/marks/bar/create.js +26 -5
  95. package/src/actions/marks/bar/edit.js +1 -1
  96. package/src/actions/marks/bar/materialize.js +25 -31
  97. package/src/actions/marks/index.js +12 -4
  98. package/src/actions/marks/lifecycle.js +27 -0
  99. package/src/actions/marks/line/actions.js +373 -0
  100. package/src/actions/marks/line/index.js +1 -0
  101. package/src/actions/marks/{point.js → point/actions.js} +67 -108
  102. package/src/actions/marks/point/index.js +1 -0
  103. package/src/actions/marks/rect/actions.js +165 -0
  104. package/src/actions/marks/rect/index.js +1 -0
  105. package/src/actions/marks/remove.js +214 -0
  106. package/src/actions/marks/{rule.js → rule/actions.js} +34 -28
  107. package/src/actions/marks/rule/index.js +1 -0
  108. package/src/actions/marks/shared.js +156 -25
  109. package/src/actions/marks/text/actions.js +192 -0
  110. package/src/actions/marks/text/index.js +1 -0
  111. package/src/actions/primitives/createGraphics.js +13 -6
  112. package/src/actions/primitives/editGraphics.js +10 -3
  113. package/src/actions/primitives/semantic.js +26 -3
  114. package/src/actions/primitives/semanticValue.js +26 -4
  115. package/src/actions/regression/components.js +2 -2
  116. package/src/actions/regression/create.js +19 -2
  117. package/src/actions/regression/edit.js +247 -0
  118. package/src/actions/regression/index.js +3 -0
  119. package/src/actions/regression/resolve.js +3 -1
  120. package/src/actions/scales/consumers/common.js +91 -0
  121. package/src/actions/scales/consumers/families.js +47 -0
  122. package/src/actions/scales/consumers/index.js +41 -0
  123. package/src/actions/scales/{consumers.js → consumers/seriesLayout.js} +14 -127
  124. package/src/actions/scales/create.js +1 -1
  125. package/src/actions/scales/definitions.js +15 -6
  126. package/src/actions/scales/edit.js +45 -22
  127. package/src/actions/scales/materialize.js +58 -409
  128. package/src/actions/selection/actions.js +38 -24
  129. package/src/actions/selection/index.js +2 -0
  130. package/src/actions/titles/actions.js +63 -2
  131. package/src/actions/titles/index.js +2 -0
  132. package/src/actions/titles/resolve.js +12 -17
  133. package/src/composition.js +10 -0
  134. package/src/core/ChartProgram.js +49 -65
  135. package/src/core/action.js +10 -0
  136. package/src/core/compositionState.js +169 -0
  137. package/src/core/materializationState.js +65 -0
  138. package/src/core/programState.js +28 -0
  139. package/src/core/validation.js +16 -0
  140. package/src/core/vocabulary.js +154 -4
  141. package/src/grammar/arcs.js +154 -0
  142. package/src/grammar/areaSeries.js +1 -1
  143. package/src/grammar/bars/aggregate.js +3 -3
  144. package/src/grammar/bars/geometry.js +3 -3
  145. package/src/grammar/bars/policy.js +7 -1
  146. package/src/grammar/coordinates.js +3 -7
  147. package/src/grammar/density.js +21 -2
  148. package/src/grammar/facets/dependencies.js +185 -0
  149. package/src/grammar/facets/guides.js +257 -0
  150. package/src/grammar/facets/index.js +122 -0
  151. package/src/grammar/facets/scales.js +254 -0
  152. package/src/grammar/interval.js +2 -96
  153. package/src/grammar/lineSeries.js +112 -4
  154. package/src/grammar/palettes.js +5 -7
  155. package/src/grammar/polar.js +102 -0
  156. package/src/grammar/polarGuides.js +243 -0
  157. package/src/grammar/polarLineCommands.js +43 -0
  158. package/src/grammar/polarPaths.js +161 -0
  159. package/src/grammar/positionCompatibility.js +18 -2
  160. package/src/grammar/rects.js +26 -0
  161. package/src/grammar/regression/derive.js +97 -0
  162. package/src/grammar/regression/index.js +22 -0
  163. package/src/grammar/regression/models.js +282 -0
  164. package/src/grammar/regression/parameters.js +106 -0
  165. package/src/grammar/rules.js +1 -1
  166. package/src/grammar/scales/color.js +4 -2
  167. package/src/grammar/scales/continuous.js +6 -1
  168. package/src/grammar/scales/fields.js +7 -0
  169. package/src/grammar/scales/ordinal.js +5 -2
  170. package/src/grammar/scales/policies.js +1 -1
  171. package/src/grammar/schemas/graphic.js +1 -1
  172. package/src/grammar/schemas/graphicBounds.js +64 -9
  173. package/src/grammar/schemas/graphicTree.js +44 -10
  174. package/src/grammar/schemas/semanticPath.js +31 -9
  175. package/src/grammar/seriesLayout.js +13 -2
  176. package/src/grammar/statistics/studentT.js +98 -0
  177. package/src/grammar/text.js +71 -0
  178. package/src/grammar/ticks.js +50 -13
  179. package/src/grammar/transforms.js +1 -1
  180. package/src/index.js +1 -0
  181. package/src/layout/composition.js +310 -0
  182. package/src/layout/facets.js +131 -0
  183. package/src/layout/title.js +6 -0
  184. package/src/materialization/bars/aggregate.js +6 -3
  185. package/src/materialization/bars/grouped.js +75 -37
  186. package/src/materialization/bars/histogram.js +1 -1
  187. package/src/materialization/bars/ranged.js +1 -1
  188. package/src/materialization/composition.js +152 -0
  189. package/src/materialization/compositionSnapshot.js +114 -0
  190. package/src/materialization/density.js +1 -1
  191. package/src/materialization/dependencies.js +47 -73
  192. package/src/materialization/encodings.js +14 -28
  193. package/src/materialization/facetGuides/index.js +2 -0
  194. package/src/materialization/facetGuides/legacyCategorical.js +125 -0
  195. package/src/materialization/facetGuides/placement.js +126 -0
  196. package/src/materialization/facetGuides/preparation.js +188 -0
  197. package/src/materialization/facets.js +214 -0
  198. package/src/materialization/graphicHierarchy.js +15 -5
  199. package/src/materialization/guides/resources.js +46 -0
  200. package/src/materialization/marks/capabilities.js +141 -0
  201. package/src/materialization/marks/index.js +105 -0
  202. package/src/materialization/marks/policies.js +87 -0
  203. package/src/materialization/planner.js +105 -12
  204. package/src/materialization/rect.js +138 -0
  205. package/src/materialization/rectConfig.js +38 -0
  206. package/src/materialization/rowEncoding.js +33 -0
  207. package/src/materialization/scaleGuideDependencies.js +94 -0
  208. package/src/materialization/scales/map.js +40 -0
  209. package/src/materialization/scales/policies/arc.js +37 -0
  210. package/src/materialization/scales/policies/bar.js +132 -0
  211. package/src/materialization/scales/policies/series.js +76 -0
  212. package/src/materialization/scales/resolve.js +326 -0
  213. package/src/materialization/selection/items/arc.js +29 -0
  214. package/src/materialization/selection/items/bar.js +255 -0
  215. package/src/materialization/selection/items/common.js +131 -0
  216. package/src/materialization/selection/items/index.js +6 -0
  217. package/src/materialization/selection/items/path.js +59 -0
  218. package/src/materialization/selection/items/point.js +55 -0
  219. package/src/materialization/selection/items/rect.js +23 -0
  220. package/src/materialization/selection/items/rule.js +25 -0
  221. package/src/materialization/selection/policies/arc.js +10 -0
  222. package/src/materialization/selection/policies/area.js +1 -1
  223. package/src/materialization/selection/policies/bar.js +1 -1
  224. package/src/materialization/selection/policies/index.js +5 -1
  225. package/src/materialization/selection/policies/line.js +1 -1
  226. package/src/materialization/selection/policies/point.js +1 -1
  227. package/src/materialization/selection/policies/rect.js +10 -0
  228. package/src/materialization/selection/policies/rule.js +1 -1
  229. package/src/materialization/selection/styles.js +25 -17
  230. package/src/materialization/text.js +156 -0
  231. package/src/renderers/canvas/index.js +68 -22
  232. package/src/renderers/canvas/text.js +14 -1
  233. package/types/extension.d.ts +5 -1
  234. package/types/index.d.ts +56 -1
  235. package/types/program.d.ts +664 -27
  236. package/src/actions/encodings/color.js +0 -329
  237. package/src/actions/encodings/position.js +0 -176
  238. package/src/actions/marks/line.js +0 -248
  239. package/src/grammar/regression.js +0 -578
  240. package/src/grammar/scales.js +0 -1
  241. package/src/materialization/marks.js +0 -110
  242. package/src/materialization/selection/items.js +0 -503
@@ -22,8 +22,12 @@ import {
22
22
  validateScalePropertyForType,
23
23
  validateScaleTypeForRole,
24
24
  isDiscretePositionScaleType
25
- } from "../../grammar/scales.js";
26
- import { withScaleUnknown } from "../../grammar/scales.js";
25
+ } from "../../grammar/scales/index.js";
26
+ import {
27
+ validateRadialRange,
28
+ validateThetaRange
29
+ } from "../../grammar/polar.js";
30
+ import { withScaleUnknown } from "../../grammar/scales/index.js";
27
31
  import { findSemanticScale } from "../../selectors/scales.js";
28
32
 
29
33
  const BASE_OPTIONS = Object.freeze(["id", "type", "domain", "range"]);
@@ -87,6 +91,7 @@ export function resolvePositionScaleDefinition(
87
91
  );
88
92
  }
89
93
  }
94
+ else if (channel === "theta") validateLinearScaleType(type);
90
95
  else validateScaleTypeForRole(type, SCALE_ROLES.quantitativePosition);
91
96
  const scale = {
92
97
  id,
@@ -108,7 +113,11 @@ export function resolvePositionScaleDefinition(
108
113
  ["ordinal", "nominal"].includes(fieldType)
109
114
  ? validateOrdinalDomain(value)
110
115
  : validateScaleDomain(value),
111
- validateRange: (_scaleType, value) => validateScaleRange(value)
116
+ validateRange: (_scaleType, value) => channel === "theta"
117
+ ? validateThetaRange(value)
118
+ : channel === "radius"
119
+ ? validateRadialRange(value)
120
+ : validateScaleRange(value)
112
121
  })
113
122
  };
114
123
  return withScaleUnknown(scale, { ...existing, ...options }, channel);
@@ -305,15 +314,15 @@ export function resolveOpacityScaleDefinition(program, options) {
305
314
  return withScaleUnknown(scale, { ...existing, ...options }, "opacity");
306
315
  }
307
316
 
308
- export function resolveOffsetScaleDefinition(program, options) {
317
+ export function resolveOffsetScaleDefinition(program, options, channel = "xOffset") {
309
318
  optionsObject(options);
310
319
  validateKeys(options, [...BASE_OPTIONS, "unknown"], "scale");
311
- const id = validateUserId(options.id ?? "xOffset", "Scale id");
320
+ const id = validateUserId(options.id ?? channel, "Scale id");
312
321
  const existing = findSemanticScale(program, id);
313
322
  return withScaleUnknown({
314
323
  id,
315
324
  type: validateOrdinalScaleType(options.type ?? existing?.type ?? "ordinal"),
316
325
  domain: validateOrdinalDomain(options.domain ?? existing?.domain ?? "auto"),
317
326
  range: validateScaleRange(options.range ?? existing?.range ?? "auto")
318
- }, { ...existing, ...options }, "xOffset");
327
+ }, { ...existing, ...options }, channel);
319
328
  }
@@ -1,7 +1,6 @@
1
1
  import { action } from "../../core/action.js";
2
2
  import { validateUserId } from "../../core/identifiers.js";
3
- import { isPlainObject } from "../../core/immutable.js";
4
- import { validateKeys } from "../../core/validation.js";
3
+ import { validateOptionObject } from "../../core/validation.js";
5
4
  import {
6
5
  isTransformedScaleType,
7
6
  SCALE_ROLES,
@@ -22,8 +21,12 @@ import {
22
21
  isDiscretePositionScaleType,
23
22
  hasOrdinalDomain,
24
23
  normalizeScaleDefinition
25
- } from "../../grammar/scales.js";
26
- import { getMarkMaterializationStep } from "../../materialization/marks.js";
24
+ } from "../../grammar/scales/index.js";
25
+ import {
26
+ validateRadialRange,
27
+ validateThetaRange
28
+ } from "../../grammar/polar.js";
29
+ import { getMarkMaterializationStep } from "../../materialization/marks/index.js";
27
30
  import {
28
31
  applyMaterializationPlan
29
32
  } from "../../materialization/dependencies.js";
@@ -31,14 +34,18 @@ import {
31
34
  findSemanticScale,
32
35
  requireSemanticScale
33
36
  } from "../../selectors/scales.js";
34
- import { findScaleConsumers } from "./consumers.js";
37
+ import { findScaleConsumers } from "./consumers/index.js";
38
+ import { normalizePositionScaleChannel } from "../../core/vocabulary.js";
35
39
 
36
40
  const OPTIONS = Object.freeze([
37
41
  "id", "type", "domain", "range", "nice", "zero", "clamp", "reverse",
38
42
  "base", "exponent", "constant", "paddingInner", "paddingOuter", "padding",
39
- "align", "interpolate", "unknown"
43
+ "align", "interpolate", "unknown", "palette"
40
44
  ]);
41
- const EDITABLE = Object.freeze(OPTIONS.filter(option => option !== "id"));
45
+ const EDITABLE = Object.freeze(
46
+ OPTIONS.filter(option => !["id", "palette"].includes(option))
47
+ );
48
+ const REQUESTED_CHANGES = Object.freeze(OPTIONS.filter(option => option !== "id"));
42
49
 
43
50
  function resolveScaleId(program, requested) {
44
51
  if (requested !== undefined) {
@@ -60,13 +67,9 @@ function resolveScaleId(program, requested) {
60
67
  );
61
68
  }
62
69
 
63
- function normalizeChannel(channel) {
64
- return channel === "x2" ? "x" : channel === "y2" ? "y" : channel;
65
- }
66
-
67
70
  function resolveChannel(consumers, id) {
68
71
  const channels = new Set(
69
- consumers.map(consumer => normalizeChannel(consumer.channel))
72
+ consumers.map(consumer => normalizePositionScaleChannel(consumer.channel))
70
73
  );
71
74
  if (channels.size > 1) {
72
75
  throw new Error(`Scale "${id}" cannot be shared across channels.`);
@@ -76,6 +79,8 @@ function resolveChannel(consumers, id) {
76
79
 
77
80
  function validateRangeForChannel(scale, channel, value) {
78
81
  if (value === "auto") return value;
82
+ if (channel === "theta") return validateThetaRange(value);
83
+ if (channel === "radius") return validateRadialRange(value);
79
84
  if (scale.type === "sequential") {
80
85
  return validateSequentialColorRange(value);
81
86
  }
@@ -97,7 +102,7 @@ function validateTypeTransition(scale, nextType, channel, consumers) {
97
102
  if (nextType === "sequential" || isDiscretizedColorScaleType(nextType)) {
98
103
  const discretized = isDiscretizedColorScaleType(nextType);
99
104
  if (channel !== "color" || consumers.some(consumer =>
100
- consumer.encoding.fieldType === "nominal" ||
105
+ ["nominal", "ordinal"].includes(consumer.encoding.fieldType) ||
101
106
  (discretized && (
102
107
  consumer.encoding.fieldType !== "quantitative" ||
103
108
  consumer.layer.mark?.type !== "point"
@@ -113,7 +118,7 @@ function validateTypeTransition(scale, nextType, channel, consumers) {
113
118
  if (nextType === "time") {
114
119
  if (
115
120
  consumers.length > 0 &&
116
- (!["x", "y"].includes(channel) ||
121
+ (!["x", "y", "theta"].includes(channel) ||
117
122
  consumers.some(consumer => consumer.encoding.fieldType !== "temporal"))
118
123
  ) {
119
124
  throw new Error(
@@ -126,7 +131,7 @@ function validateTypeTransition(scale, nextType, channel, consumers) {
126
131
  if (discrete) {
127
132
  if (
128
133
  consumers.length > 0 &&
129
- (!["x", "y"].includes(channel) || consumers.some(consumer =>
134
+ (!["x", "y", "theta"].includes(channel) || consumers.some(consumer =>
130
135
  !["nominal", "ordinal"].includes(consumer.encoding.fieldType)
131
136
  ))
132
137
  ) {
@@ -145,13 +150,16 @@ function validateTypeTransition(scale, nextType, channel, consumers) {
145
150
  const quantitative = nextType === "linear" || isTransformedScaleType(nextType);
146
151
  if (
147
152
  !quantitative ||
148
- (consumers.length > 0 && !["x", "y"].includes(channel))
153
+ (consumers.length > 0 && !["x", "y", "theta", "radius"].includes(channel))
149
154
  ) {
150
155
  throw new Error(
151
156
  "editScale type transition currently requires a quantitative position scale."
152
157
  );
153
158
  }
154
159
  validateScaleTypeForRole(nextType, SCALE_ROLES.quantitativePosition);
160
+ if (channel === "theta" && nextType !== "linear") {
161
+ throw new Error("Theta quantitative position currently requires a linear scale.");
162
+ }
155
163
  if (consumers.some(consumer => consumer.encoding.fieldType !== "quantitative")) {
156
164
  throw new Error(
157
165
  `Scale "${scale.id}" has a consumer incompatible with type "${nextType}".`
@@ -242,20 +250,35 @@ export const editScale = action(
242
250
  description: "Edit an existing scale and rematerialize its consumers."
243
251
  },
244
252
  function (args = {}) {
245
- if (!isPlainObject(args)) {
246
- throw new TypeError("editScale options must be a plain object.");
247
- }
248
- validateKeys(args, OPTIONS, "editScale");
249
- if (!EDITABLE.some(property => Object.hasOwn(args, property))) {
253
+ validateOptionObject(args, OPTIONS, "editScale");
254
+ if (!REQUESTED_CHANGES.some(property => Object.hasOwn(args, property))) {
250
255
  throw new Error("editScale requires at least one editable property.");
251
256
  }
257
+ const hasPalette = Object.hasOwn(args, "palette");
258
+ if (hasPalette && Object.hasOwn(args, "range")) {
259
+ throw new Error("editScale cannot specify both palette and range.");
260
+ }
252
261
 
253
262
  const id = resolveScaleId(this, args.id);
254
263
  const scale = requireSemanticScale(this, id);
255
264
  const consumers = findScaleConsumers(this, id);
256
265
  const channel = resolveChannel(consumers, id);
266
+ if (
267
+ hasPalette &&
268
+ channel !== "color" &&
269
+ scale.type !== "sequential" &&
270
+ !isDiscretizedColorScaleType(scale.type)
271
+ ) {
272
+ throw new Error("editScale palette requires a color scale.");
273
+ }
274
+ const patch = !hasPalette
275
+ ? args
276
+ : Object.fromEntries([
277
+ ...Object.entries(args).filter(([key]) => key !== "palette"),
278
+ ["range", { palette: args.palette }]
279
+ ]);
257
280
  validateLegendTypeTransition(this, scale, args.type ?? scale.type);
258
- const definition = normalizeDefinition(scale, channel, consumers, args);
281
+ const definition = normalizeDefinition(scale, channel, consumers, patch);
259
282
 
260
283
  let next = this;
261
284
  for (const property of EDITABLE) {