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
@@ -1,382 +1 @@
1
- import { cloneAndFreeze, isPlainObject } from "../../core/immutable.js";
2
- import { validateGeneratedItemLimit } from "../../core/validation.js";
3
- import {
4
- normalizePalette,
5
- resolveContinuousPalette
6
- } from "../palettes.js";
7
- import { inverseLerp } from "../numeric.js";
8
-
9
- export const CONTINUOUS_COLOR_INTERPOLATIONS = cloneAndFreeze([
10
- "rgb",
11
- "hsl",
12
- "hsl-long",
13
- "lab",
14
- "hcl",
15
- "hcl-long",
16
- "cubehelix",
17
- "cubehelix-long"
18
- ]);
19
-
20
- const BASIC_COLORS = Object.freeze({
21
- black: "#000000",
22
- blue: "#0000ff",
23
- cyan: "#00ffff",
24
- gray: "#808080",
25
- green: "#008000",
26
- grey: "#808080",
27
- magenta: "#ff00ff",
28
- navy: "#000080",
29
- orange: "#ffa500",
30
- purple: "#800080",
31
- red: "#ff0000",
32
- teal: "#008080",
33
- white: "#ffffff",
34
- yellow: "#ffff00"
35
- });
36
-
37
- function clamp(value, minimum = 0, maximum = 1) {
38
- return Math.max(minimum, Math.min(maximum, value));
39
- }
40
-
41
- function hue(value) {
42
- return ((value % 360) + 360) % 360;
43
- }
44
-
45
- function hslToRgb({ h, s, l }) {
46
- const chroma = (1 - Math.abs(2 * l - 1)) * s;
47
- const segment = hue(h) / 60;
48
- const second = chroma * (1 - Math.abs(segment % 2 - 1));
49
- const [red, green, blue] = segment < 1 ? [chroma, second, 0]
50
- : segment < 2 ? [second, chroma, 0]
51
- : segment < 3 ? [0, chroma, second]
52
- : segment < 4 ? [0, second, chroma]
53
- : segment < 5 ? [second, 0, chroma]
54
- : [chroma, 0, second];
55
- const match = l - chroma / 2;
56
- return { r: red + match, g: green + match, b: blue + match };
57
- }
58
-
59
- function parseColor(value) {
60
- if (typeof value !== "string" || value.length === 0) {
61
- throw new TypeError("Continuous color range requires non-empty color strings.");
62
- }
63
- const normalized = BASIC_COLORS[value.toLowerCase()] ?? value.toLowerCase();
64
- let match = normalized.match(/^#([0-9a-f]{3})$/i);
65
- if (match) {
66
- return Object.fromEntries(["r", "g", "b"].map((channel, index) => [
67
- channel,
68
- Number.parseInt(match[1][index].repeat(2), 16) / 255
69
- ]));
70
- }
71
- match = normalized.match(/^#([0-9a-f]{6})$/i);
72
- if (match) {
73
- return {
74
- r: Number.parseInt(match[1].slice(0, 2), 16) / 255,
75
- g: Number.parseInt(match[1].slice(2, 4), 16) / 255,
76
- b: Number.parseInt(match[1].slice(4, 6), 16) / 255
77
- };
78
- }
79
- match = normalized.match(
80
- /^rgb\(\s*([\d.]+)%?\s*,\s*([\d.]+)%?\s*,\s*([\d.]+)%?\s*\)$/
81
- );
82
- if (match) {
83
- const percentage = normalized.includes("%");
84
- const divisor = percentage ? 100 : 255;
85
- const channels = match.slice(1).map(item => Number(item) / divisor);
86
- if (channels.every(item => Number.isFinite(item) && item >= 0 && item <= 1)) {
87
- return { r: channels[0], g: channels[1], b: channels[2] };
88
- }
89
- }
90
- match = normalized.match(
91
- /^hsl\(\s*([-\d.]+)\s*,\s*([\d.]+)%\s*,\s*([\d.]+)%\s*\)$/
92
- );
93
- if (match) {
94
- const h = Number(match[1]);
95
- const s = Number(match[2]) / 100;
96
- const l = Number(match[3]) / 100;
97
- if ([h, s, l].every(Number.isFinite) && s >= 0 && s <= 1 && l >= 0 && l <= 1) {
98
- return hslToRgb({ h, s, l });
99
- }
100
- }
101
- throw new Error(`Unsupported continuous color "${value}".`);
102
- }
103
-
104
- function rgbToHex({ r, g, b }) {
105
- return `#${[r, g, b].map(channel =>
106
- Math.round(clamp(channel) * 255).toString(16).padStart(2, "0")
107
- ).join("")}`;
108
- }
109
-
110
- function byteChannels({ r, g, b }) {
111
- return [r, g, b].map(channel => Math.round(channel * 255));
112
- }
113
-
114
- function rgbToHsl({ r, g, b }) {
115
- const maximum = Math.max(r, g, b);
116
- const minimum = Math.min(r, g, b);
117
- const delta = maximum - minimum;
118
- const l = (maximum + minimum) / 2;
119
- if (delta === 0) return { h: 0, s: 0, l };
120
- const s = delta / (1 - Math.abs(2 * l - 1));
121
- const raw = maximum === r
122
- ? ((g - b) / delta) % 6
123
- : maximum === g
124
- ? (b - r) / delta + 2
125
- : (r - g) / delta + 4;
126
- return { h: hue(raw * 60), s, l };
127
- }
128
-
129
- function linearRgb(channel) {
130
- return channel <= 0.04045
131
- ? channel / 12.92
132
- : ((channel + 0.055) / 1.055) ** 2.4;
133
- }
134
-
135
- function encodedRgb(channel) {
136
- return channel <= 0.0031308
137
- ? 12.92 * channel
138
- : 1.055 * channel ** (1 / 2.4) - 0.055;
139
- }
140
-
141
- function rgbToLab(color) {
142
- const r = linearRgb(color.r);
143
- const g = linearRgb(color.g);
144
- const b = linearRgb(color.b);
145
- const x = (0.4124564 * r + 0.3575761 * g + 0.1804375 * b) / 0.95047;
146
- const y = 0.2126729 * r + 0.7151522 * g + 0.072175 * b;
147
- const z = (0.0193339 * r + 0.119192 * g + 0.9503041 * b) / 1.08883;
148
- const convert = value => value > 216 / 24389
149
- ? Math.cbrt(value)
150
- : 841 / 108 * value + 4 / 29;
151
- const fx = convert(x);
152
- const fy = convert(y);
153
- const fz = convert(z);
154
- return { l: 116 * fy - 16, a: 500 * (fx - fy), b: 200 * (fy - fz) };
155
- }
156
-
157
- function labToRgb({ l, a, b }) {
158
- const fy = (l + 16) / 116;
159
- const fx = fy + a / 500;
160
- const fz = fy - b / 200;
161
- const convert = value => value ** 3 > 216 / 24389
162
- ? value ** 3
163
- : 108 / 841 * (value - 4 / 29);
164
- const x = 0.95047 * convert(fx);
165
- const y = convert(fy);
166
- const z = 1.08883 * convert(fz);
167
- return {
168
- r: encodedRgb(3.2404542 * x - 1.5371385 * y - 0.4985314 * z),
169
- g: encodedRgb(-0.969266 * x + 1.8760108 * y + 0.041556 * z),
170
- b: encodedRgb(0.0556434 * x - 0.2040259 * y + 1.0572252 * z)
171
- };
172
- }
173
-
174
- function labToHcl({ l, a, b }) {
175
- return { h: hue(Math.atan2(b, a) * 180 / Math.PI), c: Math.hypot(a, b), l };
176
- }
177
-
178
- function hclToLab({ h, c, l }) {
179
- const radians = h * Math.PI / 180;
180
- return { l, a: Math.cos(radians) * c, b: Math.sin(radians) * c };
181
- }
182
-
183
- function rgbToCubehelix({ r, g, b }) {
184
- const A = -0.14861;
185
- const B = 1.78277;
186
- const C = -0.29227;
187
- const D = -0.90649;
188
- const E = 1.97294;
189
- const ED = E * D;
190
- const EB = E * B;
191
- const BC_DA = B * C - D * A;
192
- const l = (BC_DA * b + ED * r - EB * g) / (BC_DA + ED - EB);
193
- const blue = b - l;
194
- const k = (E * (g - l) - C * blue) / D;
195
- const denominator = E * l * (1 - l);
196
- return {
197
- h: hue(Math.atan2(k, blue) * 180 / Math.PI - 120),
198
- s: denominator === 0 ? 0 : Math.hypot(k, blue) / denominator,
199
- l
200
- };
201
- }
202
-
203
- function cubehelixToRgb({ h, s, l }) {
204
- const angle = (h + 120) * Math.PI / 180;
205
- const amplitude = s * l * (1 - l);
206
- const cosine = Math.cos(angle);
207
- const sine = Math.sin(angle);
208
- return {
209
- r: l + amplitude * (-0.14861 * cosine + 1.78277 * sine),
210
- g: l + amplitude * (-0.29227 * cosine - 0.90649 * sine),
211
- b: l + amplitude * (1.97294 * cosine)
212
- };
213
- }
214
-
215
- function interpolateHue(left, right, amount, long) {
216
- let delta = right - left;
217
- if (!long) delta = ((delta + 540) % 360) - 180;
218
- return hue(left + delta * amount);
219
- }
220
-
221
- function mix(left, right, amount, method) {
222
- if (method.startsWith("hsl")) {
223
- const a = rgbToHsl(left);
224
- const b = rgbToHsl(right);
225
- return hslToRgb({
226
- h: interpolateHue(a.h, b.h, amount, method.endsWith("-long")),
227
- s: a.s + (b.s - a.s) * amount,
228
- l: a.l + (b.l - a.l) * amount
229
- });
230
- }
231
- if (method === "lab") {
232
- const a = rgbToLab(left);
233
- const b = rgbToLab(right);
234
- return labToRgb({
235
- l: a.l + (b.l - a.l) * amount,
236
- a: a.a + (b.a - a.a) * amount,
237
- b: a.b + (b.b - a.b) * amount
238
- });
239
- }
240
- if (method.startsWith("hcl")) {
241
- const a = labToHcl(rgbToLab(left));
242
- const b = labToHcl(rgbToLab(right));
243
- return labToRgb(hclToLab({
244
- h: interpolateHue(a.h, b.h, amount, method.endsWith("-long")),
245
- c: a.c + (b.c - a.c) * amount,
246
- l: a.l + (b.l - a.l) * amount
247
- }));
248
- }
249
- const a = rgbToCubehelix(left);
250
- const b = rgbToCubehelix(right);
251
- return cubehelixToRgb({
252
- h: interpolateHue(a.h, b.h, amount, method.endsWith("-long")),
253
- s: a.s + (b.s - a.s) * amount,
254
- l: a.l + (b.l - a.l) * amount
255
- });
256
- }
257
-
258
- export function validateContinuousColorInterpolation(value) {
259
- if (!CONTINUOUS_COLOR_INTERPOLATIONS.includes(value)) {
260
- throw new Error(`Unsupported continuous color interpolation "${value}".`);
261
- }
262
- return value;
263
- }
264
-
265
- export function validateSequentialColorRange(value) {
266
- if (value === "auto") return value;
267
- if (Array.isArray(value)) {
268
- validateGeneratedItemLimit(value.length, "Sequential color range length");
269
- if (value.length < 2) {
270
- throw new TypeError("Sequential color range requires at least two colors.");
271
- }
272
- value.forEach(parseColor);
273
- return cloneAndFreeze(value);
274
- }
275
- if (
276
- !isPlainObject(value) ||
277
- Object.keys(value).length !== 1 ||
278
- !Object.hasOwn(value, "palette")
279
- ) {
280
- throw new TypeError("Sequential color range requires colors or a palette descriptor.");
281
- }
282
- const palette = normalizePalette(value.palette);
283
- if (palette.count !== undefined && palette.count < 2) {
284
- throw new RangeError(
285
- "Sequential palette count must be an integer of at least 2."
286
- );
287
- }
288
- return cloneAndFreeze({ palette });
289
- }
290
-
291
- export function resolveSequentialColorStops(value) {
292
- const range = validateSequentialColorRange(value);
293
- if (range === "auto") return resolveContinuousPalette("viridis");
294
- return Array.isArray(range)
295
- ? cloneAndFreeze(range.map(color => rgbToHex(parseColor(color))))
296
- : resolveContinuousPalette(range.palette);
297
- }
298
-
299
- function interpolateColors(colors, position, method, shouldClamp) {
300
- const bounded = shouldClamp ? clamp(position) : position;
301
- const scaled = bounded * (colors.length - 1);
302
- const left = Math.max(0, Math.min(colors.length - 2, Math.floor(scaled)));
303
- const right = left + 1;
304
- const amount = scaled - left;
305
- if (method === "rgb") {
306
- const leftChannels = byteChannels(colors[left]);
307
- const rightChannels = byteChannels(colors[right]);
308
- return `#${leftChannels.map((channel, index) =>
309
- Math.round(clamp(
310
- channel + (rightChannels[index] - channel) * amount,
311
- 0,
312
- 255
313
- )).toString(16).padStart(2, "0")
314
- ).join("")}`;
315
- }
316
- return rgbToHex(mix(colors[left], colors[right], amount, method));
317
- }
318
-
319
- export function interpolateColorStops(stops, position, interpolation = "rgb") {
320
- const method = validateContinuousColorInterpolation(interpolation);
321
- if (!Array.isArray(stops) || stops.length < 2) {
322
- throw new TypeError("Color interpolation requires at least two stops.");
323
- }
324
- const colors = stops.map(parseColor);
325
- return interpolateColors(colors, position, method, true);
326
- }
327
-
328
- export function validateSequentialMidpoint(value, type, domain = "auto") {
329
- if (value === undefined || value === "auto") return undefined;
330
- if (type !== "sequential") {
331
- throw new Error(`Scale type "${type}" does not support midpoint.`);
332
- }
333
- if (!Number.isFinite(value)) {
334
- throw new TypeError("Scale midpoint must be finite or auto.");
335
- }
336
- if (domain !== "auto" && (
337
- !Array.isArray(domain) || domain.length !== 2 || !domain.every(Number.isFinite) ||
338
- !(value > Math.min(...domain) && value < Math.max(...domain))
339
- )) {
340
- throw new RangeError("Scale midpoint must lie strictly inside its resolved domain.");
341
- }
342
- return value;
343
- }
344
-
345
- export function mapSequentialColors(
346
- values,
347
- domain,
348
- stops,
349
- options = {}
350
- ) {
351
- const { interpolation = "rgb", clamp: shouldClamp = false } = options;
352
- const hasUnknown = Object.hasOwn(options, "unknown");
353
- if (!Array.isArray(domain) || domain.length !== 2 || !domain.every(Number.isFinite)) {
354
- throw new TypeError("Sequential color domain must contain two finite numbers.");
355
- }
356
- if (!Array.isArray(values) || (!hasUnknown && !values.every(Number.isFinite))) {
357
- throw new TypeError("Sequential color values must be finite numbers.");
358
- }
359
- if (typeof shouldClamp !== "boolean") {
360
- throw new TypeError("Sequential color clamp must be a boolean.");
361
- }
362
- const midpoint = validateSequentialMidpoint(options.midpoint, "sequential", domain);
363
- const [start, end] = domain;
364
- const constant = start === end;
365
- const method = validateContinuousColorInterpolation(interpolation);
366
- if (!Array.isArray(stops) || stops.length < 2) {
367
- throw new TypeError("Color interpolation requires at least two stops.");
368
- }
369
- const colors = stops.map(parseColor);
370
- return cloneAndFreeze(values.map(value => {
371
- if (!Number.isFinite(value)) {
372
- if (hasUnknown) return options.unknown;
373
- throw new TypeError("Sequential color values must be finite numbers.");
374
- }
375
- const raw = midpoint === undefined
376
- ? constant ? 0.5 : inverseLerp(value, start, end)
377
- : (end > start ? value <= midpoint : value >= midpoint)
378
- ? inverseLerp(value, start, midpoint) / 2
379
- : 0.5 + inverseLerp(value, midpoint, end) / 2;
380
- return interpolateColors(colors, raw, method, shouldClamp);
381
- }));
382
- }
1
+ import{mapTransformedValues as $}from"./transformed.js";import{cloneAndFreeze as p,isPlainObject as k}from"../../core/immutable.js";import{validateGeneratedItemLimit as F}from"../../core/validation.js";import{normalizePalette as P,resolveContinuousPalette as T}from"../palettes.js";import{inverseLerp as w}from"../numeric.js";const B=p(["rgb","hsl","hsl-long","lab","hcl","hcl-long","cubehelix","cubehelix-long"]),D=Object.freeze({black:"#000000",blue:"#0000ff",cyan:"#00ffff",gray:"#808080",green:"#008000",grey:"#808080",magenta:"#ff00ff",navy:"#000080",orange:"#ffa500",purple:"#800080",red:"#ff0000",teal:"#008080",white:"#ffffff",yellow:"#ffff00"});function M(t,r=0,n=1){return Math.max(r,Math.min(n,t))}function m(t){return(t%360+360)%360}function x({h:t,s:r,l:n}){const e=(1-Math.abs(2*n-1))*r,s=m(t)/60,i=e*(1-Math.abs(s%2-1)),[o,c,l]=s<1?[e,i,0]:s<2?[i,e,0]:s<3?[0,e,i]:s<4?[0,i,e]:s<5?[i,0,e]:[e,0,i],a=n-e/2;return{r:o+a,g:c+a,b:l+a}}function y(t){if(typeof t!="string"||t.length===0)throw new TypeError("Continuous color range requires non-empty color strings.");const r=D[t.toLowerCase()]??t.toLowerCase();let n=r.match(/^#([0-9a-f]{3})$/i);if(n)return Object.fromEntries(["r","g","b"].map((e,s)=>[e,Number.parseInt(n[1][s].repeat(2),16)/255]));if(n=r.match(/^#([0-9a-f]{6})$/i),n)return{r:Number.parseInt(n[1].slice(0,2),16)/255,g:Number.parseInt(n[1].slice(2,4),16)/255,b:Number.parseInt(n[1].slice(4,6),16)/255};if(n=r.match(/^rgb\(\s*([\d.]+)%?\s*,\s*([\d.]+)%?\s*,\s*([\d.]+)%?\s*\)$/),n){const s=r.includes("%")?100:255,i=n.slice(1).map(o=>Number(o)/s);if(i.every(o=>Number.isFinite(o)&&o>=0&&o<=1))return{r:i[0],g:i[1],b:i[2]}}if(n=r.match(/^hsl\(\s*([-\d.]+)\s*,\s*([\d.]+)%\s*,\s*([\d.]+)%\s*\)$/),n){const e=Number(n[1]),s=Number(n[2])/100,i=Number(n[3])/100;if([e,s,i].every(Number.isFinite)&&s>=0&&s<=1&&i>=0&&i<=1)return x({h:e,s,l:i})}throw new Error(`Unsupported continuous color "${t}".`)}function q({r:t,g:r,b:n}){return`#${[t,r,n].map(e=>Math.round(M(e)*255).toString(16).padStart(2,"0")).join("")}`}function N({r:t,g:r,b:n}){return[t,r,n].map(e=>Math.round(e*255))}function A({r:t,g:r,b:n}){const e=Math.max(t,r,n),s=Math.min(t,r,n),i=e-s,o=(e+s)/2;if(i===0)return{h:0,s:0,l:o};const c=i/(1-Math.abs(2*o-1)),l=e===t?(r-n)/i%6:e===r?(n-t)/i+2:(t-r)/i+4;return{h:m(l*60),s:c,l:o}}function C(t){return t<=.04045?t/12.92:((t+.055)/1.055)**2.4}function E(t){return t<=.0031308?12.92*t:1.055*t**(1/2.4)-.055}function d(t){const r=C(t.r),n=C(t.g),e=C(t.b),s=(.4124564*r+.3575761*n+.1804375*e)/.95047,i=.2126729*r+.7151522*n+.072175*e,o=(.0193339*r+.119192*n+.9503041*e)/1.08883,c=u=>u>216/24389?Math.cbrt(u):841/108*u+4/29,l=c(s),a=c(i),f=c(o);return{l:116*a-16,a:500*(l-a),b:200*(a-f)}}function O({l:t,a:r,b:n}){const e=(t+16)/116,s=e+r/500,i=e-n/200,o=f=>f**3>216/24389?f**3:108/841*(f-4/29),c=.95047*o(s),l=o(e),a=1.08883*o(i);return{r:E(3.2404542*c-1.5371385*l-.4985314*a),g:E(-.969266*c+1.8760108*l+.041556*a),b:E(.0556434*c-.2040259*l+1.0572252*a)}}function I({l:t,a:r,b:n}){return{h:m(Math.atan2(n,r)*180/Math.PI),c:Math.hypot(r,n),l:t}}function U({h:t,c:r,l:n}){const e=t*Math.PI/180;return{l:n,a:Math.cos(e)*r,b:Math.sin(e)*r}}function R({r:t,g:r,b:n}){const l=-1.7884503806,a=1.97294*1.78277,f=1.78277*-.29227- -.90649*-.14861,u=(f*n+l*t-a*r)/(f+l-a),b=n-u,h=(1.97294*(r-u)- -.29227*b)/-.90649,g=1.97294*u*(1-u);return{h:m(Math.atan2(h,b)*180/Math.PI-120),s:g===0?0:Math.hypot(h,b)/g,l:u}}function W({h:t,s:r,l:n}){const e=(t+120)*Math.PI/180,s=r*n*(1-n),i=Math.cos(e),o=Math.sin(e);return{r:n+s*(-.14861*i+1.78277*o),g:n+s*(-.29227*i-.90649*o),b:n+s*(1.97294*i)}}function S(t,r,n,e){let s=r-t;return e||(s=(s+540)%360-180),m(t+s*n)}function H(t,r,n,e){if(e.startsWith("hsl")){const o=A(t),c=A(r);return x({h:S(o.h,c.h,n,e.endsWith("-long")),s:o.s+(c.s-o.s)*n,l:o.l+(c.l-o.l)*n})}if(e==="lab"){const o=d(t),c=d(r);return O({l:o.l+(c.l-o.l)*n,a:o.a+(c.a-o.a)*n,b:o.b+(c.b-o.b)*n})}if(e.startsWith("hcl")){const o=I(d(t)),c=I(d(r));return O(U({h:S(o.h,c.h,n,e.endsWith("-long")),c:o.c+(c.c-o.c)*n,l:o.l+(c.l-o.l)*n}))}const s=R(t),i=R(r);return W({h:S(s.h,i.h,n,e.endsWith("-long")),s:s.s+(i.s-s.s)*n,l:s.l+(i.l-s.l)*n})}function j(t){if(!B.includes(t))throw new Error(`Unsupported continuous color interpolation "${t}".`);return t}function _(t){if(t==="auto")return t;if(Array.isArray(t)){if(F(t.length,"Sequential color range length"),t.length<2)throw new TypeError("Sequential color range requires at least two colors.");return t.forEach(y),p(t)}if(!k(t)||Object.keys(t).length!==1||!Object.hasOwn(t,"palette"))throw new TypeError("Sequential color range requires colors or a palette descriptor.");const r=P(t.palette);if(r.count!==void 0&&r.count<2)throw new RangeError("Sequential palette count must be an integer of at least 2.");return p({palette:r})}function Y(t){const r=_(t);return r==="auto"?T("viridis"):Array.isArray(r)?p(r.map(n=>q(y(n)))):T(r.palette)}function z(t,r,n,e){const i=(e?M(r):r)*(t.length-1),o=Math.max(0,Math.min(t.length-2,Math.floor(i))),c=o+1,l=i-o;if(n==="rgb"){const a=N(t[o]),f=N(t[c]);return`#${a.map((u,b)=>Math.round(M(u+(f[b]-u)*l,0,255)).toString(16).padStart(2,"0")).join("")}`}return q(H(t[o],t[c],l,n))}function Z(t,r,n="rgb"){const e=j(n);if(!Array.isArray(t)||t.length<2)throw new TypeError("Color interpolation requires at least two stops.");const s=t.map(y);return z(s,r,e,!0)}function L(t,r,n="auto"){if(!(t===void 0||t==="auto")){if(r!=="sequential")throw new Error(`Scale type "${r}" does not support midpoint.`);if(!Number.isFinite(t))throw new TypeError("Scale midpoint must be finite or auto.");if(n!=="auto"&&(!Array.isArray(n)||n.length!==2||!n.every(Number.isFinite)||!(t>Math.min(...n)&&t<Math.max(...n))))throw new RangeError("Scale midpoint must lie strictly inside its resolved domain.");return t}}function G(t,r,n,e={}){const{interpolation:s="rgb",clamp:i=!1}=e;if(["log","sqrt","symlog"].includes(e.type)){L(e.midpoint,e.type,r);const h=$(t,r,[0,1],{type:e.type,clamp:i,...e.type==="log"?{base:e.base}:{},...e.type==="symlog"?{constant:e.constant}:{},...Object.hasOwn(e,"unknown")?{unknown:NaN}:{}});return G(h,[0,1],n,{...e,type:"sequential"})}const o=Object.hasOwn(e,"unknown");if(!Array.isArray(r)||r.length!==2||!r.every(Number.isFinite))throw new TypeError("Sequential color domain must contain two finite numbers.");if(!Array.isArray(t)||!o&&!t.every(Number.isFinite))throw new TypeError("Sequential color values must be finite numbers.");if(typeof i!="boolean")throw new TypeError("Sequential color clamp must be a boolean.");const c=L(e.midpoint,"sequential",r),[l,a]=r,f=l===a,u=j(s);if(!Array.isArray(n)||n.length<2)throw new TypeError("Color interpolation requires at least two stops.");const b=n.map(y);return p(t.map(h=>{if(!Number.isFinite(h)){if(o)return e.unknown;throw new TypeError("Sequential color values must be finite numbers.")}const g=c===void 0?f?.5:w(h,l,a):(a>l?h<=c:h>=c)?w(h,l,c)/2:.5+w(h,c,a)/2;return z(b,g,u,i)}))}export{B as CONTINUOUS_COLOR_INTERPOLATIONS,Z as interpolateColorStops,G as mapSequentialColors,Y as resolveSequentialColorStops,j as validateContinuousColorInterpolation,_ as validateSequentialColorRange,L as validateSequentialMidpoint};
@@ -7,6 +7,9 @@ export function validateContinuousColorConsumer(layer, encoding, scale, {
7
7
  channel = "color"
8
8
  } = {}) {
9
9
  const kind = layer.mark?.type;
10
+ if (["log", "sqrt", "symlog"].includes(scale.type) && encoding.fieldType !== "quantitative") {
11
+ throw new Error(`Scale type "${scale.type}" requires quantitative color.`);
12
+ }
10
13
  if (channel === "stroke") {
11
14
  if (!["point", "line", "area", "bar", "rect", "arc", "rule", "tick"].includes(kind)) {
12
15
  throw new Error("Continuous stroke requires a supported graphical mark consumer.");
@@ -23,8 +26,8 @@ export function validateContinuousColorConsumer(layer, encoding, scale, {
23
26
  }
24
27
  return undefined;
25
28
  }
26
- if (!["point", "bar", "rect"].includes(kind)) {
27
- throw new Error("Continuous color requires a Point, aggregate Bar, or Rect consumer.");
29
+ if (!["point", "bar", "rect", "text"].includes(kind)) {
30
+ throw new Error("Continuous color requires a Point, aggregate Bar, Rect, or Text consumer.");
28
31
  }
29
32
  if (!["quantitative", "temporal"].includes(encoding.fieldType) ||
30
33
  (isDiscretizedColorScaleType(scale.type) && encoding.fieldType !== "quantitative")) {
@@ -1,190 +1 @@
1
- import { validateMeasuredRadiusScale } from "./radial.js";
2
- import { validateContinuousColorInterpolation, validateSequentialMidpoint } from "./color.js";
3
- import { isTransformedScaleType } from "./mapping.js";
4
- import {
5
- normalizeTransformParameters,
6
- validateTransformedDomain
7
- } from "./transformed.js";
8
- import {
9
- isContinuousColorScaleType,
10
- validateScalePropertyForType
11
- } from "./types.js";
12
-
13
- const BOOLEAN_PROPERTIES = Object.freeze([
14
- "nice", "zero", "clamp", "reverse"
15
- ]);
16
- const TYPE_PARAMETERS = Object.freeze(["base", "exponent", "constant"]);
17
-
18
- function retainedValue(previous, patch, defaults, property, typeChanged) {
19
- if (Object.hasOwn(patch, property)) return patch[property];
20
- if (!typeChanged && Object.hasOwn(previous, property)) {
21
- return previous[property];
22
- }
23
- return defaults[property];
24
- }
25
-
26
- function validateBandParameters(definition, previous, patch, defaults, typeChanged) {
27
- const hasPadding = Object.hasOwn(patch, "padding");
28
- if (
29
- hasPadding &&
30
- (Object.hasOwn(patch, "paddingInner") || Object.hasOwn(patch, "paddingOuter"))
31
- ) {
32
- throw new Error(
33
- "Scale padding cannot be combined with paddingInner or paddingOuter."
34
- );
35
- }
36
- if (
37
- hasPadding &&
38
- (!Number.isFinite(patch.padding) || patch.padding < 0 || patch.padding >= 1)
39
- ) {
40
- throw new RangeError(
41
- "Scale padding must be from 0 (inclusive) to 1 (exclusive)."
42
- );
43
- }
44
- const normalizedPatch = hasPadding
45
- ? { ...patch, paddingInner: patch.padding, paddingOuter: patch.padding }
46
- : patch;
47
- const paddingInner = retainedValue(
48
- previous, normalizedPatch, defaults, "paddingInner", typeChanged
49
- ) ?? 0;
50
- const paddingOuter = retainedValue(
51
- previous, normalizedPatch, defaults, "paddingOuter", typeChanged
52
- ) ?? 0;
53
- const align = retainedValue(
54
- previous, normalizedPatch, defaults, "align", typeChanged
55
- ) ?? 0.5;
56
- if (!Number.isFinite(paddingInner) || paddingInner < 0 || paddingInner >= 1) {
57
- throw new RangeError(
58
- "Scale paddingInner must be from 0 (inclusive) to 1 (exclusive)."
59
- );
60
- }
61
- if (!Number.isFinite(paddingOuter) || paddingOuter < 0) {
62
- throw new RangeError("Scale paddingOuter must be non-negative and finite.");
63
- }
64
- if (!Number.isFinite(align) || align < 0 || align > 1) {
65
- throw new RangeError("Scale align must be between 0 and 1.");
66
- }
67
- Object.assign(definition, { paddingInner, paddingOuter, align });
68
- }
69
-
70
- function validatePointParameters(definition, previous, patch, defaults, typeChanged) {
71
- const padding = retainedValue(
72
- previous, patch, defaults, "padding", typeChanged
73
- ) ?? 0.5;
74
- const align = retainedValue(previous, patch, defaults, "align", typeChanged) ?? 0.5;
75
- if (!Number.isFinite(padding) || padding < 0) {
76
- throw new RangeError("Scale padding must be non-negative and finite.");
77
- }
78
- if (!Number.isFinite(align) || align < 0 || align > 1) {
79
- throw new RangeError("Scale align must be between 0 and 1.");
80
- }
81
- Object.assign(definition, { padding, align });
82
- }
83
-
84
- export function normalizeScaleDefinition({
85
- type,
86
- previous = {},
87
- patch = {},
88
- defaults = {},
89
- retainCoreOnTypeChange = false,
90
- retainCompatibleOnTypeChange = false,
91
- allowOrdinalBandParameters = false,
92
- validateDomain,
93
- validateRange
94
- }) {
95
- const typeChanged = previous.type !== undefined && previous.type !== type;
96
- const rawDomain = Object.hasOwn(patch, "domain")
97
- ? patch.domain
98
- : (!typeChanged || retainCoreOnTypeChange) && Object.hasOwn(previous, "domain")
99
- ? previous.domain
100
- : defaults.domain ?? "auto";
101
- const rawRange = Object.hasOwn(patch, "range")
102
- ? patch.range
103
- : (!typeChanged || retainCoreOnTypeChange) && Object.hasOwn(previous, "range")
104
- ? previous.range
105
- : defaults.range ?? "auto";
106
- const definition = {
107
- type,
108
- domain: validateDomain(type, rawDomain),
109
- range: validateRange(type, rawRange)
110
- };
111
-
112
- for (const property of BOOLEAN_PROPERTIES) {
113
- let value = retainedValue(previous, patch, defaults, property, typeChanged);
114
- if (
115
- value === undefined &&
116
- typeChanged &&
117
- retainCompatibleOnTypeChange &&
118
- Object.hasOwn(previous, property)
119
- ) {
120
- try {
121
- validateScalePropertyForType(type, property);
122
- value = previous[property];
123
- } catch {
124
- value = undefined;
125
- }
126
- }
127
- if (value === undefined) continue;
128
- if (typeof value !== "boolean") {
129
- throw new TypeError(`Scale ${property} must be a boolean.`);
130
- }
131
- validateScalePropertyForType(type, property);
132
- definition[property] = value;
133
- }
134
-
135
- const requested = Object.fromEntries(TYPE_PARAMETERS.flatMap(property => {
136
- const value = retainedValue(previous, patch, defaults, property, typeChanged);
137
- return value === undefined ? [] : [[property, value]];
138
- }));
139
- if (isTransformedScaleType(type)) {
140
- const parameters = normalizeTransformParameters(type, requested);
141
- if (type === "log") definition.base = parameters.base;
142
- if (type === "pow") definition.exponent = parameters.exponent;
143
- if (type === "symlog") definition.constant = parameters.constant;
144
- if (definition.domain !== "auto") {
145
- validateTransformedDomain(type, definition.domain, requested);
146
- }
147
- } else {
148
- for (const property of Object.keys(requested)) {
149
- validateScalePropertyForType(type, property);
150
- }
151
- }
152
-
153
- const interpolate = retainedValue(
154
- previous, patch, defaults, "interpolate", typeChanged
155
- );
156
- if (isContinuousColorScaleType(type)) {
157
- definition.interpolate = validateContinuousColorInterpolation(
158
- interpolate ?? "rgb"
159
- );
160
- } else if (interpolate !== undefined) {
161
- throw new Error(`Scale type "${type}" does not support interpolate.`);
162
- }
163
-
164
- const midpoint = validateSequentialMidpoint(
165
- retainedValue(previous, patch, defaults, "midpoint", typeChanged), type, definition.domain
166
- );
167
- if (midpoint !== undefined) definition.midpoint = midpoint;
168
-
169
- if (type === "band" || (type === "ordinal" && allowOrdinalBandParameters)) {
170
- validateBandParameters(definition, previous, patch, defaults, typeChanged);
171
- } else if (type === "point") {
172
- validatePointParameters(definition, previous, patch, defaults, typeChanged);
173
- } else {
174
- for (const property of ["paddingInner", "paddingOuter", "padding", "align"]) {
175
- if (Object.hasOwn(patch, property)) {
176
- validateScalePropertyForType(type, property);
177
- }
178
- }
179
- }
180
-
181
- const radialMapping = Object.hasOwn(patch, "radialMapping") ? patch.radialMapping : previous.radialMapping;
182
- if (radialMapping !== undefined) {
183
- definition.radialMapping = radialMapping;
184
- validateMeasuredRadiusScale({ ...definition,
185
- ...(Object.hasOwn(patch, "unknown") || Object.hasOwn(previous, "unknown")
186
- ? { unknown: patch.unknown ?? previous.unknown } : {})
187
- }, { allowAuto: true });
188
- }
189
- return definition;
190
- }
1
+ import{validateMeasuredRadiusScale as I}from"./radial.js";import{validateContinuousColorInterpolation as M,validateSequentialMidpoint as x}from"./color.js";import{isTransformedScaleType as T}from"./mapping.js";import{normalizeTransformParameters as D,validateTransformedDomain as F}from"./transformed.js";import{isContinuousColorScaleType as N,validateScalePropertyForType as O}from"./types.js";const k=Object.freeze(["nice","zero","clamp","reverse"]),z=Object.freeze(["base","exponent","constant"]);function m(i,t,n,e,o){return Object.hasOwn(t,e)?t[e]:!o&&Object.hasOwn(i,e)?i[e]:n[e]}function q(i,t,n,e,o){const l=Object.hasOwn(n,"padding");if(l&&(Object.hasOwn(n,"paddingInner")||Object.hasOwn(n,"paddingOuter")))throw new Error("Scale padding cannot be combined with paddingInner or paddingOuter.");if(l&&(!Number.isFinite(n.padding)||n.padding<0||n.padding>=1))throw new RangeError("Scale padding must be from 0 (inclusive) to 1 (exclusive).");const d=l?{...n,paddingInner:n.padding,paddingOuter:n.padding}:n,g=m(t,d,e,"paddingInner",o)??0,w=m(t,d,e,"paddingOuter",o)??0,c=m(t,d,e,"align",o)??.5;if(!Number.isFinite(g)||g<0||g>=1)throw new RangeError("Scale paddingInner must be from 0 (inclusive) to 1 (exclusive).");if(!Number.isFinite(w)||w<0)throw new RangeError("Scale paddingOuter must be non-negative and finite.");if(!Number.isFinite(c)||c<0||c>1)throw new RangeError("Scale align must be between 0 and 1.");Object.assign(i,{paddingInner:g,paddingOuter:w,align:c})}function A(i,t,n,e,o){const l=m(t,n,e,"padding",o)??.5,d=m(t,n,e,"align",o)??.5;if(!Number.isFinite(l)||l<0)throw new RangeError("Scale padding must be non-negative and finite.");if(!Number.isFinite(d)||d<0||d>1)throw new RangeError("Scale align must be between 0 and 1.");Object.assign(i,{padding:l,align:d})}function V({type:i,color:t=!1,previous:n={},patch:e={},defaults:o={},retainCoreOnTypeChange:l=!1,retainCompatibleOnTypeChange:d=!1,allowOrdinalBandParameters:g=!1,validateDomain:w,validateRange:c}){const s=n.type!==void 0&&n.type!==i,R=Object.hasOwn(e,"domain")?e.domain:(!s||l)&&Object.hasOwn(n,"domain")?n.domain:o.domain??"auto",P=Object.hasOwn(e,"range")?e.range:(!s||l)&&Object.hasOwn(n,"range")?n.range:o.range??"auto",r={type:i,domain:w(i,R),range:c(i,P)},u=m(n,e,o,"emptyDomain",s);if(u!==void 0){if(!["preserve","require-explicit"].includes(u))throw new Error('Scale emptyDomain must be "preserve" or "require-explicit".');r.emptyDomain=u}for(const a of k){let f=m(n,e,o,a,s);if(f===void 0&&s&&d&&Object.hasOwn(n,a))try{O(i,a),f=n[a]}catch{f=void 0}if(f!==void 0){if(typeof f!="boolean")throw new TypeError(`Scale ${a} must be a boolean.`);O(i,a),r[a]=f}}const j=Object.fromEntries(z.flatMap(a=>{const f=m(n,e,o,a,s);return f===void 0?[]:[[a,f]]}));if(T(i)){const a=D(i,j);i==="log"&&(r.base=a.base),i==="pow"&&(r.exponent=a.exponent),i==="symlog"&&(r.constant=a.constant),r.domain!=="auto"&&F(i,r.domain,j)}else for(const a of Object.keys(j))O(i,a);let b=m(n,e,o,"interpolate",s);if(i==="sequential"||t&&N(i))b===void 0&&d&&(b=n.interpolate),r.interpolate=M(b??"rgb");else if(b!==void 0)throw new Error(`Scale type "${i}" does not support interpolate.`);const S=x(m(n,e,o,"midpoint",s),i,r.domain);if(S!==void 0&&(r.midpoint=S),i==="band"||i==="ordinal"&&g)q(r,n,e,o,s);else if(i==="point")A(r,n,e,o,s);else for(const a of["paddingInner","paddingOuter","padding","align"])Object.hasOwn(e,a)&&O(i,a);const E=Object.hasOwn(e,"radialMapping")?e.radialMapping:n.radialMapping;return E!==void 0&&(r.radialMapping=E,I({...r,...Object.hasOwn(e,"unknown")||Object.hasOwn(n,"unknown")?{unknown:e.unknown??n.unknown}:{}},{allowAuto:!0})),r}export{V as normalizeScaleDefinition};