ggaction 0.0.17 → 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 (263) hide show
  1. package/CHANGELOG.md +46 -0
  2. package/README.md +2 -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 +3 -3
  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/box.js +2 -1
  34. package/src/actions/data/edit.js +1 -1
  35. package/src/actions/data/regression.js +2 -1
  36. package/src/actions/data/shared.js +3 -2
  37. package/src/actions/data/stack.js +3 -1
  38. package/src/actions/encodings/appearance.js +37 -29
  39. package/src/actions/encodings/barWidth.js +36 -11
  40. package/src/actions/encodings/channels.js +0 -1
  41. package/src/actions/encodings/color/continuous.js +1 -1
  42. package/src/actions/encodings/color/index.js +1 -1
  43. package/src/actions/encodings/color/policy.js +10 -3
  44. package/src/actions/encodings/density/resolve.js +1 -6
  45. package/src/actions/encodings/position/policies/arc.js +12 -10
  46. package/src/actions/encodings/position/policies/area.js +3 -3
  47. package/src/actions/encodings/position/policies/bar.js +15 -6
  48. package/src/actions/encodings/position/policies/line.js +17 -6
  49. package/src/actions/encodings/position/resolve.js +3 -2
  50. package/src/actions/encodings/ranged.js +17 -0
  51. package/src/actions/encodings/remove.js +3 -2
  52. package/src/actions/encodings/seriesLayout.js +1 -0
  53. package/src/actions/encodings/text.js +6 -3
  54. package/src/actions/errorBands/create.js +2 -2
  55. package/src/actions/errorBands/edit.js +2 -1
  56. package/src/actions/facets/actions.js +158 -240
  57. package/src/actions/gradientPlots/resolve.js +2 -17
  58. package/src/actions/guides/applicability.js +1 -1
  59. package/src/actions/guides/axes/axis.js +16 -4
  60. package/src/actions/guides/axes/edit.js +4 -4
  61. package/src/actions/guides/axes/labels.js +120 -46
  62. package/src/actions/guides/axes/lines.js +6 -5
  63. package/src/actions/guides/axes/parallel/lifecycle.js +1 -1
  64. package/src/actions/guides/axes/parallel/policy.js +8 -7
  65. package/src/actions/guides/axes/remove.js +3 -2
  66. package/src/actions/guides/axes/tickGroups.js +5 -2
  67. package/src/actions/guides/axes/ticks.js +6 -3
  68. package/src/actions/guides/axes/titles.js +71 -26
  69. package/src/actions/guides/basic.js +2 -0
  70. package/src/actions/guides/facadeLegend.js +10 -2
  71. package/src/actions/guides/grids/grid.js +7 -1
  72. package/src/actions/guides/grids/resolve.js +59 -12
  73. package/src/actions/guides/legends/blocks.js +3 -1
  74. package/src/actions/guides/legends/categorical/actions.js +70 -17
  75. package/src/actions/guides/legends/categorical/components.js +12 -8
  76. package/src/actions/guides/legends/categorical/index.js +6 -0
  77. package/src/actions/guides/legends/categorical/layout.js +37 -8
  78. package/src/actions/guides/legends/categorical/options.js +31 -20
  79. package/src/actions/guides/legends/categorical/resolve.js +2 -2
  80. package/src/actions/guides/legends/categorical/symbols.js +18 -12
  81. package/src/actions/guides/legends/categorical/validation.js +1 -6
  82. package/src/actions/guides/legends/continuous/colorSymbols.js +1 -0
  83. package/src/actions/guides/legends/continuous/common.js +1 -447
  84. package/src/actions/guides/legends/continuous/gradient.js +47 -34
  85. package/src/actions/guides/legends/continuous/interval.js +4 -4
  86. package/src/actions/guides/legends/continuous/opacity.js +19 -12
  87. package/src/actions/guides/legends/edit.js +1 -604
  88. package/src/actions/guides/legends/focused.js +2 -2
  89. package/src/actions/guides/legends/group.js +1 -0
  90. package/src/actions/guides/legends/lane.js +1 -516
  91. package/src/actions/guides/legends/remove.js +3 -0
  92. package/src/actions/guides/legends/sampling.js +1 -1
  93. package/src/actions/guides/legends/size.js +51 -43
  94. package/src/actions/guides/legends/strokeWidth.js +11 -29
  95. package/src/actions/guides/legends/target.js +3 -3
  96. package/src/actions/guides/legends/transition.js +21 -7
  97. package/src/actions/guides/polar/axes/labels.js +4 -2
  98. package/src/actions/guides/polar/axes/titles.js +7 -5
  99. package/src/actions/guides/polar/resolve.js +6 -14
  100. package/src/actions/index.js +16 -16
  101. package/src/actions/marks/arc/actions.js +3 -10
  102. package/src/actions/marks/area/actions.js +8 -5
  103. package/src/actions/marks/area/materialize.js +8 -9
  104. package/src/actions/marks/bar/create.js +10 -4
  105. package/src/actions/marks/bar/edit.js +8 -4
  106. package/src/actions/marks/bar/materialize.js +9 -6
  107. package/src/actions/marks/line/actions.js +11 -4
  108. package/src/actions/marks/line/materialize.js +9 -5
  109. package/src/actions/marks/point/edit.js +1 -1
  110. package/src/actions/marks/rect/actions.js +3 -3
  111. package/src/actions/marks/remove.js +2 -0
  112. package/src/actions/marks/rule/actions.js +7 -4
  113. package/src/actions/marks/text/actions.js +17 -5
  114. package/src/actions/marks/text/layout.js +3 -0
  115. package/src/actions/primitives/semanticValidation/layer.js +4 -0
  116. package/src/actions/regression/create.js +1 -1
  117. package/src/actions/regression/edit.js +3 -3
  118. package/src/actions/regression/resolve.js +2 -6
  119. package/src/actions/scales/channels.js +9 -4
  120. package/src/actions/scales/consumers/families.js +16 -5
  121. package/src/actions/scales/create.js +8 -3
  122. package/src/actions/scales/definitions.js +1 -425
  123. package/src/actions/scales/edit.js +2 -2
  124. package/src/actions/scales/editPolicy.js +9 -3
  125. package/src/actions/scales/materialize.js +1 -1
  126. package/src/actions/scales/preview.js +21 -1
  127. package/src/actions/scales/quantitativeColor.js +3 -3
  128. package/src/actions/selection/actions.js +1 -13
  129. package/src/actions/theme/reconcile.js +81 -27
  130. package/src/actions/theme/state.js +12 -0
  131. package/src/actions/titles/actions.js +5 -18
  132. package/src/actions/titles/resolve.js +41 -19
  133. package/src/actions/violinPlots/edit.js +3 -20
  134. package/src/core/compositionState.js +4 -1
  135. package/src/core/font.js +9 -2
  136. package/src/core/optionRequirements.js +1 -0
  137. package/src/core/resourceReferences.js +3 -0
  138. package/src/core/textMetricProfile.js +3 -2
  139. package/src/core/textMetrics.js +41 -4
  140. package/src/core/validation.js +26 -0
  141. package/src/core/vocabulary.js +4 -0
  142. package/src/grammar/aggregate.js +4 -18
  143. package/src/grammar/arcs.js +1 -386
  144. package/src/grammar/areaPaint.js +10 -0
  145. package/src/grammar/areaSeries.js +18 -10
  146. package/src/grammar/bars/geometry.js +30 -3
  147. package/src/grammar/bars/policy.js +12 -1
  148. package/src/grammar/bin.js +2 -12
  149. package/src/grammar/bin2d.js +1 -6
  150. package/src/grammar/boxPlot.js +56 -9
  151. package/src/grammar/categoryOrder.js +1 -6
  152. package/src/grammar/complete.js +15 -19
  153. package/src/grammar/computed.js +92 -25
  154. package/src/grammar/curveCommands.js +29 -16
  155. package/src/grammar/datasetSchema.js +3 -7
  156. package/src/grammar/displayLabels.js +28 -0
  157. package/src/grammar/ecdf.js +2 -9
  158. package/src/grammar/facets/dependencies.js +6 -2
  159. package/src/grammar/facets/guides.js +5 -0
  160. package/src/grammar/facets/index.js +2 -5
  161. package/src/grammar/fold.js +2 -12
  162. package/src/grammar/gradientProfile.js +1 -6
  163. package/src/grammar/impute.js +21 -48
  164. package/src/grammar/interval.js +2 -9
  165. package/src/grammar/legendGradient.js +18 -0
  166. package/src/grammar/legendGroups.js +1 -0
  167. package/src/grammar/legendTitleStyle.js +22 -0
  168. package/src/grammar/lineSeries.js +32 -17
  169. package/src/grammar/markLabels.js +5 -2
  170. package/src/grammar/normalize.js +4 -54
  171. package/src/grammar/numeric.js +1 -290
  172. package/src/grammar/parallelCoordinates.js +1 -6
  173. package/src/grammar/parseTime.js +41 -0
  174. package/src/grammar/pathCommands.js +11 -4
  175. package/src/grammar/polar.js +1 -184
  176. package/src/grammar/positionCompatibility.js +3 -3
  177. package/src/grammar/regression/derive.js +7 -1
  178. package/src/grammar/regression/models.js +83 -55
  179. package/src/grammar/regression/parameters.js +14 -3
  180. package/src/grammar/roundedRect.js +42 -54
  181. package/src/grammar/scales/appearance.js +1 -206
  182. package/src/grammar/scales/color.js +1 -382
  183. package/src/grammar/scales/colorConsumers.js +5 -2
  184. package/src/grammar/scales/definition.js +1 -197
  185. package/src/grammar/scales/discretized.js +1 -195
  186. package/src/grammar/scales/size.js +1 -456
  187. package/src/grammar/scales/temporal.js +2 -13
  188. package/src/grammar/scales/transformed.js +1 -383
  189. package/src/grammar/scales/types.js +1 -1
  190. package/src/grammar/scales/validation.js +1 -66
  191. package/src/grammar/schemas/concreteGraphic.js +11 -0
  192. package/src/grammar/schemas/graphic.js +3 -0
  193. package/src/grammar/schemas/semanticPath.js +2 -1
  194. package/src/grammar/stack.js +2 -10
  195. package/src/grammar/statisticalReference.js +1 -6
  196. package/src/grammar/summary.js +3 -26
  197. package/src/grammar/text.js +19 -0
  198. package/src/grammar/timeUnit.js +16 -7
  199. package/src/grammar/transformKeys.js +47 -0
  200. package/src/grammar/transforms.js +4 -1
  201. package/src/grammar/valueFormat.js +17 -5
  202. package/src/grammar/weightedStatistics.js +1 -6
  203. package/src/grammar/window.js +4 -58
  204. package/src/inspectionDescriptors.js +1 -1
  205. package/src/layout/canvas.js +1 -110
  206. package/src/layout/facets.js +1 -244
  207. package/src/layout/labels.js +1 -0
  208. package/src/layout/legend.js +13 -0
  209. package/src/layout/legendGroup.js +1 -0
  210. package/src/layout/legendItems.js +59 -15
  211. package/src/layout/legendLane.js +1 -441
  212. package/src/layout/legendText.js +1 -0
  213. package/src/layout/title.js +35 -13
  214. package/src/materialization/bars/aggregate.js +11 -5
  215. package/src/materialization/bars/histogram.js +4 -1
  216. package/src/materialization/bars/ranged.js +19 -6
  217. package/src/materialization/bars/resolve.js +22 -1
  218. package/src/materialization/coordinateBounds.js +8 -0
  219. package/src/materialization/dependencies.js +4 -44
  220. package/src/materialization/facetGuides/layout.js +1 -0
  221. package/src/materialization/facetGuides/placement.js +19 -8
  222. package/src/materialization/facetGuides/preparation.js +15 -7
  223. package/src/materialization/facetHeaders.js +1 -347
  224. package/src/materialization/facets.js +1 -185
  225. package/src/materialization/graphicHierarchy.js +1 -1
  226. package/src/materialization/guides/layout.js +1 -57
  227. package/src/materialization/guides/resources.js +1 -123
  228. package/src/materialization/layout.js +53 -0
  229. package/src/materialization/legendGroups.js +1 -0
  230. package/src/materialization/legendText.js +1 -0
  231. package/src/materialization/legends.js +1 -1
  232. package/src/materialization/marks/capabilities.js +5 -6
  233. package/src/materialization/rect.js +1 -1
  234. package/src/materialization/scaleGuideDependencies.js +1 -1
  235. package/src/materialization/scales/map.js +3 -0
  236. package/src/materialization/scales/policies/arc.js +8 -7
  237. package/src/materialization/scales/policies/bar.js +19 -7
  238. package/src/materialization/scales/policies/series.js +2 -1
  239. package/src/materialization/scales/resolve.js +5 -3
  240. package/src/materialization/selection/items/arc.js +1 -1
  241. package/src/materialization/selection/items/bar.js +7 -6
  242. package/src/materialization/selection/items/path.js +7 -6
  243. package/src/materialization/selection/items/rect.js +2 -2
  244. package/src/materialization/text.js +13 -4
  245. package/src/materialization/textLines.js +15 -0
  246. package/src/persistence/codec.js +37 -6
  247. package/src/persistence/validation.js +47 -0
  248. package/src/persistence.js +18 -5
  249. package/src/renderers/canvas/circle.js +6 -3
  250. package/src/renderers/canvas/fill.js +7 -1
  251. package/src/renderers/canvas/index.js +2 -1
  252. package/src/renderers/canvas/line.js +1 -0
  253. package/src/renderers/canvas/path.js +1 -1
  254. package/src/renderers/canvas/rect.js +11 -8
  255. package/src/renderers/canvas/stroke.js +2 -1
  256. package/src/renderers/canvas/text.js +5 -3
  257. package/src/renderers/svg.js +4 -1
  258. package/src/selectors/layers.js +19 -0
  259. package/src/theme/defaults.js +8 -2
  260. package/src/version.js +1 -1
  261. package/types/basic.d.ts +1 -0
  262. package/types/index.d.ts +7 -0
  263. package/types/program.d.ts +347 -85
