ggaction 0.0.21 → 0.0.23

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 (265) hide show
  1. package/CHANGELOG.md +90 -0
  2. package/README.md +83 -90
  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/package.json +11 -4
  8. package/src/BasicChartProgram.js +1 -1
  9. package/src/accessibility.js +1 -0
  10. package/src/actions/boxPlots/components.js +1 -96
  11. package/src/actions/boxPlots/create.js +6 -1
  12. package/src/actions/boxPlots/edit.js +8 -0
  13. package/src/actions/boxPlots/materialize.js +3 -0
  14. package/src/actions/boxPlots/options.js +1 -1
  15. package/src/actions/canvas/actions.js +2 -1
  16. package/src/actions/canvas/index.js +3 -0
  17. package/src/actions/canvas/plotBorder.js +2 -1
  18. package/src/actions/canvas/plotOrder.js +14 -0
  19. package/src/actions/charts/area.js +1 -1
  20. package/src/actions/charts/bar.js +4 -4
  21. package/src/actions/charts/density.js +1 -1
  22. package/src/actions/charts/ecdf.js +1 -1
  23. package/src/actions/charts/endpoints.js +54 -5
  24. package/src/actions/charts/heatmap.js +1 -1
  25. package/src/actions/charts/histogram.js +1 -1
  26. package/src/actions/charts/horizon.js +1 -1
  27. package/src/actions/charts/index.js +2 -1
  28. package/src/actions/charts/interval-regression.js +3 -3
  29. package/src/actions/charts/line.js +1 -1
  30. package/src/actions/charts/radar.js +63 -3
  31. package/src/actions/charts/raincloud.js +37 -6
  32. package/src/actions/charts/rug-strip.js +2 -2
  33. package/src/actions/charts/scatter.js +3 -3
  34. package/src/actions/charts/text.js +1 -1
  35. package/src/actions/composition/actions.js +10 -3
  36. package/src/actions/coordinates/actions.js +2 -0
  37. package/src/actions/data/basic.js +6 -0
  38. package/src/actions/data/derived.js +6 -2
  39. package/src/actions/data/edit.js +22 -36
  40. package/src/actions/data/filter.js +1 -376
  41. package/src/actions/data/flatten.js +19 -0
  42. package/src/actions/data/index.js +6 -0
  43. package/src/actions/data/lookup.js +50 -0
  44. package/src/actions/data/raincloudFilter.js +56 -0
  45. package/src/actions/data/shared.js +10 -0
  46. package/src/actions/data/timeUnit.js +1 -1
  47. package/src/actions/distributions/revision.js +3 -1
  48. package/src/actions/encodings/angle.js +2 -1
  49. package/src/actions/encodings/appearance.js +38 -13
  50. package/src/actions/encodings/channels.js +14 -3
  51. package/src/actions/encodings/color/continuous.js +26 -10
  52. package/src/actions/encodings/color/index.js +50 -20
  53. package/src/actions/encodings/color/policy.js +57 -4
  54. package/src/actions/encodings/parallel.js +4 -0
  55. package/src/actions/encodings/position/policies/bar.js +10 -6
  56. package/src/actions/encodings/position/policies/line.js +1 -152
  57. package/src/actions/encodings/position/resolve.js +4 -1
  58. package/src/actions/encodings/ranged.js +46 -0
  59. package/src/actions/encodings/remove.js +1 -1
  60. package/src/actions/encodings/ruleAppearance.js +7 -6
  61. package/src/actions/encodings/shared.js +14 -2
  62. package/src/actions/encodings/stroke.js +20 -14
  63. package/src/actions/encodings/strokeDash.js +9 -11
  64. package/src/actions/encodings/text.js +30 -2
  65. package/src/actions/errorBars/edit.js +24 -4
  66. package/src/actions/facets/actions.js +1 -793
  67. package/src/actions/facets/derive.js +34 -5
  68. package/src/actions/facets/replay.js +1 -38
  69. package/src/actions/gradientPlots/components.js +21 -9
  70. package/src/actions/gradientPlots/create.js +4 -2
  71. package/src/actions/gradientPlots/edit.js +18 -1
  72. package/src/actions/gradientPlots/materialize.js +35 -36
  73. package/src/actions/gradientPlots/options.js +1 -1
  74. package/src/actions/gradientPlots/paint.js +13 -7
  75. package/src/actions/guides/applicability.js +2 -0
  76. package/src/actions/guides/axes/axes.js +39 -0
  77. package/src/actions/guides/axes/axis.js +9 -5
  78. package/src/actions/guides/axes/edit.js +11 -8
  79. package/src/actions/guides/axes/labels.js +24 -8
  80. package/src/actions/guides/axes/parallel/policy.js +3 -5
  81. package/src/actions/guides/axes/parallel/resolve.js +4 -3
  82. package/src/actions/guides/axes/policy.js +22 -0
  83. package/src/actions/guides/axes/tickGroups.js +4 -2
  84. package/src/actions/guides/axes/ticks.js +22 -4
  85. package/src/actions/guides/axes/titles.js +19 -6
  86. package/src/actions/guides/facadeAxes.js +3 -0
  87. package/src/actions/guides/grids/grid.js +3 -1
  88. package/src/actions/guides/grids/resolve.js +7 -11
  89. package/src/actions/guides/guides.js +21 -1
  90. package/src/actions/guides/legends/categorical/actions.js +1 -515
  91. package/src/actions/guides/legends/categorical/components.js +1 -4
  92. package/src/actions/guides/legends/categorical/layout.js +5 -2
  93. package/src/actions/guides/legends/categorical/options.js +4 -0
  94. package/src/actions/guides/legends/categorical/resolve.js +8 -3
  95. package/src/actions/guides/legends/categorical/symbols.js +3 -3
  96. package/src/actions/guides/legends/colorSize.js +2 -0
  97. package/src/actions/guides/legends/continuous/common.js +1 -1
  98. package/src/actions/guides/legends/continuous/gradient.js +1 -360
  99. package/src/actions/guides/legends/continuous/interval.js +1 -1
  100. package/src/actions/guides/legends/continuous/opacity.js +15 -1
  101. package/src/actions/guides/legends/edit.js +1 -1
  102. package/src/actions/guides/legends/focused.js +1 -1
  103. package/src/actions/guides/legends/lane.js +1 -1
  104. package/src/actions/guides/legends/sampling.js +1 -140
  105. package/src/actions/guides/legends/strokeWidth.js +3 -2
  106. package/src/actions/guides/legends/transition.js +19 -2
  107. package/src/actions/guides/polar/axes/facade.js +5 -4
  108. package/src/actions/guides/polar/axes/labels.js +5 -4
  109. package/src/actions/guides/polar/axes/titles.js +5 -4
  110. package/src/actions/guides/polar/resolve.js +2 -1
  111. package/src/actions/guides/tickValues.js +7 -7
  112. package/src/actions/marks/arc/actions.js +5 -7
  113. package/src/actions/marks/area/actions.js +9 -3
  114. package/src/actions/marks/bar/create.js +4 -2
  115. package/src/actions/marks/bar/edit.js +9 -6
  116. package/src/actions/marks/bar/materialize.js +5 -3
  117. package/src/actions/marks/dependentReferences.js +87 -0
  118. package/src/actions/marks/index.js +2 -0
  119. package/src/actions/marks/lifecycle.js +2 -1
  120. package/src/actions/marks/line/actions.js +24 -6
  121. package/src/actions/marks/line/materialize.js +7 -3
  122. package/src/actions/marks/point/create.js +5 -4
  123. package/src/actions/marks/point/edit.js +6 -3
  124. package/src/actions/marks/point/jitter.js +6 -6
  125. package/src/actions/marks/point/materialize.js +36 -39
  126. package/src/actions/marks/rect/actions.js +16 -4
  127. package/src/actions/marks/references.js +183 -35
  128. package/src/actions/marks/rule/actions.js +20 -9
  129. package/src/actions/marks/shared.js +2 -1
  130. package/src/actions/marks/text/actions.js +10 -3
  131. package/src/actions/marks/tick/actions.js +11 -2
  132. package/src/actions/primitives/editGraphics.js +28 -3
  133. package/src/actions/primitives/index.js +9 -0
  134. package/src/actions/primitives/semanticAction.js +13 -7
  135. package/src/actions/primitives/semanticValidation/layer.js +20 -0
  136. package/src/actions/primitives/semanticValidation/scale.js +8 -1
  137. package/src/actions/regression/create.js +6 -1
  138. package/src/actions/regression/edit.js +10 -1
  139. package/src/actions/scales/channels.js +1 -1
  140. package/src/actions/scales/consumers/common.js +19 -1
  141. package/src/actions/scales/consumers/families.js +2 -2
  142. package/src/actions/scales/consumers/seriesLayout.js +4 -3
  143. package/src/actions/scales/edit.js +11 -0
  144. package/src/actions/scales/editPolicy.js +5 -3
  145. package/src/actions/scales/preview.js +2 -1
  146. package/src/actions/scales/quantitativeColor.js +2 -4
  147. package/src/actions/selection/actions.js +10 -1
  148. package/src/actions/theme/reconcile.js +37 -9
  149. package/src/core/compositionState.js +26 -7
  150. package/src/core/datasetReferences.js +17 -0
  151. package/src/core/facetAxisPolicy.js +30 -0
  152. package/src/core/immutable.js +1 -0
  153. package/src/core/resourceReferences.js +5 -3
  154. package/src/core/validation.js +4 -0
  155. package/src/core/vocabulary.js +24 -2
  156. package/src/grammar/aggregate.js +1 -0
  157. package/src/grammar/arcs.js +1 -1
  158. package/src/grammar/areaSeries.js +1 -1
  159. package/src/grammar/axisTextPlacement.js +1 -1
  160. package/src/grammar/bars/policy.js +2 -2
  161. package/src/grammar/curveCommands.js +35 -2
  162. package/src/grammar/datasetDependencies.js +97 -0
  163. package/src/grammar/datasetSchema.js +32 -2
  164. package/src/grammar/facetHeaders.js +1 -0
  165. package/src/grammar/facets/dependencies.js +6 -2
  166. package/src/grammar/facets/guides.js +7 -5
  167. package/src/grammar/facets/legendIntent.js +6 -2
  168. package/src/grammar/facets/scales.js +27 -7
  169. package/src/grammar/flatten.js +85 -0
  170. package/src/grammar/histogram.js +13 -1
  171. package/src/grammar/horizon.js +1 -494
  172. package/src/grammar/jitter.js +2 -2
  173. package/src/grammar/legendSpacing.js +45 -0
  174. package/src/grammar/lineMissing.js +90 -0
  175. package/src/grammar/lineSeries.js +1 -376
  176. package/src/grammar/lookup.js +97 -0
  177. package/src/grammar/markFilter.js +4 -2
  178. package/src/grammar/markLabels.js +8 -3
  179. package/src/grammar/numeric.js +1 -1
  180. package/src/grammar/pathCommands.js +1 -1
  181. package/src/grammar/pathSeries.js +1 -109
  182. package/src/grammar/pointPolygon.js +81 -0
  183. package/src/grammar/pointShapes.js +15 -15
  184. package/src/grammar/rects.js +1 -1
  185. package/src/grammar/regression/derive.js +1 -195
  186. package/src/grammar/regression/parameters.js +7 -0
  187. package/src/grammar/scales/appearance.js +1 -1
  188. package/src/grammar/scales/color.js +1 -1
  189. package/src/grammar/scales/colorConsumers.js +1 -63
  190. package/src/grammar/scales/continuous.js +58 -1
  191. package/src/grammar/scales/definition.js +1 -1
  192. package/src/grammar/scales/ordinal.js +5 -2
  193. package/src/grammar/scales/policies.js +3 -3
  194. package/src/grammar/schemas/graphicBounds.js +40 -12
  195. package/src/grammar/schemas/graphicClip.js +23 -0
  196. package/src/grammar/schemas/graphicTree.js +16 -0
  197. package/src/grammar/statisticalReference.js +22 -0
  198. package/src/grammar/text.js +65 -1
  199. package/src/grammar/ticks.js +92 -1
  200. package/src/grammar/timeUnit.js +9 -3
  201. package/src/grammar/transformTopology.js +3 -1
  202. package/src/grammar/transforms.js +24 -0
  203. package/src/inspection.js +1 -495
  204. package/src/inspectionDescriptors.js +1 -1
  205. package/src/layout/canvas.js +1 -1
  206. package/src/layout/facetContentFlow.js +101 -0
  207. package/src/layout/facetHeaderTitles.js +1 -0
  208. package/src/layout/facetTopLane.js +29 -0
  209. package/src/layout/facets.js +1 -1
  210. package/src/layout/guideCollisions.js +9 -3
  211. package/src/layout/legendGroup.js +1 -1
  212. package/src/layout/legendItems.js +26 -10
  213. package/src/layout/legendSpacing.js +66 -0
  214. package/src/layout/plotDrawOrder.js +17 -0
  215. package/src/materialization/bars/histogram.js +8 -2
  216. package/src/materialization/bars/resolve.js +1 -1
  217. package/src/materialization/composition.js +1 -0
  218. package/src/materialization/compositionSnapshot.js +22 -2
  219. package/src/materialization/dataProvenance.js +1 -1
  220. package/src/materialization/facetContentBounds.js +96 -0
  221. package/src/materialization/facetGuides/layout.js +1 -1
  222. package/src/materialization/facetGuides/placement.js +39 -11
  223. package/src/materialization/facetGuides/preparation.js +43 -24
  224. package/src/materialization/facetHeaders.js +1 -1
  225. package/src/materialization/facetTopLane.js +25 -0
  226. package/src/materialization/facets.js +1 -1
  227. package/src/materialization/graphicHierarchy.js +30 -1
  228. package/src/materialization/graphicTranslation.js +2 -0
  229. package/src/materialization/guides/layout.js +1 -1
  230. package/src/materialization/guides/resources.js +1 -1
  231. package/src/materialization/legends.js +1 -1
  232. package/src/materialization/markClip.js +26 -0
  233. package/src/materialization/marks/capabilities.js +3 -2
  234. package/src/materialization/marks/grouping.js +7 -5
  235. package/src/materialization/marks/index.js +4 -2
  236. package/src/materialization/marks/policies.js +4 -0
  237. package/src/materialization/plotDrawOrder.js +44 -0
  238. package/src/materialization/rect.js +11 -3
  239. package/src/materialization/scaleGuideDependencies.js +13 -5
  240. package/src/materialization/selection/items/common.js +1 -1
  241. package/src/materialization/selection/items/path.js +1 -0
  242. package/src/materialization/selection/policies/index.js +2 -1
  243. package/src/materialization/text.js +10 -5
  244. package/src/mcp/cli.js +0 -0
  245. package/src/persistence/validation.js +114 -18
  246. package/src/persistence.js +4 -2
  247. package/src/renderers/canvas/index.js +16 -0
  248. package/src/renderers/canvas/isolated.js +11 -1
  249. package/src/renderers/canvas/native.js +7 -0
  250. package/src/renderers/canvas/scene.js +66 -0
  251. package/src/renderers/canvas/text.js +3 -2
  252. package/src/renderers/svg.js +1 -617
  253. package/src/renderers/svgSerialization.js +643 -0
  254. package/src/renderers/transitionScene.js +67 -0
  255. package/src/scene.js +89 -0
  256. package/src/selectors/axes.js +1 -1
  257. package/src/selectors/datasets.js +1 -0
  258. package/src/selectors/grids.js +9 -0
  259. package/src/selectors/markClip.js +28 -0
  260. package/src/selectors/raincloud.js +7 -0
  261. package/src/version.js +1 -1
  262. package/types/basic.d.ts +7 -0
  263. package/types/index.d.ts +8 -0
  264. package/types/program.d.ts +286 -70
  265. package/types/scene.d.ts +35 -0
