ggaction 0.0.18 → 0.0.19
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 +50 -0
- package/README.md +6 -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/canvas/fitting.js +6 -2
- package/src/actions/charts/heatmap.js +4 -3
- package/src/actions/data/derived.js +11 -1
- package/src/actions/data/edit.js +2 -0
- package/src/actions/data/index.js +4 -0
- package/src/actions/data/regression.js +24 -16
- package/src/actions/data/regressionStatistics.js +73 -0
- package/src/actions/data/shared.js +5 -2
- package/src/actions/distributions/revision.js +24 -18
- package/src/actions/encodings/remove.js +11 -6
- package/src/actions/encodings/shared.js +26 -24
- package/src/actions/facets/actions.js +18 -7
- package/src/actions/facets/guides.js +2 -1
- package/src/actions/guides/axes/axes.js +30 -11
- package/src/actions/guides/axes/axis.js +58 -8
- package/src/actions/guides/axes/components.js +13 -13
- package/src/actions/guides/axes/edit.js +36 -24
- package/src/actions/guides/axes/labels.js +37 -27
- package/src/actions/guides/axes/lines.js +22 -20
- package/src/actions/guides/axes/remove.js +10 -6
- package/src/actions/guides/axes/tickGroups.js +8 -7
- package/src/actions/guides/axes/ticks.js +31 -22
- package/src/actions/guides/axes/titles.js +53 -60
- package/src/actions/guides/facadeAxes.js +33 -24
- package/src/actions/guides/facadeLegend.js +3 -3
- package/src/actions/guides/grids/grid.js +1 -1
- package/src/actions/guides/grids/resolve.js +48 -51
- package/src/actions/guides/legends/blocks.js +43 -19
- package/src/actions/guides/legends/categorical/actions.js +30 -7
- package/src/actions/guides/legends/categorical/components.js +3 -10
- package/src/actions/guides/legends/categorical/index.js +2 -0
- package/src/actions/guides/legends/categorical/layout.js +9 -13
- package/src/actions/guides/legends/categorical/options.js +8 -2
- package/src/actions/guides/legends/categorical/recipes.js +7 -3
- package/src/actions/guides/legends/categorical/resolve.js +9 -2
- package/src/actions/guides/legends/categorical/symbols.js +22 -8
- package/src/actions/guides/legends/colorSize.js +110 -0
- package/src/actions/guides/legends/combine.js +37 -0
- package/src/actions/guides/legends/continuous/colorSymbols.js +1 -1
- package/src/actions/guides/legends/continuous/common.js +1 -1
- package/src/actions/guides/legends/continuous/gradient.js +27 -13
- package/src/actions/guides/legends/continuous/opacity.js +16 -11
- package/src/actions/guides/legends/creation.js +2 -0
- package/src/actions/guides/legends/edit.js +1 -1
- package/src/actions/guides/legends/focused.js +6 -5
- package/src/actions/guides/legends/lane.js +1 -1
- package/src/actions/guides/legends/lifecycle.js +2 -1
- package/src/actions/guides/legends/remove.js +6 -3
- package/src/actions/guides/legends/size.js +16 -6
- package/src/actions/guides/legends/strokeWidth.js +2 -0
- package/src/actions/guides/legends/target.js +2 -79
- package/src/actions/guides/legends/transition.js +24 -5
- package/src/actions/guides/tickValues.js +8 -5
- package/src/actions/marks/bar/edit.js +23 -12
- package/src/actions/marks/bar/materialize.js +6 -1
- package/src/actions/marks/point/materialize.js +5 -1
- package/src/actions/marks/remove.js +10 -10
- package/src/actions/primitives/createGraphics.js +3 -2
- package/src/actions/primitives/editGraphics.js +15 -11
- package/src/actions/primitives/graphicProperties.js +1 -6
- package/src/actions/primitives/semanticAction.js +27 -1
- package/src/actions/primitives/semanticValidation/guide.js +11 -1
- package/src/actions/primitives/semanticValidation/layer.js +4 -0
- package/src/actions/regression/edit.js +15 -3
- package/src/actions/scales/channels.js +2 -2
- package/src/actions/scales/create.js +3 -3
- package/src/actions/scales/definitions.js +1 -1
- package/src/actions/scales/edit.js +1 -1
- package/src/actions/scales/editPolicy.js +3 -0
- package/src/actions/scales/patch.js +1 -1
- package/src/actions/scales/quantitativeColor.js +8 -3
- package/src/actions/theme/reconcile.js +50 -23
- package/src/core/compositionState.js +2 -2
- package/src/core/graphicProperties.js +1 -0
- package/src/core/programState.js +4 -0
- package/src/core/resourceReferences.js +2 -2
- package/src/core/validation.js +9 -0
- package/src/core/vocabulary.js +3 -0
- package/src/grammar/axisTextPlacement.js +1 -0
- package/src/grammar/colorSizeLegend.js +39 -0
- package/src/grammar/computed.js +23 -1
- package/src/grammar/datasetSchema.js +10 -2
- package/src/grammar/displayLabels.js +8 -0
- package/src/grammar/facets/guides.js +54 -31
- package/src/grammar/facets/legendIntent.js +65 -0
- package/src/grammar/guideDash.js +1 -0
- package/src/grammar/legendBlocks.js +1 -0
- package/src/grammar/legendBorder.js +9 -0
- package/src/grammar/legendClip.js +19 -0
- package/src/grammar/legendCombinations.js +45 -0
- package/src/grammar/legendGradient.js +9 -0
- package/src/grammar/legendGroups.js +1 -1
- package/src/grammar/legendOpacity.js +6 -0
- package/src/grammar/pointShapes.js +16 -2
- package/src/grammar/regression/derive.js +9 -1
- package/src/grammar/regression/models.js +60 -0
- package/src/grammar/regression/parameters.js +9 -1
- package/src/grammar/regression/statistics.js +64 -0
- package/src/grammar/scales/color.js +1 -1
- package/src/grammar/scales/colorConsumers.js +1 -1
- package/src/grammar/scales/definition.js +1 -1
- package/src/grammar/scales/types.js +1 -1
- package/src/grammar/schemas/concreteGraphic.js +3 -0
- package/src/grammar/schemas/graphic.js +3 -0
- package/src/grammar/schemas/graphicBounds.js +31 -7
- package/src/grammar/schemas/semanticPath.js +17 -2
- package/src/grammar/summary.js +1 -1
- package/src/grammar/timeUnit.js +6 -4
- package/src/grammar/transformTopology.js +1 -0
- package/src/grammar/transforms.js +11 -1
- package/src/inspectionDescriptors.js +1 -1
- package/src/layout/guideCollisions.js +9 -1
- package/src/layout/legendGroup.js +1 -1
- package/src/materialization/compositionSnapshot.js +2 -7
- package/src/materialization/coordinateBounds.js +17 -4
- package/src/materialization/facetGuides/edit.js +30 -0
- package/src/materialization/facetGuides/layout.js +1 -1
- package/src/materialization/facetGuides/owner.js +125 -0
- package/src/materialization/facetGuides/ownerLayout.js +71 -0
- package/src/materialization/facetGuides/placement.js +52 -6
- package/src/materialization/facetGuides/preparation.js +7 -0
- package/src/materialization/facets.js +1 -1
- package/src/materialization/graphicHierarchy.js +5 -1
- package/src/materialization/graphicTranslation.js +73 -0
- package/src/materialization/guides/layout.js +1 -1
- package/src/materialization/guides/resources.js +1 -1
- package/src/materialization/legendBorder.js +28 -0
- package/src/materialization/legendClip.js +76 -0
- package/src/materialization/legendGroups.js +1 -1
- package/src/materialization/legends.js +1 -1
- package/src/materialization/scaleGuideDependencies.js +13 -14
- package/src/materialization/scales/map.js +3 -0
- package/src/materialization/scales/resolve.js +2 -0
- package/src/materialization/typography.js +10 -2
- package/src/persistence/validation.js +174 -1
- package/src/persistence.js +1 -1
- package/src/renderers/canvas/index.js +20 -10
- package/src/renderers/canvas/isolated.js +166 -0
- package/src/renderers/canvas/limits.js +3 -0
- package/src/renderers/canvas/rect.js +1 -1
- package/src/renderers/pdf.js +2 -2
- package/src/renderers/png.js +2 -2
- package/src/renderers/svg.js +10 -3
- package/src/selectors/axes.js +1 -0
- package/src/selectors/graphicCapacity.js +38 -0
- package/src/version.js +1 -1
- package/types/basic.d.ts +2 -0
- package/types/index.d.ts +5 -0
- package/types/program.d.ts +206 -61
|
@@ -376,7 +376,7 @@ function hasActiveStroke(properties) {
|
|
|
376
376
|
(properties.strokeWidth ?? 0) > 0;
|
|
377
377
|
}
|
|
378
378
|
|
|
379
|
-
function
|
|
379
|
+
export function resolvePrimitiveGraphicBounds(type, properties = {}, profile) {
|
|
380
380
|
const strokeExtent = hasActiveStroke(properties)
|
|
381
381
|
? properties.strokeWidth / 2
|
|
382
382
|
: 0;
|
|
@@ -469,15 +469,34 @@ function ancestorOffset(graphicSpec, target) {
|
|
|
469
469
|
}
|
|
470
470
|
}
|
|
471
471
|
|
|
472
|
+
function intersectVisibleBounds(bounds,clip) {
|
|
473
|
+
if(bounds===undefined)return undefined;
|
|
474
|
+
const result={left:Math.max(bounds.left,clip.left),right:Math.min(bounds.right,clip.right),
|
|
475
|
+
top:Math.max(bounds.top,clip.top),bottom:Math.min(bounds.bottom,clip.bottom)};
|
|
476
|
+
return result.right<=result.left||result.bottom<=result.top?undefined:result;
|
|
477
|
+
}
|
|
478
|
+
|
|
479
|
+
function clipAncestorBounds(graphicSpec,id,bounds) {
|
|
480
|
+
let parent=findGraphicParent(graphicSpec,id);
|
|
481
|
+
while(parent!==undefined){
|
|
482
|
+
if(parent.object.type==="canvas"&&findGraphicParent(graphicSpec,parent.id)!==undefined){
|
|
483
|
+
const [x,y]=ancestorOffset(graphicSpec,parent.id),p=parent.object.properties;
|
|
484
|
+
bounds=intersectVisibleBounds(bounds,{left:x+(p.x??0),right:x+(p.x??0)+p.width,top:y+(p.y??0),bottom:y+(p.y??0)+p.height});
|
|
485
|
+
}
|
|
486
|
+
parent=findGraphicParent(graphicSpec,parent.id);
|
|
487
|
+
}
|
|
488
|
+
return bounds;
|
|
489
|
+
}
|
|
490
|
+
|
|
472
491
|
function objectBounds(graphicSpec, id, object, ancestors, x, y, profile) {
|
|
473
492
|
if (ancestors.has(id)) {
|
|
474
493
|
throw new Error(`Graphic attachment cycle includes "${id}".`);
|
|
475
494
|
}
|
|
476
495
|
ancestors.add(id);
|
|
477
496
|
let result = object.items === undefined
|
|
478
|
-
? translateBounds(
|
|
497
|
+
? translateBounds(resolvePrimitiveGraphicBounds(object.type, object.properties, profile), x, y)
|
|
479
498
|
: unionBounds(object.items.map(item => translateBounds(
|
|
480
|
-
|
|
499
|
+
resolvePrimitiveGraphicBounds(item.type ?? object.type, item.properties, profile),
|
|
481
500
|
x,
|
|
482
501
|
y
|
|
483
502
|
)));
|
|
@@ -497,20 +516,25 @@ function objectBounds(graphicSpec, id, object, ancestors, x, y, profile) {
|
|
|
497
516
|
);
|
|
498
517
|
}
|
|
499
518
|
}
|
|
519
|
+
if(object.type==="canvas"&&findGraphicParent(graphicSpec,id)!==undefined){
|
|
520
|
+
result=intersectVisibleBounds(result,{left:childX,right:childX+object.properties.width,
|
|
521
|
+
top:childY,bottom:childY+object.properties.height});
|
|
522
|
+
}
|
|
500
523
|
ancestors.delete(id);
|
|
501
524
|
return result;
|
|
502
525
|
}
|
|
503
526
|
|
|
504
527
|
export function resolveConcreteGraphicBounds(graphicSpec, target, profile) {
|
|
505
528
|
const found = requireGraphic(graphicSpec, target);
|
|
506
|
-
const
|
|
507
|
-
|
|
529
|
+
const anchor=found.kind==="item"?found.ownerId:found.id;
|
|
530
|
+
const [x, y] = ancestorOffset(graphicSpec, anchor);
|
|
531
|
+
return requireFiniteBounds(clipAncestorBounds(graphicSpec,anchor,found.kind === "item"
|
|
508
532
|
? translateBounds(
|
|
509
|
-
|
|
533
|
+
resolvePrimitiveGraphicBounds(found.object.type ?? found.owner.type, found.object.properties, profile),
|
|
510
534
|
x,
|
|
511
535
|
y
|
|
512
536
|
)
|
|
513
|
-
: objectBounds(graphicSpec, found.id, found.object, new Set(), x, y, profile));
|
|
537
|
+
: objectBounds(graphicSpec, found.id, found.object, new Set(), x, y, profile)));
|
|
514
538
|
}
|
|
515
539
|
|
|
516
540
|
export function unionConcreteGraphicBounds(graphicSpec, targets, profile) {
|
|
@@ -1,5 +1,6 @@
|
|
|
1
1
|
import { USER_ID_SOURCE } from "../../core/identifiers.js";
|
|
2
2
|
import {
|
|
3
|
+
AXIS_RESOURCE_CHANNELS,
|
|
3
4
|
CARTESIAN_POSITION_CHANNELS,
|
|
4
5
|
ENCODING_CHANNELS,
|
|
5
6
|
SCALED_ENCODING_CHANNELS
|
|
@@ -65,6 +66,7 @@ const ENTITY_PATHS = Object.freeze({
|
|
|
65
66
|
"mark.type",
|
|
66
67
|
"mark.missing",
|
|
67
68
|
"mark.orientation",
|
|
69
|
+
"mark.blend",
|
|
68
70
|
"derivedBindings.regression",
|
|
69
71
|
"layout.mode",
|
|
70
72
|
...ENCODING_PATHS
|
|
@@ -74,7 +76,7 @@ const ENTITY_PATHS = Object.freeze({
|
|
|
74
76
|
collection: "scales",
|
|
75
77
|
properties: new Set([
|
|
76
78
|
"type", "domain", "range", "emptyDomain", "nice", "zero", "clamp", "reverse",
|
|
77
|
-
"unknown", "base", "exponent", "constant", "interpolate", "radialMapping", "midpoint",
|
|
79
|
+
"unknown", "base", "exponent", "constant", "interpolate", "whitePoint", "gamma", "radialMapping", "midpoint",
|
|
78
80
|
"paddingInner", "paddingOuter", "padding", "align"
|
|
79
81
|
])
|
|
80
82
|
},
|
|
@@ -101,6 +103,9 @@ const GUIDE_PATHS = new Set([
|
|
|
101
103
|
"axis.parallel.coordinate",
|
|
102
104
|
"axis.parallel.scales",
|
|
103
105
|
"axis.parallel.titles",
|
|
106
|
+
"legend.colorSize.colorScale",
|
|
107
|
+
"legend.colorSize.sizeScale",
|
|
108
|
+
"legend.colorSize.title",
|
|
104
109
|
"legend.color.scale",
|
|
105
110
|
"legend.color.title",
|
|
106
111
|
"legend.color.order",
|
|
@@ -137,6 +142,7 @@ const GUIDE_REMOVABLE_CONTAINERS = new Set([
|
|
|
137
142
|
"grid.vertical",
|
|
138
143
|
"grid.theta",
|
|
139
144
|
"grid.radial",
|
|
145
|
+
"legend.colorSize",
|
|
140
146
|
"legend.color",
|
|
141
147
|
"legend.stroke",
|
|
142
148
|
"legend.size",
|
|
@@ -147,6 +153,13 @@ const GUIDE_REMOVABLE_CONTAINERS = new Set([
|
|
|
147
153
|
|
|
148
154
|
const TITLE_PATHS = new Set(["text", "subtitle"]);
|
|
149
155
|
|
|
156
|
+
function isNamedAxisPath(path, container = false) {
|
|
157
|
+
const match = path.match(new RegExp(container
|
|
158
|
+
? `^axis\\.(${USER_ID_SOURCE})$`
|
|
159
|
+
: `^axis\\.(${USER_ID_SOURCE})\\.(scale|coordinate|title|channel|position)$`));
|
|
160
|
+
return match !== null && !AXIS_RESOURCE_CHANNELS.includes(match[1]);
|
|
161
|
+
}
|
|
162
|
+
|
|
150
163
|
function splitPropertyPath(property) {
|
|
151
164
|
return property.split(".");
|
|
152
165
|
}
|
|
@@ -201,7 +214,9 @@ export function parseSemanticPath(property, { allowContainer = false } = {}) {
|
|
|
201
214
|
|
|
202
215
|
if (
|
|
203
216
|
!GUIDE_PATHS.has(propertyPath) &&
|
|
204
|
-
!(
|
|
217
|
+
!isNamedAxisPath(propertyPath) &&
|
|
218
|
+
!(allowContainer && (GUIDE_REMOVABLE_CONTAINERS.has(propertyPath) ||
|
|
219
|
+
isNamedAxisPath(propertyPath, true)))
|
|
205
220
|
) {
|
|
206
221
|
throw new Error(`Unknown semantic property "${property}".`);
|
|
207
222
|
}
|
package/src/grammar/summary.js
CHANGED
|
@@ -23,7 +23,7 @@ const TRANSFORM_KEYS = Object.freeze([
|
|
|
23
23
|
]);
|
|
24
24
|
const AGGREGATE_KEYS = Object.freeze(["op", "field", "as"]);
|
|
25
25
|
const NOMINAL_OPERATIONS = new Set(["distinct", "valid", "missing"]);
|
|
26
|
-
const MAX_OUTPUT_ROWS =
|
|
26
|
+
const MAX_OUTPUT_ROWS = 30_000;
|
|
27
27
|
|
|
28
28
|
function normalizeGroupBy(value) {
|
|
29
29
|
if (value === undefined) return [];
|
package/src/grammar/timeUnit.js
CHANGED
|
@@ -52,6 +52,7 @@ function formatter(timeZone) {
|
|
|
52
52
|
try {
|
|
53
53
|
value = new Intl.DateTimeFormat("en-US-u-ca-gregory-nu-latn", {
|
|
54
54
|
timeZone,
|
|
55
|
+
era: "short",
|
|
55
56
|
year: "numeric",
|
|
56
57
|
month: "2-digit",
|
|
57
58
|
day: "2-digit",
|
|
@@ -68,7 +69,7 @@ function formatter(timeZone) {
|
|
|
68
69
|
return CALENDAR_FORMATTERS.get(timeZone);
|
|
69
70
|
}
|
|
70
71
|
|
|
71
|
-
function validateTimeZone(timeZone) {
|
|
72
|
+
export function validateTimeZone(timeZone) {
|
|
72
73
|
if (typeof timeZone !== "string" || timeZone.length === 0) {
|
|
73
74
|
throw new TypeError("Time-unit timeZone must be a non-empty IANA time-zone name.");
|
|
74
75
|
}
|
|
@@ -178,17 +179,18 @@ export function calendarParts(timestamp, timeZone) {
|
|
|
178
179
|
validateTimeZone(timeZone);
|
|
179
180
|
const parts = Object.fromEntries(formatter(timeZone).formatToParts(timestamp)
|
|
180
181
|
.filter(part => part.type !== "literal")
|
|
181
|
-
.map(part => [part.type, Number(part.value)]));
|
|
182
|
+
.map(part => [part.type, part.type === "era" ? part.value : Number(part.value)]));
|
|
183
|
+
const year = parts.era === "BC" ? 1 - parts.year : parts.year;
|
|
182
184
|
const millisecond = ((timestamp % 1000) + 1000) % 1000;
|
|
183
185
|
return {
|
|
184
|
-
year
|
|
186
|
+
year,
|
|
185
187
|
month: parts.month,
|
|
186
188
|
day: parts.day,
|
|
187
189
|
hour: parts.hour,
|
|
188
190
|
minute: parts.minute,
|
|
189
191
|
second: parts.second,
|
|
190
192
|
millisecond,
|
|
191
|
-
weekday: weekdayFromDate(
|
|
193
|
+
weekday: weekdayFromDate(year, parts.month, parts.day)
|
|
192
194
|
};
|
|
193
195
|
}
|
|
194
196
|
|
|
@@ -16,6 +16,7 @@ const TRANSFORM_TOPOLOGY = Object.freeze({
|
|
|
16
16
|
markFilter: Object.freeze({ provenanceTransparent: true }),
|
|
17
17
|
normalize: Object.freeze({ facetTopology: "statistical" }),
|
|
18
18
|
regression: Object.freeze({ facetTopology: "statistical" }),
|
|
19
|
+
regressionStatistics: Object.freeze({ facetTopology: "statistical" }),
|
|
19
20
|
sort: Object.freeze({ facetTopology: "statistical" }),
|
|
20
21
|
summary: Object.freeze({ facetTopology: "statistical" }),
|
|
21
22
|
stack: Object.freeze({ facetTopology: "statistical" }),
|
|
@@ -1,4 +1,5 @@
|
|
|
1
1
|
import { cloneAndFreeze, isPlainObject } from "../core/immutable.js";
|
|
2
|
+
import { validateRegressionStatisticsTransform } from "./regression/statistics.js";
|
|
2
3
|
import { validateBoxTransform } from "./boxPlot.js";
|
|
3
4
|
import { normalizeBinTransform, validateBinTransform } from "./bin.js";
|
|
4
5
|
import {
|
|
@@ -203,7 +204,7 @@ function normalizeRegressionEdit(transform, patch) {
|
|
|
203
204
|
delete base.span;
|
|
204
205
|
delete base.robustIterations;
|
|
205
206
|
}
|
|
206
|
-
if (
|
|
207
|
+
if (["loess", "exp"].includes(method) || ["loess", "exp"].includes(base.method)) {
|
|
207
208
|
for (const key of [
|
|
208
209
|
"confidenceMethod", "level", "confidence", "interval"
|
|
209
210
|
]) delete base[key];
|
|
@@ -446,6 +447,15 @@ const TRANSFORM_POLICIES = Object.freeze({
|
|
|
446
447
|
normalizeEdit: normalizeRegressionEdit,
|
|
447
448
|
outputRoles: () => ({})
|
|
448
449
|
}),
|
|
450
|
+
regressionStatistics: Object.freeze({
|
|
451
|
+
...findTransformTopology("regressionStatistics"),
|
|
452
|
+
validate: validateRegressionStatisticsTransform,
|
|
453
|
+
materializeOp: "materializeRegressionStatisticsData",
|
|
454
|
+
replayTransform: requestedTransform,
|
|
455
|
+
editable: true,
|
|
456
|
+
normalizeEdit: (transform, patch) => validateRegressionStatisticsTransform({ ...transform, ...patch }),
|
|
457
|
+
outputRoles: () => ({ count: "count", intercept: "intercept", slope: "slope", rSquared: "rSquared" })
|
|
458
|
+
}),
|
|
449
459
|
sort: Object.freeze({
|
|
450
460
|
...findTransformTopology("sort"),
|
|
451
461
|
validate: validateSortTransform,
|