ggaction 0.0.24 → 0.0.26
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 +47 -0
- package/README.md +2 -2
- package/knowledge/action-cards.json +1 -1
- package/knowledge/intent-taxonomy.json +1 -1
- package/knowledge/mcp-resources.json +1 -1
- package/knowledge/task-resolver.js +1 -1
- package/package.json +1 -1
- package/src/accessibility.js +13 -0
- package/src/actions/canvas/actions.js +2 -1
- package/src/actions/canvas/fitting.js +68 -13
- package/src/actions/charts/beeswarm.js +2 -1
- package/src/actions/charts/ecdf.js +2 -1
- package/src/actions/charts/endpoints.js +25 -16
- package/src/actions/charts/heatmap.js +5 -3
- package/src/actions/charts/missing.js +17 -0
- package/src/actions/charts/radar.js +70 -33
- package/src/actions/charts/raincloud.js +18 -4
- package/src/actions/charts/rug-strip.js +2 -2
- package/src/actions/charts/shared.js +17 -0
- package/src/actions/composition/actions.js +24 -7
- package/src/actions/composition/adjacent.js +90 -0
- package/src/actions/composition/index.js +11 -1
- package/src/actions/composition/layer.js +42 -0
- package/src/actions/composition/layerPlan.js +176 -0
- package/src/actions/composition/targets.js +105 -0
- package/src/actions/data/derived.js +3 -0
- package/src/actions/data/filter.js +1 -1
- package/src/actions/data/raincloudFilter.js +3 -1
- package/src/actions/encodings/appearance.js +26 -7
- package/src/actions/encodings/channels.js +1 -0
- package/src/actions/encodings/color/continuous.js +37 -34
- package/src/actions/encodings/color/index.js +57 -43
- package/src/actions/encodings/color/policy.js +15 -0
- package/src/actions/encodings/density/resolve.js +3 -2
- package/src/actions/encodings/density.js +2 -2
- package/src/actions/encodings/offset.js +2 -0
- package/src/actions/encodings/pathOrder.js +2 -0
- package/src/actions/encodings/position/areaAlignment.js +42 -0
- package/src/actions/encodings/position/index.js +37 -3
- package/src/actions/encodings/position/policies/line.js +1 -1
- package/src/actions/encodings/ranged.js +2 -0
- package/src/actions/encodings/remove.js +13 -10
- package/src/actions/encodings/ruleAppearance.js +14 -2
- package/src/actions/facets/actions.js +1 -1
- package/src/actions/guides/axes/axes.js +2 -1
- package/src/actions/guides/axes/edit.js +1 -1
- package/src/actions/guides/axes/labels.js +2 -1
- package/src/actions/guides/axes/parallel/lifecycle.js +11 -4
- package/src/actions/guides/axes/parallel/policy.js +5 -2
- package/src/actions/guides/axes/parallel/resolve.js +3 -1
- package/src/actions/guides/axes/parallel.js +9 -4
- package/src/actions/guides/axes/titles.js +1 -1
- package/src/actions/guides/facadeLegend.js +3 -2
- package/src/actions/guides/grids/grid.js +3 -2
- package/src/actions/guides/grids/resolve.js +2 -1
- package/src/actions/guides/guides.js +3 -2
- package/src/actions/guides/legends/automatic.js +28 -0
- package/src/actions/guides/legends/blocks.js +15 -21
- package/src/actions/guides/legends/categorical/actions.js +1 -1
- package/src/actions/guides/legends/categorical/components.js +4 -3
- package/src/actions/guides/legends/categorical/layout.js +5 -2
- package/src/actions/guides/legends/categorical/options.js +9 -14
- package/src/actions/guides/legends/categorical/recipes.js +3 -0
- package/src/actions/guides/legends/categorical/resolve.js +7 -5
- package/src/actions/guides/legends/colorSize.js +51 -14
- package/src/actions/guides/legends/continuous/common.js +1 -1
- package/src/actions/guides/legends/continuous/gradient.js +1 -1
- package/src/actions/guides/legends/continuous/opacity.js +2 -0
- package/src/actions/guides/legends/edit.js +1 -1
- package/src/actions/guides/legends/focused.js +2 -2
- package/src/actions/guides/legends/group.js +1 -1
- package/src/actions/guides/legends/lane.js +1 -1
- package/src/actions/guides/legends/lifecycle.js +2 -2
- package/src/actions/guides/legends/remove.js +18 -4
- package/src/actions/guides/legends/size.js +1 -1
- package/src/actions/guides/legends/transition.js +15 -6
- package/src/actions/guides/polar/axes/facade.js +4 -2
- package/src/actions/guides/polar/axes/labels.js +6 -1
- package/src/actions/guides/polar/axes/shared.js +4 -4
- package/src/actions/guides/polar/axes/titles.js +13 -2
- package/src/actions/guides/polar/grids.js +6 -3
- package/src/actions/guides/tickValues.js +7 -1
- package/src/actions/index.js +2 -0
- package/src/actions/marks/area/actions.js +9 -2
- package/src/actions/marks/area/materialize.js +1 -1
- package/src/actions/marks/bar/materialize.js +4 -4
- package/src/actions/marks/lifecycle.js +14 -0
- package/src/actions/marks/line/actions.js +3 -0
- package/src/actions/marks/line/materialize.js +4 -2
- package/src/actions/marks/point/edit.js +2 -0
- package/src/actions/marks/point/jitter.js +2 -0
- package/src/actions/marks/point/materialize.js +5 -4
- package/src/actions/marks/point/packing.js +2 -0
- package/src/actions/marks/references.js +5 -3
- package/src/actions/marks/remove.js +16 -0
- package/src/actions/marks/shared.js +2 -1
- package/src/actions/marks/text/actions.js +5 -2
- package/src/actions/overlays/index.js +168 -0
- package/src/actions/overlays/snapshot.js +45 -0
- package/src/actions/primitives/editGraphics.js +21 -27
- package/src/actions/primitives/semanticAction.js +4 -5
- package/src/actions/primitives/semanticValidation/guide.js +1 -0
- package/src/actions/primitives/semanticValidation/layer.js +7 -0
- package/src/actions/scales/consumers/common.js +10 -0
- package/src/actions/scales/consumers/families.js +1 -1
- package/src/actions/scales/preview.js +1 -1
- package/src/actions/selection/actions.js +63 -11
- package/src/actions/titles/actions.js +3 -14
- package/src/actions/titles/resolve.js +12 -9
- package/src/core/action.js +41 -25
- package/src/core/compositionScales.js +12 -0
- package/src/core/compositionState.js +16 -2
- package/src/core/immutable.js +11 -6
- package/src/core/programState.js +16 -0
- package/src/core/resourceReferences.js +19 -3
- package/src/core/validation.js +7 -0
- package/src/core/vocabulary.js +8 -2
- package/src/grammar/actionTargets.js +24 -0
- package/src/grammar/bin2d.js +7 -0
- package/src/grammar/colorSizeLegend.js +56 -5
- package/src/grammar/displayLabels.js +10 -0
- package/src/grammar/facetHeaders.js +1 -1
- package/src/grammar/facets/dependencies.js +10 -3
- package/src/grammar/facets/guides.js +2 -1
- package/src/grammar/facets/legendIntent.js +7 -5
- package/src/grammar/legendBlocks.js +1 -1
- package/src/grammar/legendCombinations.js +1 -1
- package/src/grammar/legendGroups.js +1 -1
- package/src/grammar/legendItemsOffset.js +12 -0
- package/src/grammar/legendOverflow.js +25 -0
- package/src/grammar/lineSeries.js +1 -1
- package/src/grammar/markSelection.js +23 -0
- package/src/grammar/overlay.js +51 -0
- package/src/grammar/parallelCoordinates.js +1 -208
- package/src/grammar/pathCommands.js +8 -2
- package/src/grammar/pathSeries.js +1 -1
- package/src/grammar/plotComposition.js +152 -0
- package/src/grammar/pointShapes.js +18 -0
- package/src/grammar/scales/transformed.js +1 -1
- package/src/grammar/schemas/concreteGraphic.js +8 -1
- package/src/grammar/schemas/graphicBounds.js +8 -1
- package/src/grammar/schemas/graphicTree.js +18 -2
- package/src/grammar/schemas/semanticPath.js +3 -0
- package/src/grammar/strokeStyle.js +14 -8
- package/src/grammar/text.js +72 -0
- package/src/inspection.js +1 -1
- package/src/inspectionDescriptors.js +1 -1
- package/src/layout/composition.js +30 -4
- package/src/layout/compositionLegend.js +91 -0
- package/src/layout/facetHeaderTitles.js +1 -1
- package/src/layout/labels.js +55 -27
- package/src/layout/legend.js +3 -2
- package/src/layout/legendGroup.js +1 -1
- package/src/layout/legendItems.js +7 -6
- package/src/layout/legendLane.js +1 -1
- package/src/layout/legendText.js +1 -1
- package/src/materialization/adjacentSource.js +27 -0
- package/src/materialization/composition.js +165 -52
- package/src/materialization/compositionLegends.js +120 -0
- package/src/materialization/compositionScales.js +125 -0
- package/src/materialization/compositionTitle.js +96 -0
- package/src/materialization/facetGuides/edit.js +22 -2
- package/src/materialization/facetGuides/layout.js +1 -1
- package/src/materialization/facetGuides/owner.js +4 -3
- package/src/materialization/facetGuides/ownerLayout.js +12 -6
- package/src/materialization/facetGuides/placement.js +19 -22
- package/src/materialization/facetGuides/preparation.js +17 -5
- package/src/materialization/facetHeaders.js +5 -1
- package/src/materialization/facets.js +1 -1
- package/src/materialization/guides/layout.js +1 -1
- package/src/materialization/guides/resources.js +1 -1
- package/src/materialization/guides/visibility.js +105 -0
- package/src/materialization/legendClip.js +1 -1
- package/src/materialization/legendGroups.js +1 -1
- package/src/materialization/legendItemsOffset.js +68 -0
- package/src/materialization/legendSuppression.js +22 -0
- package/src/materialization/legends.js +3 -2
- package/src/materialization/marks/capabilities.js +4 -0
- package/src/materialization/marks/index.js +5 -1
- package/src/materialization/marks/pathOrder.js +1 -1
- package/src/materialization/marks/policies.js +2 -1
- package/src/materialization/overlayItems.js +154 -0
- package/src/materialization/scales/policies/binnedPosition.js +43 -5
- package/src/materialization/scales/policies/series.js +12 -4
- package/src/materialization/scales/resolve.js +2 -0
- package/src/materialization/selection/items/bar.js +21 -3
- package/src/materialization/selection/items/common.js +18 -5
- package/src/materialization/selection/items/overlay.js +15 -0
- package/src/materialization/selection/items/path.js +1 -0
- package/src/materialization/selection/items/point.js +2 -3
- package/src/materialization/selection/items/tick.js +3 -12
- package/src/materialization/selection/path.js +2 -2
- package/src/materialization/selection/policies/bar.js +2 -0
- package/src/materialization/selection/policies/index.js +35 -1
- package/src/materialization/selection/policies/point.js +2 -0
- package/src/materialization/selection/policies/text.js +17 -0
- package/src/materialization/selection/rows.js +103 -0
- package/src/materialization/selection/state.js +19 -3
- package/src/materialization/selection/styles.js +8 -0
- package/src/materialization/text.js +6 -489
- package/src/materialization/textGeometry.js +503 -0
- package/src/materialization/textLines.js +20 -0
- package/src/persistence/validation.js +97 -24
- package/src/renderers/canvas/index.js +12 -7
- package/src/renderers/canvas/text.js +5 -5
- package/src/renderers/nativeBackend.js +25 -0
- package/src/renderers/pdf.js +3 -3
- package/src/renderers/png.js +4 -3
- package/src/renderers/svgSerialization.js +1 -643
- package/src/scene.js +5 -3
- package/src/selectors/plotComposition.js +115 -0
- package/src/selectors/selectionTargets.js +19 -0
- package/src/version.js +1 -1
- package/types/basic.d.ts +2 -2
- package/types/index.d.ts +11 -0
- package/types/inspection.d.ts +34 -0
- package/types/program.d.ts +553 -365
|
@@ -20,11 +20,11 @@ export const TICK_EDIT_OPTIONS = Object.freeze([
|
|
|
20
20
|
]);
|
|
21
21
|
export const LABEL_CREATE_OPTIONS = Object.freeze([
|
|
22
22
|
"scale", "coordinate", "angle", "count", "values", "offset", "format",
|
|
23
|
-
"color", "fontSize", "fontFamily", "fontWeight"
|
|
23
|
+
"color", "fontSize", "fontFamily", "fontWeight", "align"
|
|
24
24
|
]);
|
|
25
25
|
export const LABEL_EDIT_OPTIONS = Object.freeze([
|
|
26
26
|
"count", "values", "offset", "format", "color", "fontSize",
|
|
27
|
-
"fontFamily", "fontWeight"
|
|
27
|
+
"fontFamily", "fontWeight", "align"
|
|
28
28
|
]);
|
|
29
29
|
const THETA_LABEL_CREATE_OPTIONS = Object.freeze([
|
|
30
30
|
...LABEL_CREATE_OPTIONS,
|
|
@@ -44,10 +44,10 @@ export function labelEditOptions(kind) {
|
|
|
44
44
|
}
|
|
45
45
|
export const TITLE_CREATE_OPTIONS = Object.freeze([
|
|
46
46
|
"scale", "coordinate", "angle", "text", "offset", "color", "fontSize",
|
|
47
|
-
"fontFamily", "fontWeight", "position"
|
|
47
|
+
"fontFamily", "fontWeight", "align", "position"
|
|
48
48
|
]);
|
|
49
49
|
export const TITLE_EDIT_OPTIONS = Object.freeze([
|
|
50
|
-
"text", "offset", "color", "fontSize", "fontFamily", "fontWeight",
|
|
50
|
+
"text", "offset", "color", "fontSize", "fontFamily", "fontWeight", "align",
|
|
51
51
|
"position"
|
|
52
52
|
]);
|
|
53
53
|
|
|
@@ -1,6 +1,8 @@
|
|
|
1
1
|
import { withGuideLayoutValidation } from "../../../../materialization/guides/layout.js";
|
|
2
2
|
import { axisThemeTypography } from "../../../theme/state.js";
|
|
3
3
|
import { action } from "../../../../core/action.js";
|
|
4
|
+
import { resolveTextLines } from "../../../../core/textMetrics.js";
|
|
5
|
+
import { materializeTextLines } from "../../../../materialization/textLines.js";
|
|
4
6
|
import {
|
|
5
7
|
validateNonEmptyString,
|
|
6
8
|
validateNonNegativeFinite
|
|
@@ -33,7 +35,7 @@ import {
|
|
|
33
35
|
|
|
34
36
|
function titleGeometry(program, kind, config, angle = resolveAngle(program, kind, {})) {
|
|
35
37
|
const frame = resolvePolarFrameForProgram(program, config.coordinate);
|
|
36
|
-
|
|
38
|
+
const geometry = kind === "theta"
|
|
37
39
|
? resolveThetaAxisTitle({ frame, offset: config.offset })
|
|
38
40
|
: resolveRadialAxisTitle({
|
|
39
41
|
frame,
|
|
@@ -41,6 +43,7 @@ function titleGeometry(program, kind, config, angle = resolveAngle(program, kind
|
|
|
41
43
|
offset: config.offset,
|
|
42
44
|
position: config.position
|
|
43
45
|
});
|
|
46
|
+
return config.align === undefined ? geometry : { ...geometry, textAlign: config.align };
|
|
44
47
|
}
|
|
45
48
|
|
|
46
49
|
function validateTitleGeometry(program, kind, config, geometry, text) {
|
|
@@ -50,6 +53,7 @@ function validateTitleGeometry(program, kind, config, geometry, text) {
|
|
|
50
53
|
items: [{
|
|
51
54
|
...geometry,
|
|
52
55
|
text,
|
|
56
|
+
lines: titleLines(text, config, geometry),
|
|
53
57
|
fontSize: config.fontSize,
|
|
54
58
|
fontFamily: config.fontFamily,
|
|
55
59
|
fontWeight: config.fontWeight
|
|
@@ -57,10 +61,17 @@ function validateTitleGeometry(program, kind, config, geometry, text) {
|
|
|
57
61
|
}, program.materializationConfigs.textMetrics);
|
|
58
62
|
}
|
|
59
63
|
|
|
64
|
+
function titleLines(text, config, geometry) {
|
|
65
|
+
const lines = resolveTextLines(text, { fontSize: config.fontSize,
|
|
66
|
+
align: geometry.textAlign, baseline: geometry.textBaseline, blockAlign: "middle" });
|
|
67
|
+
return lines.length > 1 ? lines : undefined;
|
|
68
|
+
}
|
|
69
|
+
|
|
60
70
|
function resolveTitleConfig(program, kind, args, resources, previous) {
|
|
61
71
|
const typography = axisThemeTypography(program.materializationConfigs.theme, "title");
|
|
62
72
|
const config = {
|
|
63
73
|
...(previous ?? {}),
|
|
74
|
+
...(Object.hasOwn(args, "align") ? { align: args.align } : {}),
|
|
64
75
|
scale: resources.scale,
|
|
65
76
|
coordinate: resources.coordinate,
|
|
66
77
|
inferredText: previous?.inferredText ?? !Object.hasOwn(args, "text"),
|
|
@@ -136,7 +147,7 @@ function makeEditTitle(kind) {
|
|
|
136
147
|
for (const [property, value] of Object.entries(properties)) {
|
|
137
148
|
next = next.editGraphics({ target: names.title, property, value });
|
|
138
149
|
}
|
|
139
|
-
return next;
|
|
150
|
+
return materializeTextLines(next, names.title, titleLines(text, config, geometry));
|
|
140
151
|
}));
|
|
141
152
|
}
|
|
142
153
|
|
|
@@ -1,3 +1,4 @@
|
|
|
1
|
+
import { withGuideVisibilityPaint } from "../../../materialization/guides/visibility.js";
|
|
1
2
|
import { editGraphicProperties } from "../../primitives/graphicProperties.js";
|
|
2
3
|
import { action } from "../../../core/action.js";
|
|
3
4
|
import {
|
|
@@ -25,7 +26,7 @@ const CREATE_OPTIONS = Object.freeze([
|
|
|
25
26
|
"scale", "coordinate", "count", "values", "color", "lineWidth",
|
|
26
27
|
"strokeDash"
|
|
27
28
|
]);
|
|
28
|
-
const EDIT_OPTIONS = Object.freeze([
|
|
29
|
+
const EDIT_OPTIONS = Object.freeze(["visible",
|
|
29
30
|
"count", "values", "color", "lineWidth", "strokeDash"
|
|
30
31
|
]);
|
|
31
32
|
|
|
@@ -48,6 +49,7 @@ function validateStrokeDash(value) {
|
|
|
48
49
|
}
|
|
49
50
|
|
|
50
51
|
export function validatePolarGridOptions(args, operation, create) {
|
|
52
|
+
if (Object.hasOwn(args, "visible") && typeof args.visible !== "boolean") throw new TypeError("Grid visible must be a boolean.");
|
|
51
53
|
validateOptionObject(
|
|
52
54
|
args,
|
|
53
55
|
create ? CREATE_OPTIONS : EDIT_OPTIONS,
|
|
@@ -86,6 +88,7 @@ function resolveConfig(program, kind, args, resources, previous) {
|
|
|
86
88
|
: { mode: "count", count: previous.count, inferredValues: false };
|
|
87
89
|
const config = {
|
|
88
90
|
...(previous ?? {}),
|
|
91
|
+
...(Object.hasOwn(args, "visible") ? { visible: args.visible } : {}),
|
|
89
92
|
kind,
|
|
90
93
|
scale: resources.scale,
|
|
91
94
|
coordinate: resources.coordinate,
|
|
@@ -156,7 +159,7 @@ function makeRematerialize(kind) {
|
|
|
156
159
|
return action({
|
|
157
160
|
op: operations.rematerialize,
|
|
158
161
|
description: `Recompute concrete Polar ${kind} grid geometry.`
|
|
159
|
-
}, function (args = {}) {
|
|
162
|
+
}, withGuideVisibilityPaint(function (args = {}) {
|
|
160
163
|
noOptions(args, operations.rematerialize);
|
|
161
164
|
const config = this.guideConfigs.grid?.[kind];
|
|
162
165
|
const semantic = this.semanticSpec.guides.grid?.[kind];
|
|
@@ -175,7 +178,7 @@ function makeRematerialize(kind) {
|
|
|
175
178
|
refreshed,
|
|
176
179
|
geometry
|
|
177
180
|
);
|
|
178
|
-
});
|
|
181
|
+
}));
|
|
179
182
|
}
|
|
180
183
|
|
|
181
184
|
function makeCreate(kind) {
|
|
@@ -41,7 +41,13 @@ export function inferHistogramBoundaries(program, channel, scaleId) {
|
|
|
41
41
|
values.some((value, index) => value !== unique[index]))) {
|
|
42
42
|
throw new Error(`Guide values cannot infer shared histogram bins for scale "${scaleId}".`);
|
|
43
43
|
}
|
|
44
|
-
|
|
44
|
+
const domain = program.resolvedScales[scaleId]?.domain;
|
|
45
|
+
// Retained histogram bins can extend beyond an auto domain after filtering.
|
|
46
|
+
// Inferred guides follow the displayed interval; user-specified tick values
|
|
47
|
+
// still use the normal strict validation path.
|
|
48
|
+
if (domain === undefined) return unique;
|
|
49
|
+
const minimum = Math.min(...domain), maximum = Math.max(...domain);
|
|
50
|
+
return unique.filter(value => value >= minimum && value <= maximum);
|
|
45
51
|
}
|
|
46
52
|
|
|
47
53
|
export function valuesFromTickConfig(program, config) {
|
package/src/actions/index.js
CHANGED
|
@@ -21,6 +21,7 @@ import { registerResourceActions } from "./resources/index.js";
|
|
|
21
21
|
import { registerTextMetricActions } from "./textMetrics/index.js";
|
|
22
22
|
import { registerCompositionActions } from "./composition/index.js";
|
|
23
23
|
import { registerFacetActions } from "./facets/index.js";
|
|
24
|
+
import { registerOverlayActions } from "./overlays/index.js";
|
|
24
25
|
import { registerThemeActions } from "./theme/index.js";
|
|
25
26
|
import {
|
|
26
27
|
applyCompositionTheme,
|
|
@@ -38,6 +39,7 @@ export function registerActions(ProgramClass) {
|
|
|
38
39
|
registerCanvasActions(ProgramClass);
|
|
39
40
|
registerDataActions(ProgramClass);
|
|
40
41
|
registerMarkActions(ProgramClass);
|
|
42
|
+
registerOverlayActions(ProgramClass);
|
|
41
43
|
registerScaleActions(ProgramClass);
|
|
42
44
|
registerEncodingActions(ProgramClass);
|
|
43
45
|
registerBasicCoordinateActions(ProgramClass);
|
|
@@ -194,6 +194,7 @@ const rematerializeAreaMark = /* @__PURE__ */ action(
|
|
|
194
194
|
}
|
|
195
195
|
const colorEncoding = layer.encoding?.color;
|
|
196
196
|
const strokeEncoding = layer.encoding?.stroke;
|
|
197
|
+
const opacityEncoding = layer.encoding?.opacity;
|
|
197
198
|
let resolved = args.scales === false
|
|
198
199
|
? this
|
|
199
200
|
: this
|
|
@@ -205,8 +206,11 @@ const rematerializeAreaMark = /* @__PURE__ */ action(
|
|
|
205
206
|
if (args.scales !== false && strokeEncoding?.scale !== undefined) {
|
|
206
207
|
resolved = resolved.rematerializeScale({ id: strokeEncoding.scale });
|
|
207
208
|
}
|
|
209
|
+
if (args.scales !== false && opacityEncoding?.scale !== undefined) {
|
|
210
|
+
resolved = resolved.rematerializeScale({ id: opacityEncoding.scale });
|
|
211
|
+
}
|
|
208
212
|
const config = validateAreaPaintConfig(this.markConfigs[id]);
|
|
209
|
-
const { paths, fills, strokes } = resolveAreaMaterialization({
|
|
213
|
+
const { paths, fills, strokes, opacities } = resolveAreaMaterialization({
|
|
210
214
|
rows: dataset.values,
|
|
211
215
|
layer,
|
|
212
216
|
densityTransform,
|
|
@@ -227,7 +231,7 @@ const rematerializeAreaMark = /* @__PURE__ */ action(
|
|
|
227
231
|
length: paths.length,
|
|
228
232
|
commands: paths,
|
|
229
233
|
fill: fills,
|
|
230
|
-
opacity: config.opacity,
|
|
234
|
+
opacity: opacities ?? config.opacity ?? 0.2,
|
|
231
235
|
...(hasOutline ? {
|
|
232
236
|
stroke: strokes ?? (config.strokeFromFill === true ? fills : config.stroke),
|
|
233
237
|
strokeWidth: config.strokeWidth ?? (strokes === undefined ? undefined : 1)
|
|
@@ -273,6 +277,9 @@ const editAreaMark = /* @__PURE__ */ action(
|
|
|
273
277
|
"editAreaMark stroke conflicts with a field encoding; use encodeStroke with value to replace it."
|
|
274
278
|
);
|
|
275
279
|
}
|
|
280
|
+
if (Object.hasOwn(args, "opacity") && layer.encoding?.opacity !== undefined) {
|
|
281
|
+
throw new Error("editAreaMark opacity conflicts with a field encoding; use encodeOpacity with value to replace it.");
|
|
282
|
+
}
|
|
276
283
|
if (args.stroke === false && Object.hasOwn(args, "strokeWidth")) {
|
|
277
284
|
throw new Error("editAreaMark cannot set strokeWidth while removing stroke.");
|
|
278
285
|
}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
import{deriveCenteredAreaSeries as
|
|
1
|
+
import{deriveCenteredAreaSeries as E,deriveAreaSeries as w,deriveDensityAreaSeries as z,layoutDensityAreaSeries as q}from"../../../grammar/areaSeries.js";import{mapContinuousScaleValues as s,mapOrdinalPositionValues as D}from"../../../grammar/scales/index.js";import{mapScaleConsumerValues as b}from"../../../materialization/scales/map.js";import{buildAreaCurvePathCommands as A}from"../../../grammar/curveCommands.js";import{buildLinearPathCommands as C}from"../../../grammar/pathCommands.js";import{buildCategoricalDensityPaths as B}from"../../../grammar/categoricalDensity.js";import{derivePathSeriesFieldValues as k}from"../../../grammar/pathSeries.js";function F({derived:p,densityTransform:o,categoricalDensity:m,xScale:c,yScale:u,densityScale:x,layout:v,curve:r}){return m?B(p,{categoryScale:o.placement.channel==="x"?c:u,valueScale:o.placement.channel==="x"?u:c,curve:r}):p.series.map(t=>{if(o===void 0&&p.orientation==="horizontal"){const e=(["point","band"].includes(u.type)?D:s)(t.values.map(n=>n.y),u),a=s(t.values.map(n=>n.x),c),d=s(t.values.map(n=>n.x2),c);return A(e.map((n,l)=>({x:a[l],y:n})),e.map((n,l)=>({x:d[l],y:n})),r,{independentAxis:"y"})}if(o!==void 0&&p.mode==="x-density"){const e=(["point","band"].includes(u.type)?D:s)(t.values.map(n=>n.y),u),a=s(t.values.map(n=>n.x),c),d=s([0],x)[0];return r==="linear"?C([{x:d,y:e[0]},...e.map((n,l)=>({x:a[l],y:n})),{x:d,y:e.at(-1)}],{close:!0}):A(e.map(n=>({x:d,y:n})),e.map((n,l)=>({x:a[l],y:n})),r,{independentAxis:"y"})}const i=(["point","band"].includes(c.type)?D:s)(t.values.map(e=>e.x),c),h=o===void 0?p.mode==="y-center"?t.values.map(e=>e.lower):t.values.map(e=>e.y):p.mode==="y-density"?t.values.map(e=>e.lower):t.values.map(e=>e.y),g=s(h,u),f=o===void 0?p.mode==="y-center"?t.values.map(e=>e.upper):t.values.map(e=>e.y2):t.values.map(e=>e.upper),y=s(f,u);if(o!==void 0&&v==="overlay"){const e=s([0],u)[0];return r==="linear"?C([{x:i[0],y:e},...i.map((a,d)=>({x:a,y:y[d]})),{x:i.at(-1),y:e}],{close:!0}):A(i.map(a=>({x:a,y:e})),i.map((a,d)=>({x:a,y:y[d]})),r)}return A(i.map((e,a)=>({x:e,y:g[a]})),i.map((e,a)=>({x:e,y:y[a]})),r)})}function I({rows:p,layer:o,densityTransform:m,resolvedScales:c,config:u}){const x=c[o.encoding.x.scale],v=c[o.encoding.y.scale],r=m===void 0&&o.encoding?.y?.stack==="center",t=m===void 0?r?E(p,o,{xDomain:x.domain}):w(p,o,{xDomain:x.domain,yDomain:v.domain}):z(p,o,m),i=o.encoding?.color,h=o.layout?.mode??i?.layout??"overlay",g=m?.placement?.type==="category",f=m===void 0||g?t:q(t,h),y=m===void 0||g?void 0:f.mode==="y-density"?v:x;if(y!==void 0&&(y.domain[0]>0||y.domain[1]<0))throw new Error(`Density area mark "${o.id}" requires a scale domain containing zero.`);const e=F({derived:f,densityTransform:m,categoricalDensity:g,xScale:x,yScale:v,densityScale:y,layout:h,curve:u.curve??"linear"}),a=u.errorBand?.fill!==void 0?e.map(()=>u.errorBand.fill):i?.scale===void 0?e.map(()=>u.fill):b(i.fieldType!=="quantitative"&&(m!==void 0||r)?f.series.map(V=>V.key[i.field]):k(p,f.series,i.field,"color",i),c[i.scale],"color"),d=o.encoding?.stroke,n=d?.scale===void 0?void 0:b(k(p,f.series,d.field,"stroke",d),c[d.scale],"stroke"),l=o.encoding?.opacity,P=l?.scale===void 0?void 0:b(k(p,f.series,l.field,"opacity",l),c[l.scale],"opacity");return{paths:e,fills:a,strokes:n,opacities:P}}export{I as resolveAreaMaterialization};
|
|
@@ -12,7 +12,7 @@ import {
|
|
|
12
12
|
BAR_GRAINS,
|
|
13
13
|
resolveBarOffsetChannel
|
|
14
14
|
} from "../../../grammar/bars/policy.js";
|
|
15
|
-
import { rematerializeHighlightBaseline } from "../lifecycle.js";
|
|
15
|
+
import { rematerializeHighlightBaseline, materializeFollowingOverlays } from "../lifecycle.js";
|
|
16
16
|
import { offsetCategoryRectangles } from
|
|
17
17
|
"../../../materialization/categorySlotOffset.js";
|
|
18
18
|
import { materializeRectItem, RECT_STYLE_PROPERTIES } from "../../../grammar/roundedRect.js";
|
|
@@ -30,12 +30,12 @@ function editRectangles(program, id, rectangles) {
|
|
|
30
30
|
item.properties?.blend !== undefined);
|
|
31
31
|
if (hasShapeStyle || blend !== undefined || previousBlend) {
|
|
32
32
|
const radius = appearance;
|
|
33
|
-
return materializeMarkClip(replaceGraphicItems(
|
|
33
|
+
return materializeFollowingOverlays(materializeMarkClip(replaceGraphicItems(
|
|
34
34
|
program,
|
|
35
35
|
id,
|
|
36
36
|
"rect",
|
|
37
37
|
rectangles.map(rectangle => materializeRectItem(rectangle, radius))
|
|
38
|
-
), id);
|
|
38
|
+
), id), id);
|
|
39
39
|
}
|
|
40
40
|
let next = editGraphicProperties(program, id, {
|
|
41
41
|
length: rectangles.length,
|
|
@@ -54,7 +54,7 @@ function editRectangles(program, id, rectangles) {
|
|
|
54
54
|
value: rectangles.map(rect => rect.opacity ?? 1)
|
|
55
55
|
});
|
|
56
56
|
}
|
|
57
|
-
return materializeMarkClip(next, id);
|
|
57
|
+
return materializeFollowingOverlays(materializeMarkClip(next, id), id);
|
|
58
58
|
}
|
|
59
59
|
|
|
60
60
|
export const rematerializeBarMark = /* @__PURE__ */ action(
|
|
@@ -1,3 +1,17 @@
|
|
|
1
|
+
// Called explicitly by source mark materializers after their concrete geometry is complete.
|
|
2
|
+
// A surrounding plan owns any overlay rebuild that it has already scheduled.
|
|
3
|
+
export function materializeFollowingOverlays(program, source) {
|
|
4
|
+
const pending = program.context?.pendingMaterializationPlan;
|
|
5
|
+
const scheduled = new Set((pending?.steps.slice(pending.next) ?? [])
|
|
6
|
+
.filter(step => step.op === "rematerializeOverlay").map(step => step.args.id));
|
|
7
|
+
for (const layer of program.semanticSpec.layers) {
|
|
8
|
+
if (layer.derivedBindings?.overlay?.source === source && !scheduled.has(layer.id)) {
|
|
9
|
+
program = program.rematerializeOverlay({ id: layer.id });
|
|
10
|
+
}
|
|
11
|
+
}
|
|
12
|
+
return program;
|
|
13
|
+
}
|
|
14
|
+
|
|
1
15
|
export function rematerializeHighlightBaseline(program, {
|
|
2
16
|
target,
|
|
3
17
|
operation,
|
|
@@ -1,3 +1,4 @@
|
|
|
1
|
+
import { assertIndependentOverlayGeometry } from "../../../grammar/overlay.js";
|
|
1
2
|
import { requestedMarkClip, validateMarkClipCoordinate } from "../../../selectors/markClip.js";
|
|
2
3
|
import { action } from "../../../core/action.js";
|
|
3
4
|
import { validateUserId } from "../../../core/identifiers.js";
|
|
@@ -209,6 +210,7 @@ const rematerializeLineMark = /* @__PURE__ */ action(
|
|
|
209
210
|
"rematerializeLineMark"
|
|
210
211
|
);
|
|
211
212
|
const id = validateUserId(args.id, "Line mark id");
|
|
213
|
+
if (findLayer(this, id)?.derivedBindings?.overlay) return this.rematerializeOverlay({ id });
|
|
212
214
|
const highlighted = rematerializeHighlightBaseline(this, {
|
|
213
215
|
target: id,
|
|
214
216
|
operation: "rematerializeLineMark",
|
|
@@ -301,6 +303,7 @@ const editLineMark = /* @__PURE__ */ action(
|
|
|
301
303
|
predicate: candidate => candidate.mark?.type === "line",
|
|
302
304
|
label: "line mark"
|
|
303
305
|
});
|
|
306
|
+
if (Object.hasOwn(args, "missing")) assertIndependentOverlayGeometry(layer, "editLineMark missing");
|
|
304
307
|
if (Object.hasOwn(args, "stroke") && (
|
|
305
308
|
layer.encoding?.color !== undefined ||
|
|
306
309
|
layer.encoding?.stroke !== undefined
|
|
@@ -101,7 +101,7 @@ export function resolvePositionedLineMaterialization({
|
|
|
101
101
|
const radiusScaleId = layer.encoding?.radius?.scale;
|
|
102
102
|
const lineOptions = polar
|
|
103
103
|
? { thetaDomain: resolvedScales[thetaScaleId].domain }
|
|
104
|
-
: { xBinBoundaries, xDomain: resolvedScales[xScaleId].domain };
|
|
104
|
+
: { xBinBoundaries, xDomain: resolvedScales[xScaleId].domain, yDomain: resolvedScales[yScaleId].domain };
|
|
105
105
|
const derived = deriveLineSeries(rows, layer, { ...lineOptions, scales: resolvedScales });
|
|
106
106
|
const commands = polar
|
|
107
107
|
? derived.series.map(series => buildPolarLinePathCommands({
|
|
@@ -119,7 +119,9 @@ export function resolvePositionedLineMaterialization({
|
|
|
119
119
|
series.values.map(value => value.x),
|
|
120
120
|
resolvedScales[xScaleId]
|
|
121
121
|
);
|
|
122
|
-
const
|
|
122
|
+
const mapY = ["nominal", "ordinal"].includes(layer.encoding.y.fieldType)
|
|
123
|
+
? mapOrdinalPositionValues : mapContinuousScaleValues;
|
|
124
|
+
const y = mapY(
|
|
123
125
|
series.values.map(value => value.y),
|
|
124
126
|
resolvedScales[yScaleId]
|
|
125
127
|
);
|
|
@@ -1,3 +1,4 @@
|
|
|
1
|
+
import { assertIndependentOverlayGeometry } from "../../../grammar/overlay.js";
|
|
1
2
|
import { requestedMarkClip, validateMarkClipCoordinate } from "../../../selectors/markClip.js";
|
|
2
3
|
import { action } from "../../../core/action.js";
|
|
3
4
|
import { validateUserId } from "../../../core/identifiers.js";
|
|
@@ -45,6 +46,7 @@ export const editPointMark = /* @__PURE__ */ action(
|
|
|
45
46
|
predicate: candidate => candidate.mark?.type === "point",
|
|
46
47
|
label: "point mark"
|
|
47
48
|
});
|
|
49
|
+
if (Object.hasOwn(args, "missing")) assertIndependentOverlayGeometry(layer, "editPointMark missing");
|
|
48
50
|
const id = layer.id;
|
|
49
51
|
if (Object.hasOwn(args, "shape") && layer.encoding?.shape !== undefined) {
|
|
50
52
|
throw new Error(
|
|
@@ -1,3 +1,4 @@
|
|
|
1
|
+
import { assertIndependentOverlayGeometry } from "../../../grammar/overlay.js";
|
|
1
2
|
import { closedAction } from "../../../core/action.js";
|
|
2
3
|
import { validateUserId } from "../../../core/identifiers.js";
|
|
3
4
|
|
|
@@ -36,6 +37,7 @@ export const jitterPoints = /* @__PURE__ */ closedAction(
|
|
|
36
37
|
function (args = {}) {
|
|
37
38
|
const policy = normalizePointJitterPolicy(args);
|
|
38
39
|
const layer = resolveJitterTarget(this, args.target);
|
|
40
|
+
assertIndependentOverlayGeometry(layer, "jitterPoints");
|
|
39
41
|
if (this.materializationConfigs.pointPacking?.[layer.id] !== undefined) {
|
|
40
42
|
throw new Error(`Point jitter on "${layer.id}" conflicts with point packing.`);
|
|
41
43
|
}
|
|
@@ -34,7 +34,7 @@ import { findLayer } from "../../../selectors/layers.js";
|
|
|
34
34
|
import { resolveGraphicItemCapacity } from "../../../selectors/graphicCapacity.js";
|
|
35
35
|
import { getMarkGraphicTypes } from "../../../core/vocabulary.js";
|
|
36
36
|
import { canMaterializePoint } from "../../../materialization/marks/capabilities.js";
|
|
37
|
-
import { rematerializeHighlightBaseline } from "../lifecycle.js";
|
|
37
|
+
import { rematerializeHighlightBaseline, materializeFollowingOverlays } from "../lifecycle.js";
|
|
38
38
|
import {
|
|
39
39
|
resolveRowEncodingValues,
|
|
40
40
|
resolveRowPositionValues
|
|
@@ -307,6 +307,7 @@ export const rematerializePointMark = /* @__PURE__ */ action(
|
|
|
307
307
|
function (args = {}) {
|
|
308
308
|
validateMarkOptions(args, REMATERIALIZE_OPTIONS, "rematerializePointMark");
|
|
309
309
|
const id = validateUserId(args.id, "Point mark id");
|
|
310
|
+
if (findLayer(this, id)?.derivedBindings?.overlay) return this.rematerializeOverlay({ id });
|
|
310
311
|
const highlighted = rematerializeHighlightBaseline(this, {
|
|
311
312
|
target: id,
|
|
312
313
|
operation: "rematerializePointMark",
|
|
@@ -453,11 +454,11 @@ export const rematerializePointMark = /* @__PURE__ */ action(
|
|
|
453
454
|
...strokeDetails
|
|
454
455
|
});
|
|
455
456
|
});
|
|
456
|
-
return materializeMarkClip(jittered.program.editGraphics({
|
|
457
|
+
return materializeFollowingOverlays(materializeMarkClip(jittered.program.editGraphics({
|
|
457
458
|
target: id,
|
|
458
459
|
property: "items",
|
|
459
460
|
value: items
|
|
460
|
-
}), id);
|
|
461
|
+
}), id), id);
|
|
461
462
|
}
|
|
462
463
|
|
|
463
464
|
let next = graphic.items.length === dataset.values.length
|
|
@@ -552,6 +553,6 @@ export const rematerializePointMark = /* @__PURE__ */ action(
|
|
|
552
553
|
for (const [property, value] of Object.entries(strokeDetails)) {
|
|
553
554
|
next = next.editGraphics({ target: id, property, value });
|
|
554
555
|
}
|
|
555
|
-
return materializeMarkClip(next, id);
|
|
556
|
+
return materializeFollowingOverlays(materializeMarkClip(next, id), id);
|
|
556
557
|
}
|
|
557
558
|
);
|
|
@@ -1,3 +1,4 @@
|
|
|
1
|
+
import { assertIndependentOverlayGeometry } from "../../../grammar/overlay.js";
|
|
1
2
|
import { closedAction } from "../../../core/action.js";
|
|
2
3
|
import { validateUserId } from "../../../core/identifiers.js";
|
|
3
4
|
|
|
@@ -33,6 +34,7 @@ export const packPoints = /* @__PURE__ */ closedAction(
|
|
|
33
34
|
function (args = {}) {
|
|
34
35
|
const policy = normalizePointPackingPolicy(args);
|
|
35
36
|
const layer = target(this, args.target, policy.channel);
|
|
37
|
+
assertIndependentOverlayGeometry(layer, "packPoints");
|
|
36
38
|
if (this.materializationConfigs.jitters?.[layer.id] !== undefined) {
|
|
37
39
|
throw new Error(`Point packing on "${layer.id}" conflicts with point jitter.`);
|
|
38
40
|
}
|
|
@@ -410,14 +410,16 @@ function resolvePopulationValues(
|
|
|
410
410
|
const { field } = resolveBoundPopulation(program, source, config, referenceId);
|
|
411
411
|
if (field !== undefined) return strictFieldValues(dataset.values, field,
|
|
412
412
|
`Statistical reference "${referenceId}" boundData`);
|
|
413
|
-
if (source.mark.type === "line" && isAggregate(source.encoding?.y?.aggregate)) {
|
|
413
|
+
if (source.mark.type === "line" && (isAggregate(source.encoding?.y?.aggregate) || isAggregate(source.encoding?.x?.aggregate))) {
|
|
414
414
|
const x = source.encoding.x;
|
|
415
415
|
const bins = x.bin === undefined ? undefined : resolveLineBins(
|
|
416
416
|
dataset.values, source, findSemanticScale(program, x.scale)
|
|
417
417
|
);
|
|
418
418
|
const derived = deriveLineSeries(dataset.values, source, {
|
|
419
419
|
...(bins === undefined ? {} : { xBinBoundaries: bins.boundaries }),
|
|
420
|
-
allowSingleton: true
|
|
420
|
+
allowSingleton: true,
|
|
421
|
+
xDomain: program.resolvedScales[source.encoding.x.scale]?.domain,
|
|
422
|
+
yDomain: program.resolvedScales[source.encoding.y.scale]?.domain
|
|
421
423
|
});
|
|
422
424
|
return config.axis === "x" ? derived.xValues : derived.yValues;
|
|
423
425
|
}
|
|
@@ -458,7 +460,7 @@ function statisticalRows(program, referenceId) {
|
|
|
458
460
|
);
|
|
459
461
|
const { dataset } = resolveBoundPopulation(program, source, { ...config, population }, referenceId);
|
|
460
462
|
const groupBy = normalizeReferenceGroupBy(config.groupBy);
|
|
461
|
-
if (population === "visibleItems" && findSelectionPolicy(source.mark?.type) === undefined) {
|
|
463
|
+
if (population === "visibleItems" && (source.mark?.type === "text" || findSelectionPolicy(source.mark?.type) === undefined)) {
|
|
462
464
|
throw new Error(
|
|
463
465
|
`Statistical reference "${referenceId}" visibleItems population is unavailable for ${source.mark?.type} marks. Use boundData.`
|
|
464
466
|
);
|
|
@@ -4,6 +4,7 @@ import { isSourceOwnedText } from "../../grammar/text.js";
|
|
|
4
4
|
import { closedAction } from "../../core/action.js";
|
|
5
5
|
import { validateUserId } from "../../core/identifiers.js";
|
|
6
6
|
|
|
7
|
+
import { findSemanticScale } from "../../selectors/scales.js";
|
|
7
8
|
import { findDataset } from "../../selectors/datasets.js";
|
|
8
9
|
import { findLayer } from "../../selectors/layers.js";
|
|
9
10
|
import { applyDetachedScaleRematerialization } from "../../materialization/dependencies.js";
|
|
@@ -113,6 +114,13 @@ function ownedDerivedData(program, ids) {
|
|
|
113
114
|
candidates.add(dataset.id);
|
|
114
115
|
}
|
|
115
116
|
}
|
|
117
|
+
// Release leaf transforms before their complete-case input chain.
|
|
118
|
+
for (const id of ids) {
|
|
119
|
+
const config = program.markConfigs[id] ?? {};
|
|
120
|
+
for (const data of config.alignedPositionData ?? []) candidates.add(data);
|
|
121
|
+
for (const data of config.raincloudPlot?.ownedData ?? config.endpointPlot?.ownedData ?? []) candidates.add(data);
|
|
122
|
+
for (const data of [...(config.radarPlot?.ownedData ?? [])].reverse()) candidates.add(data);
|
|
123
|
+
}
|
|
116
124
|
return candidates;
|
|
117
125
|
}
|
|
118
126
|
|
|
@@ -165,6 +173,7 @@ export function removeOwnedMark(program, id, partial = false) {
|
|
|
165
173
|
}
|
|
166
174
|
return next
|
|
167
175
|
._withoutMaterializationConfig(["guides", "legendGroups", id])
|
|
176
|
+
._withoutMaterializationConfig(["guides", "suppressedLegends", id])
|
|
168
177
|
._withoutMaterializationConfig(["marks", id])
|
|
169
178
|
._withContext({
|
|
170
179
|
...(program.context.currentMark === id ? { currentMark: undefined } : {}),
|
|
@@ -222,6 +231,7 @@ export const removeMark = /* @__PURE__ */ closedAction(
|
|
|
222
231
|
}
|
|
223
232
|
const previousLayers = ids.map(id => findLayer(this, id));
|
|
224
233
|
const derived = ownedDerivedData(this, ids);
|
|
234
|
+
const ownedScales = new Set(ids.map(id => this.markConfigs[id]?.seriesOffsetScale).filter(Boolean));
|
|
225
235
|
const positionScales = usedPositionScales(this, ids);
|
|
226
236
|
let next = this;
|
|
227
237
|
|
|
@@ -264,6 +274,7 @@ export const removeMark = /* @__PURE__ */ closedAction(
|
|
|
264
274
|
next = next.editGraphics({ target: id, remove: true });
|
|
265
275
|
}
|
|
266
276
|
next = next._withoutMaterializationConfig(["guides", "legendGroups", id]);
|
|
277
|
+
next = next._withoutMaterializationConfig(["guides", "suppressedLegends", id]);
|
|
267
278
|
next = next._withoutMaterializationConfig(["marks", id]);
|
|
268
279
|
next = next._withoutMaterializationConfig(["jitters", id]);
|
|
269
280
|
next = next._withoutMaterializationConfig(["pointPacking", id]);
|
|
@@ -277,6 +288,11 @@ export const removeMark = /* @__PURE__ */ closedAction(
|
|
|
277
288
|
}
|
|
278
289
|
}
|
|
279
290
|
next = applyDetachedScaleRematerialization(next, previousLayers);
|
|
291
|
+
for (const id of ownedScales) {
|
|
292
|
+
const references = collectResourceReferences(next, { kind: "scale", id })
|
|
293
|
+
.filter(reference => reference.strength !== "context");
|
|
294
|
+
if (references.length === 0 && findSemanticScale(next, id) !== undefined) next = next.removeScale({ id });
|
|
295
|
+
}
|
|
280
296
|
return next._withContext({
|
|
281
297
|
...(ids.includes(this.context.currentMark) ? { currentMark: undefined } : {}),
|
|
282
298
|
...(selectionCleanup.selectionIds.includes(this.context.currentSelection)
|
|
@@ -1,4 +1,5 @@
|
|
|
1
1
|
import { materializeMarkClip } from "../../materialization/markClip.js";
|
|
2
|
+
import { materializeFollowingOverlays } from "./lifecycle.js";
|
|
2
3
|
import { isSourceOwnedText } from "../../grammar/text.js";
|
|
3
4
|
import {
|
|
4
5
|
resolveOptionalUserId,
|
|
@@ -244,5 +245,5 @@ export function editMarkGraphic(program, target, properties) {
|
|
|
244
245
|
for (const [property, value] of Object.entries(properties)) {
|
|
245
246
|
program = program.editGraphics({ target, property, value });
|
|
246
247
|
}
|
|
247
|
-
return materializeMarkClip(program, target);
|
|
248
|
+
return materializeFollowingOverlays(materializeMarkClip(program, target), target);
|
|
248
249
|
}
|
|
@@ -1,3 +1,4 @@
|
|
|
1
|
+
import { rematerializeHighlightBaseline } from "../lifecycle.js";
|
|
1
2
|
import { materializeMarkClip } from "../../../materialization/markClip.js";
|
|
2
3
|
import { requestedMarkClip, validateMarkClipCoordinate } from "../../../selectors/markClip.js";
|
|
3
4
|
import { TEXT_LABEL_LAYOUT_OPTIONS } from "./layout.js";
|
|
@@ -46,7 +47,7 @@ import { validateItemMissing } from "../../../grammar/itemMissing.js";
|
|
|
46
47
|
|
|
47
48
|
const STYLE_OPTIONS = Object.freeze(["clip", ...TEXT_MARK_STYLE_OPTIONS]);
|
|
48
49
|
const CREATE_OPTIONS = Object.freeze(["id", "data", "source", "text", "missing", ...STYLE_OPTIONS]);
|
|
49
|
-
const EDIT_OPTIONS = Object.freeze(["target", "missing", ...STYLE_OPTIONS]);
|
|
50
|
+
const EDIT_OPTIONS = Object.freeze(["target", "missing", "textOverrides", ...STYLE_OPTIONS]);
|
|
50
51
|
const REMATERIALIZE_OPTIONS = Object.freeze(["id", "replayLayout"]);
|
|
51
52
|
|
|
52
53
|
function sourceMatchesData(program, layer, requestedData) {
|
|
@@ -460,6 +461,8 @@ const rematerializeTextMark = /* @__PURE__ */ action(
|
|
|
460
461
|
? next
|
|
461
462
|
: next.materializeMarkLabelPlacement({ id });
|
|
462
463
|
}
|
|
464
|
+
const highlighted = rematerializeHighlightBaseline(this, { target: id, operation: 'rematerializeTextMark', resetProperty: 'items', resetValue: [] });
|
|
465
|
+
if (highlighted) return highlighted;
|
|
463
466
|
let next = materializeMarkClip(this.editGraphics({
|
|
464
467
|
target: id,
|
|
465
468
|
property: "items",
|
|
@@ -486,7 +489,7 @@ const editTextMark = /* @__PURE__ */ action(
|
|
|
486
489
|
function (args = {}) {
|
|
487
490
|
validateMarkOptions(args, EDIT_OPTIONS, "editTextMark");
|
|
488
491
|
requestedMarkClip(args);
|
|
489
|
-
if (!["missing", ...STYLE_OPTIONS].some(option => Object.hasOwn(args, option))) {
|
|
492
|
+
if (!["missing", "textOverrides", ...STYLE_OPTIONS].some(option => Object.hasOwn(args, option))) {
|
|
490
493
|
throw new Error("editTextMark requires at least one editable property.");
|
|
491
494
|
}
|
|
492
495
|
const layer = requireTextLayer(this, args.target, "editTextMark");
|