ggaction 0.0.15 → 0.0.16
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 +68 -0
- package/README.md +22 -2
- package/knowledge/action-cards.json +1 -1
- package/knowledge/intent-taxonomy.json +1 -1
- package/knowledge/mcp-resources.json +1 -1
- package/knowledge/task-packet.schema.json +1 -1
- package/knowledge/task-resolver.js +1 -1
- package/package.json +33 -6
- package/src/BasicChartProgram.js +3 -1
- package/src/ChartProgram.js +2 -0
- package/src/accessibility.js +157 -0
- package/src/actions/boxPlots/components.js +6 -8
- package/src/actions/boxPlots/create.js +4 -5
- package/src/actions/boxPlots/edit.js +3 -4
- package/src/actions/boxPlots/materialize.js +1 -1
- package/src/actions/canvas/actions.js +3 -3
- package/src/actions/canvas/fitting.js +1 -1
- package/src/actions/categoryOrder/index.js +6 -8
- package/src/actions/charts/area.js +1 -1
- package/src/actions/charts/bar.js +1 -1
- package/src/actions/charts/beeswarm.js +1 -1
- package/src/actions/charts/density.js +1 -1
- package/src/actions/charts/ecdf.js +2 -2
- package/src/actions/charts/endpoints.js +4 -4
- package/src/actions/charts/heatmap.js +1 -1
- package/src/actions/charts/histogram.js +1 -1
- package/src/actions/charts/horizon.js +1 -1
- package/src/actions/charts/interval-regression.js +2 -2
- package/src/actions/charts/line.js +1 -1
- package/src/actions/charts/parallel.js +1 -1
- package/src/actions/charts/pie.js +1 -1
- package/src/actions/charts/polar.js +2 -2
- package/src/actions/charts/radar.js +1 -1
- package/src/actions/charts/radial.js +2 -2
- package/src/actions/charts/raincloud.js +2 -2
- package/src/actions/charts/rug-strip.js +2 -2
- package/src/actions/charts/scatter.js +1 -1
- package/src/actions/composition/actions.js +20 -24
- package/src/actions/coordinates/actions.js +1 -1
- package/src/actions/coordinates/edit.js +1 -1
- package/src/actions/data/basicBin2d.js +4 -5
- package/src/actions/data/bin.js +2 -2
- package/src/actions/data/bin2d.js +6 -8
- package/src/actions/data/bin2dMaterialize.js +4 -5
- package/src/actions/data/box.js +4 -4
- package/src/actions/data/complete.js +2 -2
- package/src/actions/data/computed.js +2 -2
- package/src/actions/data/create.js +5 -12
- package/src/actions/data/density.js +3 -3
- package/src/actions/data/derived.js +10 -14
- package/src/actions/data/ecdf.js +2 -2
- package/src/actions/data/edit.js +35 -23
- package/src/actions/data/filter.js +14 -20
- package/src/actions/data/fold.js +2 -2
- package/src/actions/data/gradientProfile.js +2 -2
- package/src/actions/data/horizon.js +2 -2
- package/src/actions/data/impute.js +2 -2
- package/src/actions/data/index.js +55 -54
- package/src/actions/data/interval.js +2 -2
- package/src/actions/data/intervalEdit.js +26 -18
- package/src/actions/data/normalize.js +2 -2
- package/src/actions/data/regression.js +5 -6
- package/src/actions/data/revise.js +48 -0
- package/src/actions/data/revisionBindings.js +13 -33
- package/src/actions/data/stack.js +2 -2
- package/src/actions/data/summary.js +2 -2
- package/src/actions/data/timeUnit.js +2 -2
- package/src/actions/data/window.js +2 -2
- package/src/actions/encodings/angle.js +1 -1
- package/src/actions/encodings/appearance.js +4 -4
- package/src/actions/encodings/barWidth.js +1 -1
- package/src/actions/encodings/channels.js +2 -2
- package/src/actions/encodings/color/index.js +1 -1
- package/src/actions/encodings/density.js +2 -2
- package/src/actions/encodings/histogram.js +1 -1
- package/src/actions/encodings/horizon.js +6 -8
- package/src/actions/encodings/offset.js +2 -2
- package/src/actions/encodings/parallel.js +4 -5
- package/src/actions/encodings/pathOrder.js +6 -11
- package/src/actions/encodings/position/index.js +4 -4
- package/src/actions/encodings/ranged.js +5 -5
- package/src/actions/encodings/remove.js +4 -5
- package/src/actions/encodings/ruleAppearance.js +1 -1
- package/src/actions/encodings/seriesLayout.js +1 -1
- package/src/actions/encodings/stroke.js +1 -1
- package/src/actions/encodings/strokeDash.js +2 -2
- package/src/actions/encodings/text.js +1 -1
- package/src/actions/errorBands/create.js +11 -17
- package/src/actions/errorBands/edit.js +13 -131
- package/src/actions/errorBars/create.js +8 -13
- package/src/actions/errorBars/edit.js +10 -121
- package/src/actions/facets/actions.js +30 -16
- package/src/actions/facets/derive.js +8 -2
- package/src/actions/facets/guides.js +4 -5
- package/src/actions/facets/replay.js +4 -5
- package/src/actions/gradientPlots/components.js +5 -6
- package/src/actions/gradientPlots/create.js +4 -5
- package/src/actions/gradientPlots/edit.js +4 -5
- package/src/actions/gradientPlots/materialize.js +2 -2
- package/src/actions/gradientPlots/rebind.js +4 -5
- package/src/actions/guides/axes/axes.js +23 -4
- package/src/actions/guides/axes/axis.js +2 -2
- package/src/actions/guides/axes/edit.js +2 -2
- package/src/actions/guides/axes/labels.js +9 -9
- package/src/actions/guides/axes/lines.js +9 -7
- package/src/actions/guides/axes/parallel/lifecycle.js +13 -13
- package/src/actions/guides/axes/parallel.js +5 -5
- package/src/actions/guides/axes/remove.js +4 -4
- package/src/actions/guides/axes/tickGroups.js +4 -4
- package/src/actions/guides/axes/ticks.js +13 -4
- package/src/actions/guides/axes/titles.js +10 -10
- package/src/actions/guides/grids/grid.js +18 -29
- package/src/actions/guides/guides.js +1 -1
- package/src/actions/guides/legends/blocks.js +1 -1
- package/src/actions/guides/legends/categorical/actions.js +4 -4
- package/src/actions/guides/legends/categorical/components.js +38 -33
- package/src/actions/guides/legends/categorical/layout.js +1 -1
- package/src/actions/guides/legends/categorical/symbols.js +27 -30
- package/src/actions/guides/legends/continuous/common.js +46 -8
- package/src/actions/guides/legends/continuous/gradient.js +89 -155
- package/src/actions/guides/legends/continuous/interval.js +13 -13
- package/src/actions/guides/legends/continuous/opacity.js +30 -79
- package/src/actions/guides/legends/continuous/stroke.js +22 -322
- package/src/actions/guides/legends/edit.js +1 -1
- package/src/actions/guides/legends/focused.js +5 -5
- package/src/actions/guides/legends/lane.js +6 -6
- package/src/actions/guides/legends/remove.js +4 -5
- package/src/actions/guides/legends/size.js +21 -82
- package/src/actions/guides/legends/strokeWidth.js +17 -77
- package/src/actions/guides/polar/axes/facade.js +4 -4
- package/src/actions/guides/polar/axes/labels.js +5 -5
- package/src/actions/guides/polar/axes/lines.js +9 -15
- package/src/actions/guides/polar/axes/ticks.js +9 -15
- package/src/actions/guides/polar/axes/titles.js +5 -5
- package/src/actions/guides/polar/grids.js +11 -13
- package/src/actions/index.js +2 -0
- package/src/actions/intervals/revision.js +126 -0
- package/src/actions/marks/arc/actions.js +3 -3
- package/src/actions/marks/area/actions.js +4 -4
- package/src/actions/marks/bar/create.js +1 -1
- package/src/actions/marks/bar/edit.js +1 -1
- package/src/actions/marks/bar/materialize.js +12 -38
- package/src/actions/marks/line/actions.js +3 -3
- package/src/actions/marks/point/create.js +1 -1
- package/src/actions/marks/point/edit.js +1 -1
- package/src/actions/marks/point/jitter.js +6 -8
- package/src/actions/marks/point/materialize.js +16 -24
- package/src/actions/marks/point/packing.js +6 -8
- package/src/actions/marks/rect/actions.js +3 -3
- package/src/actions/marks/references.js +8 -10
- package/src/actions/marks/remove.js +5 -49
- package/src/actions/marks/rule/actions.js +4 -4
- package/src/actions/marks/text/actions.js +5 -5
- package/src/actions/marks/text/layout.js +12 -20
- package/src/actions/marks/text/removal.js +1 -1
- package/src/actions/marks/text/selection.js +4 -5
- package/src/actions/marks/tick/actions.js +3 -3
- package/src/actions/primitives/createGraphics.js +5 -4
- package/src/actions/primitives/editGraphics.js +5 -4
- package/src/actions/primitives/graphicProperties.js +6 -0
- package/src/actions/primitives/semantic.js +10 -3
- package/src/actions/primitives/semanticAction.js +7 -4
- package/src/actions/primitives/semanticValidation/dataset.js +2 -4
- package/src/actions/regression/components.js +10 -14
- package/src/actions/regression/create.js +3 -4
- package/src/actions/regression/edit.js +3 -4
- package/src/actions/resources/remove.js +12 -11
- package/src/actions/scales/create.js +1 -1
- package/src/actions/scales/edit.js +1 -1
- package/src/actions/scales/materialize.js +1 -1
- package/src/actions/scales/offset.js +2 -2
- package/src/actions/scales/parallel.js +1 -1
- package/src/actions/scales/quantitativeColor.js +4 -5
- package/src/actions/selection/actions.js +25 -36
- package/src/actions/textMetrics/index.js +56 -0
- package/src/actions/theme/actions.js +2 -2
- package/src/actions/theme/reconcile.js +65 -121
- package/src/actions/titles/actions.js +8 -8
- package/src/actions/titles/resolve.js +3 -3
- package/src/actions/violinPlots/create.js +1 -1
- package/src/actions/violinPlots/edit.js +1 -1
- package/src/core/action.js +107 -35
- package/src/core/diagnostics.js +16 -0
- package/src/core/extensionRegistry.js +27 -0
- package/src/core/font.js +18 -0
- package/src/core/identifiers.js +5 -4
- package/src/core/immutable.js +10 -3
- package/src/core/optionRequirements.js +8 -0
- package/src/core/programState.js +1 -1
- package/src/core/resourceReferences.js +15 -6
- package/src/core/textMetricProfile.js +28 -0
- package/src/core/textMetrics.js +24 -3
- package/src/core/validation.js +22 -10
- package/src/diagnostics.js +1 -0
- package/src/grammar/impute.js +3 -2
- package/src/grammar/scales/types.js +8 -0
- package/src/grammar/schemas/graphicBounds.js +11 -11
- package/src/layout/labels.js +11 -10
- package/src/layout/legend.js +4 -4
- package/src/layout/legendItems.js +6 -6
- package/src/layout/text.js +10 -9
- package/src/layout/title.js +9 -9
- package/src/materialization/facetGuides/placement.js +1 -1
- package/src/materialization/facetGuides/preparation.js +1 -1
- package/src/materialization/facetHeaders.js +11 -10
- package/src/materialization/guides/layout.js +3 -3
- package/src/materialization/scaleGuideDependencies.js +10 -0
- package/src/materialization/selection/items/common.js +1 -1
- package/src/materialization/text.js +2 -2
- package/src/materialization/typography.js +31 -0
- package/src/mcp/cli.js +5 -3
- package/src/persistence/codec.js +65 -0
- package/src/persistence/validation.js +185 -0
- package/src/persistence.js +74 -0
- package/src/renderers/canvas/index.js +5 -4
- package/src/renderers/nativeBackend.js +10 -0
- package/src/renderers/options.js +13 -0
- package/src/renderers/pdf.js +25 -54
- package/src/renderers/png.js +22 -17
- package/src/renderers/svg.js +10 -14
- package/src/renderers/text.js +1 -11
- package/src/selectors/coordinates.js +3 -1
- package/src/selectors/datasets.js +8 -6
- package/src/selectors/layers.js +6 -4
- package/src/selectors/markOwners.js +46 -0
- package/src/selectors/scales.js +6 -4
- package/src/theme/defaults.js +2 -1
- package/src/version.js +2 -0
- package/types/accessibility.d.ts +37 -0
- package/types/basic.d.ts +4 -2
- package/types/diagnostics.d.ts +15 -0
- package/types/index.d.ts +5 -0
- package/types/pdf.d.ts +9 -0
- package/types/persistence.d.ts +7 -0
- package/types/png.d.ts +9 -0
- package/types/program.d.ts +34 -1
|
@@ -20,7 +20,7 @@ const STROKE_DASH_ENCODING_OPTIONS = Object.freeze([
|
|
|
20
20
|
"field", "value", "target", "fieldType", "scale"
|
|
21
21
|
]);
|
|
22
22
|
|
|
23
|
-
const clearStrokeDashEncoding = action(
|
|
23
|
+
const clearStrokeDashEncoding = /* @__PURE__ */ action(
|
|
24
24
|
{
|
|
25
25
|
op: "clearStrokeDashEncoding",
|
|
26
26
|
description: "Remove the current semantic stroke-dash assignment."
|
|
@@ -58,7 +58,7 @@ function reconcileLegendAfterDashRemoval(program, target) {
|
|
|
58
58
|
.rematerializeLegend();
|
|
59
59
|
}
|
|
60
60
|
|
|
61
|
-
const encodeStrokeDash = action(
|
|
61
|
+
const encodeStrokeDash = /* @__PURE__ */ action(
|
|
62
62
|
{
|
|
63
63
|
op: "encodeStrokeDash",
|
|
64
64
|
description: "Encode a nominal field as line stroke dash."
|
|
@@ -25,7 +25,7 @@ function validateTextField(rows, field, format) {
|
|
|
25
25
|
if (!found) throw new Error(`Unknown text field "${field}".`);
|
|
26
26
|
}
|
|
27
27
|
|
|
28
|
-
export const encodeText = action(
|
|
28
|
+
export const encodeText = /* @__PURE__ */ action(
|
|
29
29
|
{
|
|
30
30
|
op: "encodeText",
|
|
31
31
|
description: "Assign field, constant, or source semantic text content."
|
|
@@ -1,9 +1,7 @@
|
|
|
1
|
-
import {
|
|
1
|
+
import { editGraphicProperties } from "../primitives/graphicProperties.js";
|
|
2
|
+
import { action, closedAction } from "../../core/action.js";
|
|
2
3
|
import { isPlainObject } from "../../core/immutable.js";
|
|
3
|
-
import {
|
|
4
|
-
validateKeys,
|
|
5
|
-
validateNonEmptyString,
|
|
6
|
-
} from "../../core/validation.js";
|
|
4
|
+
import { validateNonEmptyString } from "../../core/validation.js";
|
|
7
5
|
import { DEFAULT_COLORS } from "../../theme/defaults.js";
|
|
8
6
|
import { validateCurveInterpolation } from "../../grammar/curveCommands.js";
|
|
9
7
|
import {
|
|
@@ -82,7 +80,7 @@ function positionOptions({ target, field, fieldType, coordinate, scale, temporal
|
|
|
82
80
|
...(temporalUnit === undefined ? {} : { temporalUnit }) };
|
|
83
81
|
}
|
|
84
82
|
|
|
85
|
-
export const createErrorBandBoundary = action(
|
|
83
|
+
export const createErrorBandBoundary = /* @__PURE__ */ action(
|
|
86
84
|
{
|
|
87
85
|
op: "createErrorBandBoundary",
|
|
88
86
|
description: "Create one lower or upper error-band boundary line."
|
|
@@ -138,14 +136,11 @@ export const createErrorBandBoundary = action(
|
|
|
138
136
|
if (groupBy !== undefined) {
|
|
139
137
|
next = next.encodeGroup({ target: id, field: groupBy });
|
|
140
138
|
}
|
|
141
|
-
return next
|
|
142
|
-
|
|
143
|
-
.
|
|
144
|
-
|
|
145
|
-
|
|
146
|
-
value: next.graphicSpec.objects[id].items.map(() => strokeDash)
|
|
147
|
-
})
|
|
148
|
-
.editGraphics({ target: id, property: "opacity", value: opacity });
|
|
139
|
+
return editGraphicProperties(next, id, {
|
|
140
|
+
stroke: stroke,
|
|
141
|
+
strokeDash: next.graphicSpec.objects[id].items.map(() => strokeDash),
|
|
142
|
+
opacity: opacity
|
|
143
|
+
});
|
|
149
144
|
}
|
|
150
145
|
);
|
|
151
146
|
|
|
@@ -171,13 +166,12 @@ function rangeArgs(resolved) {
|
|
|
171
166
|
};
|
|
172
167
|
}
|
|
173
168
|
|
|
174
|
-
export const createErrorBand =
|
|
169
|
+
export const createErrorBand = /* @__PURE__ */ closedAction(
|
|
175
170
|
{
|
|
176
171
|
op: "createErrorBand",
|
|
177
172
|
description: "Create a statistical or explicit interval band."
|
|
178
|
-
},
|
|
173
|
+
}, OPTIONS,
|
|
179
174
|
function (args = {}) {
|
|
180
|
-
validateKeys(args, OPTIONS, "createErrorBand");
|
|
181
175
|
const strokeDetails = requestedStrokeDetails(args, "createErrorBand");
|
|
182
176
|
const resolved = resolveErrorBand(this, args);
|
|
183
177
|
const curve = validateCurveInterpolation(args.curve ?? "linear");
|
|
@@ -1,13 +1,8 @@
|
|
|
1
|
-
import {
|
|
1
|
+
import { currentIntervalRoleArgs, resolveIntervalRoleScales, applyIntervalStatistics } from "../intervals/revision.js";
|
|
2
|
+
import { closedAction } from "../../core/action.js";
|
|
2
3
|
import { isPlainObject } from "../../core/immutable.js";
|
|
3
4
|
import { validateUserId } from "../../core/identifiers.js";
|
|
4
|
-
import {
|
|
5
|
-
validateOptionObject,
|
|
6
|
-
validateKeys,
|
|
7
|
-
validateNonEmptyString,
|
|
8
|
-
validateNonNegativeFinite,
|
|
9
|
-
validateUnitInterval
|
|
10
|
-
} from "../../core/validation.js";
|
|
5
|
+
import { validateKeys, validateNonEmptyString, validateNonNegativeFinite, validateUnitInterval } from "../../core/validation.js";
|
|
11
6
|
import { validateCurveInterpolation } from "../../grammar/curveCommands.js";
|
|
12
7
|
import { normalizeStrokeDashPattern } from "../../grammar/scales/index.js";
|
|
13
8
|
import {
|
|
@@ -15,12 +10,10 @@ import {
|
|
|
15
10
|
STROKE_STYLE_PROPERTIES
|
|
16
11
|
} from "../../grammar/strokeStyle.js";
|
|
17
12
|
import { findLayer } from "../../selectors/layers.js";
|
|
18
|
-
import { findSemanticScale } from "../../selectors/scales.js";
|
|
19
13
|
import { removeOwnedMark } from "../marks/remove.js";
|
|
20
14
|
import { DEFAULT_COLORS } from "../../theme/defaults.js";
|
|
21
15
|
import { resolveIntervalComposite } from "../intervals/resolve.js";
|
|
22
16
|
import {
|
|
23
|
-
resolveDistributionScalePlan,
|
|
24
17
|
setCartesianPosition,
|
|
25
18
|
updateDistributionPositions
|
|
26
19
|
} from "../distributions/revision.js";
|
|
@@ -68,7 +61,6 @@ const EDIT_OPTIONS = Object.freeze([
|
|
|
68
61
|
"target", "data", "x", "y", "groupBy", "fill", "opacity", "curve",
|
|
69
62
|
"statistics", "boundaries", ...STROKE_STYLE_PROPERTIES
|
|
70
63
|
]);
|
|
71
|
-
const STATISTICS_OPTIONS = Object.freeze(["center", "extent", "method", "level"]);
|
|
72
64
|
const EDIT_POLICY = Object.freeze({
|
|
73
65
|
operation: "editErrorBand",
|
|
74
66
|
resourceLabel: "error-band",
|
|
@@ -116,48 +108,13 @@ function resolveOwner(program, requested) {
|
|
|
116
108
|
});
|
|
117
109
|
}
|
|
118
110
|
|
|
119
|
-
function currentRoleArgs(program, owner, current) {
|
|
120
|
-
const transform = findIntervalTransform(program, current.data);
|
|
121
|
-
const intervalChannel = current.orientation === "vertical" ? "y" : "x";
|
|
122
|
-
const positionChannel = intervalChannel === "x" ? "y" : "x";
|
|
123
|
-
const position = {
|
|
124
|
-
field: current.position.field,
|
|
125
|
-
fieldType: current.position.fieldType,
|
|
126
|
-
...(current.position.temporalUnit === undefined
|
|
127
|
-
? {}
|
|
128
|
-
: { temporalUnit: current.position.temporalUnit }),
|
|
129
|
-
scale: { id: current.positionScale }
|
|
130
|
-
};
|
|
131
|
-
const interval = transform === undefined
|
|
132
|
-
? {
|
|
133
|
-
center: current.centerField ?? owner.encoding[intervalChannel].title,
|
|
134
|
-
lower: current.lowerField,
|
|
135
|
-
upper: current.upperField,
|
|
136
|
-
scale: { id: current.intervalScale }
|
|
137
|
-
}
|
|
138
|
-
: {
|
|
139
|
-
field: transform.field,
|
|
140
|
-
center: transform.center,
|
|
141
|
-
extent: transform.extent,
|
|
142
|
-
...(transform.method === undefined ? {} : { method: transform.method }),
|
|
143
|
-
...(transform.level === undefined ? {} : { level: transform.level }),
|
|
144
|
-
scale: { id: current.intervalScale }
|
|
145
|
-
};
|
|
146
|
-
return {
|
|
147
|
-
source: current.source ?? transform?.source ?? current.data,
|
|
148
|
-
x: positionChannel === "x" ? position : interval,
|
|
149
|
-
y: positionChannel === "y" ? position : interval,
|
|
150
|
-
groupBy: current.groupBy
|
|
151
|
-
};
|
|
152
|
-
}
|
|
153
|
-
|
|
154
111
|
function channelArgs(requested, fallback) {
|
|
155
112
|
if (requested === undefined) return fallback;
|
|
156
113
|
return requested;
|
|
157
114
|
}
|
|
158
115
|
|
|
159
116
|
function resolveRoleCandidate(program, owner, current, args) {
|
|
160
|
-
const previous =
|
|
117
|
+
const previous = currentIntervalRoleArgs(program, owner, current, false);
|
|
161
118
|
const full = {
|
|
162
119
|
data: Object.hasOwn(args, "data") ? args.data : previous.source,
|
|
163
120
|
x: channelArgs(args.x, previous.x),
|
|
@@ -179,75 +136,11 @@ function resolveRoleCandidate(program, owner, current, args) {
|
|
|
179
136
|
"editErrorBand groupBy must differ from the independent position field."
|
|
180
137
|
);
|
|
181
138
|
}
|
|
182
|
-
|
|
183
|
-
|
|
184
|
-
throw new TypeError("editErrorBand statistics must be a plain object.");
|
|
185
|
-
}
|
|
186
|
-
validateKeys(args.statistics, STATISTICS_OPTIONS, "editErrorBand statistics");
|
|
187
|
-
if (!STATISTICS_OPTIONS.some(key => Object.hasOwn(args.statistics, key))) {
|
|
188
|
-
throw new Error(
|
|
189
|
-
"editErrorBand statistics requires center, extent, method, or level."
|
|
190
|
-
);
|
|
191
|
-
}
|
|
192
|
-
full[resolved.interval.channel] = {
|
|
193
|
-
...full[resolved.interval.channel],
|
|
194
|
-
...args.statistics
|
|
195
|
-
};
|
|
196
|
-
resolved = resolveIntervalComposite(program, full, policy);
|
|
197
|
-
}
|
|
198
|
-
const positionRole = {
|
|
199
|
-
field: resolved.position.field,
|
|
200
|
-
fieldType: resolved.position.fieldType,
|
|
201
|
-
scale: resolved.position.scale
|
|
202
|
-
};
|
|
203
|
-
const intervalTitle = resolved.interval.mode === "statistical"
|
|
204
|
-
? resolved.interval.field
|
|
205
|
-
: resolved.interval.title;
|
|
206
|
-
const intervalRole = {
|
|
207
|
-
field: intervalTitle,
|
|
208
|
-
fieldType: "quantitative",
|
|
209
|
-
scale: resolved.interval.scale
|
|
210
|
-
};
|
|
211
|
-
const x = resolved.position.channel === "x" ? positionRole : intervalRole;
|
|
212
|
-
const y = resolved.position.channel === "y" ? positionRole : intervalRole;
|
|
213
|
-
const plan = (channel, role) => {
|
|
214
|
-
const fallback = role === intervalRole
|
|
215
|
-
? current.intervalScale
|
|
216
|
-
: current.positionScale;
|
|
217
|
-
const stored = findSemanticScale(program, fallback);
|
|
218
|
-
const compatible = role.fieldType === "temporal"
|
|
219
|
-
? stored?.type === "time"
|
|
220
|
-
: ["linear", "log", "pow", "sqrt", "symlog"].includes(stored?.type);
|
|
221
|
-
const requested = role.scale.type !== undefined || compatible
|
|
222
|
-
? role.scale
|
|
223
|
-
: { ...role.scale, type: role.fieldType === "temporal" ? "time" : "linear" };
|
|
224
|
-
return resolveDistributionScalePlan(program, {
|
|
225
|
-
channel,
|
|
226
|
-
fieldType: role.fieldType,
|
|
227
|
-
requested,
|
|
228
|
-
fallback,
|
|
229
|
-
defaults: role === intervalRole
|
|
230
|
-
? EDIT_POLICY.intervalScaleDefaults
|
|
231
|
-
: EDIT_POLICY.scaleDefaults(role.fieldType)
|
|
232
|
-
});
|
|
233
|
-
};
|
|
234
|
-
const xScale = plan("x", x);
|
|
235
|
-
const yScale = plan("y", y);
|
|
139
|
+
resolved = applyIntervalStatistics(program, full, policy, args, resolved);
|
|
140
|
+
const roles = resolveIntervalRoleScales(program, resolved, current, EDIT_POLICY, owner, previous);
|
|
236
141
|
return {
|
|
237
142
|
...resolved,
|
|
238
|
-
|
|
239
|
-
y: { ...y, scale: yScale.id },
|
|
240
|
-
xScale,
|
|
241
|
-
yScale,
|
|
242
|
-
category: resolved.position.field,
|
|
243
|
-
categoryType: resolved.position.fieldType,
|
|
244
|
-
measure: intervalTitle,
|
|
245
|
-
previous: {
|
|
246
|
-
x: { field: previous.x.center ?? previous.x.field,
|
|
247
|
-
fieldType: owner.encoding.x.fieldType, scale: owner.encoding.x.scale },
|
|
248
|
-
y: { field: previous.y.center ?? previous.y.field,
|
|
249
|
-
fieldType: owner.encoding.y.fieldType, scale: owner.encoding.y.scale }
|
|
250
|
-
}
|
|
143
|
+
...roles
|
|
251
144
|
};
|
|
252
145
|
}
|
|
253
146
|
|
|
@@ -389,17 +282,12 @@ function removeBoundary(program, id) {
|
|
|
389
282
|
return removeOwnedMark(program, id);
|
|
390
283
|
}
|
|
391
284
|
|
|
392
|
-
export const rematerializeErrorBandBoundary =
|
|
285
|
+
export const rematerializeErrorBandBoundary = /* @__PURE__ */ closedAction(
|
|
393
286
|
{
|
|
394
287
|
op: "rematerializeErrorBandBoundary",
|
|
395
288
|
description: "Rematerialize one owned error-band boundary."
|
|
396
|
-
},
|
|
289
|
+
}, REMATERIALIZE_OPTIONS,
|
|
397
290
|
function (args = {}) {
|
|
398
|
-
validateOptionObject(
|
|
399
|
-
args,
|
|
400
|
-
REMATERIALIZE_OPTIONS,
|
|
401
|
-
"rematerializeErrorBandBoundary"
|
|
402
|
-
);
|
|
403
291
|
const id = validateUserId(args.id, "Error-band boundary id");
|
|
404
292
|
currentBoundaryAppearance(this, id);
|
|
405
293
|
const graphic = this.graphicSpec.objects[id];
|
|
@@ -422,13 +310,12 @@ export const rematerializeErrorBandBoundary = action(
|
|
|
422
310
|
}
|
|
423
311
|
);
|
|
424
312
|
|
|
425
|
-
export const editErrorBand =
|
|
313
|
+
export const editErrorBand = /* @__PURE__ */ closedAction(
|
|
426
314
|
{
|
|
427
315
|
op: "editErrorBand",
|
|
428
316
|
description: "Revise one error band's roles, statistics, body, and boundaries."
|
|
429
|
-
},
|
|
317
|
+
}, EDIT_OPTIONS,
|
|
430
318
|
function (args = {}) {
|
|
431
|
-
validateOptionObject(args, EDIT_OPTIONS, "editErrorBand");
|
|
432
319
|
if (!["data", "x", "y", "groupBy", "fill", "opacity", "curve",
|
|
433
320
|
"statistics", "boundaries", ...STROKE_STYLE_PROPERTIES]
|
|
434
321
|
.some(key => Object.hasOwn(args, key))) {
|
|
@@ -585,17 +472,12 @@ export const editErrorBand = action(
|
|
|
585
472
|
}
|
|
586
473
|
);
|
|
587
474
|
|
|
588
|
-
export const editErrorBandBoundary =
|
|
475
|
+
export const editErrorBandBoundary = /* @__PURE__ */ closedAction(
|
|
589
476
|
{
|
|
590
477
|
op: "editErrorBandBoundary",
|
|
591
478
|
description: "Edit one or both owned error-band boundaries."
|
|
592
|
-
},
|
|
479
|
+
}, BOUNDARY_EDIT_OPTIONS,
|
|
593
480
|
function (args = {}) {
|
|
594
|
-
validateOptionObject(
|
|
595
|
-
args,
|
|
596
|
-
BOUNDARY_EDIT_OPTIONS,
|
|
597
|
-
"editErrorBandBoundary"
|
|
598
|
-
);
|
|
599
481
|
if (!ERROR_BAND_BOUNDARY_OPTIONS.some(key => Object.hasOwn(args, key))) {
|
|
600
482
|
throw new Error("editErrorBandBoundary requires an appearance change.");
|
|
601
483
|
}
|
|
@@ -1,8 +1,5 @@
|
|
|
1
|
-
import {
|
|
2
|
-
import {
|
|
3
|
-
validateKeys,
|
|
4
|
-
validateOptionObject
|
|
5
|
-
} from "../../core/validation.js";
|
|
1
|
+
import { closedAction } from "../../core/action.js";
|
|
2
|
+
import { validateOptionObject } from "../../core/validation.js";
|
|
6
3
|
import { findLayer } from "../../selectors/layers.js";
|
|
7
4
|
import { findDataset } from "../../selectors/datasets.js";
|
|
8
5
|
import { findSemanticScale } from "../../selectors/scales.js";
|
|
@@ -144,20 +141,19 @@ function resolveAppearance(args) {
|
|
|
144
141
|
});
|
|
145
142
|
}
|
|
146
143
|
|
|
147
|
-
export const createErrorBarCap =
|
|
144
|
+
export const createErrorBarCap = /* @__PURE__ */ closedAction(
|
|
148
145
|
{
|
|
149
146
|
op: "createErrorBarCap",
|
|
150
147
|
description: "Create one fixed-pixel error-bar cap."
|
|
151
|
-
},
|
|
152
|
-
function (args = {}) {
|
|
153
|
-
validateKeys(args, [
|
|
148
|
+
}, [
|
|
154
149
|
"id", "data", "orientation", "positionField", "positionFieldType",
|
|
155
150
|
"intervalField", "coordinate", "positionScale", "intervalScale", "positionTemporalUnit",
|
|
156
151
|
"offsetChannel", "offsetField", "offsetFieldType", "offsetScale",
|
|
157
152
|
"offsetPaddingInner", "offsetPaddingOuter",
|
|
158
153
|
"capSize", "stroke", "strokeWidth", "strokeDash", "opacity",
|
|
159
154
|
...STROKE_STYLE_PROPERTIES
|
|
160
|
-
],
|
|
155
|
+
],
|
|
156
|
+
function (args = {}) {
|
|
161
157
|
if (!["vertical", "horizontal"].includes(args.orientation)) {
|
|
162
158
|
throw new Error(`Unsupported error-bar orientation "${args.orientation}".`);
|
|
163
159
|
}
|
|
@@ -256,13 +252,12 @@ function intervalArgs(resolved, field) {
|
|
|
256
252
|
};
|
|
257
253
|
}
|
|
258
254
|
|
|
259
|
-
export const createErrorBar =
|
|
255
|
+
export const createErrorBar = /* @__PURE__ */ closedAction(
|
|
260
256
|
{
|
|
261
257
|
op: "createErrorBar",
|
|
262
258
|
description: "Create a statistical or explicit vertical or horizontal interval."
|
|
263
|
-
},
|
|
259
|
+
}, OPTIONS,
|
|
264
260
|
function (args = {}) {
|
|
265
|
-
validateKeys(args, OPTIONS, "createErrorBar");
|
|
266
261
|
const resolved = resolveErrorBar(this, args);
|
|
267
262
|
const appearance = resolveAppearance(args);
|
|
268
263
|
let next = createResolvedIntervalData(this, resolved);
|
|
@@ -1,5 +1,5 @@
|
|
|
1
|
-
import {
|
|
2
|
-
import {
|
|
1
|
+
import { currentIntervalRoleArgs, resolveIntervalRoleScales, applyIntervalStatistics } from "../intervals/revision.js";
|
|
2
|
+
import { closedAction } from "../../core/action.js";
|
|
3
3
|
import { validateUserId } from "../../core/identifiers.js";
|
|
4
4
|
import {
|
|
5
5
|
validateKeys,
|
|
@@ -14,10 +14,8 @@ import {
|
|
|
14
14
|
validateRuleStrokeWidth
|
|
15
15
|
} from "../../grammar/ruleAppearance.js";
|
|
16
16
|
import { findLayer } from "../../selectors/layers.js";
|
|
17
|
-
import { findSemanticScale } from "../../selectors/scales.js";
|
|
18
17
|
import { resolveIntervalComposite } from "../intervals/resolve.js";
|
|
19
18
|
import {
|
|
20
|
-
resolveDistributionScalePlan,
|
|
21
19
|
setCartesianPosition,
|
|
22
20
|
updateDistributionPositions
|
|
23
21
|
} from "../distributions/revision.js";
|
|
@@ -46,7 +44,6 @@ export const ERROR_BAR_APPEARANCE_OPTIONS = Object.freeze([
|
|
|
46
44
|
"caps", "capSize", "stroke", "strokeWidth", "strokeDash", "opacity",
|
|
47
45
|
...STROKE_STYLE_PROPERTIES
|
|
48
46
|
]);
|
|
49
|
-
const STATISTICS_OPTIONS = Object.freeze(["center", "extent", "method", "level"]);
|
|
50
47
|
const EDIT_POLICY = Object.freeze({
|
|
51
48
|
operation: "editErrorBar",
|
|
52
49
|
resourceLabel: "error-bar",
|
|
@@ -115,45 +112,8 @@ function resolveOwner(program, requested) {
|
|
|
115
112
|
});
|
|
116
113
|
}
|
|
117
114
|
|
|
118
|
-
function currentRoleArgs(program, owner, current) {
|
|
119
|
-
const transform = findIntervalTransform(program, current.data);
|
|
120
|
-
const intervalChannel = current.orientation === "vertical" ? "y" : "x";
|
|
121
|
-
const positionChannel = intervalChannel === "x" ? "y" : "x";
|
|
122
|
-
const position = {
|
|
123
|
-
field: current.positionField,
|
|
124
|
-
fieldType: current.positionFieldType,
|
|
125
|
-
...(current.positionTemporalUnit === undefined
|
|
126
|
-
? {}
|
|
127
|
-
: { temporalUnit: current.positionTemporalUnit }),
|
|
128
|
-
scale: { id: current.positionScale }
|
|
129
|
-
};
|
|
130
|
-
const interval = transform === undefined
|
|
131
|
-
? {
|
|
132
|
-
center: current.centerField ?? owner.encoding[intervalChannel].title,
|
|
133
|
-
lower: current.lowerField,
|
|
134
|
-
upper: current.upperField,
|
|
135
|
-
scale: { id: current.intervalScale }
|
|
136
|
-
}
|
|
137
|
-
: {
|
|
138
|
-
field: transform.field,
|
|
139
|
-
center: transform.center,
|
|
140
|
-
extent: transform.extent,
|
|
141
|
-
...(transform.method === undefined ? {} : { method: transform.method }),
|
|
142
|
-
...(transform.level === undefined ? {} : { level: transform.level }),
|
|
143
|
-
scale: { id: current.intervalScale }
|
|
144
|
-
};
|
|
145
|
-
return {
|
|
146
|
-
source: current.source ?? transform?.source ?? current.data,
|
|
147
|
-
x: positionChannel === "x" ? position : interval,
|
|
148
|
-
y: positionChannel === "y" ? position : interval,
|
|
149
|
-
groupBy: current.groupField ?? transform?.groupBy?.find(
|
|
150
|
-
field => field !== current.positionField
|
|
151
|
-
)
|
|
152
|
-
};
|
|
153
|
-
}
|
|
154
|
-
|
|
155
115
|
function resolveRoleCandidate(program, owner, current, args) {
|
|
156
|
-
const previous =
|
|
116
|
+
const previous = currentIntervalRoleArgs(program, owner, current, true);
|
|
157
117
|
const full = {
|
|
158
118
|
data: Object.hasOwn(args, "data") ? args.data : previous.source,
|
|
159
119
|
x: Object.hasOwn(args, "x") ? args.x : previous.x,
|
|
@@ -170,65 +130,8 @@ function resolveRoleCandidate(program, owner, current, args) {
|
|
|
170
130
|
generatedFields: findIntervalTransform(program, current.data)?.as
|
|
171
131
|
};
|
|
172
132
|
let resolved = resolveIntervalComposite(program, full, policy);
|
|
173
|
-
|
|
174
|
-
|
|
175
|
-
throw new TypeError("editErrorBar statistics must be a plain object.");
|
|
176
|
-
}
|
|
177
|
-
validateKeys(args.statistics, STATISTICS_OPTIONS, "editErrorBar statistics");
|
|
178
|
-
if (!STATISTICS_OPTIONS.some(key => Object.hasOwn(args.statistics, key))) {
|
|
179
|
-
throw new Error(
|
|
180
|
-
"editErrorBar statistics requires center, extent, method, or level."
|
|
181
|
-
);
|
|
182
|
-
}
|
|
183
|
-
full[resolved.interval.channel] = {
|
|
184
|
-
...full[resolved.interval.channel],
|
|
185
|
-
...args.statistics
|
|
186
|
-
};
|
|
187
|
-
resolved = resolveIntervalComposite(program, full, policy);
|
|
188
|
-
}
|
|
189
|
-
const positionRole = {
|
|
190
|
-
field: resolved.position.field,
|
|
191
|
-
fieldType: resolved.position.fieldType,
|
|
192
|
-
scale: resolved.position.scale
|
|
193
|
-
};
|
|
194
|
-
const intervalTitle = resolved.interval.mode === "statistical"
|
|
195
|
-
? resolved.interval.field
|
|
196
|
-
: resolved.interval.title;
|
|
197
|
-
const intervalRole = {
|
|
198
|
-
field: intervalTitle,
|
|
199
|
-
fieldType: "quantitative",
|
|
200
|
-
scale: resolved.interval.scale
|
|
201
|
-
};
|
|
202
|
-
const x = resolved.position.channel === "x" ? positionRole : intervalRole;
|
|
203
|
-
const y = resolved.position.channel === "y" ? positionRole : intervalRole;
|
|
204
|
-
const plan = (channel, role) => {
|
|
205
|
-
const fallback = role === intervalRole
|
|
206
|
-
? current.intervalScale
|
|
207
|
-
: current.positionScale;
|
|
208
|
-
const stored = findSemanticScale(program, fallback);
|
|
209
|
-
const compatible = role.fieldType === "temporal"
|
|
210
|
-
? stored?.type === "time"
|
|
211
|
-
: ["nominal", "ordinal"].includes(role.fieldType)
|
|
212
|
-
? ["band", "point"].includes(stored?.type)
|
|
213
|
-
: ["linear", "log", "pow", "sqrt", "symlog"].includes(stored?.type);
|
|
214
|
-
const defaultType = role.fieldType === "temporal"
|
|
215
|
-
? "time"
|
|
216
|
-
: ["nominal", "ordinal"].includes(role.fieldType) ? "band" : "linear";
|
|
217
|
-
const requested = role.scale.type !== undefined || compatible
|
|
218
|
-
? role.scale
|
|
219
|
-
: { ...role.scale, type: defaultType };
|
|
220
|
-
return resolveDistributionScalePlan(program, {
|
|
221
|
-
channel,
|
|
222
|
-
fieldType: role.fieldType,
|
|
223
|
-
requested,
|
|
224
|
-
fallback,
|
|
225
|
-
defaults: role === intervalRole
|
|
226
|
-
? EDIT_POLICY.intervalScaleDefaults
|
|
227
|
-
: EDIT_POLICY.scaleDefaults(role.fieldType)
|
|
228
|
-
});
|
|
229
|
-
};
|
|
230
|
-
const xScale = plan("x", x);
|
|
231
|
-
const yScale = plan("y", y);
|
|
133
|
+
resolved = applyIntervalStatistics(program, full, policy, args, resolved);
|
|
134
|
+
const roles = resolveIntervalRoleScales(program, resolved, current, EDIT_POLICY, owner, previous);
|
|
232
135
|
const expectedOffset = `${resolved.position.channel}Offset`;
|
|
233
136
|
const incompatibleOffset = expectedOffset === "xOffset" ? "yOffset" : "xOffset";
|
|
234
137
|
if (Object.hasOwn(args, incompatibleOffset)) {
|
|
@@ -270,19 +173,7 @@ function resolveRoleCandidate(program, owner, current, args) {
|
|
|
270
173
|
return {
|
|
271
174
|
...resolved,
|
|
272
175
|
offset: normalizedOffset,
|
|
273
|
-
|
|
274
|
-
y: { ...y, scale: yScale.id },
|
|
275
|
-
xScale,
|
|
276
|
-
yScale,
|
|
277
|
-
category: resolved.position.field,
|
|
278
|
-
categoryType: resolved.position.fieldType,
|
|
279
|
-
measure: intervalTitle,
|
|
280
|
-
previous: {
|
|
281
|
-
x: { field: previous.x.center ?? previous.x.field,
|
|
282
|
-
fieldType: owner.encoding.x.fieldType, scale: owner.encoding.x.scale },
|
|
283
|
-
y: { field: previous.y.center ?? previous.y.field,
|
|
284
|
-
fieldType: owner.encoding.y.fieldType, scale: owner.encoding.y.scale }
|
|
285
|
-
}
|
|
176
|
+
...roles
|
|
286
177
|
};
|
|
287
178
|
}
|
|
288
179
|
|
|
@@ -460,13 +351,12 @@ function updateErrorBarRoles(program, owner, current, candidate, dataId, capIds)
|
|
|
460
351
|
return next.rematerializeErrorBar({ id: owner.id });
|
|
461
352
|
}
|
|
462
353
|
|
|
463
|
-
export const rematerializeErrorBar =
|
|
354
|
+
export const rematerializeErrorBar = /* @__PURE__ */ closedAction(
|
|
464
355
|
{
|
|
465
356
|
op: "rematerializeErrorBar",
|
|
466
357
|
description: "Reconcile one error bar and its owned caps."
|
|
467
|
-
},
|
|
358
|
+
}, REMATERIALIZE_OPTIONS,
|
|
468
359
|
function (args = {}) {
|
|
469
|
-
validateKeys(args, REMATERIALIZE_OPTIONS, "rematerializeErrorBar");
|
|
470
360
|
const id = validateUserId(args.id, "Error-bar id");
|
|
471
361
|
const layer = findLayer(this, id);
|
|
472
362
|
const config = this.markConfigs[id]?.errorBar;
|
|
@@ -494,13 +384,12 @@ export const rematerializeErrorBar = action(
|
|
|
494
384
|
}
|
|
495
385
|
);
|
|
496
386
|
|
|
497
|
-
export const editErrorBar =
|
|
387
|
+
export const editErrorBar = /* @__PURE__ */ closedAction(
|
|
498
388
|
{
|
|
499
389
|
op: "editErrorBar",
|
|
500
390
|
description: "Revise one error bar's roles, statistics, and owned caps."
|
|
501
|
-
},
|
|
391
|
+
}, ERROR_BAR_EDIT_OPTIONS,
|
|
502
392
|
function (args = {}) {
|
|
503
|
-
validateKeys(args, ERROR_BAR_EDIT_OPTIONS, "editErrorBar");
|
|
504
393
|
const editable = ERROR_BAR_EDIT_OPTIONS.filter(option => option !== "target");
|
|
505
394
|
if (!editable.some(option => Object.hasOwn(args, option))) {
|
|
506
395
|
throw new Error("editErrorBar requires at least one change.");
|
|
@@ -1,4 +1,5 @@
|
|
|
1
|
-
import { action } from "../../core/action.js";
|
|
1
|
+
import { action, closedAction } from "../../core/action.js";
|
|
2
|
+
import { registerFacetDataRevision, reviseUnitData } from "../data/revise.js";
|
|
2
3
|
import { freezeOwned, isPlainObject } from "../../core/immutable.js";
|
|
3
4
|
import { validateUserId } from "../../core/identifiers.js";
|
|
4
5
|
import {
|
|
@@ -183,13 +184,12 @@ function rederiveFacet(program, { scales, guides }) {
|
|
|
183
184
|
}, compositionSpec.children);
|
|
184
185
|
}
|
|
185
186
|
|
|
186
|
-
export const facet =
|
|
187
|
+
export const facet = /* @__PURE__ */ closedAction(
|
|
187
188
|
{
|
|
188
189
|
op: "facet",
|
|
189
190
|
description: "Repeat one direct-source chart by field value."
|
|
190
|
-
},
|
|
191
|
+
}, FACET_OPTIONS,
|
|
191
192
|
function (args = {}) {
|
|
192
|
-
validateOptionObject(args, FACET_OPTIONS, "facet");
|
|
193
193
|
const guides = normalizeGuides(args.guides);
|
|
194
194
|
const definition = resolveFacetDefinition(this.semanticSpec, args);
|
|
195
195
|
if (definition.family !== "cartesian" && guides.axes === "outer") {
|
|
@@ -428,13 +428,12 @@ function deriveRepeatChildren(base, definition, scales, closeInheritedAction) {
|
|
|
428
428
|
);
|
|
429
429
|
}
|
|
430
430
|
|
|
431
|
-
export const repeatCharts =
|
|
431
|
+
export const repeatCharts = /* @__PURE__ */ closedAction(
|
|
432
432
|
{
|
|
433
433
|
op: "repeatCharts",
|
|
434
434
|
description: "Repeat one direct chart across an ordered field-role list."
|
|
435
|
-
},
|
|
435
|
+
}, REPEAT_OPTIONS,
|
|
436
436
|
function (args = {}) {
|
|
437
|
-
validateOptionObject(args, REPEAT_OPTIONS, "repeatCharts");
|
|
438
437
|
const guides = normalizeGuides(args.guides);
|
|
439
438
|
if (guides.axes === "outer") {
|
|
440
439
|
throw new Error("repeatCharts does not promote axes across different repeated fields.");
|
|
@@ -495,13 +494,12 @@ export const repeatCharts = action(
|
|
|
495
494
|
}
|
|
496
495
|
);
|
|
497
496
|
|
|
498
|
-
export const facetGrid =
|
|
497
|
+
export const facetGrid = /* @__PURE__ */ closedAction(
|
|
499
498
|
{
|
|
500
499
|
op: "facetGrid",
|
|
501
500
|
description: "Repeat one direct-source Cartesian chart across a row and column field grid."
|
|
502
|
-
},
|
|
501
|
+
}, FACET_GRID_OPTIONS,
|
|
503
502
|
function (args = {}) {
|
|
504
|
-
validateOptionObject(args, FACET_GRID_OPTIONS, "facetGrid");
|
|
505
503
|
const guides = normalizeGuides(args.guides);
|
|
506
504
|
const definition = resolveFacetGridDefinition(this.semanticSpec, args);
|
|
507
505
|
if (definition.family !== "cartesian" && guides.axes === "outer") {
|
|
@@ -565,7 +563,7 @@ export const facetGrid = action(
|
|
|
565
563
|
}
|
|
566
564
|
);
|
|
567
565
|
|
|
568
|
-
export const editFacetHeaders = action(
|
|
566
|
+
export const editFacetHeaders = /* @__PURE__ */ action(
|
|
569
567
|
{
|
|
570
568
|
op: "editFacetHeaders",
|
|
571
569
|
description: "Edit parent-owned facet header appearance.",
|
|
@@ -656,7 +654,7 @@ export const editFacetHeaders = action(
|
|
|
656
654
|
}
|
|
657
655
|
);
|
|
658
656
|
|
|
659
|
-
export const editFacetScales = action(
|
|
657
|
+
export const editFacetScales = /* @__PURE__ */ action(
|
|
660
658
|
{
|
|
661
659
|
op: "editFacetScales",
|
|
662
660
|
description: "Edit facet scale-resolution policies and rederive every cell.",
|
|
@@ -691,7 +689,7 @@ export const editFacetScales = action(
|
|
|
691
689
|
}
|
|
692
690
|
);
|
|
693
691
|
|
|
694
|
-
export const editFacetGuides = action(
|
|
692
|
+
export const editFacetGuides = /* @__PURE__ */ action(
|
|
695
693
|
{
|
|
696
694
|
op: "editFacetGuides",
|
|
697
695
|
description: "Edit facet guide ownership and rederive every cell.",
|
|
@@ -764,14 +762,13 @@ function adoptUnitState(program, actionOwner) {
|
|
|
764
762
|
});
|
|
765
763
|
}
|
|
766
764
|
|
|
767
|
-
export const editFacetSource =
|
|
765
|
+
export const editFacetSource = /* @__PURE__ */ closedAction(
|
|
768
766
|
{
|
|
769
767
|
op: "editFacetSource",
|
|
770
768
|
description: "Reapply one facet, grid, or repeat recipe to a revised complete unit program.",
|
|
771
769
|
scope: "composition"
|
|
772
|
-
},
|
|
770
|
+
}, SOURCE_EDIT_OPTIONS,
|
|
773
771
|
function (args = {}) {
|
|
774
|
-
validateOptionObject(args, SOURCE_EDIT_OPTIONS, "editFacetSource");
|
|
775
772
|
requireFacetProgram(this, "editFacetSource");
|
|
776
773
|
const current = this.compositionSpec;
|
|
777
774
|
const facetConfig = this.materializationConfigs.facets?.[current.id];
|
|
@@ -838,6 +835,23 @@ export const editFacetSource = action(
|
|
|
838
835
|
);
|
|
839
836
|
|
|
840
837
|
export function registerFacetActions(ProgramClass) {
|
|
838
|
+
registerFacetDataRevision((program, args) => {
|
|
839
|
+
const { program: unit, plan } = reviseUnitData(facetUnitTemplate(program), args);
|
|
840
|
+
const current = program.compositionSpec;
|
|
841
|
+
// Adopt an already-materialized unit revision into the retained parent.
|
|
842
|
+
const revised = new program.constructor({
|
|
843
|
+
...unit,
|
|
844
|
+
graphicSpec: program.graphicSpec,
|
|
845
|
+
children: program.children,
|
|
846
|
+
materializationConfigs: { ...unit.materializationConfigs,
|
|
847
|
+
facets: program.materializationConfigs.facets,
|
|
848
|
+
...(program.titleConfig === undefined ? {} : { title: program.titleConfig }) },
|
|
849
|
+
actionSequence: unit._actionSequence,
|
|
850
|
+
compositionSpec: { ...current, facet: { ...current.facet,
|
|
851
|
+
data: plan.replacements.get(current.facet.data) ?? current.facet.data } }
|
|
852
|
+
});
|
|
853
|
+
return rederiveFacet(revised, current.facet);
|
|
854
|
+
});
|
|
841
855
|
ProgramClass.prototype.replayDerivedData = replayDerivedData;
|
|
842
856
|
ProgramClass.prototype.composeFacetGuides = composeFacetGuides;
|
|
843
857
|
ProgramClass.prototype.facet = facet;
|