ggaction 0.0.5 → 0.0.6
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 +25 -0
- package/README.md +1 -1
- package/package.json +1 -1
- package/src/actions/boxPlots/edit.js +455 -3
- package/src/actions/boxPlots/options.js +3 -3
- package/src/actions/composition/actions.js +13 -3
- package/src/actions/data/bin2d.js +140 -17
- package/src/actions/data/index.js +6 -1
- package/src/actions/data/intervalEdit.js +76 -0
- package/src/actions/distributions/revision.js +326 -0
- package/src/actions/encodings/appearance.js +35 -1
- package/src/actions/encodings/density.js +215 -80
- package/src/actions/encodings/index.js +2 -0
- package/src/actions/encodings/remove.js +268 -0
- package/src/actions/errorBands/edit.js +121 -13
- package/src/actions/errorBars/edit.js +45 -8
- package/src/actions/errorBars/options.js +7 -1
- package/src/actions/facets/actions.js +136 -1
- package/src/actions/gradientPlots/edit.js +352 -4
- package/src/actions/guides/axes/edit.js +129 -47
- package/src/actions/guides/legends/categorical/actions.js +19 -8
- package/src/actions/guides/legends/continuous/common.js +3 -3
- package/src/actions/guides/legends/edit.js +61 -3
- package/src/actions/guides/legends/remove.js +124 -23
- package/src/actions/guides/legends/strokeWidth.js +42 -14
- package/src/actions/marks/arc/actions.js +46 -14
- package/src/actions/marks/point/edit.js +15 -3
- package/src/actions/marks/point/materialize.js +9 -3
- package/src/actions/marks/rule/actions.js +4 -1
- package/src/actions/regression/edit.js +235 -74
- package/src/actions/selection/actions.js +122 -2
- package/src/actions/selection/index.js +6 -0
- package/src/core/vocabulary.js +7 -0
- package/types/index.d.ts +1 -0
- package/types/program.d.ts +71 -7
|
@@ -1,4 +1,5 @@
|
|
|
1
1
|
import { action } from "../../core/action.js";
|
|
2
|
+
import { isPlainObject } from "../../core/immutable.js";
|
|
2
3
|
import { validateUserId } from "../../core/identifiers.js";
|
|
3
4
|
import {
|
|
4
5
|
validateOptionObject,
|
|
@@ -8,12 +9,15 @@ import {
|
|
|
8
9
|
import { validateCurveInterpolation } from "../../grammar/curveCommands.js";
|
|
9
10
|
import { findLayer, resolveEligibleLayer } from "../../selectors/layers.js";
|
|
10
11
|
import { DEFAULT_COLORS } from "../../theme/defaults.js";
|
|
12
|
+
import { planIntervalEdit } from "../data/intervalEdit.js";
|
|
11
13
|
import {
|
|
12
14
|
ERROR_BAND_BOUNDARY_OPTIONS,
|
|
13
15
|
resolveBoundaryAppearance
|
|
14
16
|
} from "./options.js";
|
|
15
17
|
|
|
16
|
-
const EDIT_OPTIONS = Object.freeze([
|
|
18
|
+
const EDIT_OPTIONS = Object.freeze([
|
|
19
|
+
"target", "fill", "opacity", "curve", "statistics", "boundaries"
|
|
20
|
+
]);
|
|
17
21
|
const BOUNDARY_EDIT_OPTIONS = Object.freeze([
|
|
18
22
|
"target", "boundary", ...ERROR_BAND_BOUNDARY_OPTIONS
|
|
19
23
|
]);
|
|
@@ -49,13 +53,16 @@ function currentBoundaryAppearance(program, id) {
|
|
|
49
53
|
}
|
|
50
54
|
|
|
51
55
|
function defaultBoundaryAppearance(program, owner) {
|
|
52
|
-
return {
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
|
|
56
|
+
return resolveBoundaryAppearance({}, {
|
|
57
|
+
defaults: {
|
|
58
|
+
stroke: DEFAULT_COLORS.mark,
|
|
59
|
+
strokeWidth: 1,
|
|
60
|
+
strokeDash: "solid",
|
|
61
|
+
opacity: 1,
|
|
62
|
+
curve: program.markConfigs[owner]?.curve ?? "linear"
|
|
63
|
+
},
|
|
64
|
+
operation: "editErrorBand boundaries"
|
|
65
|
+
});
|
|
59
66
|
}
|
|
60
67
|
|
|
61
68
|
function createBoundary(program, owner, id, bound, appearance) {
|
|
@@ -82,6 +89,34 @@ function createBoundary(program, owner, id, bound, appearance) {
|
|
|
82
89
|
});
|
|
83
90
|
}
|
|
84
91
|
|
|
92
|
+
function removeBoundary(program, id) {
|
|
93
|
+
if (findLayer(program, id) === undefined) return program;
|
|
94
|
+
const selectionIds = Object.entries(
|
|
95
|
+
program.materializationConfigs.selections ?? {}
|
|
96
|
+
).filter(([, config]) => config.target === id).map(([selection]) => selection);
|
|
97
|
+
let next = program;
|
|
98
|
+
for (const [highlight, config] of Object.entries(
|
|
99
|
+
program.materializationConfigs.highlights ?? {}
|
|
100
|
+
)) {
|
|
101
|
+
if (config.target === id || selectionIds.includes(config.selection)) {
|
|
102
|
+
next = next._withoutMaterializationConfig(["highlights", highlight]);
|
|
103
|
+
}
|
|
104
|
+
}
|
|
105
|
+
for (const selection of selectionIds) {
|
|
106
|
+
next = next._withoutMaterializationConfig(["selections", selection]);
|
|
107
|
+
}
|
|
108
|
+
return next
|
|
109
|
+
.editSemantic({ property: `layer[${id}]`, remove: true })
|
|
110
|
+
.editGraphics({ target: id, remove: true })
|
|
111
|
+
._withoutMaterializationConfig(["marks", id])
|
|
112
|
+
._withContext({
|
|
113
|
+
...(program.context.currentMark === id ? { currentMark: undefined } : {}),
|
|
114
|
+
...(selectionIds.includes(program.context.currentSelection)
|
|
115
|
+
? { currentSelection: undefined }
|
|
116
|
+
: {})
|
|
117
|
+
});
|
|
118
|
+
}
|
|
119
|
+
|
|
85
120
|
export const rematerializeErrorBandBoundary = action(
|
|
86
121
|
{
|
|
87
122
|
op: "rematerializeErrorBandBoundary",
|
|
@@ -121,8 +156,9 @@ export const editErrorBand = action(
|
|
|
121
156
|
},
|
|
122
157
|
function (args = {}) {
|
|
123
158
|
validateOptionObject(args, EDIT_OPTIONS, "editErrorBand");
|
|
124
|
-
if (!["fill", "opacity", "curve"
|
|
125
|
-
|
|
159
|
+
if (!["fill", "opacity", "curve", "statistics", "boundaries"]
|
|
160
|
+
.some(key => Object.hasOwn(args, key))) {
|
|
161
|
+
throw new Error("editErrorBand requires at least one change.");
|
|
126
162
|
}
|
|
127
163
|
const owner = resolveOwner(this, args.target);
|
|
128
164
|
const config = { ...this.markConfigs[owner.id] };
|
|
@@ -136,9 +172,81 @@ export const editErrorBand = action(
|
|
|
136
172
|
if (Object.hasOwn(args, "curve")) {
|
|
137
173
|
config.curve = validateCurveInterpolation(args.curve);
|
|
138
174
|
}
|
|
139
|
-
|
|
140
|
-
|
|
141
|
-
|
|
175
|
+
const interval = Object.hasOwn(args, "statistics")
|
|
176
|
+
? planIntervalEdit(this, {
|
|
177
|
+
owner: owner.id,
|
|
178
|
+
data: errorBand.data,
|
|
179
|
+
consumers: [
|
|
180
|
+
owner.id,
|
|
181
|
+
...[errorBand.lowerBoundaryId, errorBand.upperBoundaryId]
|
|
182
|
+
.filter(id => findLayer(this, id) !== undefined)
|
|
183
|
+
],
|
|
184
|
+
statistics: args.statistics,
|
|
185
|
+
operation: "editErrorBand"
|
|
186
|
+
})
|
|
187
|
+
: { changed: false };
|
|
188
|
+
if (
|
|
189
|
+
Object.hasOwn(args, "boundaries") &&
|
|
190
|
+
args.boundaries !== false &&
|
|
191
|
+
!isPlainObject(args.boundaries)
|
|
192
|
+
) {
|
|
193
|
+
throw new TypeError(
|
|
194
|
+
"editErrorBand boundaries must be false or a plain object."
|
|
195
|
+
);
|
|
196
|
+
}
|
|
197
|
+
|
|
198
|
+
const applyEdit = program => {
|
|
199
|
+
let next = program;
|
|
200
|
+
if (interval.changed) {
|
|
201
|
+
next = next.createIntervalData(interval.dataArgs);
|
|
202
|
+
for (const rebind of interval.revision.rebinds) {
|
|
203
|
+
next = next.rebindLayerData(rebind);
|
|
204
|
+
}
|
|
205
|
+
errorBand.data = interval.revision.id;
|
|
206
|
+
}
|
|
207
|
+
next = next
|
|
208
|
+
._withMarkConfig(owner.id, { ...config, errorBand })
|
|
209
|
+
.rematerializeAreaMark({ id: owner.id });
|
|
210
|
+
if (Object.hasOwn(args, "boundaries")) {
|
|
211
|
+
if (args.boundaries === false) {
|
|
212
|
+
next = removeBoundary(next, errorBand.lowerBoundaryId);
|
|
213
|
+
next = removeBoundary(next, errorBand.upperBoundaryId);
|
|
214
|
+
} else if (Object.keys(args.boundaries).length === 0) {
|
|
215
|
+
for (const [id, bound] of [
|
|
216
|
+
[errorBand.lowerBoundaryId, errorBand.lowerField],
|
|
217
|
+
[errorBand.upperBoundaryId, errorBand.upperField]
|
|
218
|
+
]) {
|
|
219
|
+
next = findLayer(next, id) === undefined
|
|
220
|
+
? createBoundary(
|
|
221
|
+
next,
|
|
222
|
+
owner.id,
|
|
223
|
+
id,
|
|
224
|
+
bound,
|
|
225
|
+
defaultBoundaryAppearance(next, owner.id)
|
|
226
|
+
)
|
|
227
|
+
: interval.changed
|
|
228
|
+
? next.rematerializeLineMark({ id })
|
|
229
|
+
: next;
|
|
230
|
+
}
|
|
231
|
+
} else {
|
|
232
|
+
next = next.editErrorBandBoundary({
|
|
233
|
+
target: owner.id,
|
|
234
|
+
...args.boundaries
|
|
235
|
+
});
|
|
236
|
+
}
|
|
237
|
+
} else if (interval.changed) {
|
|
238
|
+
for (const id of [errorBand.lowerBoundaryId, errorBand.upperBoundaryId]) {
|
|
239
|
+
if (findLayer(next, id) !== undefined) {
|
|
240
|
+
next = next.rematerializeLineMark({ id });
|
|
241
|
+
}
|
|
242
|
+
}
|
|
243
|
+
}
|
|
244
|
+
return interval.changed
|
|
245
|
+
? next.releaseDerivedData(interval.revision.release)
|
|
246
|
+
: next;
|
|
247
|
+
};
|
|
248
|
+
if (interval.changed || Object.hasOwn(args, "boundaries")) applyEdit(this);
|
|
249
|
+
return applyEdit(this);
|
|
142
250
|
}
|
|
143
251
|
);
|
|
144
252
|
|
|
@@ -2,7 +2,9 @@ import { action } from "../../core/action.js";
|
|
|
2
2
|
import { validateUserId } from "../../core/identifiers.js";
|
|
3
3
|
import { validateKeys } from "../../core/validation.js";
|
|
4
4
|
import { findLayer, resolveEligibleLayer } from "../../selectors/layers.js";
|
|
5
|
+
import { planIntervalEdit } from "../data/intervalEdit.js";
|
|
5
6
|
import {
|
|
7
|
+
ERROR_BAR_APPEARANCE_OPTIONS,
|
|
6
8
|
ERROR_BAR_EDIT_OPTIONS,
|
|
7
9
|
resolveErrorBarAppearance
|
|
8
10
|
} from "./options.js";
|
|
@@ -112,19 +114,54 @@ export const editErrorBar = action(
|
|
|
112
114
|
validateKeys(args, ERROR_BAR_EDIT_OPTIONS, "editErrorBar");
|
|
113
115
|
const editable = ERROR_BAR_EDIT_OPTIONS.filter(option => option !== "target");
|
|
114
116
|
if (!editable.some(option => Object.hasOwn(args, option))) {
|
|
115
|
-
throw new Error("editErrorBar requires at least one
|
|
117
|
+
throw new Error("editErrorBar requires at least one change.");
|
|
116
118
|
}
|
|
117
119
|
const owner = resolveOwner(this, args.target);
|
|
118
120
|
const current = this.markConfigs[owner.id].errorBar;
|
|
119
|
-
const
|
|
121
|
+
const appearanceArgs = Object.fromEntries(
|
|
122
|
+
ERROR_BAR_APPEARANCE_OPTIONS
|
|
123
|
+
.filter(key => Object.hasOwn(args, key))
|
|
124
|
+
.map(key => [key, args[key]])
|
|
125
|
+
);
|
|
126
|
+
const appearance = resolveErrorBarAppearance(appearanceArgs, {
|
|
120
127
|
defaults: current,
|
|
121
128
|
operation: "editErrorBar"
|
|
122
129
|
});
|
|
123
|
-
|
|
124
|
-
|
|
125
|
-
|
|
126
|
-
|
|
127
|
-
|
|
128
|
-
|
|
130
|
+
const interval = Object.hasOwn(args, "statistics")
|
|
131
|
+
? planIntervalEdit(this, {
|
|
132
|
+
owner: owner.id,
|
|
133
|
+
data: current.data,
|
|
134
|
+
consumers: [
|
|
135
|
+
owner.id,
|
|
136
|
+
...[current.lowerCapId, current.upperCapId]
|
|
137
|
+
.filter(id => findLayer(this, id) !== undefined)
|
|
138
|
+
],
|
|
139
|
+
statistics: args.statistics,
|
|
140
|
+
operation: "editErrorBar"
|
|
141
|
+
})
|
|
142
|
+
: { changed: false };
|
|
143
|
+
|
|
144
|
+
const applyEdit = program => {
|
|
145
|
+
let next = program;
|
|
146
|
+
if (interval.changed) {
|
|
147
|
+
next = next.createIntervalData(interval.dataArgs);
|
|
148
|
+
for (const rebind of interval.revision.rebinds) {
|
|
149
|
+
next = next.rebindLayerData(rebind);
|
|
150
|
+
}
|
|
151
|
+
}
|
|
152
|
+
next = next._withMarkConfig(owner.id, {
|
|
153
|
+
...next.markConfigs[owner.id],
|
|
154
|
+
errorBar: {
|
|
155
|
+
...current,
|
|
156
|
+
...appearance,
|
|
157
|
+
...(interval.changed ? { data: interval.revision.id } : {})
|
|
158
|
+
}
|
|
159
|
+
}).rematerializeErrorBar({ id: owner.id });
|
|
160
|
+
return interval.changed
|
|
161
|
+
? next.releaseDerivedData(interval.revision.release)
|
|
162
|
+
: next;
|
|
163
|
+
};
|
|
164
|
+
if (interval.changed) applyEdit(this);
|
|
165
|
+
return applyEdit(this);
|
|
129
166
|
}
|
|
130
167
|
);
|
|
@@ -13,9 +13,15 @@ import {
|
|
|
13
13
|
|
|
14
14
|
export const ERROR_BAR_EDIT_OPTIONS = Object.freeze([
|
|
15
15
|
"target", "caps", "capSize", "stroke", "strokeWidth",
|
|
16
|
-
"strokeDash", "opacity"
|
|
16
|
+
"strokeDash", "opacity", "statistics"
|
|
17
17
|
]);
|
|
18
18
|
|
|
19
|
+
export const ERROR_BAR_APPEARANCE_OPTIONS = Object.freeze(
|
|
20
|
+
ERROR_BAR_EDIT_OPTIONS.filter(option =>
|
|
21
|
+
option !== "target" && option !== "statistics"
|
|
22
|
+
)
|
|
23
|
+
);
|
|
24
|
+
|
|
19
25
|
export function resolveErrorBarAppearance(args, {
|
|
20
26
|
defaults,
|
|
21
27
|
operation
|
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import { action } from "../../core/action.js";
|
|
2
|
-
import { isPlainObject } from "../../core/immutable.js";
|
|
2
|
+
import { freezeOwned, isPlainObject } from "../../core/immutable.js";
|
|
3
3
|
import {
|
|
4
4
|
validateNonEmptyString,
|
|
5
5
|
validateNonNegativeFinite,
|
|
@@ -9,6 +9,7 @@ import {
|
|
|
9
9
|
import { resolveFacetDefinition } from "../../grammar/facets/index.js";
|
|
10
10
|
import { normalizeFacetScalePolicies } from
|
|
11
11
|
"../../grammar/facets/scales.js";
|
|
12
|
+
import { FACET_SCALE_CHANNELS } from "../../grammar/facets/scales.js";
|
|
12
13
|
import { resolveFacetLayout } from "../../layout/facets.js";
|
|
13
14
|
import { compositionChildDescriptor } from
|
|
14
15
|
"../../materialization/composition.js";
|
|
@@ -73,6 +74,76 @@ function requireFacetProgram(program, operation) {
|
|
|
73
74
|
}
|
|
74
75
|
}
|
|
75
76
|
|
|
77
|
+
function currentFacetDefinition(program) {
|
|
78
|
+
const current = program.compositionSpec;
|
|
79
|
+
return resolveFacetDefinition(program.semanticSpec, {
|
|
80
|
+
id: current.id,
|
|
81
|
+
data: current.facet.data,
|
|
82
|
+
field: current.facet.field,
|
|
83
|
+
values: current.facet.values
|
|
84
|
+
});
|
|
85
|
+
}
|
|
86
|
+
|
|
87
|
+
function facetUnitTemplate(program) {
|
|
88
|
+
const seed = program.children[program.compositionSpec.children[0]];
|
|
89
|
+
if (seed === undefined) {
|
|
90
|
+
throw new Error(`Facet "${program.compositionSpec.id}" requires a retained child.`);
|
|
91
|
+
}
|
|
92
|
+
const { facets: _facets, ...unitConfigs } = program.materializationConfigs;
|
|
93
|
+
return new program.constructor({
|
|
94
|
+
semanticSpec: program.semanticSpec,
|
|
95
|
+
graphicSpec: seed.graphicSpec,
|
|
96
|
+
resolvedScales: program.resolvedScales,
|
|
97
|
+
materializationConfigs: freezeOwned({
|
|
98
|
+
...unitConfigs,
|
|
99
|
+
canvas: seed.materializationConfigs.canvas
|
|
100
|
+
}),
|
|
101
|
+
children: {},
|
|
102
|
+
context: program.context,
|
|
103
|
+
trace: program.trace,
|
|
104
|
+
actionStack: program.actionStack,
|
|
105
|
+
actionSequence: program._actionSequence
|
|
106
|
+
});
|
|
107
|
+
}
|
|
108
|
+
|
|
109
|
+
function applicableScaleRequest(program, channels) {
|
|
110
|
+
return Object.fromEntries(FACET_SCALE_CHANNELS.flatMap(channel =>
|
|
111
|
+
program.semanticSpec.layers.some(
|
|
112
|
+
layer => layer.encoding?.[channel]?.scale !== undefined
|
|
113
|
+
)
|
|
114
|
+
? [[channel, channels[channel]]]
|
|
115
|
+
: []
|
|
116
|
+
));
|
|
117
|
+
}
|
|
118
|
+
|
|
119
|
+
function rederiveFacet(program, { scales, guides }) {
|
|
120
|
+
const current = program.compositionSpec;
|
|
121
|
+
const definition = currentFacetDefinition(program);
|
|
122
|
+
const request = applicableScaleRequest(program, scales);
|
|
123
|
+
const normalized = normalizeFacetScalePolicies(program.semanticSpec, request);
|
|
124
|
+
const derived = deriveFacetChildren(facetUnitTemplate(program), definition, {
|
|
125
|
+
closeInheritedAction: true,
|
|
126
|
+
stripTitle: true,
|
|
127
|
+
scales: request
|
|
128
|
+
});
|
|
129
|
+
const compositionSpec = {
|
|
130
|
+
...current,
|
|
131
|
+
facet: {
|
|
132
|
+
...current.facet,
|
|
133
|
+
scales: normalized.channels,
|
|
134
|
+
guides
|
|
135
|
+
}
|
|
136
|
+
};
|
|
137
|
+
let next = program._withCompositionState({
|
|
138
|
+
children: derived.children,
|
|
139
|
+
compositionSpec
|
|
140
|
+
});
|
|
141
|
+
for (const id of compositionSpec.children) {
|
|
142
|
+
next = next.useProgram({ id });
|
|
143
|
+
}
|
|
144
|
+
return next.materializeComposition();
|
|
145
|
+
}
|
|
146
|
+
|
|
76
147
|
export const facet = action(
|
|
77
148
|
{
|
|
78
149
|
op: "facet",
|
|
@@ -153,9 +224,73 @@ export const editFacetHeaders = action(
|
|
|
153
224
|
}
|
|
154
225
|
);
|
|
155
226
|
|
|
227
|
+
export const editFacetScales = action(
|
|
228
|
+
{
|
|
229
|
+
op: "editFacetScales",
|
|
230
|
+
description: "Edit facet scale-resolution policies and rederive every cell.",
|
|
231
|
+
scope: "composition"
|
|
232
|
+
},
|
|
233
|
+
function (args = {}) {
|
|
234
|
+
requireFacetProgram(this, "editFacetScales");
|
|
235
|
+
validateOptionObject(args, FACET_SCALE_CHANNELS, "editFacetScales", {
|
|
236
|
+
allowEmpty: false,
|
|
237
|
+
emptyMessage: "editFacetScales requires at least one channel policy change."
|
|
238
|
+
});
|
|
239
|
+
for (const channel of Object.keys(args)) {
|
|
240
|
+
if (!this.semanticSpec.layers.some(
|
|
241
|
+
layer => layer.encoding?.[channel]?.scale !== undefined
|
|
242
|
+
)) {
|
|
243
|
+
throw new Error(
|
|
244
|
+
`Facet scale channel "${channel}" is not used by an affected layer.`
|
|
245
|
+
);
|
|
246
|
+
}
|
|
247
|
+
}
|
|
248
|
+
const current = this.compositionSpec.facet;
|
|
249
|
+
const scales = { ...current.scales, ...args };
|
|
250
|
+
if (FACET_SCALE_CHANNELS.every(
|
|
251
|
+
channel => scales[channel] === current.scales[channel]
|
|
252
|
+
)) {
|
|
253
|
+
throw new Error("editFacetScales requires at least one channel policy change.");
|
|
254
|
+
}
|
|
255
|
+
const request = applicableScaleRequest(this, scales);
|
|
256
|
+
const normalized = normalizeFacetScalePolicies(this.semanticSpec, request);
|
|
257
|
+
const applyEdit = program => rederiveFacet(program, {
|
|
258
|
+
scales: normalized.channels,
|
|
259
|
+
guides: current.guides
|
|
260
|
+
});
|
|
261
|
+
applyEdit(this);
|
|
262
|
+
return applyEdit(this);
|
|
263
|
+
}
|
|
264
|
+
);
|
|
265
|
+
|
|
266
|
+
export const editFacetGuides = action(
|
|
267
|
+
{
|
|
268
|
+
op: "editFacetGuides",
|
|
269
|
+
description: "Edit facet guide ownership and rederive every cell.",
|
|
270
|
+
scope: "composition"
|
|
271
|
+
},
|
|
272
|
+
function (args = {}) {
|
|
273
|
+
requireFacetProgram(this, "editFacetGuides");
|
|
274
|
+
validateOptionObject(args, GUIDE_OPTIONS, "editFacetGuides", {
|
|
275
|
+
allowEmpty: false,
|
|
276
|
+
emptyMessage: "editFacetGuides requires at least one guide policy."
|
|
277
|
+
});
|
|
278
|
+
const current = this.compositionSpec.facet;
|
|
279
|
+
const guides = normalizeGuides({ ...current.guides, ...args });
|
|
280
|
+
const applyEdit = program => rederiveFacet(program, {
|
|
281
|
+
scales: current.scales,
|
|
282
|
+
guides
|
|
283
|
+
});
|
|
284
|
+
applyEdit(this);
|
|
285
|
+
return applyEdit(this);
|
|
286
|
+
}
|
|
287
|
+
);
|
|
288
|
+
|
|
156
289
|
export function registerFacetActions(ProgramClass) {
|
|
157
290
|
ProgramClass.prototype.replayDerivedData = replayDerivedData;
|
|
158
291
|
ProgramClass.prototype.composeFacetGuides = composeFacetGuides;
|
|
159
292
|
ProgramClass.prototype.facet = facet;
|
|
160
293
|
ProgramClass.prototype.editFacetHeaders = editFacetHeaders;
|
|
294
|
+
ProgramClass.prototype.editFacetScales = editFacetScales;
|
|
295
|
+
ProgramClass.prototype.editFacetGuides = editFacetGuides;
|
|
161
296
|
}
|