@@ -1,206 +1 @@
1
- import { cloneAndFreeze, isPlainObject } from "../../core/immutable.js";
2
- import { validateUnitInterval } from "../../core/validation.js";
3
- import { POINT_SHAPES } from "../pointShapes.js";
4
- import {
5
- normalizePalette,
6
- resolvePalette
7
- } from "../palettes.js";
8
-
9
- export const DASH10 = cloneAndFreeze([
10
- [], [8, 4], [3, 3], [12, 4], [8, 3, 2, 3],
11
- [12, 3, 3, 3], [2, 2], [10, 3, 2, 3, 2, 3], [14, 4, 4, 4], [6, 2, 2, 2]
12
- ]);
13
- export const NAMED_DASH_PATTERNS = cloneAndFreeze({
14
- solid: [],
15
- dashed: [6, 4],
16
- dotted: [1, 3],
17
- dashdot: [6, 3, 1, 3]
18
- });
19
-
20
- export { POINT_SHAPES } from "../pointShapes.js";
21
- export const DEFAULT_SIZE_RANGE = cloneAndFreeze([24, 196]);
22
- export const DEFAULT_OPACITY_RANGE = cloneAndFreeze([0.2, 1]);
23
- export const DEFAULT_STROKE_WIDTH_RANGE = cloneAndFreeze([1, 8]);
24
-
25
- export function validateColorRange(range) {
26
- if (range === "auto") return range;
27
- if (Array.isArray(range)) {
28
- if (
29
- range.length === 0 ||
30
- !range.every(color => typeof color === "string" && color.length > 0)
31
- ) {
32
- throw new TypeError("Color range must contain non-empty color strings.");
33
- }
34
- return cloneAndFreeze(range);
35
- }
36
- if (
37
- !isPlainObject(range) ||
38
- Object.keys(range).length !== 1 ||
39
- !Object.hasOwn(range, "palette")
40
- ) {
41
- throw new Error("Color range must contain only a palette descriptor.");
42
- }
43
- normalizePalette(range.palette);
44
- return cloneAndFreeze(range);
45
- }
46
-
47
- function isDashPattern(pattern) {
48
- return (
49
- Array.isArray(pattern) &&
50
- pattern.length % 2 === 0 &&
51
- pattern.every(value => Number.isFinite(value) && value >= 0) &&
52
- (pattern.length === 0 || pattern.some(value => value > 0))
53
- );
54
- }
55
-
56
- export function normalizeStrokeDashPattern(pattern) {
57
- if (typeof pattern === "string") {
58
- const resolved = NAMED_DASH_PATTERNS[pattern];
59
- if (resolved === undefined) {
60
- throw new Error(`Unknown stroke dash style "${pattern}".`);
61
- }
62
- return cloneAndFreeze(resolved);
63
- }
64
- if (!isDashPattern(pattern)) {
65
- throw new TypeError(
66
- "Stroke dash pattern must be a named style or an empty or nonzero even-length array of non-negative finite numbers."
67
- );
68
- }
69
- return cloneAndFreeze(pattern);
70
- }
71
-
72
- export function validateStrokeDashRange(range) {
73
- if (range === "auto") return range;
74
- if (!Array.isArray(range) || range.length === 0) {
75
- throw new TypeError(
76
- "StrokeDash range must contain one or more named styles or direct patterns."
77
- );
78
- }
79
- for (const pattern of range) normalizeStrokeDashPattern(pattern);
80
- return cloneAndFreeze(range);
81
- }
82
-
83
- export function validateShapeRange(range) {
84
- if (range === "auto") return range;
85
- if (
86
- !Array.isArray(range) ||
87
- range.length === 0 ||
88
- !range.every(shape => POINT_SHAPES.includes(shape)) ||
89
- new Set(range).size !== range.length
90
- ) {
91
- throw new TypeError(
92
- "Shape range must contain unique supported point shapes."
93
- );
94
- }
95
- return cloneAndFreeze(range);
96
- }
97
-
98
- export function validateSizeRange(range) {
99
- if (range === "auto") return range;
100
- if (
101
- !Array.isArray(range) ||
102
- range.length !== 2 ||
103
- !range.every(value => Number.isFinite(value) && value >= 0) ||
104
- range[0] > range[1]
105
- ) {
106
- throw new TypeError(
107
- "Size range must be an ascending pair of non-negative finite areas."
108
- );
109
- }
110
- return cloneAndFreeze(range);
111
- }
112
-
113
- export function validateOpacityRange(range) {
114
- if (range === "auto") return range;
115
- if (
116
- !Array.isArray(range) ||
117
- range.length !== 2 ||
118
- !range.every(value => Number.isFinite(value) && value >= 0 && value <= 1)
119
- ) {
120
- throw new TypeError(
121
- "Opacity range must contain two finite values from 0 to 1."
122
- );
123
- }
124
- return cloneAndFreeze(range);
125
- }
126
-
127
- export function validateStrokeWidthRange(range) {
128
- if (range === "auto") return range;
129
- if (
130
- !Array.isArray(range) ||
131
- range.length !== 2 ||
132
- !range.every(value => Number.isFinite(value) && value >= 0) ||
133
- range[0] > range[1]
134
- ) {
135
- throw new TypeError(
136
- "StrokeWidth range must be an ascending pair of non-negative finite widths."
137
- );
138
- }
139
- return cloneAndFreeze(range);
140
- }
141
-
142
- export function validateOpacityValue(value, label = "Opacity") {
143
- return validateUnitInterval(value, label);
144
- }
145
-
146
- export function validateSemanticScaleRange(range) {
147
- if (range === "auto") return range;
148
- if (Array.isArray(range) && range.length > 0) return cloneAndFreeze(range);
149
- if (isPlainObject(range) && Object.hasOwn(range, "palette")) {
150
- normalizePalette(range.palette);
151
- return cloneAndFreeze(range);
152
- }
153
- throw new TypeError("Scale range has an unsupported value.");
154
- }
155
-
156
- export function resolveColorRange(range, domainCount) {
157
- const validated = validateColorRange(range);
158
- if (validated === "auto") return TABLEAU10;
159
- if (Array.isArray(validated)) return validated;
160
- return resolvePalette(validated.palette, domainCount);
161
- }
162
-
163
- export function resolveStrokeDashRange(range) {
164
- const validated = validateStrokeDashRange(range);
165
- return validated === "auto"
166
- ? DASH10
167
- : cloneAndFreeze(validated.map(normalizeStrokeDashPattern));
168
- }
169
-
170
- export function resolveShapeRange(range) {
171
- const validated = validateShapeRange(range);
172
- return validated === "auto" ? POINT_SHAPES : validated;
173
- }
174
-
175
- export function resolveSizeRange(range) {
176
- const validated = validateSizeRange(range);
177
- return validated === "auto" ? DEFAULT_SIZE_RANGE : validated;
178
- }
179
-
180
- export function resolveOpacityRange(range) {
181
- const validated = validateOpacityRange(range);
182
- return validated === "auto" ? DEFAULT_OPACITY_RANGE : validated;
183
- }
184
-
185
- export function resolveStrokeWidthRange(range) {
186
- const validated = validateStrokeWidthRange(range);
187
- return validated === "auto" ? DEFAULT_STROKE_WIDTH_RANGE : validated;
188
- }
189
-
190
- export function mapOrdinalValues(values, domain, range, options = {}) {
191
- const hasUnknown = Object.hasOwn(options, "unknown");
192
- const indices = new Map(domain.map((value, index) => [value, index]));
193
- return cloneAndFreeze(values.map(value => {
194
- const index = indices.get(value);
195
- if (index === undefined) {
196
- if (hasUnknown) return options.unknown;
197
- throw new Error(`Value "${value}" is outside the ordinal domain.`);
198
- }
199
- return range[index % range.length];
200
- }));
201
- }
202
-
203
- export const TABLEAU10 = resolvePalette(
204
- { name: "tableau10", count: 10 },
205
- 10
206
- );
1
+ import{cloneAndFreeze as r,isPlainObject as s}from"../../core/immutable.js";import{validateUnitInterval as y}from"../../core/validation.js";import{POINT_SHAPES as u}from"../pointShapes.js";import{normalizePalette as c,resolvePalette as l}from"../palettes.js";const m=r([[],[8,4],[3,3],[12,4],[8,3,2,3],[12,3,3,3],[2,2],[10,3,2,3,2,3],[14,4,4,4],[6,2,2,2]]),A=r({solid:[],dashed:[6,4],dotted:[1,3],dashdot:[6,3,1,3]});import{POINT_SHAPES as g}from"../pointShapes.js";const v=r([24,196]),w=r([.2,1]),S=r([1,8]);function x(t){if(t==="auto")return t;if(Array.isArray(t)){if(t.length===0||!t.every(e=>typeof e=="string"&&e.length>0))throw new TypeError("Color range must contain non-empty color strings.");return r(t)}if(!s(t)||Object.keys(t).length!==1||!Object.hasOwn(t,"palette"))throw new Error("Color range must contain only a palette descriptor.");return c(t.palette),r(t)}function E(t){return Array.isArray(t)&&t.length%2===0&&t.every(e=>Number.isFinite(e)&&e>=0)&&(t.length===0||t.some(e=>e>0))}function p(t){if(typeof t=="string"){const e=A[t];if(e===void 0)throw new Error(`Unknown stroke dash style "${t}".`);return r(e)}if(!E(t))throw new TypeError("Stroke dash pattern must be a named style or an empty or nonzero even-length array of non-negative finite numbers.");return r(t)}function R(t){if(t==="auto")return t;if(!Array.isArray(t)||t.length===0)throw new TypeError("StrokeDash range must contain one or more named styles or direct patterns.");for(const e of t)p(e);return r(t)}function O(t){if(t==="auto")return t;if(!Array.isArray(t)||t.length===0||!t.every(e=>u.includes(e)))throw new TypeError("Shape range must contain supported point shapes.");return r(t)}function f(t,e){if(t==="auto")return t;if(!Array.isArray(t)||t.length!==2||!t.every(o=>Number.isFinite(o)&&o>=0)||t[0]>t[1])throw new TypeError(`${e} must be an ascending pair of non-negative finite ${e==="Size range"?"areas":"widths"}.`);return r(t)}function T(t){return f(t,"Size range")}function k(t){if(t==="auto")return t;if(!Array.isArray(t)||t.length!==2||!t.every(e=>Number.isFinite(e)&&e>=0&&e<=1))throw new TypeError("Opacity range must contain two finite values from 0 to 1.");return r(t)}function D(t){return f(t,"StrokeWidth range")}function F(t,e="Opacity"){return y(t,e)}function U(t){if(t==="auto")return t;if(Array.isArray(t)&&t.length>0)return r(t);if(s(t)&&Object.hasOwn(t,"palette"))return c(t.palette),r(t);throw new TypeError("Scale range has an unsupported value.")}function I(t,e){const o=x(t);return o==="auto"?b:Array.isArray(o)?o:l(o.palette,e)}function j(t){const e=R(t);return e==="auto"?m:r(e.map(p))}function C(t){const e=O(t);return e==="auto"?u:e}function H(t){const e=T(t);return e==="auto"?v:e}function L(t){const e=k(t);return e==="auto"?w:e}function W(t){const e=D(t);return e==="auto"?S:e}function $(t,e,o,a={}){const d=Object.hasOwn(a,"unknown"),h=new Map(e.map((n,i)=>[n,i]));return r(t.map(n=>{const i=h.get(n);if(i===void 0){if(d)return a.unknown;throw new Error(`Value "${n}" is outside the ordinal domain.`)}return o[i%o.length]}))}const b=l({name:"tableau10",count:10},10);export{m as DASH10,w as DEFAULT_OPACITY_RANGE,v as DEFAULT_SIZE_RANGE,S as DEFAULT_STROKE_WIDTH_RANGE,A as NAMED_DASH_PATTERNS,g as POINT_SHAPES,b as TABLEAU10,$ as mapOrdinalValues,p as normalizeStrokeDashPattern,I as resolveColorRange,L as resolveOpacityRange,C as resolveShapeRange,H as resolveSizeRange,j as resolveStrokeDashRange,W as resolveStrokeWidthRange,x as validateColorRange,k as validateOpacityRange,F as validateOpacityValue,U as validateSemanticScaleRange,O as validateShapeRange,T as validateSizeRange,R as validateStrokeDashRange,D as validateStrokeWidthRange};
@@ -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")) {