ggaction 0.0.20 → 0.0.22

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 (254) hide show
  1. package/CHANGELOG.md +77 -0
  2. package/README.md +3 -2
  3. package/knowledge/action-cards.json +1 -1
  4. package/knowledge/intent-taxonomy.json +1 -1
  5. package/knowledge/mcp-resources.json +1 -1
  6. package/package.json +6 -2
  7. package/src/BasicChartProgram.js +1 -1
  8. package/src/accessibility.js +1 -0
  9. package/src/actions/boxPlots/components.js +1 -96
  10. package/src/actions/boxPlots/create.js +6 -1
  11. package/src/actions/boxPlots/edit.js +8 -0
  12. package/src/actions/boxPlots/materialize.js +3 -0
  13. package/src/actions/boxPlots/options.js +1 -1
  14. package/src/actions/canvas/actions.js +2 -1
  15. package/src/actions/canvas/index.js +3 -0
  16. package/src/actions/canvas/plotBorder.js +2 -1
  17. package/src/actions/canvas/plotOrder.js +14 -0
  18. package/src/actions/charts/area.js +1 -1
  19. package/src/actions/charts/bar.js +4 -4
  20. package/src/actions/charts/density.js +1 -1
  21. package/src/actions/charts/ecdf.js +1 -1
  22. package/src/actions/charts/endpoints.js +54 -5
  23. package/src/actions/charts/heatmap.js +1 -1
  24. package/src/actions/charts/histogram.js +1 -1
  25. package/src/actions/charts/horizon.js +1 -1
  26. package/src/actions/charts/index.js +2 -1
  27. package/src/actions/charts/interval-regression.js +1 -1
  28. package/src/actions/charts/line.js +1 -1
  29. package/src/actions/charts/radar.js +63 -3
  30. package/src/actions/charts/raincloud.js +37 -6
  31. package/src/actions/charts/rug-strip.js +2 -2
  32. package/src/actions/charts/scatter.js +3 -3
  33. package/src/actions/charts/text.js +1 -1
  34. package/src/actions/composition/actions.js +10 -3
  35. package/src/actions/coordinates/actions.js +2 -0
  36. package/src/actions/data/basic.js +6 -0
  37. package/src/actions/data/derived.js +6 -2
  38. package/src/actions/data/edit.js +21 -35
  39. package/src/actions/data/filter.js +1 -376
  40. package/src/actions/data/flatten.js +19 -0
  41. package/src/actions/data/index.js +6 -0
  42. package/src/actions/data/lookup.js +50 -0
  43. package/src/actions/data/raincloudFilter.js +56 -0
  44. package/src/actions/data/shared.js +10 -0
  45. package/src/actions/distributions/revision.js +3 -1
  46. package/src/actions/encodings/angle.js +2 -1
  47. package/src/actions/encodings/appearance.js +38 -13
  48. package/src/actions/encodings/channels.js +14 -3
  49. package/src/actions/encodings/color/continuous.js +26 -10
  50. package/src/actions/encodings/color/index.js +50 -20
  51. package/src/actions/encodings/color/policy.js +57 -4
  52. package/src/actions/encodings/parallel.js +4 -0
  53. package/src/actions/encodings/position/policies/bar.js +10 -6
  54. package/src/actions/encodings/position/policies/line.js +1 -152
  55. package/src/actions/encodings/position/resolve.js +4 -1
  56. package/src/actions/encodings/ranged.js +46 -0
  57. package/src/actions/encodings/remove.js +1 -1
  58. package/src/actions/encodings/ruleAppearance.js +7 -6
  59. package/src/actions/encodings/shared.js +14 -2
  60. package/src/actions/encodings/stroke.js +20 -14
  61. package/src/actions/encodings/strokeDash.js +9 -11
  62. package/src/actions/encodings/text.js +30 -2
  63. package/src/actions/errorBars/edit.js +24 -4
  64. package/src/actions/facets/actions.js +1 -793
  65. package/src/actions/facets/derive.js +34 -5
  66. package/src/actions/facets/replay.js +1 -38
  67. package/src/actions/gradientPlots/components.js +21 -9
  68. package/src/actions/gradientPlots/create.js +4 -2
  69. package/src/actions/gradientPlots/edit.js +18 -1
  70. package/src/actions/gradientPlots/materialize.js +35 -36
  71. package/src/actions/gradientPlots/options.js +1 -1
  72. package/src/actions/gradientPlots/paint.js +13 -7
  73. package/src/actions/guides/applicability.js +2 -0
  74. package/src/actions/guides/axes/axes.js +39 -0
  75. package/src/actions/guides/axes/axis.js +9 -5
  76. package/src/actions/guides/axes/edit.js +11 -8
  77. package/src/actions/guides/axes/labels.js +24 -8
  78. package/src/actions/guides/axes/parallel/policy.js +3 -5
  79. package/src/actions/guides/axes/parallel/resolve.js +4 -3
  80. package/src/actions/guides/axes/policy.js +22 -0
  81. package/src/actions/guides/axes/tickGroups.js +4 -2
  82. package/src/actions/guides/axes/ticks.js +22 -4
  83. package/src/actions/guides/axes/titles.js +19 -6
  84. package/src/actions/guides/facadeAxes.js +3 -0
  85. package/src/actions/guides/grids/grid.js +3 -1
  86. package/src/actions/guides/grids/resolve.js +7 -11
  87. package/src/actions/guides/guides.js +21 -1
  88. package/src/actions/guides/legends/categorical/actions.js +1 -515
  89. package/src/actions/guides/legends/categorical/layout.js +5 -2
  90. package/src/actions/guides/legends/categorical/options.js +4 -0
  91. package/src/actions/guides/legends/categorical/resolve.js +8 -3
  92. package/src/actions/guides/legends/categorical/symbols.js +3 -3
  93. package/src/actions/guides/legends/colorSize.js +2 -0
  94. package/src/actions/guides/legends/continuous/common.js +1 -1
  95. package/src/actions/guides/legends/continuous/gradient.js +1 -360
  96. package/src/actions/guides/legends/continuous/interval.js +1 -1
  97. package/src/actions/guides/legends/continuous/opacity.js +15 -1
  98. package/src/actions/guides/legends/edit.js +1 -1
  99. package/src/actions/guides/legends/focused.js +1 -1
  100. package/src/actions/guides/legends/lane.js +1 -1
  101. package/src/actions/guides/legends/sampling.js +1 -140
  102. package/src/actions/guides/legends/strokeWidth.js +3 -2
  103. package/src/actions/guides/legends/transition.js +19 -2
  104. package/src/actions/guides/polar/axes/facade.js +5 -4
  105. package/src/actions/guides/polar/axes/labels.js +5 -4
  106. package/src/actions/guides/polar/axes/titles.js +5 -4
  107. package/src/actions/guides/polar/resolve.js +2 -1
  108. package/src/actions/guides/tickValues.js +7 -7
  109. package/src/actions/marks/arc/actions.js +5 -7
  110. package/src/actions/marks/area/actions.js +9 -3
  111. package/src/actions/marks/bar/create.js +4 -2
  112. package/src/actions/marks/bar/edit.js +9 -6
  113. package/src/actions/marks/bar/materialize.js +5 -3
  114. package/src/actions/marks/dependentReferences.js +87 -0
  115. package/src/actions/marks/index.js +2 -0
  116. package/src/actions/marks/lifecycle.js +2 -1
  117. package/src/actions/marks/line/actions.js +24 -6
  118. package/src/actions/marks/line/materialize.js +7 -3
  119. package/src/actions/marks/point/create.js +5 -4
  120. package/src/actions/marks/point/edit.js +6 -3
  121. package/src/actions/marks/point/jitter.js +6 -6
  122. package/src/actions/marks/point/materialize.js +36 -39
  123. package/src/actions/marks/rect/actions.js +16 -4
  124. package/src/actions/marks/references.js +183 -35
  125. package/src/actions/marks/rule/actions.js +20 -9
  126. package/src/actions/marks/shared.js +2 -1
  127. package/src/actions/marks/text/actions.js +10 -3
  128. package/src/actions/marks/tick/actions.js +11 -2
  129. package/src/actions/primitives/editGraphics.js +28 -3
  130. package/src/actions/primitives/index.js +9 -0
  131. package/src/actions/primitives/semanticAction.js +13 -7
  132. package/src/actions/primitives/semanticValidation/layer.js +20 -0
  133. package/src/actions/primitives/semanticValidation/scale.js +8 -1
  134. package/src/actions/scales/channels.js +1 -1
  135. package/src/actions/scales/consumers/common.js +19 -1
  136. package/src/actions/scales/consumers/families.js +2 -2
  137. package/src/actions/scales/consumers/seriesLayout.js +4 -3
  138. package/src/actions/scales/edit.js +11 -0
  139. package/src/actions/scales/editPolicy.js +5 -3
  140. package/src/actions/scales/preview.js +2 -1
  141. package/src/actions/scales/quantitativeColor.js +2 -4
  142. package/src/actions/selection/actions.js +10 -1
  143. package/src/actions/theme/reconcile.js +37 -9
  144. package/src/core/compositionState.js +21 -4
  145. package/src/core/datasetReferences.js +17 -0
  146. package/src/core/immutable.js +1 -0
  147. package/src/core/resourceReferences.js +5 -3
  148. package/src/core/validation.js +4 -0
  149. package/src/core/vocabulary.js +24 -2
  150. package/src/grammar/aggregate.js +1 -0
  151. package/src/grammar/arcs.js +1 -1
  152. package/src/grammar/areaSeries.js +1 -1
  153. package/src/grammar/axisTextPlacement.js +1 -1
  154. package/src/grammar/bars/policy.js +2 -2
  155. package/src/grammar/datasetDependencies.js +97 -0
  156. package/src/grammar/datasetSchema.js +31 -1
  157. package/src/grammar/facetHeaders.js +1 -0
  158. package/src/grammar/facets/dependencies.js +6 -2
  159. package/src/grammar/facets/legendIntent.js +6 -2
  160. package/src/grammar/facets/scales.js +27 -7
  161. package/src/grammar/flatten.js +85 -0
  162. package/src/grammar/histogram.js +13 -1
  163. package/src/grammar/horizon.js +1 -494
  164. package/src/grammar/interval.js +4 -3
  165. package/src/grammar/jitter.js +2 -2
  166. package/src/grammar/legendSpacing.js +45 -0
  167. package/src/grammar/lineMissing.js +90 -0
  168. package/src/grammar/lineSeries.js +1 -376
  169. package/src/grammar/lookup.js +97 -0
  170. package/src/grammar/markFilter.js +4 -2
  171. package/src/grammar/markLabels.js +8 -3
  172. package/src/grammar/numeric.js +1 -1
  173. package/src/grammar/pathCommands.js +1 -1
  174. package/src/grammar/pathSeries.js +1 -109
  175. package/src/grammar/pointPolygon.js +81 -0
  176. package/src/grammar/pointShapes.js +15 -15
  177. package/src/grammar/rects.js +1 -1
  178. package/src/grammar/regression/derive.js +1 -195
  179. package/src/grammar/scales/appearance.js +1 -1
  180. package/src/grammar/scales/color.js +1 -1
  181. package/src/grammar/scales/colorConsumers.js +1 -63
  182. package/src/grammar/scales/continuous.js +58 -1
  183. package/src/grammar/scales/definition.js +1 -1
  184. package/src/grammar/scales/ordinal.js +5 -2
  185. package/src/grammar/scales/policies.js +3 -3
  186. package/src/grammar/schemas/graphicBounds.js +40 -12
  187. package/src/grammar/schemas/graphicClip.js +23 -0
  188. package/src/grammar/schemas/graphicTree.js +16 -0
  189. package/src/grammar/statisticalReference.js +22 -0
  190. package/src/grammar/text.js +65 -1
  191. package/src/grammar/ticks.js +92 -1
  192. package/src/grammar/transformTopology.js +3 -1
  193. package/src/grammar/transforms.js +24 -0
  194. package/src/inspection.js +1 -495
  195. package/src/inspectionDescriptors.js +1 -1
  196. package/src/layout/canvas.js +1 -1
  197. package/src/layout/facetContentFlow.js +101 -0
  198. package/src/layout/facetHeaderTitles.js +1 -0
  199. package/src/layout/facetTopLane.js +29 -0
  200. package/src/layout/facets.js +1 -1
  201. package/src/layout/legendGroup.js +1 -1
  202. package/src/layout/legendItems.js +26 -10
  203. package/src/layout/legendSpacing.js +66 -0
  204. package/src/layout/plotDrawOrder.js +17 -0
  205. package/src/materialization/bars/histogram.js +8 -2
  206. package/src/materialization/bars/resolve.js +1 -1
  207. package/src/materialization/composition.js +1 -0
  208. package/src/materialization/compositionSnapshot.js +22 -2
  209. package/src/materialization/dataProvenance.js +1 -1
  210. package/src/materialization/facetGuides/layout.js +1 -1
  211. package/src/materialization/facetGuides/placement.js +23 -11
  212. package/src/materialization/facetGuides/preparation.js +43 -24
  213. package/src/materialization/facetHeaders.js +1 -1
  214. package/src/materialization/facetTopLane.js +25 -0
  215. package/src/materialization/facets.js +1 -1
  216. package/src/materialization/graphicHierarchy.js +5 -0
  217. package/src/materialization/graphicTranslation.js +2 -0
  218. package/src/materialization/guides/layout.js +1 -1
  219. package/src/materialization/guides/resources.js +1 -1
  220. package/src/materialization/legends.js +1 -1
  221. package/src/materialization/markClip.js +26 -0
  222. package/src/materialization/marks/capabilities.js +3 -2
  223. package/src/materialization/marks/grouping.js +7 -5
  224. package/src/materialization/marks/index.js +4 -2
  225. package/src/materialization/marks/policies.js +4 -0
  226. package/src/materialization/plotDrawOrder.js +44 -0
  227. package/src/materialization/rect.js +11 -3
  228. package/src/materialization/scaleGuideDependencies.js +13 -5
  229. package/src/materialization/selection/items/common.js +1 -1
  230. package/src/materialization/selection/items/path.js +1 -0
  231. package/src/materialization/selection/policies/index.js +2 -1
  232. package/src/materialization/text.js +10 -5
  233. package/src/mcp/cli.js +0 -0
  234. package/src/persistence/validation.js +108 -18
  235. package/src/persistence.js +4 -2
  236. package/src/renderers/canvas/index.js +16 -0
  237. package/src/renderers/canvas/isolated.js +11 -1
  238. package/src/renderers/canvas/native.js +7 -0
  239. package/src/renderers/canvas/scene.js +66 -0
  240. package/src/renderers/canvas/text.js +3 -2
  241. package/src/renderers/svg.js +1 -617
  242. package/src/renderers/svgSerialization.js +643 -0
  243. package/src/renderers/transitionScene.js +67 -0
  244. package/src/scene.js +89 -0
  245. package/src/selectors/axes.js +1 -1
  246. package/src/selectors/datasets.js +1 -0
  247. package/src/selectors/grids.js +9 -0
  248. package/src/selectors/markClip.js +28 -0
  249. package/src/selectors/raincloud.js +7 -0
  250. package/src/version.js +1 -1
  251. package/types/basic.d.ts +7 -0
  252. package/types/index.d.ts +8 -0
  253. package/types/program.d.ts +270 -60
  254. package/types/scene.d.ts +35 -0
