ggaction 0.0.23 → 0.0.24
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.
- package/CHANGELOG.md +18 -0
- package/README.md +2 -2
- package/knowledge/action-cards.json +1 -1
- package/knowledge/intent-taxonomy.json +1 -1
- package/knowledge/mcp-resources.json +1 -1
- package/package.json +1 -1
- package/src/actions/charts/heatmap.js +1 -1
- package/src/actions/data/basicBin2d.js +1 -1
- package/src/actions/data/bin2d.js +2 -2
- package/src/actions/encodings/ranged.js +2 -2
- package/src/actions/facets/actions.js +1 -1
- package/src/actions/guides/axes/components.js +5 -0
- package/src/actions/guides/axes/edit.js +1 -188
- package/src/actions/guides/axes/labels.js +1 -537
- package/src/actions/guides/axes/tickGroups.js +16 -1
- package/src/actions/guides/axes/ticks.js +33 -24
- package/src/actions/guides/axes/titles.js +1 -389
- package/src/actions/titles/resolve.js +11 -1
- package/src/core/compositionState.js +4 -1
- package/src/core/facetGap.js +44 -0
- package/src/grammar/axisTextPlacement.js +1 -1
- package/src/grammar/bin2d.js +34 -4
- package/src/inspectionDescriptors.js +1 -1
- package/src/layout/composition.js +2 -6
- package/src/layout/facetContentFlow.js +15 -7
- package/src/layout/facets.js +1 -1
- package/src/layout/title.js +1 -1
- package/src/materialization/guides/layout.js +1 -1
- package/src/materialization/guides/resources.js +1 -1
- package/src/materialization/planner.js +19 -4
- package/src/persistence/validation.js +19 -1
- package/src/version.js +1 -1
- package/types/basic.d.ts +2 -0
- package/types/index.d.ts +3 -0
- package/types/program.d.ts +19 -7
package/src/grammar/bin2d.js
CHANGED
|
@@ -11,7 +11,7 @@ const MAX_CELLS = 1_000_000;
|
|
|
11
11
|
|
|
12
12
|
const TRANSFORM_KEYS = Object.freeze([
|
|
13
13
|
"type", "x", "y", "bins", "extent", "includeEmpty", "members", "as",
|
|
14
|
-
"resolved"
|
|
14
|
+
"resolved", "assignment"
|
|
15
15
|
]);
|
|
16
16
|
const AXIS_KEYS = Object.freeze(["x", "y"]);
|
|
17
17
|
const FIELD_KEYS = Object.freeze(["x0", "x1", "y0", "y1", "count", "members"]);
|
|
@@ -180,6 +180,11 @@ export function validateBin2DTransform(transform) {
|
|
|
180
180
|
}
|
|
181
181
|
requireField(transform.x, "2D bin x field");
|
|
182
182
|
requireField(transform.y, "2D bin y field");
|
|
183
|
+
if (transform.assignment !== undefined && transform.assignment !== "step") {
|
|
184
|
+
throw new TypeError(
|
|
185
|
+
'Stored 2D bin assignment must be "step" or omitted.'
|
|
186
|
+
);
|
|
187
|
+
}
|
|
183
188
|
validateBins(transform.bins);
|
|
184
189
|
validateRequestedExtent(transform.extent);
|
|
185
190
|
if (typeof transform.includeEmpty !== "boolean") {
|
|
@@ -201,10 +206,16 @@ export function normalizeBin2DTransform({
|
|
|
201
206
|
y,
|
|
202
207
|
bins,
|
|
203
208
|
extent,
|
|
209
|
+
assignment = "edges",
|
|
204
210
|
includeEmpty = false,
|
|
205
211
|
members = false,
|
|
206
212
|
as
|
|
207
213
|
} = {}) {
|
|
214
|
+
if (assignment !== "edges" && assignment !== "step") {
|
|
215
|
+
throw new TypeError(
|
|
216
|
+
'2D bin assignment must be "edges" or "step".'
|
|
217
|
+
);
|
|
218
|
+
}
|
|
208
219
|
const normalizedBins = normalizeBins(bins);
|
|
209
220
|
const transform = {
|
|
210
221
|
type: "bin2d",
|
|
@@ -214,7 +225,8 @@ export function normalizeBin2DTransform({
|
|
|
214
225
|
extent: normalizeRequestedExtent(extent),
|
|
215
226
|
includeEmpty,
|
|
216
227
|
members,
|
|
217
|
-
as: normalizeOutputFields(id, as, members)
|
|
228
|
+
as: normalizeOutputFields(id, as, members),
|
|
229
|
+
...(assignment === "step" ? { assignment } : {})
|
|
218
230
|
};
|
|
219
231
|
validateBin2DTransform(transform);
|
|
220
232
|
return cloneAndFreeze(transform);
|
|
@@ -266,6 +278,20 @@ function findBinIndex(value, edges) {
|
|
|
266
278
|
return low;
|
|
267
279
|
}
|
|
268
280
|
|
|
281
|
+
function findStepBinIndex(value, extent, count) {
|
|
282
|
+
if (count === 1 || value === extent[1]) return count - 1;
|
|
283
|
+
const [minimum, maximum] = extent;
|
|
284
|
+
const span = maximum - minimum;
|
|
285
|
+
const step = Number.isFinite(span)
|
|
286
|
+
? span / count
|
|
287
|
+
: maximum / count - minimum / count;
|
|
288
|
+
const distance = value - minimum;
|
|
289
|
+
const position = Number.isFinite(distance)
|
|
290
|
+
? distance / step
|
|
291
|
+
: value / step - minimum / step;
|
|
292
|
+
return Math.max(0, Math.min(count - 1, Math.floor(1e-14 + position)));
|
|
293
|
+
}
|
|
294
|
+
|
|
269
295
|
export function deriveBin2DRows(rows, transform) {
|
|
270
296
|
if (!Array.isArray(rows)) {
|
|
271
297
|
throw new TypeError("2D bin source rows must be an array.");
|
|
@@ -304,8 +330,12 @@ export function deriveBin2DRows(rows, transform) {
|
|
|
304
330
|
() => []
|
|
305
331
|
);
|
|
306
332
|
for (const item of eligible) {
|
|
307
|
-
const xIndex =
|
|
308
|
-
|
|
333
|
+
const xIndex = transform.assignment === "step"
|
|
334
|
+
? findStepBinIndex(item.row[transform.x], extent.x, transform.bins.x)
|
|
335
|
+
: findBinIndex(item.row[transform.x], edges.x);
|
|
336
|
+
const yIndex = transform.assignment === "step"
|
|
337
|
+
? findStepBinIndex(item.row[transform.y], extent.y, transform.bins.y)
|
|
338
|
+
: findBinIndex(item.row[transform.y], edges.y);
|
|
309
339
|
buckets[yIndex * transform.bins.x + xIndex].push(item.index);
|
|
310
340
|
}
|
|
311
341
|
const values = [];
|