@@ -1,109 +1 @@
1
- import { validateNonEmptyString } from "../core/validation.js";
2
- import {
3
- readNominalField,
4
- readQuantitativeField,
5
- readScaleField
6
- } from "./scales/fields.js";
7
-
8
- export function normalizeGroupFields(value) {
9
- const fields = Array.isArray(value) ? [...value] : [value];
10
- for (const field of fields) validateNonEmptyString(field, "Path group field");
11
- if (fields.length === 0 || new Set(fields).size !== fields.length) {
12
- throw new Error("Path group fields must be non-empty and unique.");
13
- }
14
- return fields;
15
- }
16
-
17
- export function pathGroupFields(layer) {
18
- const group = layer.encoding?.group;
19
- if (group !== undefined) {
20
- if (group.fieldType !== "nominal") {
21
- throw new Error(`Path group on mark "${layer.id}" must be nominal.`);
22
- }
23
- if (Object.hasOwn(group, "field") && Object.hasOwn(group, "fields")) {
24
- throw new Error("Path group requires exactly one of field or fields.");
25
- }
26
- return normalizeGroupFields(group.fields ?? group.field);
27
- }
28
- if (layer.mark?.type !== "line") return [];
29
- const color = layer.encoding?.color?.field;
30
- const dash = layer.encoding?.strokeDash?.field;
31
- if (color !== undefined && dash !== undefined && color !== dash) {
32
- throw new Error("Line color field must match strokeDash field unless encodeGroup defines the series.");
33
- }
34
- return color === undefined && dash === undefined ? [] : [color ?? dash];
35
- }
36
-
37
- export function readPathSeriesFields(rows, layer) {
38
- const fields = pathGroupFields(layer);
39
- for (const field of fields) readNominalField(rows, field);
40
- return fields;
41
- }
42
-
43
- function seriesValueIndex(rows, fields, field, channel, encoding = {}) {
44
- const quantitative = channel === "strokeWidth" || channel === "opacity";
45
- const values = channel === "stroke" || (channel === "color" && encoding.fieldType === "quantitative")
46
- ? readScaleField(rows, field, encoding.fieldType ?? "nominal", {
47
- temporalUnit: encoding.temporalUnit
48
- })
49
- : quantitative
50
- ? readQuantitativeField(rows, field)
51
- : readNominalField(rows, field);
52
- const result = new Map();
53
- rows.forEach((row, index) => {
54
- const key = JSON.stringify(fields.map(field => row[field]));
55
- const value = values[index];
56
- if (channel === "strokeWidth" && value < 0) {
57
- throw new RangeError(`Line strokeWidth field "${field}" cannot contain negative values.`);
58
- }
59
- if (result.has(key) && result.get(key) !== value) {
60
- throw new Error(`Path ${channel} field "${field}" must have one value within each series.`);
61
- }
62
- result.set(key, value);
63
- });
64
- return result;
65
- }
66
-
67
- export function derivePathSeriesFieldValues(
68
- rows,
69
- series,
70
- field,
71
- channel,
72
- encoding
73
- ) {
74
- const fields = Object.keys(series[0]?.key ?? {});
75
- const values = seriesValueIndex(rows, fields, field, channel, encoding);
76
- return series.map(item => values.get(JSON.stringify(Object.values(item.key))));
77
- }
78
-
79
- export function validatePathSeriesAppearance(rows, layer) {
80
- if (!["line", "area"].includes(layer.mark?.type) ||
81
- layer.encoding?.parallel !== undefined) return;
82
- const grouping = readPathSeriesFields(rows, layer);
83
- const channels = layer.mark.type === "line"
84
- ? ["color", "stroke", "strokeDash", "strokeWidth", "opacity"]
85
- : ["color", "stroke"];
86
- for (const channel of channels) {
87
- const encoding = layer.encoding?.[channel];
88
- if (encoding?.field === undefined) continue;
89
- const allowed = ["color", "stroke"].includes(channel)
90
- ? channel === "color"
91
- ? layer.mark.type === "area" ? ["nominal", "ordinal", "quantitative"] : ["nominal", "ordinal"]
92
- : ["nominal", "ordinal", "quantitative", "temporal"]
93
- : channel === "strokeDash" ? ["nominal"] : ["quantitative"];
94
- if (!allowed.includes(encoding.fieldType)) {
95
- throw new Error(`Path ${channel} encoding has an unsupported field type.`);
96
- }
97
- seriesValueIndex(rows, grouping, encoding.field, channel, encoding);
98
- }
99
- return grouping;
100
- }
101
-
102
- export function readSeriesIdentity(rows, layer) {
103
- const group = layer.encoding?.group;
104
- const fields = group === undefined ? [] : normalizeGroupFields(group.fields ?? group.field);
105
- for (const field of fields) readNominalField(rows, field);
106
- const values = rows.map(row => fields.length === 0 ? undefined : fields.length === 1
107
- ? row[fields[0]] : JSON.stringify(fields.map(field => row[field])));
108
- return { fields, values, domain: [...new Set(values)] };
109
- }
1
+ import{validateNonEmptyString as S}from"../core/validation.js";import{readCategoricalLineColor as p,validateCategoricalColorConsumer as y}from"./scales/colorConsumers.js";import{readNominalField as f,readQuantitativeField as O,readScaleField as x}from"./scales/fields.js";function m(n){const e=Array.isArray(n)?[...n]:[n];for(const i of e)S(i,"Path group field");if(e.length===0||new Set(e).size!==e.length)throw new Error("Path group fields must be non-empty and unique.");return e}function E(n){const e=n.encoding?.group;if(e!==void 0){if(e.fieldType!=="nominal")throw new Error(`Path group on mark "${n.id}" must be nominal.`);if(Object.hasOwn(e,"field")&&Object.hasOwn(e,"fields"))throw new Error("Path group requires exactly one of field or fields.");return m(e.fields??e.field)}if(n.mark?.type!=="line")return[];const i=["nominal","ordinal"].includes(n.encoding?.color?.fieldType)?n.encoding.color.field:void 0,o=n.encoding?.strokeDash?.field;if(i!==void 0&&o!==void 0&&i!==o)throw new Error("Line color field must match strokeDash field unless encodeGroup defines the series.");return i===void 0&&o===void 0?[]:[i??o]}function h(n){return JSON.stringify(n.map(e=>e===void 0?{}:e))}function g(n,e){const i=n.encoding?.color,o=Array.isArray(e)?e.find(t=>t.id===i?.scale):e?.[i?.scale];return o!==void 0&&y(n,i,o)?o:void 0}function P(n,e,i){const o=E(e),t=g(e,i);for(const r of o)t&&e.encoding?.group===void 0&&r===e.encoding.color.field?p(n,r):f(n,r);return o}function k(n,e,i,o,t={},r){const l=o==="strokeWidth"||o==="opacity",d=o==="color"&&r!==void 0?p(n,i):o==="stroke"||o==="color"&&["quantitative","temporal"].includes(t.fieldType)?x(n,i,t.fieldType??"nominal",{temporalUnit:t.temporalUnit}):l?O(n,i):f(n,i),a=new Map;return n.forEach((c,v)=>{const s=h(e.map(w=>c[w])),u=d[v];if(o==="strokeWidth"&&u<0)throw new RangeError(`Line strokeWidth field "${i}" cannot contain negative values.`);if(a.has(s)&&a.get(s)!==u)throw new Error(`Path ${o} field "${i}" must have one value within each series.`);a.set(s,u)}),a}function F(n,e,i,o,t,r){if(e.length===0)return[];const l=Object.keys(e[0]?.key??{}),d=k(n,l,i,o,t,Object.hasOwn(r??{},"unknown")?r:void 0);return e.map(a=>d.get(h(Object.values(a.key))))}function j(n,e,i,o){if(!["line","area"].includes(e.mark?.type)||e.encoding?.parallel!==void 0)return;const t=o??P(n,e,i);if(o!==void 0)for(const d of t)f(n,d);const r=g(e,i),l=e.mark.type==="line"?["color","stroke","strokeDash","strokeWidth","opacity"]:["color","stroke"];for(const d of l){const a=e.encoding?.[d];if(a?.field===void 0)continue;if(!(["color","stroke"].includes(d)?d==="color"?e.mark.type==="area"?["nominal","ordinal","quantitative"]:["nominal","ordinal","quantitative","temporal"]:["nominal","ordinal","quantitative","temporal"]:d==="strokeDash"?["nominal","ordinal"]:["quantitative"]).includes(a.fieldType))throw new Error(`Path ${d} encoding has an unsupported field type.`);k(n,t,a.field,d,a,d==="color"?r:void 0)}return t}function A(n,e){const i=e.encoding?.group,o=i===void 0?[]:m(i.fields??i.field);for(const r of o)f(n,r);const t=n.map(r=>o.length===0?void 0:o.length===1?r[o[0]]:JSON.stringify(o.map(l=>r[l])));return{fields:o,values:t,domain:[...new Set(t)]}}export{F as derivePathSeriesFieldValues,m as normalizeGroupFields,E as pathGroupFields,h as pathSeriesKey,P as readPathSeriesFields,A as readSeriesIdentity,j as validatePathSeriesAppearance};
@@ -0,0 +1,81 @@
1
+ import { cloneAndFreeze, isOwned, isPlainObject } from "../core/immutable.js";
2
+
3
+ const normalizedShapes = new WeakMap();
4
+ const MAX_VERTICES = 1024;
5
+ const MAX_COORDINATE = 1_000_000;
6
+
7
+ export function pointPolygonArea(points) {
8
+ let twiceArea = 0;
9
+ for (let index = 0; index < points.length; index += 1) {
10
+ const current = points[index], next = points[(index + 1) % points.length];
11
+ twiceArea += current.x * next.y - next.x * current.y;
12
+ }
13
+ return Math.abs(twiceArea) / 2;
14
+ }
15
+
16
+ function samePoint(a, b) {
17
+ return a.x === b.x && a.y === b.y;
18
+ }
19
+
20
+ function turn(a, b, c) {
21
+ return (b.x - a.x) * (c.y - a.y) - (b.y - a.y) * (c.x - a.x);
22
+ }
23
+
24
+ function onSegment(a, b, p) {
25
+ return p.x >= Math.min(a.x, b.x) && p.x <= Math.max(a.x, b.x) &&
26
+ p.y >= Math.min(a.y, b.y) && p.y <= Math.max(a.y, b.y);
27
+ }
28
+
29
+ function intersects(a, b, c, d) {
30
+ const abC = turn(a, b, c), abD = turn(a, b, d);
31
+ const cdA = turn(c, d, a), cdB = turn(c, d, b);
32
+ return (Math.sign(abC) * Math.sign(abD) < 0 && Math.sign(cdA) * Math.sign(cdB) < 0) ||
33
+ (abC === 0 && onSegment(a, b, c)) || (abD === 0 && onSegment(a, b, d)) ||
34
+ (cdA === 0 && onSegment(c, d, a)) || (cdB === 0 && onSegment(c, d, b));
35
+ }
36
+
37
+ export function normalizePointPolygon(shape) {
38
+ if (isOwned(shape) && normalizedShapes.has(shape)) return normalizedShapes.get(shape);
39
+ if (!isPlainObject(shape) || !Object.hasOwn(shape, "polygon") ||
40
+ Object.keys(shape).some(key => !["polygon", "normalization"].includes(key)) ||
41
+ !Array.isArray(shape.polygon) || shape.polygon.length < 3 || shape.polygon.length > MAX_VERTICES + 1) {
42
+ throw new TypeError("Point polygon requires a polygon array of 3 to 1024 vertices and optional normalization.");
43
+ }
44
+ if (Object.hasOwn(shape, "normalization") && !["area", "radius"].includes(shape.normalization)) {
45
+ throw new Error('Point polygon normalization must be "area" or "radius".');
46
+ }
47
+ for (const point of shape.polygon) {
48
+ if (!isPlainObject(point) || Object.keys(point).length !== 2 ||
49
+ !Object.hasOwn(point, "x") || !Object.hasOwn(point, "y") ||
50
+ ![point.x, point.y].every(value => Number.isFinite(value) && Math.abs(value) <= MAX_COORDINATE)) {
51
+ throw new TypeError("Point polygon vertices require finite x/y coordinates with magnitude at most 1000000.");
52
+ }
53
+ }
54
+ const points = samePoint(shape.polygon[0], shape.polygon.at(-1))
55
+ ? shape.polygon.slice(0, -1) : shape.polygon;
56
+ if (points.length < 3 || points.length > MAX_VERTICES) {
57
+ throw new RangeError("Point polygon requires 3 to 1024 vertices after closing-point normalization.");
58
+ }
59
+ const area = pointPolygonArea(points);
60
+ if (!Number.isFinite(area) || area <= 0) {
61
+ throw new RangeError("Point polygon must have positive finite area.");
62
+ }
63
+ for (let i = 0; i < points.length; i += 1) {
64
+ const a = points[i], b = points[(i + 1) % points.length], c = points[(i + 2) % points.length];
65
+ if (samePoint(a, b) || (turn(a, b, c) === 0 &&
66
+ (b.x - a.x) * (c.x - b.x) + (b.y - a.y) * (c.y - b.y) < 0)) {
67
+ throw new Error("Point polygon edges must not be empty or backtrack.");
68
+ }
69
+ for (let j = i + 1; j < points.length; j += 1) {
70
+ if (j === i + 1 || (i === 0 && j === points.length - 1)) continue;
71
+ if (intersects(a, b, points[j], points[(j + 1) % points.length])) {
72
+ throw new Error("Point polygon must be simple, without crossing or touching nonadjacent edges.");
73
+ }
74
+ }
75
+ }
76
+ const normalized = cloneAndFreeze({ polygon: points,
77
+ ...(Object.hasOwn(shape, "normalization") ? { normalization: shape.normalization } : {}) });
78
+ normalizedShapes.set(normalized, normalized);
79
+ if (isOwned(shape)) normalizedShapes.set(shape, normalized);
80
+ return normalized;
81
+ }
@@ -1,6 +1,7 @@
1
1
  import { cloneAndFreeze } from "../core/immutable.js";
