ggaction 0.0.10 → 0.0.12
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 +97 -0
- package/README.md +5 -3
- package/knowledge/action-card.schema.json +1 -0
- package/knowledge/action-cards.json +1 -10941
- package/knowledge/action-cards.schema.json +1 -0
- package/knowledge/intent-taxonomy.json +1 -183
- package/knowledge/intent-taxonomy.schema.json +1 -0
- package/knowledge/mcp-resources.json +1 -95
- package/knowledge/mcp-resources.schema.json +1 -0
- package/knowledge/task-packet.schema.json +1 -159
- package/knowledge/task-resolver.js +1 -1230
- package/package.json +18 -2
- package/src/actions/boxPlots/edit.js +45 -298
- package/src/actions/boxPlots/options.js +46 -77
- package/src/actions/boxPlots/resolve.js +1 -1
- package/src/actions/charts/bar.js +3 -0
- package/src/actions/charts/heatmap.js +73 -83
- package/src/actions/charts/index.js +1 -1
- package/src/actions/charts/parallel.js +35 -1
- package/src/actions/charts/shared.js +20 -0
- package/src/actions/composition/actions.js +46 -49
- package/src/actions/data/bin2d.js +105 -2
- package/src/actions/data/box.js +17 -17
- package/src/actions/data/density.js +42 -78
- package/src/actions/data/gradientProfile.js +22 -52
- package/src/actions/data/horizon.js +16 -41
- package/src/actions/data/index.js +10 -10
- package/src/actions/data/interval.js +16 -38
- package/src/actions/data/intervalEdit.js +55 -0
- package/src/actions/data/regression.js +7 -17
- package/src/actions/data/shared.js +47 -0
- package/src/actions/data/timeUnit.js +14 -38
- package/src/actions/data/window.js +14 -38
- package/src/actions/distributions/revision.js +154 -34
- package/src/actions/encodings/angle.js +9 -10
- package/src/actions/encodings/appearance.js +17 -51
- package/src/actions/encodings/density/resolve.js +3 -1
- package/src/actions/encodings/density.js +1 -15
- package/src/actions/encodings/horizon/resolve.js +13 -3
- package/src/actions/encodings/horizon.js +8 -7
- package/src/actions/encodings/index.js +9 -9
- package/src/actions/encodings/offset.js +41 -45
- package/src/actions/encodings/parallel.js +9 -10
- package/src/actions/encodings/pathOrder.js +6 -13
- package/src/actions/encodings/position/apply.js +30 -0
- package/src/actions/encodings/position/policies/arc.js +23 -2
- package/src/actions/encodings/position/policies/index.js +4 -4
- package/src/actions/encodings/position/policies/line.js +47 -17
- package/src/actions/encodings/position/resolve.js +36 -7
- package/src/actions/encodings/ranged.js +18 -23
- package/src/actions/encodings/remove.js +15 -25
- package/src/actions/encodings/ruleAppearance.js +9 -24
- package/src/actions/encodings/shared.js +37 -0
- package/src/actions/encodings/strokeDash.js +8 -23
- package/src/actions/encodings/text.js +9 -10
- package/src/actions/errorBands/create.js +105 -39
- package/src/actions/errorBands/edit.js +89 -93
- package/src/actions/errorBands/index.js +1 -2
- package/src/actions/errorBars/create.js +212 -30
- package/src/actions/errorBars/edit.js +91 -48
- package/src/actions/errorBars/index.js +1 -2
- package/src/actions/facets/actions.js +45 -69
- package/src/actions/facets/derive.js +38 -53
- package/src/actions/facets/replay.js +0 -1
- package/src/actions/gradientPlots/components.js +59 -48
- package/src/actions/gradientPlots/edit.js +35 -216
- package/src/actions/gradientPlots/index.js +11 -10
- package/src/actions/gradientPlots/materialize.js +21 -35
- package/src/actions/gradientPlots/options.js +5 -7
- package/src/actions/gradientPlots/paint.js +9 -6
- package/src/actions/gradientPlots/resolve.js +1 -1
- package/src/actions/guides/axes/index.js +3 -3
- package/src/actions/guides/axes/labels.js +68 -26
- package/src/actions/guides/axes/lines.js +22 -2
- package/src/actions/guides/axes/policy.js +28 -8
- package/src/actions/guides/axes/ticks.js +27 -9
- package/src/actions/guides/axes/titles.js +113 -65
- package/src/actions/guides/grids/resolve.js +14 -0
- package/src/actions/guides/guides.js +2 -4
- package/src/actions/guides/index.js +2 -2
- package/src/actions/guides/legends/categorical/actions.js +44 -68
- package/src/actions/guides/legends/categorical/components.js +6 -1
- package/src/actions/guides/legends/categorical/index.js +2 -2
- package/src/actions/guides/legends/categorical/layout.js +148 -175
- package/src/actions/guides/legends/categorical/recipes.js +5 -0
- package/src/actions/guides/legends/categorical/resolve.js +8 -1
- package/src/actions/guides/legends/continuous/common.js +117 -66
- package/src/actions/guides/legends/continuous/gradient.js +38 -37
- package/src/actions/guides/legends/continuous/interval.js +97 -76
- package/src/actions/guides/legends/continuous/opacity.js +28 -38
- package/src/actions/guides/legends/edit.js +14 -1
- package/src/actions/guides/legends/index.js +1 -1
- package/src/actions/guides/legends/lane.js +2 -1
- package/src/actions/guides/legends/remove.js +8 -0
- package/src/actions/guides/legends/size.js +36 -43
- package/src/actions/guides/legends/strokeWidth.js +20 -26
- package/src/actions/guides/polar/axes/labels.js +17 -1
- package/src/actions/guides/polar/axes/shared.js +7 -1
- package/src/actions/guides/polar/axes/titles.js +19 -2
- package/src/actions/guides/polar/grids.js +4 -0
- package/src/actions/guides/polar/resolve.js +6 -0
- package/src/actions/index.js +13 -13
- package/src/actions/intervals/resolve.js +87 -117
- package/src/actions/marks/arc/actions.js +31 -36
- package/src/actions/marks/area/actions.js +23 -31
- package/src/actions/marks/index.js +6 -6
- package/src/actions/marks/line/actions.js +33 -52
- package/src/actions/marks/line/materialize.js +7 -5
- package/src/actions/marks/point/materialize.js +38 -16
- package/src/actions/marks/remove.js +21 -0
- package/src/actions/marks/rule/actions.js +79 -54
- package/src/actions/marks/shared.js +8 -4
- package/src/actions/marks/text/actions.js +14 -6
- package/src/actions/marks/text/layout.js +21 -45
- package/src/actions/marks/tick/actions.js +22 -21
- package/src/actions/primitives/createGraphics.js +4 -0
- package/src/actions/primitives/editGraphics.js +4 -0
- package/src/actions/primitives/index.js +3 -3
- package/src/actions/primitives/semantic.js +1 -1
- package/src/actions/primitives/semanticValidation/index.js +2 -2
- package/src/actions/primitives/semanticValidation/layer.js +1 -1
- package/src/actions/regression/edit.js +3 -43
- package/src/actions/scales/consumers/families.js +24 -4
- package/src/actions/scales/consumers/index.js +1 -1
- package/src/actions/scales/consumers/seriesLayout.js +17 -0
- package/src/actions/scales/definitions.js +100 -103
- package/src/actions/scales/materialize.js +5 -0
- package/src/actions/selection/actions.js +79 -121
- package/src/actions/titles/actions.js +48 -94
- package/src/actions/titles/resolve.js +14 -27
- package/src/actions/violinPlots/create.js +37 -44
- package/src/core/textMetrics.js +74 -37
- package/src/core/validation.js +18 -0
- package/src/core/vocabulary.js +2 -2
- package/src/grammar/aggregate.js +48 -28
- package/src/grammar/arcs.js +170 -32
- package/src/grammar/areaSeries.js +14 -16
- package/src/grammar/bin2d.js +37 -23
- package/src/grammar/boxPlot.js +14 -13
- package/src/grammar/categoricalDensity.js +14 -14
- package/src/grammar/categoryOrder.js +8 -14
- package/src/grammar/curveCommands.js +87 -20
- package/src/grammar/density.js +162 -141
- package/src/grammar/facets/index.js +14 -0
- package/src/grammar/facets/scales.js +7 -4
- package/src/grammar/gradientProfile.js +12 -15
- package/src/grammar/histogram.js +145 -83
- package/src/grammar/horizon.js +60 -23
- package/src/grammar/interval.js +14 -13
- package/src/grammar/lineSeries.js +91 -61
- package/src/grammar/numeric.js +290 -0
- package/src/grammar/paint.js +3 -4
- package/src/grammar/palettes.js +21 -32
- package/src/grammar/pathCommands.js +6 -0
- package/src/grammar/polarPaths.js +5 -5
- package/src/grammar/positionCompatibility.js +1 -1
- package/src/grammar/regression/derive.js +48 -9
- package/src/grammar/regression/models.js +248 -69
- package/src/grammar/regression/parameters.js +8 -0
- package/src/grammar/rules.js +2 -0
- package/src/grammar/scales/color.js +35 -26
- package/src/grammar/scales/continuous.js +71 -24
- package/src/grammar/scales/definition.js +1 -1
- package/src/grammar/scales/discretized.js +42 -12
- package/src/grammar/scales/fields.js +21 -4
- package/src/grammar/scales/ordinal.js +139 -60
- package/src/grammar/scales/temporal.js +40 -11
- package/src/grammar/scales/transformed.js +199 -52
- package/src/grammar/schemas/graphicBounds.js +270 -79
- package/src/grammar/seriesLayout.js +50 -18
- package/src/grammar/ticks.js +123 -53
- package/src/grammar/timeUnit.js +18 -8
- package/src/grammar/transforms.js +4 -1
- package/src/grammar/window.js +70 -57
- package/src/index.js +1 -1
- package/src/layout/canvas.js +4 -8
- package/src/layout/composition.js +39 -40
- package/src/layout/facets.js +55 -30
- package/src/layout/labels.js +91 -15
- package/src/layout/legend.js +22 -20
- package/src/layout/legendLane.js +54 -40
- package/src/layout/title.js +7 -7
- package/src/materialization/bars/aggregate.js +14 -40
- package/src/materialization/bars/grouped.js +7 -18
- package/src/materialization/bars/histogram.js +2 -19
- package/src/materialization/bars/ranged.js +20 -15
- package/src/materialization/bars/resolve.js +21 -0
- package/src/materialization/facetGuides/legacyCategorical.js +9 -2
- package/src/materialization/facetGuides/placement.js +49 -19
- package/src/materialization/facetGuides/preparation.js +35 -6
- package/src/materialization/facets.js +42 -28
- package/src/materialization/guides/resources.js +2 -1
- package/src/materialization/marks/capabilities.js +15 -4
- package/src/materialization/marks/index.js +29 -6
- package/src/materialization/rowEncoding.js +57 -1
- package/src/materialization/scales/policies/bar.js +61 -102
- package/src/materialization/scales/policies/binnedPosition.js +34 -0
- package/src/materialization/scales/policies/offset.js +54 -0
- package/src/materialization/scales/policies/series.js +13 -7
- package/src/materialization/scales/resolve.js +6 -9
- package/src/materialization/selection/items/arc.js +16 -2
- package/src/materialization/selection/items/bar.js +4 -2
- package/src/materialization/selection/items/common.js +21 -1
- package/src/materialization/selection/items/path.js +19 -2
- package/src/materialization/selection/items/point.js +4 -16
- package/src/materialization/selection/items/tick.js +13 -21
- package/src/materialization/selection/point.js +11 -4
- package/src/materialization/selection/styles.js +19 -27
- package/src/materialization/text.js +4 -1
- package/src/mcp/adapter.js +8 -3
- package/src/renderers/canvas/fill.js +2 -2
- package/src/renderers/canvas/index.js +35 -2
- package/src/renderers/canvas/native.js +160 -0
- package/src/renderers/pdf.js +14 -0
- package/src/renderers/svg.js +37 -4
- package/types/index.d.ts +3 -0
- package/types/program.d.ts +523 -131
- package/types/svg.d.ts +1 -0
- package/src/actions/errorBands/components.js +0 -81
- package/src/actions/errorBands/options.js +0 -39
- package/src/actions/errorBands/resolve.js +0 -28
- package/src/actions/errorBars/components.js +0 -62
- package/src/actions/errorBars/options.js +0 -58
- package/src/actions/errorBars/resolve.js +0 -25
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "ggaction",
|
|
3
|
-
"version": "0.0.
|
|
3
|
+
"version": "0.0.12",
|
|
4
4
|
"description": "Build charts through immutable, traceable graphical actions.",
|
|
5
5
|
"license": "MIT",
|
|
6
6
|
"author": "Hyeon Jeon",
|
|
@@ -25,9 +25,13 @@
|
|
|
25
25
|
"src/",
|
|
26
26
|
"!src/**/AGENTS.md",
|
|
27
27
|
"knowledge/action-cards.json",
|
|
28
|
+
"knowledge/action-card.schema.json",
|
|
29
|
+
"knowledge/action-cards.schema.json",
|
|
28
30
|
"knowledge/extension-authoring.md",
|
|
29
31
|
"knowledge/intent-taxonomy.json",
|
|
32
|
+
"knowledge/intent-taxonomy.schema.json",
|
|
30
33
|
"knowledge/mcp-resources.json",
|
|
34
|
+
"knowledge/mcp-resources.schema.json",
|
|
31
35
|
"knowledge/task-packet.schema.json",
|
|
32
36
|
"knowledge/task-resolver.js",
|
|
33
37
|
"types/",
|
|
@@ -72,6 +76,7 @@
|
|
|
72
76
|
"test:charts": "node scripts/run-tests.js charts",
|
|
73
77
|
"test:gates": "node scripts/run-tests.js gates",
|
|
74
78
|
"test:docs": "node scripts/run-tests.js docs",
|
|
79
|
+
"test:realistic": "node scripts/run-tests.js realistic",
|
|
75
80
|
"test:browser": "node scripts/run-tests.js browser",
|
|
76
81
|
"test:docs:built": "node scripts/check-built-docs.js _site",
|
|
77
82
|
"test:docs:browser": "node scripts/test-built-docs.js _site",
|
|
@@ -82,12 +87,19 @@
|
|
|
82
87
|
"artifacts:clean": "node test/support/artifacts.js",
|
|
83
88
|
"artifacts:gallery": "node scripts/generate-artifact-gallery.js",
|
|
84
89
|
"artifacts:gallery:test": "node scripts/test-artifact-gallery.js",
|
|
90
|
+
"datasets:sync": "node scripts/sync-dataset-corpus.js --all",
|
|
91
|
+
"scenarios:smoke": "node scripts/run-generated-scenarios.js --mode=smoke --no-tidytuesday",
|
|
92
|
+
"scenarios:deep": "node scripts/run-generated-scenarios.js --mode=deep",
|
|
93
|
+
"scenarios:realistic": "node --expose-gc scripts/run-realistic-scenarios.js",
|
|
94
|
+
"scenarios:realistic:audit": "node --expose-gc scripts/run-realistic-scenarios.js --no-artifacts",
|
|
85
95
|
"docs:images": "node scripts/generate-doc-images.js",
|
|
86
96
|
"docs:llms": "node scripts/generate-llm-docs.js",
|
|
87
97
|
"docs:capabilities": "node scripts/generate-doc-capabilities.js",
|
|
88
98
|
"docs:capabilities:check": "node scripts/generate-doc-capabilities.js --check",
|
|
89
99
|
"docs:actions": "node scripts/generate-doc-action-metadata.js",
|
|
90
100
|
"docs:actions:check": "node scripts/generate-doc-action-metadata.js --check",
|
|
101
|
+
"docs:machine": "node scripts/generate-doc-machine-artifacts.js",
|
|
102
|
+
"docs:machine:check": "node scripts/generate-doc-machine-artifacts.js --check",
|
|
91
103
|
"docs:search": "node scripts/generate-doc-search-index.js",
|
|
92
104
|
"docs:search:check": "node scripts/generate-doc-search-index.js --check",
|
|
93
105
|
"docs:reference": "node scripts/generate-doc-action-reference.js",
|
|
@@ -99,11 +111,13 @@
|
|
|
99
111
|
"docs:signatures:check": "node scripts/generate-doc-signatures.js --check",
|
|
100
112
|
"examples:index": "node scripts/generate-examples-readme.js",
|
|
101
113
|
"examples:index:check": "node scripts/generate-examples-readme.js --check",
|
|
102
|
-
"docs:generate": "npm run examples:index && npm run docs:
|
|
114
|
+
"docs:generate": "npm run examples:index && npm run docs:reference && npm run contracts:cards && npm run docs:actions && npm run docs:signatures && npm run docs:capabilities && npm run docs:metadata && npm run docs:search && npm run docs:images && npm run docs:machine && npm run docs:llms",
|
|
103
115
|
"docs:build": "bundle exec jekyll build --source docs --destination _site --baseurl /ggaction",
|
|
104
116
|
"docs:verify": "npm run docs:preflight && npm run docs:generate && npm run test:docs && npm run docs:build && npm run test:docs:built && npm run test:docs:browser",
|
|
105
117
|
"contracts:catalog": "node scripts/generate-action-catalog.js",
|
|
106
118
|
"contracts:catalog:check": "node scripts/generate-action-catalog.js --check",
|
|
119
|
+
"contracts:cards": "node scripts/generate-action-cards.js",
|
|
120
|
+
"contracts:cards:check": "node scripts/generate-action-cards.js --check",
|
|
107
121
|
"package:check": "node scripts/package-artifact.js --check",
|
|
108
122
|
"package:pack": "node scripts/package-artifact.js --pack",
|
|
109
123
|
"package:bundle": "node scripts/measure-browser-bundle.js",
|
|
@@ -124,7 +138,9 @@
|
|
|
124
138
|
},
|
|
125
139
|
"devDependencies": {
|
|
126
140
|
"@axe-core/playwright": "^4.12.1",
|
|
141
|
+
"ajv": "^8.20.0",
|
|
127
142
|
"es-module-lexer": "^1.7.0",
|
|
143
|
+
"esbuild": "0.28.2",
|
|
128
144
|
"gifenc": "^1.0.3",
|
|
129
145
|
"playwright": "^1.61.1",
|
|
130
146
|
"typescript": "^7.0.2",
|
|
@@ -8,13 +8,12 @@ import { planDerivedDataRevision } from
|
|
|
8
8
|
"../../materialization/dataProvenance.js";
|
|
9
9
|
import { findDataset } from "../../selectors/datasets.js";
|
|
10
10
|
import { findLayer } from "../../selectors/layers.js";
|
|
11
|
+
import { removeOwnedMark } from "../marks/remove.js";
|
|
11
12
|
import {
|
|
12
|
-
|
|
13
|
-
clearCartesianPositions,
|
|
14
|
-
rebindDistributionGuides,
|
|
15
|
-
resolveDistributionScalePlan,
|
|
13
|
+
resolveDistributionRoles,
|
|
16
14
|
setCartesianPosition,
|
|
17
|
-
setCartesianRange
|
|
15
|
+
setCartesianRange,
|
|
16
|
+
updateDistributionPositions
|
|
18
17
|
} from "../distributions/revision.js";
|
|
19
18
|
import {
|
|
20
19
|
resolveBoxAppearance,
|
|
@@ -73,130 +72,18 @@ function resolveEditedWhisker(current, value) {
|
|
|
73
72
|
return resolveBoxWhisker(candidate, "editBoxPlot");
|
|
74
73
|
}
|
|
75
74
|
|
|
76
|
-
function removeOwnedMark(program, id) {
|
|
77
|
-
const selections = Object.entries(
|
|
78
|
-
program.materializationConfigs.selections ?? {}
|
|
79
|
-
).filter(([, config]) => config.target === id).map(([selection]) => selection);
|
|
80
|
-
let next = program;
|
|
81
|
-
for (const [highlight, config] of Object.entries(
|
|
82
|
-
program.materializationConfigs.highlights ?? {}
|
|
83
|
-
)) {
|
|
84
|
-
if (config.target === id || selections.includes(config.selection)) {
|
|
85
|
-
next = next._withoutMaterializationConfig(["highlights", highlight]);
|
|
86
|
-
}
|
|
87
|
-
}
|
|
88
|
-
for (const selection of selections) {
|
|
89
|
-
next = next._withoutMaterializationConfig(["selections", selection]);
|
|
90
|
-
}
|
|
91
|
-
return next
|
|
92
|
-
.editSemantic({ property: `layer[${id}]`, remove: true })
|
|
93
|
-
.editGraphics({ target: id, remove: true })
|
|
94
|
-
._withoutMaterializationConfig(["marks", id])
|
|
95
|
-
._withContext({
|
|
96
|
-
...(program.context.currentMark === id ? { currentMark: undefined } : {}),
|
|
97
|
-
...(selections.includes(program.context.currentSelection)
|
|
98
|
-
? { currentSelection: undefined }
|
|
99
|
-
: {})
|
|
100
|
-
});
|
|
101
|
-
}
|
|
102
|
-
|
|
103
|
-
function currentBoxPositions(owner, current) {
|
|
104
|
-
const categoryChannel = current.orientation === "vertical" ? "x" : "y";
|
|
105
|
-
const measureChannel = current.orientation === "vertical" ? "y" : "x";
|
|
106
|
-
const categoryEncoding = owner.encoding[categoryChannel];
|
|
107
|
-
const measureEncoding = owner.encoding[measureChannel];
|
|
108
|
-
return {
|
|
109
|
-
x: current.orientation === "vertical"
|
|
110
|
-
? {
|
|
111
|
-
field: current.category,
|
|
112
|
-
fieldType: categoryEncoding.fieldType,
|
|
113
|
-
scale: categoryEncoding.scale
|
|
114
|
-
}
|
|
115
|
-
: {
|
|
116
|
-
field: current.measure,
|
|
117
|
-
fieldType: "quantitative",
|
|
118
|
-
scale: measureEncoding.scale
|
|
119
|
-
},
|
|
120
|
-
y: current.orientation === "vertical"
|
|
121
|
-
? {
|
|
122
|
-
field: current.measure,
|
|
123
|
-
fieldType: "quantitative",
|
|
124
|
-
scale: measureEncoding.scale
|
|
125
|
-
}
|
|
126
|
-
: {
|
|
127
|
-
field: current.category,
|
|
128
|
-
fieldType: categoryEncoding.fieldType,
|
|
129
|
-
scale: categoryEncoding.scale
|
|
130
|
-
},
|
|
131
|
-
categoryScale: categoryEncoding.scale,
|
|
132
|
-
measureScale: measureEncoding.scale
|
|
133
|
-
};
|
|
134
|
-
}
|
|
135
|
-
|
|
136
|
-
function requirePositionField(position, label) {
|
|
137
|
-
if (typeof position.field !== "string" || position.field.length === 0) {
|
|
138
|
-
throw new TypeError(`${label} field must be a non-empty string.`);
|
|
139
|
-
}
|
|
140
|
-
return { fieldType: position.fieldType ?? "quantitative", ...position };
|
|
141
|
-
}
|
|
142
|
-
|
|
143
75
|
function roleCandidate(program, owner, current, args) {
|
|
144
|
-
const previous = currentBoxPositions(owner, current);
|
|
145
|
-
const x = requirePositionField(
|
|
146
|
-
Object.hasOwn(args, "x")
|
|
147
|
-
? resolveBoxPosition(args.x, "x", "editBoxPlot")
|
|
148
|
-
: previous.x,
|
|
149
|
-
"editBoxPlot x"
|
|
150
|
-
);
|
|
151
|
-
const y = requirePositionField(
|
|
152
|
-
Object.hasOwn(args, "y")
|
|
153
|
-
? resolveBoxPosition(args.y, "y", "editBoxPlot")
|
|
154
|
-
: previous.y,
|
|
155
|
-
"editBoxPlot y"
|
|
156
|
-
);
|
|
157
|
-
const orientation = resolveBoxOrientation(x, y);
|
|
158
|
-
if (orientation === undefined) {
|
|
159
|
-
throw new Error(
|
|
160
|
-
"editBoxPlot requires one categorical axis and one quantitative axis."
|
|
161
|
-
);
|
|
162
|
-
}
|
|
163
|
-
const xRoleScale = orientation === "vertical"
|
|
164
|
-
? previous.categoryScale
|
|
165
|
-
: previous.measureScale;
|
|
166
|
-
const yRoleScale = orientation === "vertical"
|
|
167
|
-
? previous.measureScale
|
|
168
|
-
: previous.categoryScale;
|
|
169
|
-
const xScale = resolveDistributionScalePlan(program, {
|
|
170
|
-
channel: "x",
|
|
171
|
-
fieldType: x.fieldType,
|
|
172
|
-
requested: x.scale,
|
|
173
|
-
fallback: xRoleScale,
|
|
174
|
-
defaults: ["ordinal", "nominal"].includes(x.fieldType)
|
|
175
|
-
? { discreteType: "band" }
|
|
176
|
-
: { nice: true, zero: false }
|
|
177
|
-
});
|
|
178
|
-
const yScale = resolveDistributionScalePlan(program, {
|
|
179
|
-
channel: "y",
|
|
180
|
-
fieldType: y.fieldType,
|
|
181
|
-
requested: y.scale,
|
|
182
|
-
fallback: yRoleScale,
|
|
183
|
-
defaults: ["ordinal", "nominal"].includes(y.fieldType)
|
|
184
|
-
? { discreteType: "band" }
|
|
185
|
-
: { nice: true, zero: false }
|
|
186
|
-
});
|
|
187
76
|
return {
|
|
188
77
|
source: Object.hasOwn(args, "data")
|
|
189
78
|
? validateUserId(args.data, "Box-plot data id")
|
|
190
79
|
: current.source,
|
|
191
|
-
|
|
192
|
-
|
|
193
|
-
|
|
194
|
-
|
|
195
|
-
|
|
196
|
-
|
|
197
|
-
|
|
198
|
-
measure: orientation === "vertical" ? y.field : x.field,
|
|
199
|
-
previous
|
|
80
|
+
...resolveDistributionRoles(program, owner, current, args, {
|
|
81
|
+
operation: "editBoxPlot",
|
|
82
|
+
resolvePosition: resolveBoxPosition,
|
|
83
|
+
normalize: (x, y) => ({ x, y, orientation: resolveBoxOrientation(x, y) }),
|
|
84
|
+
quantitativeDefaults: { nice: true, zero: false },
|
|
85
|
+
defaultFieldType: true
|
|
86
|
+
})
|
|
200
87
|
};
|
|
201
88
|
}
|
|
202
89
|
|
|
@@ -223,37 +110,18 @@ function updateBoxPositions(program, owner, current, candidate, {
|
|
|
223
110
|
].filter(Boolean);
|
|
224
111
|
const owned = [owner.id, current.whiskerId, ...capIds, current.medianId,
|
|
225
112
|
...(findLayer(program, current.outlierId) ? [current.outlierId] : [])];
|
|
226
|
-
|
|
227
|
-
|
|
228
|
-
|
|
229
|
-
|
|
230
|
-
|
|
231
|
-
|
|
232
|
-
|
|
233
|
-
|
|
234
|
-
|
|
235
|
-
|
|
236
|
-
|
|
237
|
-
|
|
238
|
-
const category = candidate.orientation === "vertical" ? candidate.x : candidate.y;
|
|
239
|
-
const measure = candidate.orientation === "vertical" ? candidate.y : candidate.x;
|
|
240
|
-
const categoryChannel = candidate.orientation === "vertical" ? "x" : "y";
|
|
241
|
-
const measureChannel = candidate.orientation === "vertical" ? "y" : "x";
|
|
242
|
-
next = setCartesianPosition(next, owner.id, categoryChannel, {
|
|
243
|
-
field: category.field,
|
|
244
|
-
fieldType: category.fieldType,
|
|
245
|
-
scale: category.scale
|
|
246
|
-
});
|
|
247
|
-
next = setCartesianRange(
|
|
248
|
-
next,
|
|
249
|
-
owner.id,
|
|
250
|
-
measureChannel,
|
|
251
|
-
BOX_FIELDS.q1,
|
|
252
|
-
BOX_FIELDS.q3,
|
|
253
|
-
measure.scale,
|
|
254
|
-
candidate.measure
|
|
255
|
-
);
|
|
256
|
-
next = next._withMarkConfig(current.whiskerId, {
|
|
113
|
+
let next = updateDistributionPositions(
|
|
114
|
+
program,
|
|
115
|
+
owner,
|
|
116
|
+
current,
|
|
117
|
+
candidate,
|
|
118
|
+
{
|
|
119
|
+
owned,
|
|
120
|
+
lower: BOX_FIELDS.q1,
|
|
121
|
+
upper: BOX_FIELDS.q3,
|
|
122
|
+
title: candidate.measure,
|
|
123
|
+
update(next, { category, measure, categoryChannel, measureChannel }) {
|
|
124
|
+
next = next._withMarkConfig(current.whiskerId, {
|
|
257
125
|
...whiskerConfig,
|
|
258
126
|
errorBar: {
|
|
259
127
|
...whiskerConfig.errorBar,
|
|
@@ -265,13 +133,13 @@ function updateBoxPositions(program, owner, current, candidate, {
|
|
|
265
133
|
positionScale: category.scale,
|
|
266
134
|
intervalScale: measure.scale
|
|
267
135
|
}
|
|
268
|
-
|
|
269
|
-
|
|
136
|
+
});
|
|
137
|
+
next = setCartesianPosition(next, current.whiskerId, categoryChannel, {
|
|
270
138
|
field: category.field,
|
|
271
139
|
fieldType: category.fieldType,
|
|
272
140
|
scale: category.scale
|
|
273
141
|
});
|
|
274
|
-
|
|
142
|
+
next = setCartesianRange(
|
|
275
143
|
next,
|
|
276
144
|
current.whiskerId,
|
|
277
145
|
measureChannel,
|
|
@@ -279,8 +147,8 @@ function updateBoxPositions(program, owner, current, candidate, {
|
|
|
279
147
|
BOX_FIELDS.upperWhisker,
|
|
280
148
|
measure.scale,
|
|
281
149
|
candidate.measure
|
|
282
|
-
|
|
283
|
-
|
|
150
|
+
);
|
|
151
|
+
for (const [index, capId] of capIds.entries()) {
|
|
284
152
|
const field = index === 0 ? BOX_FIELDS.lowerWhisker : BOX_FIELDS.upperWhisker;
|
|
285
153
|
next = setCartesianPosition(next, capId, categoryChannel, {
|
|
286
154
|
field: category.field,
|
|
@@ -300,18 +168,18 @@ function updateBoxPositions(program, owner, current, candidate, {
|
|
|
300
168
|
: "vertical"
|
|
301
169
|
}
|
|
302
170
|
});
|
|
303
|
-
|
|
304
|
-
|
|
171
|
+
}
|
|
172
|
+
next = setCartesianPosition(next, current.medianId, categoryChannel, {
|
|
305
173
|
field: category.field,
|
|
306
174
|
fieldType: category.fieldType,
|
|
307
175
|
scale: category.scale
|
|
308
176
|
});
|
|
309
|
-
|
|
177
|
+
next = setCartesianPosition(next, current.medianId, measureChannel, {
|
|
310
178
|
field: BOX_FIELDS.median,
|
|
311
179
|
fieldType: "quantitative",
|
|
312
180
|
scale: measure.scale
|
|
313
181
|
});
|
|
314
|
-
|
|
182
|
+
if (hasOutliers && findLayer(next, current.outlierId) !== undefined) {
|
|
315
183
|
next = setCartesianPosition(next, current.outlierId, categoryChannel, {
|
|
316
184
|
field: category.field,
|
|
317
185
|
fieldType: category.fieldType,
|
|
@@ -322,25 +190,11 @@ function updateBoxPositions(program, owner, current, candidate, {
|
|
|
322
190
|
fieldType: "quantitative",
|
|
323
191
|
scale: measure.scale
|
|
324
192
|
});
|
|
325
|
-
|
|
326
|
-
|
|
327
|
-
|
|
328
|
-
|
|
329
|
-
|
|
330
|
-
oldXScale: candidate.previous.x.scale,
|
|
331
|
-
oldYScale: candidate.previous.y.scale,
|
|
332
|
-
newXScale: candidate.xScale.id,
|
|
333
|
-
newYScale: candidate.yScale.id,
|
|
334
|
-
oldXTitle: candidate.previous.x.field,
|
|
335
|
-
oldYTitle: candidate.previous.y.field,
|
|
336
|
-
newXTitle: candidate.x.field,
|
|
337
|
-
newYTitle: candidate.y.field,
|
|
338
|
-
oldMeasureChannel: current.orientation === "vertical" ? "y" : "x",
|
|
339
|
-
newMeasureChannel: candidate.orientation === "vertical" ? "y" : "x"
|
|
340
|
-
});
|
|
341
|
-
for (const scale of [candidate.xScale, candidate.yScale]) {
|
|
342
|
-
if (scale.edit !== undefined) next = next.editScale(scale.edit);
|
|
343
|
-
}
|
|
193
|
+
}
|
|
194
|
+
return next;
|
|
195
|
+
}
|
|
196
|
+
}
|
|
197
|
+
);
|
|
344
198
|
next = next.rematerializeBarMark({ id: owner.id })
|
|
345
199
|
.rematerializeErrorBar({ id: current.whiskerId });
|
|
346
200
|
for (const capId of capIds) {
|
|
@@ -413,7 +267,9 @@ export const editBoxPlot = action(
|
|
|
413
267
|
key => Object.hasOwn(args, key)
|
|
414
268
|
);
|
|
415
269
|
const changesRoles = !sameRoleCandidate(current, candidate);
|
|
416
|
-
|
|
270
|
+
const revisesData = JSON.stringify(whisker) !== JSON.stringify(current.whisker) ||
|
|
271
|
+
outliers !== current.outliers;
|
|
272
|
+
if (changesRoles || revisesData) {
|
|
417
273
|
const derived = deriveBoxData(
|
|
418
274
|
sourceDataset.values,
|
|
419
275
|
normalizeBoxTransform({
|
|
@@ -556,7 +412,6 @@ export const editBoxPlot = action(
|
|
|
556
412
|
currentData: candidate.source
|
|
557
413
|
});
|
|
558
414
|
};
|
|
559
|
-
applyEdit(this);
|
|
560
415
|
return applyEdit(this);
|
|
561
416
|
}
|
|
562
417
|
if (roleRequested && !OPTIONS.slice(4).some(
|
|
@@ -568,110 +423,11 @@ export const editBoxPlot = action(
|
|
|
568
423
|
});
|
|
569
424
|
}
|
|
570
425
|
|
|
571
|
-
const
|
|
572
|
-
|
|
573
|
-
const
|
|
574
|
-
Object.hasOwn(args, "width") || revisesData;
|
|
575
|
-
const changesMedian = Object.hasOwn(args, "median") ||
|
|
576
|
-
Object.hasOwn(args, "width") || revisesData;
|
|
577
|
-
const changesOutlier = Object.hasOwn(args, "outlier") || revisesData;
|
|
578
|
-
const categoryEncoding = current.orientation === "vertical"
|
|
579
|
-
? owner.encoding.x
|
|
580
|
-
: owner.encoding.y;
|
|
581
|
-
const measureEncoding = current.orientation === "vertical"
|
|
582
|
-
? owner.encoding.y
|
|
583
|
-
: owner.encoding.x;
|
|
584
|
-
let summaryId = current.summaryId;
|
|
585
|
-
let outlierDataId = current.outlierDataId;
|
|
426
|
+
const changesBox = Object.hasOwn(args, "box") || Object.hasOwn(args, "width");
|
|
427
|
+
const changesMedian = Object.hasOwn(args, "median") || Object.hasOwn(args, "width");
|
|
428
|
+
const changesOutlier = Object.hasOwn(args, "outlier");
|
|
586
429
|
let next = this;
|
|
587
430
|
|
|
588
|
-
const sourceRows = findDataset(this, current.source).values;
|
|
589
|
-
const derived = deriveBoxData(sourceRows, normalizeBoxTransform({
|
|
590
|
-
type: "boxSummary",
|
|
591
|
-
category: current.category,
|
|
592
|
-
field: current.measure,
|
|
593
|
-
whisker: whisker.type,
|
|
594
|
-
...(whisker.factor === undefined ? {} : { factor: whisker.factor })
|
|
595
|
-
}));
|
|
596
|
-
const hasOutliers = outliers && whisker.type === "tukey" &&
|
|
597
|
-
derived.outliers.length > 0;
|
|
598
|
-
|
|
599
|
-
if (revisesData) {
|
|
600
|
-
const whiskerConfig = next.markConfigs[current.whiskerId];
|
|
601
|
-
const capIds = [
|
|
602
|
-
whiskerConfig.errorBar.lowerCapId,
|
|
603
|
-
whiskerConfig.errorBar.upperCapId
|
|
604
|
-
].filter(id => id !== undefined);
|
|
605
|
-
const summaryRevision = planDerivedDataRevision(this, {
|
|
606
|
-
owner: owner.id,
|
|
607
|
-
role: "SummaryData",
|
|
608
|
-
previous: current.summaryId,
|
|
609
|
-
consumers: [owner.id, current.whiskerId, ...capIds, current.medianId]
|
|
610
|
-
});
|
|
611
|
-
summaryId = summaryRevision.id;
|
|
612
|
-
next = next.createBoxSummaryData({
|
|
613
|
-
id: summaryId,
|
|
614
|
-
source: current.source,
|
|
615
|
-
category: current.category,
|
|
616
|
-
field: current.measure,
|
|
617
|
-
whisker: whisker.type,
|
|
618
|
-
...(whisker.factor === undefined ? {} : { factor: whisker.factor })
|
|
619
|
-
});
|
|
620
|
-
if (hasOutliers) {
|
|
621
|
-
const hadOutlierLayer = findLayer(next, current.outlierId) !== undefined;
|
|
622
|
-
const outlierRevision = planDerivedDataRevision(this, {
|
|
623
|
-
owner: owner.id,
|
|
624
|
-
role: "OutlierData",
|
|
625
|
-
...(current.outlierDataId === undefined
|
|
626
|
-
? {}
|
|
627
|
-
: { previous: current.outlierDataId }),
|
|
628
|
-
consumers: hadOutlierLayer ? [current.outlierId] : []
|
|
629
|
-
});
|
|
630
|
-
outlierDataId = outlierRevision.id;
|
|
631
|
-
next = next.createBoxOutlierData({
|
|
632
|
-
id: outlierDataId,
|
|
633
|
-
source: current.source,
|
|
634
|
-
category: current.category,
|
|
635
|
-
field: current.measure,
|
|
636
|
-
whisker: whisker.type,
|
|
637
|
-
factor: whisker.factor
|
|
638
|
-
});
|
|
639
|
-
for (const rebind of outlierRevision.rebinds) {
|
|
640
|
-
next = next.rebindLayerData(rebind);
|
|
641
|
-
}
|
|
642
|
-
} else {
|
|
643
|
-
outlierDataId = undefined;
|
|
644
|
-
}
|
|
645
|
-
|
|
646
|
-
for (const rebind of summaryRevision.rebinds) {
|
|
647
|
-
next = next.rebindLayerData(rebind);
|
|
648
|
-
}
|
|
649
|
-
next = next._withMarkConfig(current.whiskerId, {
|
|
650
|
-
...whiskerConfig,
|
|
651
|
-
errorBar: { ...whiskerConfig.errorBar, data: summaryId }
|
|
652
|
-
});
|
|
653
|
-
|
|
654
|
-
const hadOutlierLayer = findLayer(next, current.outlierId) !== undefined;
|
|
655
|
-
if (hadOutlierLayer && !hasOutliers) {
|
|
656
|
-
next = removeOwnedMark(next, current.outlierId);
|
|
657
|
-
} else if (!hadOutlierLayer && hasOutliers) {
|
|
658
|
-
next = next.createBoxOutliers({
|
|
659
|
-
id: current.outlierId,
|
|
660
|
-
data: outlierDataId,
|
|
661
|
-
category: current.category,
|
|
662
|
-
categoryType: categoryEncoding.fieldType,
|
|
663
|
-
measure: current.measure,
|
|
664
|
-
orientation: current.orientation,
|
|
665
|
-
coordinate: owner.coordinate,
|
|
666
|
-
categoryScale: categoryEncoding.scale,
|
|
667
|
-
measureScale: measureEncoding.scale,
|
|
668
|
-
shape: outlier.shape,
|
|
669
|
-
radius: outlier.radius,
|
|
670
|
-
opacity: outlier.opacity
|
|
671
|
-
});
|
|
672
|
-
}
|
|
673
|
-
}
|
|
674
|
-
|
|
675
431
|
next = next._withMarkConfig(owner.id, {
|
|
676
432
|
...next.markConfigs[owner.id],
|
|
677
433
|
boxPlot: {
|
|
@@ -682,8 +438,8 @@ export const editBoxPlot = action(
|
|
|
682
438
|
box,
|
|
683
439
|
median,
|
|
684
440
|
outlier,
|
|
685
|
-
summaryId,
|
|
686
|
-
outlierDataId
|
|
441
|
+
summaryId: current.summaryId,
|
|
442
|
+
outlierDataId: current.outlierDataId
|
|
687
443
|
},
|
|
688
444
|
barWidth: { band: width },
|
|
689
445
|
fill: box.fill,
|
|
@@ -693,9 +449,6 @@ export const editBoxPlot = action(
|
|
|
693
449
|
});
|
|
694
450
|
|
|
695
451
|
if (changesBox) next = next.rematerializeBarMark({ id: owner.id });
|
|
696
|
-
if (revisesData) {
|
|
697
|
-
next = next.rematerializeErrorBar({ id: current.whiskerId });
|
|
698
|
-
}
|
|
699
452
|
if (changesMedian) {
|
|
700
453
|
next = next
|
|
701
454
|
.encodeStroke({ target: current.medianId, value: median.stroke })
|
|
@@ -714,12 +467,6 @@ export const editBoxPlot = action(
|
|
|
714
467
|
.encodeRadius({ target: current.outlierId, value: outlier.radius });
|
|
715
468
|
}
|
|
716
469
|
|
|
717
|
-
if (revisesData) {
|
|
718
|
-
next = next.releaseDerivedData({ id: current.summaryId });
|
|
719
|
-
if (current.outlierDataId !== undefined) {
|
|
720
|
-
next = next.releaseDerivedData({ id: current.outlierDataId });
|
|
721
|
-
}
|
|
722
|
-
}
|
|
723
470
|
return next._withContext({ currentMark: owner.id, currentData: current.source });
|
|
724
471
|
}
|
|
725
472
|
);
|