@@ -1,17 +1,19 @@
1
1
  import { isPlainObject } from "../../core/immutable.js";
2
+ import {validateLegendSpacing} from "../legendSpacing.js";
2
3
  import { validateOptionObject, validateNonEmptyString } from "../../core/validation.js";
3
4
  import { validateUserId } from "../../core/identifiers.js";
4
5
  import { LEGEND_CONFIG_KINDS, LEGEND_POSITIONS } from "../../core/vocabulary.js";
5
6
  import { describeLegendBlock } from "../legendBlocks.js";
6
7
  import { validateLegendGroupState } from "../legendGroups.js";
7
8
  import { resolveSharedFacetLegends, sameFacetGuideValue as same } from "./guides.js";
9
+ import { normalizeDisplayLabelMap } from "../displayLabels.js";
8
10
 
9
11
  const CONFIG_KEYS = Object.freeze([
10
12
  "kind", "target", "channels", "scales", "scale", "field", "fieldType", "domain", "title", "titleVisible",
11
13
  "inferredTitle", "inferredSymbol", "inferredStrokeWidth", "inferredOffset", "position", "align", "offset", "direction", "columns",
12
- "titlePosition", "symbol", "labels", "titleStyle", "itemGap", "layout", "overflow", "border", "gradient",
14
+ "titlePosition", "symbol", "labels", "titleStyle", "itemGap", "rowPadding", "titlePadding", "layout", "overflow", "border", "gradient",
13
15
  "count", "sampling", "representation", "gradientDirection", "inheritAppearance", "inheritPosition", "blockOverrides",
14
- "combine", "sizeAreas", "clipHeight"
16
+ "combine", "sizeAreas", "clipHeight", "defaultLabelMap"
15
17
  ]);