2
2
  import { buildLinearPathCommands } from "./pathCommands.js";
3
3
  import { requestedStrokeDetails } from "./strokeStyle.js";
4
+ import { normalizePointPolygon, pointPolygonArea } from "./pointPolygon.js";
4
5
 
5
6
  export const POINT_SHAPES = cloneAndFreeze([
6
7
  "circle",
@@ -22,6 +23,7 @@ export const POINT_SHAPES = cloneAndFreeze([
22
23
  const SHAPE_SET = new Set(POINT_SHAPES);
23
24
 
24
25
  export function validatePointShape(shape) {
26
+ if (shape !== null && typeof shape === "object") return normalizePointPolygon(shape);
25
27
  if (typeof shape !== "string" || !SHAPE_SET.has(shape)) {
26
28
  throw new Error(`Unsupported point shape "${shape}".`);
27
29
  }
@@ -35,16 +37,6 @@ export function getPointGraphicType(shape) {
35
37
  return "path";
36
38
  }
37
39
 
38
- function polygonArea(points) {
39
- let twiceArea = 0;
40
- for (let index = 0; index < points.length; index += 1) {
41
- const current = points[index];
42
- const next = points[(index + 1) % points.length];
43
- twiceArea += current.x * next.y - next.x * current.y;
44
- }
45
- return Math.abs(twiceArea) / 2;
46
- }
47
-
48
40
  function rotate(points, angle) {
49
41
  const cosine = Math.cos(angle);
50
42
  const sine = Math.sin(angle);
@@ -70,6 +62,7 @@ function alternatingPolygon(count, innerRadius, rotation = -Math.PI / 2) {
70
62
  }
71
63
 
72
64
  function shapePolygon(shape) {
65
+ if (typeof shape === "object") return shape.polygon;
73
66
  const arm = 0.32;
74
67
  const plus = [
75
68
  { x: -arm, y: -1 }, { x: arm, y: -1 },
@@ -116,12 +109,17 @@ function shapePolygon(shape) {
116
109
  }[shape];
117
110
  }
118
111
 
119
- function normalizePolygon(points, x, y, area) {
120
- const scale = Math.sqrt(area / polygonArea(points));
121
- return points.map(point => ({
112
+ function normalizePolygon(points, x, y, area, normalization = "area") {
113
+ const scale = Math.sqrt(area / (normalization === "radius" ? Math.PI : pointPolygonArea(points)));
114
+ if (!Number.isFinite(scale)) throw new RangeError("Point polygon normalization exceeds finite geometry.");
115
+ const normalized = points.map(point => ({
122
116
  x: x + point.x * scale,
123
117
  y: y + point.y * scale
124
118
  }));
119
+ if (normalized.some(point => !Number.isFinite(point.x) || !Number.isFinite(point.y))) {
120
+ throw new RangeError("Point polygon normalization exceeds finite geometry.");
121
+ }
122
+ return normalized;
125
123
  }
126
124
 
127
125
  function appearance(fill, stroke, strokeWidth, opacity, strokeDetails) {
@@ -192,7 +190,8 @@ export function createPointShapeGraphic({
192
190
  rotate(shapePolygon(validated), (angle ?? 0) * Math.PI / 180),
193
191
  x,
194
192
  y,
195
- area
193
+ area,
194
+ validated.normalization
196
195
  ),
197
196
  { close: true }
198
197
  ),
@@ -230,7 +229,8 @@ export function resolvePointShapeExtent({
230
229
  rotate(shapePolygon(validated), (angle ?? 0) * Math.PI / 180),
231
230
  0,
232
231
  0,
233
- area
232
+ area,
233
+ validated.normalization
234
234
  );
235
235
  return cloneAndFreeze({
236
236
  x: Math.max(0, ...points.map(point => Math.abs(point.x))) + strokeExtent,
@@ -30,5 +30,5 @@ export function resolveRectMode(layer) {
30
30
  }
31
31
 
32
32
  export function rectUsesFields(layer) {
33
- return ["x", "y", "x2", "y2", "color"].some(channel => Object.hasOwn(layer.encoding?.[channel] ?? {}, "field"));
33
+ return ["x", "y", "x2", "y2", "color", "stroke", "opacity", "strokeWidth"].some(channel => Object.hasOwn(layer.encoding?.[channel] ?? {}, "field"));
34
34
  }
@@ -1,195 +1 @@
1
- import { cloneAndFreeze } from "../../core/immutable.js";
2
- import {
3
- readNominalField,
4
- readQuantitativeField
5
- } from "../scales/index.js";
6
- import { fitRegressionGroup, predictRegressionAt, linearRegressionStatistics } from "./models.js";
7
- import { requireFiniteResult } from "../numeric.js";
8
- import {
9
- validateGeneratedItemLimit,
10
- validateWorkLimit
11
- } from "../../core/validation.js";
12
- import {
13
- normalizeRegressionParameters,
14
- requireRegressionField
15
- } from "./parameters.js";
16
-
17
- export const REGRESSION_LOWER_FIELD = "__regression_ci_lower";
18
- export const REGRESSION_UPPER_FIELD = "__regression_ci_upper";
19
-
20
- export function deriveRegression(values, {
21
- x,
22
- y,
23
- groupBy,
24
- method,
25
- degree,
26
- span,
27
- robustIterations,
28
- confidenceMethod,
29
- level,
30
- confidence,
31
- interval,
32
- predict,
33
- missing
34
- } = {}) {
35
- if (!Array.isArray(values)) {
36
- throw new TypeError("Regression values must be an array.");
37
- }
38
- requireRegressionField(x, "Regression x field");
39
- requireRegressionField(y, "Regression y field");
40
- if (groupBy !== undefined) {
41
- requireRegressionField(groupBy, "Regression groupBy field");
42
- }
43
- const parameters = normalizeRegressionParameters({
44
- method,
45
- degree,
46
- span,
47
- robustIterations,
48
- confidenceMethod,
49
- level,
50
- confidence,
51
- interval
52
- });
53
- let missingRows = 0;
54
- const eligibleValues = missing === undefined ? values : values.filter((row, index) => {
55
- const xValue = row?.[x];
56
- const yValue = row?.[y];
57
- if (xValue === null || xValue === undefined || yValue === null || yValue === undefined) {
58
- if (missing === "error") throw new TypeError(`Regression x/y pair is missing at row ${index}.`);
59
- missingRows += 1;
60
- return false;
61
- }
62
- if (!Number.isFinite(xValue) || !Number.isFinite(yValue)) {
63
- throw new TypeError(`Regression x/y fields must contain finite numbers at row ${index}.`);
64
- }
65
- return true;
66
- });
67
- readQuantitativeField(eligibleValues, x);
68
- readQuantitativeField(eligibleValues, y);
69
- if (groupBy !== undefined) readNominalField(eligibleValues, groupBy);
70
-
71
- const groupedRows = new Map();
72
- if (groupBy === undefined) {
73
- groupedRows.set(undefined, eligibleValues);
74
- } else {
75
- for (const row of eligibleValues) {
76
- const group = row[groupBy];
77
- const rows = groupedRows.get(group) ?? [];
78
- rows.push(row);
79
- groupedRows.set(group, rows);
80
- }
81
- }
82
- const groups = [...groupedRows.keys()];
83
- const models = [];
84
- const statistics = [];
85
- const rows = [];
86
- let work = 0;
87
-
88
- for (const group of groups) {
89
- const groupRows = groupedRows.get(group);
90
- const observedX = [...new Set(groupRows.map(row => row[x]))]
91
- .sort((left, right) => left - right);
92
- const xValues = predict?.values ?? (predict?.domain === undefined
93
- ? observedX
94
- : Array.from({ length: predict.steps }, (_, index) => {
95
- if (index === 0) return predict.domain[0];
96
- if (index === predict.steps - 1) return predict.domain[1];
97
- const ratio = index / (predict.steps - 1);
98
- return requireFiniteResult(
99
- predict.domain[0] * (1 - ratio) + predict.domain[1] * ratio,
100
- "Regression prediction grid"
101
- );
102
- }));
103
- validateGeneratedItemLimit(rows.length + xValues.length, "Regression generated row count");
104
- if (parameters.method === "polynomial") {
105
- const size = parameters.degree + 1;
106
- work += groupRows.length * size ** 2 + size ** 3;
107
- } else if (parameters.method === "loess") {
108
- const observedSet = new Set(observedX);
109
- const newPredictions = predict === undefined ? 0 :
110
- xValues.filter(value => !observedSet.has(value)).length;
111
- work += groupRows.length *
112
- (observedX.length * (1 + (parameters.robustIterations ?? 0)) + newPredictions) *
113
- Math.ceil(Math.log2(groupRows.length + 1));
114
- }
115
- validateWorkLimit(work, "Regression computation");
116
- const model = fitRegressionGroup(groupRows, {
117
- x,
118
- y,
119
- group,
120
- parameters
121
- });
122
- models.push({ ...(groupBy === undefined ? {} : { group }), ...model, xValues });
123
- if (parameters.method === "linear") statistics.push({
124
- ...(groupBy === undefined ? {} : { group }),
125
- ...linearRegressionStatistics(groupRows, model, { x, y })
126
- });
127
-
128
- for (const xValue of xValues) {
129
- const prediction = predictRegressionAt(model, xValue, parameters);
130
- const fitted = requireFiniteResult(
131
- prediction.prediction,
132
- `Regression group "${group === undefined ? "all" : String(group)}" prediction`
133
- );
134
- const lower = parameters.method === "loess" || parameters.interval === false
135
- ? undefined
136
- : requireFiniteResult(
137
- fitted - prediction.margin,
138
- `Regression group "${group === undefined ? "all" : String(group)}" lower interval`
139
- );
140
- const upper = parameters.method === "loess" || parameters.interval === false
141
- ? undefined
142
- : requireFiniteResult(
143
- fitted + prediction.margin,
144
- `Regression group "${group === undefined ? "all" : String(group)}" upper interval`
145
- );
146
- rows.push({
147
- ...(groupBy === undefined ? {} : { [groupBy]: group }),
148
- [x]: xValue,
149
- [y]: fitted,
150
- ...(parameters.method === "loess" || parameters.interval === false ? {} : {
151
- [REGRESSION_LOWER_FIELD]: lower,
152
- [REGRESSION_UPPER_FIELD]: upper
153
- })
154
- });
155
- }
156
- }
157
-
158
- return cloneAndFreeze({
159
- fields: {
160
- x,
161
- y,
162
- ...(groupBy === undefined ? {} : { group: groupBy }),
163
- ...(parameters.method === "loess" || parameters.interval === false ? {} : {
164
- lower: REGRESSION_LOWER_FIELD,
165
- upper: REGRESSION_UPPER_FIELD
166
- })
167
- },
168
- parameters,
169
- groups,
170
- models,
171
- ...(parameters.method === "linear" ? {
172
- fitStatistics: { version: 1, method: "linear", groups: statistics }
173
- } : {}),
174
- values: rows,
175
- ...(missing === undefined ? {} : {
176
- report: {
177
- version: 1,
178
- owner: { kind: "data", id: "pending" },
179
- inputs: [],
180
- units: [{
181
- role: "fit",
182
- group: {},
183
- inputRows: values.length,
184
- usedRows: eligibleValues.length,
185
- excludedRows: missingRows,
186
- excludedByReason: missingRows === 0 ? {} : { "missing-value": missingRows }
187
- }]
188
- }
189
- })
190
- });
191
- }
192
-
193
- export function deriveLinearRegression(values, options = {}) {
194
- return deriveRegression(values, { ...options, method: "linear" });
195
- }
1
+ import{cloneAndFreeze as W,isOwned as M,isPlainObject as q}from"../../core/immutable.js";import{readNominalField as J,readQuantitativeField as P}from"../scales/index.js";import{fitRegressionGroup as K,predictRegressionAt as Q,linearRegressionStatistics as U}from"./models.js";import{requireFiniteResult as _}from"../numeric.js";import{validateGeneratedItemLimit as X,validateWorkLimit as C}from"../../core/validation.js";import{normalizeRegressionParameters as H,requireRegressionField as I}from"./parameters.js";const A="__regression_ci_lower",V="__regression_ci_upper",E=new WeakMap,$=["x","y","groupBy","method","degree","span","robustIterations","confidenceMethod","level","confidence","interval","predict","missing"];function Y(s,n={}){if(!M(s)||!q(n)||$.some(e=>{const b=Object.getOwnPropertyDescriptor(n,e);return b?!Object.hasOwn(b,"value"):e in n}))return j(s,n);const a=$.map(e=>n[e]),i=M(s)&&a.every(e=>e==null||typeof e=="string"||typeof e=="boolean"||typeof e=="number"&&Number.isFinite(e)&&!Object.is(e,-0)),h=i?JSON.stringify(a.map(e=>[typeof e,e])):void 0,R=i?E.get(s)?.get(h):void 0;if(R!==void 0)return R;const w=j(s,n);if(i){E.has(s)||E.set(s,new Map);const e=E.get(s);e.size>=32&&e.delete(e.keys().next().value),e.set(h,w)}return w}function j(s,{x:n,y:a,groupBy:i,method:h,degree:R,span:w,robustIterations:e,confidenceMethod:b,level:x,confidence:z,interval:G,predict:f,missing:O}={}){if(!Array.isArray(s))throw new TypeError("Regression values must be an array.");I(n,"Regression x field"),I(a,"Regression y field"),i!==void 0&&I(i,"Regression groupBy field");const t=H({method:h,degree:R,span:w,robustIterations:e,confidenceMethod:b,level:x,confidence:z,interval:G});let S=0;const m=O===void 0?s:s.filter((r,o)=>{const u=r?.[n],c=r?.[a];if(u==null||c===null||c===void 0){if(O==="error")throw new TypeError(`Regression x/y pair is missing at row ${o}.`);return S+=1,!1}if(!Number.isFinite(u)||!Number.isFinite(c))throw new TypeError(`Regression x/y fields must contain finite numbers at row ${o}.`);return!0});P(m,n),P(m,a),i!==void 0&&J(m,i);const p=new Map;if(i===void 0)p.set(void 0,m);else for(const r of m){const o=r[i],u=p.get(o)??[];u.push(r),p.set(o,u)}const N=[...p.keys()],k=[],L=[],F=[];let y=0;for(const r of N){const o=p.get(r),u=[...new Set(o.map(d=>d[n]))].sort((d,l)=>d-l),c=f?.values??(f?.domain===void 0?u:Array.from({length:f.steps},(d,l)=>{if(l===0)return f.domain[0];if(l===f.steps-1)return f.domain[1];const g=l/(f.steps-1);return _(f.domain[0]*(1-g)+f.domain[1]*g,"Regression prediction grid")}));if(X(F.length+c.length,"Regression generated row count"),t.method==="polynomial"){const d=t.degree+1;y+=o.length*d**2+d**3}else if(t.method==="loess"){const d=new Set(u),l=f===void 0?0:c.filter(g=>!d.has(g)).length;y+=o.length*(u.length*(1+(t.robustIterations??0))+l)*Math.ceil(Math.log2(o.length+1))}C(y,"Regression computation");const v=K(o,{x:n,y:a,group:r,parameters:t});k.push({...i===void 0?{}:{group:r},...v,xValues:c}),t.method==="linear"&&L.push({...i===void 0?{}:{group:r},...U(o,v,{x:n,y:a})});for(const d of c){const l=Q(v,d,t),g=_(l.prediction,`Regression group "${r===void 0?"all":String(r)}" prediction`),D=t.method==="loess"||t.interval===!1?void 0:_(g-l.margin,`Regression group "${r===void 0?"all":String(r)}" lower interval`),T=t.method==="loess"||t.interval===!1?void 0:_(g+l.margin,`Regression group "${r===void 0?"all":String(r)}" upper interval`);F.push({...i===void 0?{}:{[i]:r},[n]:d,[a]:g,...t.method==="loess"||t.interval===!1?{}:{[A]:D,[V]:T}})}}return W({fields:{x:n,y:a,...i===void 0?{}:{group:i},...t.method==="loess"||t.interval===!1?{}:{lower:A,upper:V}},parameters:t,groups:N,models:k,...t.method==="linear"?{fitStatistics:{version:1,method:"linear",groups:L}}:{},values:F,...O===void 0?{}:{report:{version:1,owner:{kind:"data",id:"pending"},inputs:[],units:[{role:"fit",group:{},inputRows:s.length,usedRows:m.length,excludedRows:S,excludedByReason:S===0?{}:{"missing-value":S}}]}}})}function ie(s,n={}){return Y(s,{...n,method:"linear"})}export{A as REGRESSION_LOWER_FIELD,V as REGRESSION_UPPER_FIELD,ie as deriveLinearRegression,Y as deriveRegression};
@@ -233,3 +233,10 @@ export function normalizeRegressionTransform(args = {}) {
233
233
  validateRegressionTransform(transform);
234
234
  return cloneAndFreeze(transform);
235
235
  }
236
+
237
+ export function validateRegressionPlacement(value) {
238
+ if (value !== undefined && !["source", "plot-last"].includes(value)) {
239
+ throw new Error('Regression placement must be "source" or "plot-last".');
240
+ }
241
+ return value ?? "source";
242
+ }
@@ -1 +1 @@
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
+ import{cloneAndFreeze as r,isPlainObject as s}from"../../core/immutable.js";import{validateUnitInterval as h}from"../../core/validation.js";import{POINT_SHAPES as y,validatePointShape as m}from"../pointShapes.js";import{normalizePalette as u,resolvePalette as p}from"../palettes.js";const A=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]]),w=r({solid:[],dashed:[6,4],dotted:[1,3],dashdot:[6,3,1,3]});import{POINT_SHAPES as M}from"../pointShapes.js";const v=r([24,196]),S=r([.2,1]),x=r([1,8]);function E(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 u(t.palette),r(t)}function R(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 c(t){if(typeof t=="string"){const e=w[t];if(e===void 0)throw new Error(`Unknown stroke dash style "${t}".`);return r(e)}if(!R(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 T(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)c(e);return r(t)}function O(t){if(t==="auto")return t;if(!Array.isArray(t)||t.length===0)throw new TypeError("Shape range must contain supported point shapes.");try{return r(t.map(m))}catch(e){throw new TypeError("Shape range must contain supported point shapes.",{cause:e})}}function l(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 k(t){return l(t,"Size range")}function D(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 P(t){return l(t,"StrokeWidth range")}function U(t,e="Opacity"){return h(t,e)}function I(t){if(t==="auto")return t;if(Array.isArray(t)&&t.length>0)return r(t);if(s(t)&&Object.hasOwn(t,"palette"))return u(t.palette),r(t);throw new TypeError("Scale range has an unsupported value.")}function j(t,e){const o=E(t);return o==="auto"?b:Array.isArray(o)?o:p(o.palette,e)}function C(t){const e=T(t);return e==="auto"?A:r(e.map(c))}function H(t){const e=O(t);return e==="auto"?y:e}function g(t){const e=k(t);return e==="auto"?v:e}function L(t){const e=D(t);return e==="auto"?S:e}function W(t){const e=P(t);return e==="auto"?x:e}function $(t,e,o,a={}){const d=Object.hasOwn(a,"unknown"),f=new Map(e.map((n,i)=>[n,i]));return r(t.map(n=>{const i=f.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=p({name:"tableau10",count:10},10);export{A as DASH10,S as DEFAULT_OPACITY_RANGE,v as DEFAULT_SIZE_RANGE,x as DEFAULT_STROKE_WIDTH_RANGE,w as NAMED_DASH_PATTERNS,M as POINT_SHAPES,b as TABLEAU10,$ as mapOrdinalValues,c as normalizeStrokeDashPattern,j as resolveColorRange,L as resolveOpacityRange,H as resolveShapeRange,g as resolveSizeRange,C as resolveStrokeDashRange,W as resolveStrokeWidthRange,E as validateColorRange,D as validateOpacityRange,U as validateOpacityValue,I as validateSemanticScaleRange,O as validateShapeRange,k as validateSizeRange,T as validateStrokeDashRange,P as validateStrokeWidthRange};
@@ -1 +1 @@
1
- import{mapTransformedValues as F}from"./transformed.js";import{cloneAndFreeze as p,isPlainObject as j}from"../../core/immutable.js";import{validateGeneratedItemLimit as $}from"../../core/validation.js";import{normalizePalette as k,resolveContinuousPalette as S}from"../palettes.js";import{inverseLerp as C}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 E(t,e=0,n=1){return Math.max(e,Math.min(n,t))}function d(t){return(t%360+360)%360}function q({h:t,s:e,l:n}){const r=(1-Math.abs(2*n-1))*e,o=d(t)/60,i=r*(1-Math.abs(o%2-1)),[a,u,l]=o<1?[r,i,0]:o<2?[i,r,0]:o<3?[0,r,i]:o<4?[0,i,r]:o<5?[i,0,r]:[r,0,i],s=n-r/2;return{r:a+s,g:u+s,b:l+s}}function w(t){if(typeof t!="string"||t.length===0)throw new TypeError("Continuous color range requires non-empty color strings.");const e=D[t.toLowerCase()]??t.toLowerCase();let n=e.match(/^#([0-9a-f]{3})$/i);if(n)return Object.fromEntries(["r","g","b"].map((r,o)=>[r,Number.parseInt(n[1][o].repeat(2),16)/255]));if(n=e.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=e.match(/^rgb\(\s*([\d.]+)%?\s*,\s*([\d.]+)%?\s*,\s*([\d.]+)%?\s*\)$/),n){const o=e.includes("%")?100:255,i=n.slice(1).map(a=>Number(a)/o);if(i.every(a=>Number.isFinite(a)&&a>=0&&a<=1))return{r:i[0],g:i[1],b:i[2]}}if(n=e.match(/^hsl\(\s*([-\d.]+)\s*,\s*([\d.]+)%\s*,\s*([\d.]+)%\s*\)$/),n){const r=Number(n[1]),o=Number(n[2])/100,i=Number(n[3])/100;if([r,o,i].every(Number.isFinite)&&o>=0&&o<=1&&i>=0&&i<=1)return q({h:r,s:o,l:i})}throw new Error(`Unsupported continuous color "${t}".`)}function N({r:t,g:e,b:n}){return`#${[t,e,n].map(r=>Math.round(E(r)*255).toString(16).padStart(2,"0")).join("")}`}function T({r:t,g:e,b:n}){return[t,e,n].map(r=>Math.round(r*255))}function A({r:t,g:e,b:n}){const r=Math.max(t,e,n),o=Math.min(t,e,n),i=r-o,a=(r+o)/2;if(i===0)return{h:0,s:0,l:a};const u=i/(1-Math.abs(2*a-1)),l=r===t?(e-n)/i%6:r===e?(n-t)/i+2:(t-e)/i+4;return{h:d(l*60),s:u,l:a}}function x(t){return t<=.04045?t/12.92:((t+.055)/1.055)**2.4}function m(t){return t<=.0031308?12.92*t:1.055*t**(1/2.4)-.055}function y(t,e="d65"){const n=x(t.r),r=x(t.g),o=x(t.b),i=e==="d50"?(.4360747*n+.3850649*r+.1430804*o)/.96422:(.4124564*n+.3575761*r+.1804375*o)/.95047,a=e==="d50"?.2225045*n+.7168786*r+.0606169*o:.2126729*n+.7151522*r+.072175*o,u=e==="d50"?(.0139322*n+.0971045*r+.7141733*o)/.82521:(.0193339*n+.119192*r+.9503041*o)/1.08883,l=b=>b>216/24389?Math.cbrt(b):841/108*b+4/29,s=l(i),c=l(a),f=l(u);return{l:116*c-16,a:500*(s-c),b:200*(c-f)}}function O({l:t,a:e,b:n},r="d65"){const o=(t+16)/116,i=o+e/500,a=o-n/200,u=f=>f**3>216/24389?f**3:108/841*(f-4/29),l=(r==="d50"?.96422:.95047)*u(i),s=u(o),c=(r==="d50"?.82521:1.08883)*u(a);return r==="d50"?{r:m(3.1338561*l-1.6168667*s-.4906146*c),g:m(-.9787684*l+1.9161415*s+.033454*c),b:m(.0719453*l-.2289914*s+1.4052427*c)}:{r:m(3.2404542*l-1.5371385*s-.4985314*c),g:m(-.969266*l+1.8760108*s+.041556*c),b:m(.0556434*l-.2040259*s+1.0572252*c)}}function I({l:t,a:e,b:n}){return{h:d(Math.atan2(n,e)*180/Math.PI),c:Math.hypot(e,n),l:t}}function H({h:t,c:e,l:n}){const r=t*Math.PI/180;return{l:n,a:Math.cos(r)*e,b:Math.sin(r)*e}}function R({r:t,g:e,b:n}){const l=-1.7884503806,s=1.97294*1.78277,c=1.78277*-.29227- -.90649*-.14861,f=(c*n+l*t-s*e)/(c+l-s),b=n-f,h=(1.97294*(e-f)- -.29227*b)/-.90649,g=1.97294*f*(1-f);return{h:d(Math.atan2(h,b)*180/Math.PI-120),s:g===0?0:Math.hypot(h,b)/g,l:f}}function U({h:t,s:e,l:n}){const r=(t+120)*Math.PI/180,o=e*n*(1-n),i=Math.cos(r),a=Math.sin(r);return{r:n+o*(-.14861*i+1.78277*a),g:n+o*(-.29227*i-.90649*a),b:n+o*(1.97294*i)}}function M(t,e,n,r){let o=e-t;return r||(o=(o+540)%360-180),d(t+o*n)}function W(t,e,n,r,o){const i=o.whitePoint??"d65";if(r.startsWith("hsl")){const s=A(t),c=A(e);return q({h:M(s.h,c.h,n,r.endsWith("-long")),s:s.s+(c.s-s.s)*n,l:s.l+(c.l-s.l)*n})}if(r==="lab"){const s=y(t,i),c=y(e,i);return O({l:s.l+(c.l-s.l)*n,a:s.a+(c.a-s.a)*n,b:s.b+(c.b-s.b)*n},i)}if(r.startsWith("hcl")){const s=I(y(t,i)),c=I(y(e,i));return O(H({h:M(s.h,c.h,n,r.endsWith("-long")),c:s.c+(c.c-s.c)*n,l:s.l+(c.l-s.l)*n}),i)}const a=R(t),u=R(e),l=n**(o.gamma??1);if(!Number.isFinite(l))throw new RangeError("Continuous cubehelix gamma produced a nonfinite interpolation.");return U({h:M(a.h,u.h,n,r.endsWith("-long")),s:a.s+(u.s-a.s)*n,l:a.l+(u.l-a.l)*l})}function P(t){if(!B.includes(t))throw new Error(`Unsupported continuous color interpolation "${t}".`);return t}function _(t,e={}){const n={};if(e.whitePoint!==void 0){if(!["lab","hcl","hcl-long"].includes(t))throw new Error("Scale whitePoint requires Lab or HCL interpolation.");if(!["d65","d50"].includes(e.whitePoint))throw new Error("Scale whitePoint must be d65 or d50.");n.whitePoint=e.whitePoint}if(e.gamma!==void 0){if(!["cubehelix","cubehelix-long"].includes(t))throw new Error("Scale gamma requires cubehelix interpolation.");if(!Number.isFinite(e.gamma)||e.gamma<=0)throw new RangeError("Scale gamma must be a positive finite number.");n.gamma=e.gamma}return n}function G(t){if(t==="auto")return t;if(Array.isArray(t)){if($(t.length,"Sequential color range length"),t.length<2)throw new TypeError("Sequential color range requires at least two colors.");return t.forEach(w),p(t)}if(!j(t)||Object.keys(t).length!==1||!Object.hasOwn(t,"palette"))throw new TypeError("Sequential color range requires colors or a palette descriptor.");const e=k(t.palette);if(e.count!==void 0&&e.count<2)throw new RangeError("Sequential palette count must be an integer of at least 2.");return p({palette:e})}function Z(t){const e=G(t);return e==="auto"?S("viridis"):Array.isArray(e)?p(e.map(n=>N(w(n)))):S(e.palette)}function L(t,e,n,r,o={}){const a=(r?E(e):e)*(t.length-1),u=Math.max(0,Math.min(t.length-2,Math.floor(a))),l=u+1,s=a-u;if(n==="rgb"){const c=T(t[u]),f=T(t[l]);return`#${c.map((b,h)=>Math.round(E(b+(f[h]-b)*s,0,255)).toString(16).padStart(2,"0")).join("")}`}return N(W(t[u],t[l],s,n,o))}function v(t,e,n="rgb"){const r=P(n);if(!Array.isArray(t)||t.length<2)throw new TypeError("Color interpolation requires at least two stops.");const o=t.map(w);return L(o,e,r,!0)}function z(t,e,n="auto"){if(!(t===void 0||t==="auto")){if(e!=="sequential")throw new Error(`Scale type "${e}" 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 V(t,e,n,r={}){const{interpolation:o="rgb",clamp:i=!1}=r;if(_(o,r),["log","pow","sqrt","symlog"].includes(r.type)){z(r.midpoint,r.type,e);const h=F(t,e,[0,1],{type:r.type,clamp:i,...r.type==="log"?{base:r.base}:{},...r.type==="pow"?{exponent:r.exponent}:{},...r.type==="symlog"?{constant:r.constant}:{},...Object.hasOwn(r,"unknown")?{unknown:NaN}:{}});return V(h,[0,1],n,{...r,type:"sequential"})}const a=Object.hasOwn(r,"unknown");if(!Array.isArray(e)||e.length!==2||!e.every(Number.isFinite))throw new TypeError("Sequential color domain must contain two finite numbers.");if(!Array.isArray(t)||!a&&!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 u=z(r.midpoint,"sequential",e),[l,s]=e,c=l===s,f=P(o);if(!Array.isArray(n)||n.length<2)throw new TypeError("Color interpolation requires at least two stops.");const b=n.map(w);return p(t.map(h=>{if(!Number.isFinite(h)){if(a)return r.unknown;throw new TypeError("Sequential color values must be finite numbers.")}const g=u===void 0?c?.5:C(h,l,s):(s>l?h<=u:h>=u)?C(h,l,u)/2:.5+C(h,u,s)/2;return L(b,g,f,i,r)}))}export{B as CONTINUOUS_COLOR_INTERPOLATIONS,v as interpolateColorStops,V as mapSequentialColors,_ as normalizeColorInterpolationOptions,Z as resolveSequentialColorStops,P as validateContinuousColorInterpolation,G as validateSequentialColorRange,z as validateSequentialMidpoint};
1
+ import{mapTransformedValues as z}from"./transformed.js";import{cloneAndFreeze as p,isPlainObject as $}from"../../core/immutable.js";import{validateGeneratedItemLimit as k}from"../../core/validation.js";import{normalizePalette as B,resolveContinuousPalette as S}from"../palettes.js";import{inverseLerp as x}from"../numeric.js";const D=p(["rgb","hsl","hsl-long","lab","hcl","hcl-long","cubehelix","cubehelix-long"]),H=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 w(t,e=0,n=1){return Math.max(e,Math.min(n,t))}function y(t){return(t%360+360)%360}function q({h:t,s:e,l:n}){const r=(1-Math.abs(2*n-1))*e,o=y(t)/60,i=r*(1-Math.abs(o%2-1)),[s,u,c]=o<1?[r,i,0]:o<2?[i,r,0]:o<3?[0,r,i]:o<4?[0,i,r]:o<5?[i,0,r]:[r,0,i],l=n-r/2;return{r:s+l,g:u+l,b:c+l}}function E(t){if(typeof t!="string"||t.length===0)throw new TypeError("Continuous color range requires non-empty color strings.");const e=H[t.toLowerCase()]??t.toLowerCase();let n=e.match(/^#([0-9a-f]{3})$/i);if(n)return Object.fromEntries(["r","g","b"].map((r,o)=>[r,Number.parseInt(n[1][o].repeat(2),16)/255]));if(n=e.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=e.match(/^rgb\(\s*([\d.]+)%?\s*,\s*([\d.]+)%?\s*,\s*([\d.]+)%?\s*\)$/),n){const o=e.includes("%")?100:255,i=n.slice(1).map(s=>Number(s)/o);if(i.every(s=>Number.isFinite(s)&&s>=0&&s<=1))return{r:i[0],g:i[1],b:i[2]}}if(n=e.match(/^hsl\(\s*([-\d.]+)\s*,\s*([\d.]+)%\s*,\s*([\d.]+)%\s*\)$/),n){const r=Number(n[1]),o=Number(n[2])/100,i=Number(n[3])/100;if([r,o,i].every(Number.isFinite)&&o>=0&&o<=1&&i>=0&&i<=1)return q({h:r,s:o,l:i})}throw new Error(`Unsupported continuous color "${t}".`)}function T({r:t,g:e,b:n}){return`#${[t,e,n].map(r=>Math.round(w(r)*255).toString(16).padStart(2,"0")).join("")}`}function O({r:t,g:e,b:n}){return[t,e,n].map(r=>Math.round(r*255))}function A({r:t,g:e,b:n}){const r=Math.max(t,e,n),o=Math.min(t,e,n),i=r-o,s=(r+o)/2;if(i===0)return{h:0,s:0,l:s};const u=i/(1-Math.abs(2*s-1)),c=r===t?(e-n)/i%6:r===e?(n-t)/i+2:(t-e)/i+4;return{h:y(c*60),s:u,l:s}}function N(t){return t<=.04045?t/12.92:((t+.055)/1.055)**2.4}function g(t){return t<=.0031308?12.92*t:1.055*t**(1/2.4)-.055}function C(t,e="d65"){const n=N(t.r),r=N(t.g),o=N(t.b),i=e==="d50"?(.4360747*n+.3850649*r+.1430804*o)/.96422:(.4124564*n+.3575761*r+.1804375*o)/.95047,s=e==="d50"?.2225045*n+.7168786*r+.0606169*o:.2126729*n+.7151522*r+.072175*o,u=e==="d50"?(.0139322*n+.0971045*r+.7141733*o)/.82521:(.0193339*n+.119192*r+.9503041*o)/1.08883,c=m=>m>216/24389?Math.cbrt(m):841/108*m+4/29,l=c(i),f=c(s),h=c(u);return{l:116*f-16,a:500*(l-f),b:200*(f-h)}}function I({l:t,a:e,b:n},r="d65"){const o=(t+16)/116,i=o+e/500,s=o-n/200,u=h=>h**3>216/24389?h**3:108/841*(h-4/29),c=(r==="d50"?.96422:.95047)*u(i),l=u(o),f=(r==="d50"?.82521:1.08883)*u(s);return r==="d50"?{r:g(3.1338561*c-1.6168667*l-.4906146*f),g:g(-.9787684*c+1.9161415*l+.033454*f),b:g(.0719453*c-.2289914*l+1.4052427*f)}:{r:g(3.2404542*c-1.5371385*l-.4985314*f),g:g(-.969266*c+1.8760108*l+.041556*f),b:g(.0556434*c-.2040259*l+1.0572252*f)}}function R({l:t,a:e,b:n},r=!1){return{h:r?void 0:y(Math.atan2(n,e)*180/Math.PI),c:r?0:Math.hypot(e,n),l:t}}function U({h:t,c:e,l:n}){const r=t*Math.PI/180;return{l:n,a:Math.cos(r)*e,b:Math.sin(r)*e}}function j({r:t,g:e,b:n}){const c=-1.7884503806,l=1.97294*1.78277,f=1.78277*-.29227- -.90649*-.14861,h=(f*n+c*t-l*e)/(f+c-l),m=n-h,b=(1.97294*(e-h)- -.29227*m)/-.90649,a=1.97294*h*(1-h);return{h:y(Math.atan2(b,m)*180/Math.PI-120),s:a===0?0:Math.hypot(b,m)/a,l:h}}function W({h:t,s:e,l:n}){const r=(t+120)*Math.PI/180,o=e*n*(1-n),i=Math.cos(r),s=Math.sin(r);return{r:n+o*(-.14861*i+1.78277*s),g:n+o*(-.29227*i-.90649*s),b:n+o*(1.97294*i)}}function M(t,e,n,r){let o=e-t;return r||(o=(o+540)%360-180),y(t+o*n)}function _(t,e,n,r,o){const i=o.whitePoint??"d65";if(r.startsWith("hsl")){const a=A(t),d=A(e);return q({h:M(a.h,d.h,n,r.endsWith("-long")),s:a.s+(d.s-a.s)*n,l:a.l+(d.l-a.l)*n})}if(r==="lab"){const a=C(t,i),d=C(e,i);return I({l:a.l+(d.l-a.l)*n,a:a.a+(d.a-a.a)*n,b:a.b+(d.b-a.b)*n},i)}if(r.startsWith("hcl")){const a=R(C(t,i),t.r===t.g&&t.g===t.b),d=R(C(e,i),e.r===e.g&&e.g===e.b);return I(U({h:a.h===void 0?d.h??0:d.h===void 0?a.h:M(a.h,d.h,n,r.endsWith("-long")),c:a.c+(d.c-a.c)*n,l:a.l+(d.l-a.l)*n}),i)}const s=j(t),u=j(e),c=o.gamma??1,l=n**c,f=c<0&&n===0;if(!Number.isFinite(l)&&!f)throw new RangeError("Continuous cubehelix gamma produced a nonfinite interpolation.");const h=s.s+(u.s-s.s)*n,m=f&&s.l===u.l?s.l:s.l+(u.l-s.l)*l;if(f&&h===0){const a=Number.isNaN(m)?0:w(m);return{r:a,g:a,b:a}}const b=W({h:M(s.h,u.h,n,r.endsWith("-long")),s:h,l:m});if(f)return Object.fromEntries(Object.entries(b).map(([a,d])=>[a,Number.isNaN(d)?0:w(d)]));if(c<0&&!Object.values(b).every(Number.isFinite))throw new RangeError("Continuous cubehelix gamma produced a nonfinite interpolation.");return b}function P(t){if(!D.includes(t))throw new Error(`Unsupported continuous color interpolation "${t}".`);return t}function G(t,e={}){const n={};if(e.whitePoint!==void 0){if(!["lab","hcl","hcl-long"].includes(t))throw new Error("Scale whitePoint requires Lab or HCL interpolation.");if(!["d65","d50"].includes(e.whitePoint))throw new Error("Scale whitePoint must be d65 or d50.");n.whitePoint=e.whitePoint}if(e.gamma!==void 0){if(!["cubehelix","cubehelix-long"].includes(t))throw new Error("Scale gamma requires cubehelix interpolation.");if(!Number.isFinite(e.gamma))throw new RangeError("Scale gamma must be a finite number.");n.gamma=e.gamma}return n}function V(t){if(t==="auto")return t;if(Array.isArray(t)){if(k(t.length,"Sequential color range length"),t.length<2)throw new TypeError("Sequential color range requires at least two colors.");return t.forEach(E),p(t)}if(!$(t)||Object.keys(t).length!==1||!Object.hasOwn(t,"palette"))throw new TypeError("Sequential color range requires colors or a palette descriptor.");const e=B(t.palette);if(e.count!==void 0&&e.count<2)throw new RangeError("Sequential palette count must be an integer of at least 2.");return p({palette:e})}function v(t){const e=V(t);return e==="auto"?S("viridis"):Array.isArray(e)?p(e.map(n=>T(E(n)))):S(e.palette)}function F(t,e,n,r,o={}){const s=(r?w(e):e)*(t.length-1),u=Math.max(0,Math.min(t.length-2,Math.floor(s))),c=u+1,l=s-u;if(n==="rgb"){const f=O(t[u]),h=O(t[c]);return`#${f.map((m,b)=>Math.round(w(m+(h[b]-m)*l,0,255)).toString(16).padStart(2,"0")).join("")}`}return T(_(t[u],t[c],l,n,o))}function tt(t,e,n="rgb"){const r=P(n);if(!Array.isArray(t)||t.length<2)throw new TypeError("Color interpolation requires at least two stops.");const o=t.map(E);return F(o,e,r,!0)}function L(t,e,n="auto"){if(!(t===void 0||t==="auto")){if(e!=="sequential")throw new Error(`Scale type "${e}" 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 J(t,e,n,r={}){const{interpolation:o="rgb",clamp:i=!1}=r;if(G(o,r),["log","pow","sqrt","symlog"].includes(r.type)){L(r.midpoint,r.type,e);const b=z(t,e,[0,1],{type:r.type,clamp:i,...r.type==="log"?{base:r.base}:{},...r.type==="pow"?{exponent:r.exponent}:{},...r.type==="symlog"?{constant:r.constant}:{},...Object.hasOwn(r,"unknown")?{unknown:NaN}:{}});return J(b,[0,1],n,{...r,type:"sequential"})}const s=Object.hasOwn(r,"unknown");if(!Array.isArray(e)||e.length!==2||!e.every(Number.isFinite))throw new TypeError("Sequential color domain must contain two finite numbers.");if(!Array.isArray(t)||!s&&!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 u=L(r.midpoint,"sequential",e),[c,l]=e,f=c===l,h=P(o);if(!Array.isArray(n)||n.length<2)throw new TypeError("Color interpolation requires at least two stops.");const m=n.map(E);return p(t.map(b=>{if(!Number.isFinite(b)){if(s)return r.unknown;throw new TypeError("Sequential color values must be finite numbers.")}const a=u===void 0?f?.5:x(b,c,l):(l>c?b<=u:b>=u)?x(b,c,u)/2:.5+x(b,u,l)/2;return F(m,a,h,i,r)}))}export{D as CONTINUOUS_COLOR_INTERPOLATIONS,tt as interpolateColorStops,J as mapSequentialColors,G as normalizeColorInterpolationOptions,v as resolveSequentialColorStops,P as validateContinuousColorInterpolation,V as validateSequentialColorRange,L as validateSequentialMidpoint};