16
18
 
17
19
  export function isAuthoredFacetLegend(value) {
@@ -31,6 +33,8 @@ export function validateAuthoredFacetLegend(program, intent) {
31
33
  validateOptionObject(block, ["config", "guide"], "Stored parent legend block");
32
34
  validateOptionObject(block.config, kind === "colorSize" ? [...CONFIG_KEYS, "colorScale", "sizeScale"] : CONFIG_KEYS, "Stored parent legend config");
33
35
  const config = block.config;
36
+ validateLegendSpacing(kind,config);
37
+ if (config.defaultLabelMap !== undefined) normalizeDisplayLabelMap(config.defaultLabelMap, "Stored inferred legend labels");
34
38
  validateUserId(config.target, "Parent legend target");
35
39
  if (!LEGEND_POSITIONS.includes(config.position)) throw new Error("Stored parent legend requires a native position.");
36
40
  for (const flag of ["inferredTitle", "inferredSymbol", "inferredStrokeWidth", "inferredOffset", "titleVisible", "inheritAppearance", "inheritPosition"]) {
@@ -89,17 +89,37 @@ export function normalizeFacetScalePolicies(semanticSpec, requested = {}) {
89
89
  );
90
90
  }
91
91
  }
92
+ const inferred = { ...requested };
93
+ let changed = true;
94
+ while (changed) {
95
+ changed = false;
96
+ for (const [id, channelSet] of used) {
97
+ const attached = [...channelSet];
98
+ const policies = [...new Set(attached
99
+ .filter(channel => inferred[channel] !== undefined)
100
+ .map(channel => inferred[channel]))];
101
+ if (policies.length > 1) {
102
+ throw new Error(
103
+ `Facet scale "${id}" has conflicting channel policies for ${attached.join(", ")}.`
104
+ );
105
+ }
106
+ if (policies.length === 1) for (const channel of attached) {
107
+ if (inferred[channel] === undefined) {
108
+ inferred[channel] = policies[0];
109
+ changed = true;
110
+ }
111
+ }
112
+ }
113
+ }
114
+ Object.assign(channels, inferred);
92
115
  const scalePolicies = {};
93
116
  for (const [id, channelSet] of used) {
94
117
  const attached = [...channelSet];
95
- const policies = [...new Set(attached.map(channel => channels[channel]))];
96
- if (policies.length !== 1) {
97
- throw new Error(
98
- `Facet scale "${id}" has conflicting channel policies for ${attached.join(", ")}.`
99
- );
100
- }
118
+ // One semantic scale cannot have different resolutions through its aliases.
119
+ // An explicitly chosen channel policy also owns omitted aliases; only
120
+ // contradictory explicit requests are ambiguous.
101
121
  scalePolicies[id] = {
102
- policy: policies[0],
122
+ policy: channels[attached[0]],
103
123
  channels: attached
104
124
  };
105
125
  }
@@ -0,0 +1,85 @@
1
+ import { rejectUnknownProperties, requireStringValue } from "../core/validation.js";
2
+ import { cloneAndFreeze, isPlainObject } from "../core/immutable.js";
3
+
4
+ const KEYS = Object.freeze(["type", "fields", "as"]);
5
+ const MAX_FIELDS = 64;
6
+ const MAX_OUTPUT_ROWS = 10_000;
7
+
8
+ export function normalizeFlattenTransform({ fields, as } = {}) {
9
+ const aliases = as === undefined ? fields : as;
10
+ const transform = {
11
+ type: "flatten",
12
+ fields: Array.isArray(fields) ? [...fields] : fields,
13
+ as: Array.isArray(aliases) ? [...aliases] : aliases
14
+ };
15
+ validateFlattenTransform(transform);
16
+ return cloneAndFreeze(transform);
17
+ }
18
+
19
+ export function validateFlattenTransform(transform) {
20
+ if (!isPlainObject(transform)) {
21
+ throw new TypeError("Flatten transform must be a plain object.");
22
+ }
23
+ rejectUnknownProperties(transform, KEYS, "flatten transform");
24
+ if (transform.type !== "flatten") {
25
+ throw new Error(`Unsupported flatten transform "${transform.type}".`);
26
+ }
27
+ if (!Array.isArray(transform.fields) || transform.fields.length === 0) {
28
+ throw new TypeError("Flatten fields must be a non-empty array.");
29
+ }
30
+ if (transform.fields.length > MAX_FIELDS) {
31
+ throw new RangeError(`Flatten fields cannot contain more than ${MAX_FIELDS} entries.`);
32
+ }
33
+ if (!Array.isArray(transform.as) || transform.as.length !== transform.fields.length) {
34
+ throw new TypeError("Flatten as must be an array with one alias per field.");
35
+ }
36
+ for (const key of ["fields", "as"]) {
37
+ for (const [index, field] of transform[key].entries()) {
38
+ requireStringValue(field, `Flatten ${key}[${index}]`);
39
+ }
40
+ if (new Set(transform[key]).size !== transform[key].length) {
41
+ throw new Error(`Flatten ${key} must be unique.`);
42
+ }
43
+ }
44
+ return transform;
45
+ }
46
+
47
+ export function deriveFlattenRows(rows, transform) {
48
+ validateFlattenTransform(transform);
49
+ const selected = new Set(transform.fields);
50
+ const existing = new Set(rows.flatMap(row => Object.keys(row)));
51
+ for (const name of transform.as) {
52
+ if (existing.has(name) && !selected.has(name)) {
53
+ throw new Error(`Flatten output field "${name}" already exists outside the selected fields.`);
54
+ }
55
+ }
56
+ let total = 0;
57
+ const lengths = rows.map((row, rowIndex) => {
58
+ let length = 0;
59
+ for (const field of transform.fields) {
60
+ const value = row[field];
61
+ if (value === undefined || value === null) continue;
62
+ if (!Array.isArray(value)) {
63
+ throw new TypeError(`Flatten field "${field}" must be an array at row ${rowIndex}.`);
64
+ }
65
+ length = Math.max(length, value.length);
66
+ }
67
+ total += length;
68
+ if (total > MAX_OUTPUT_ROWS) {
69
+ throw new RangeError(`Flatten output cannot exceed ${MAX_OUTPUT_ROWS} rows.`);
70
+ }
71
+ return length;
72
+ });
73
+ const output = [];
74
+ rows.forEach((row, rowIndex) => {
75
+ for (let index = 0; index < lengths[rowIndex]; index += 1) {
76
+ const next = { ...row };
77
+ transform.fields.forEach((field, fieldIndex) => {
78
+ const values = row[field];
79
+ next[transform.as[fieldIndex]] = values?.[index] ?? null;
80
+ });
81
+ output.push(next);
82
+ }
83
+ });
84
+ return output;
85
+ }
@@ -1,5 +1,6 @@
1
1
  import { cloneAndFreeze, isPlainObject } from "../core/immutable.js";
2
2
  import { MAX_GENERATED_ITEMS } from "../core/validation.js";
3
+ import { niceLinearCountDomain, normalizeScaleNice } from "./scales/continuous.js";
3
4
  import {
4
5
  alignNumericStep,
5
6
  cleanNumericValue,
@@ -299,7 +300,18 @@ function niceBins(extent, maxBins) {
299
300
  return equalBins(extent, maxBins);
300
301
  }
301
302
 
302
- export function resolveHistogramBins({
303
+ export function resolveHistogramBins(options) {
304
+ if (isPlainObject(options.nice)) {
305
+ const { count } = normalizeScaleNice("linear", options.nice);
306
+ const bins = resolveBooleanHistogramBins({ ...options, nice: true });
307
+ return options.domain === undefined || options.domain === "auto"
308
+ ? cloneAndFreeze({ ...bins, domain: niceLinearCountDomain(bins.domain, count) })
309
+ : bins;
310
+ }
311
+ return resolveBooleanHistogramBins(options);
312
+ }
313
+
314
+ function resolveBooleanHistogramBins({
303
315
  values,
304
316
  bin,
305
317
  maxBins,