ggaction 0.0.13 → 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 +146 -0
- package/README.md +41 -12
- 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 +39 -7
- package/src/BasicChartProgram.js +3 -1
- package/src/ChartProgram.js +2 -0
- package/src/accessibility.js +157 -0
- package/src/actions/basic.js +2 -2
- package/src/actions/boxPlots/components.js +20 -12
- package/src/actions/boxPlots/create.js +4 -5
- package/src/actions/boxPlots/edit.js +34 -9
- package/src/actions/boxPlots/materialize.js +12 -4
- package/src/actions/boxPlots/options.js +48 -16
- package/src/actions/canvas/actions.js +3 -3
- package/src/actions/canvas/fitting.js +1 -1
- package/src/actions/categoryOrder/index.js +21 -12
- package/src/actions/charts/area.js +6 -2
- package/src/actions/charts/bar.js +3 -2
- package/src/actions/charts/beeswarm.js +1 -1
- package/src/actions/charts/density.js +7 -3
- package/src/actions/charts/ecdf.js +6 -3
- package/src/actions/charts/endpoints.js +29 -7
- package/src/actions/charts/heatmap.js +3 -2
- package/src/actions/charts/histogram.js +5 -4
- package/src/actions/charts/horizon.js +4 -2
- package/src/actions/charts/interval-regression.js +7 -4
- package/src/actions/charts/line.js +4 -2
- package/src/actions/charts/parallel.js +9 -3
- package/src/actions/charts/pie.js +11 -3
- package/src/actions/charts/polar.js +17 -6
- package/src/actions/charts/radar.js +9 -3
- package/src/actions/charts/radial.js +12 -4
- package/src/actions/charts/raincloud.js +2 -2
- package/src/actions/charts/rug-strip.js +8 -4
- package/src/actions/charts/scatter.js +4 -2
- package/src/actions/composition/actions.js +29 -24
- package/src/actions/coordinates/actions.js +2 -2
- package/src/actions/coordinates/edit.js +76 -0
- package/src/actions/data/basicBin2d.js +4 -5
- package/src/actions/data/bin.js +3 -3
- package/src/actions/data/bin2d.js +63 -193
- package/src/actions/data/bin2dMaterialize.js +4 -5
- package/src/actions/data/box.js +4 -4
- package/src/actions/data/complete.js +26 -0
- package/src/actions/data/computed.js +4 -4
- package/src/actions/data/create.js +7 -14
- package/src/actions/data/density.js +15 -23
- package/src/actions/data/derived.js +57 -31
- package/src/actions/data/ecdf.js +2 -2
- package/src/actions/data/edit.js +551 -0
- package/src/actions/data/filter.js +28 -22
- 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 +26 -0
- package/src/actions/data/index.js +62 -47
- package/src/actions/data/interval.js +2 -2
- package/src/actions/data/intervalEdit.js +26 -18
- package/src/actions/data/normalize.js +27 -0
- package/src/actions/data/regression.js +21 -27
- package/src/actions/data/revise.js +48 -0
- package/src/actions/data/revisionBindings.js +125 -0
- package/src/actions/data/shared.js +20 -4
- package/src/actions/data/stack.js +2 -2
- package/src/actions/data/summary.js +3 -3
- package/src/actions/data/timeUnit.js +6 -3
- package/src/actions/data/window.js +3 -3
- 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 +415 -0
- package/src/actions/encodings/color/index.js +3 -2
- package/src/actions/encodings/density.js +7 -4
- package/src/actions/encodings/histogram.js +4 -3
- package/src/actions/encodings/horizon.js +6 -8
- package/src/actions/encodings/index.js +4 -0
- package/src/actions/encodings/offset.js +22 -15
- package/src/actions/encodings/parallel.js +4 -5
- package/src/actions/encodings/pathOrder.js +6 -11
- package/src/actions/encodings/position/apply.js +53 -7
- package/src/actions/encodings/position/index.js +14 -6
- package/src/actions/encodings/position/policies/bar.js +9 -0
- package/src/actions/encodings/position/resolve.js +24 -7
- package/src/actions/encodings/ranged.js +5 -5
- package/src/actions/encodings/remove.js +13 -9
- package/src/actions/encodings/ruleAppearance.js +2 -24
- package/src/actions/encodings/seriesLayout.js +2 -1
- package/src/actions/encodings/shared.js +82 -14
- package/src/actions/encodings/stroke.js +226 -0
- package/src/actions/encodings/strokeDash.js +2 -2
- package/src/actions/encodings/text.js +1 -1
- package/src/actions/errorBands/create.js +34 -20
- package/src/actions/errorBands/edit.js +34 -137
- package/src/actions/errorBars/create.js +43 -20
- package/src/actions/errorBars/edit.js +29 -125
- package/src/actions/facets/actions.js +267 -73
- package/src/actions/facets/derive.js +99 -28
- package/src/actions/facets/guides.js +4 -5
- package/src/actions/facets/replay.js +4 -5
- package/src/actions/gradientPlots/components.js +15 -8
- package/src/actions/gradientPlots/create.js +4 -5
- package/src/actions/gradientPlots/edit.js +18 -9
- package/src/actions/gradientPlots/materialize.js +5 -3
- package/src/actions/gradientPlots/options.js +10 -2
- package/src/actions/gradientPlots/rebind.js +4 -5
- package/src/actions/guides/applicability.js +8 -2
- 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 +67 -21
- package/src/actions/guides/axes/lines.js +15 -9
- package/src/actions/guides/axes/parallel/lifecycle.js +13 -13
- package/src/actions/guides/axes/parallel/resolve.js +6 -2
- 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 +6 -5
- package/src/actions/guides/axes/ticks.js +19 -6
- package/src/actions/guides/axes/titles.js +21 -13
- package/src/actions/guides/grids/grid.js +18 -29
- package/src/actions/guides/grids/resolve.js +7 -2
- package/src/actions/guides/guides.js +20 -4
- package/src/actions/guides/legends/blocks.js +426 -0
- package/src/actions/guides/legends/categorical/actions.js +138 -52
- package/src/actions/guides/legends/categorical/components.js +55 -45
- package/src/actions/guides/legends/categorical/index.js +37 -33
- package/src/actions/guides/legends/categorical/layout.js +98 -16
- package/src/actions/guides/legends/categorical/options.js +2 -2
- package/src/actions/guides/legends/categorical/recipes.js +111 -20
- package/src/actions/guides/legends/categorical/resolve.js +12 -8
- package/src/actions/guides/legends/categorical/symbols.js +104 -52
- package/src/actions/guides/legends/continuous/common.js +76 -20
- package/src/actions/guides/legends/continuous/gradient.js +95 -158
- package/src/actions/guides/legends/continuous/index.js +2 -0
- package/src/actions/guides/legends/continuous/interval.js +21 -16
- package/src/actions/guides/legends/continuous/opacity.js +37 -83
- package/src/actions/guides/legends/continuous/stroke.js +225 -0
- package/src/actions/guides/legends/creation.js +14 -1
- package/src/actions/guides/legends/edit.js +159 -60
- package/src/actions/guides/legends/focused.js +5 -5
- package/src/actions/guides/legends/index.js +2 -0
- package/src/actions/guides/legends/lane.js +59 -24
- package/src/actions/guides/legends/lifecycle.js +19 -8
- package/src/actions/guides/legends/remove.js +17 -8
- package/src/actions/guides/legends/sampling.js +140 -0
- package/src/actions/guides/legends/size.js +100 -108
- package/src/actions/guides/legends/strokeWidth.js +38 -92
- package/src/actions/guides/legends/target.js +112 -1
- package/src/actions/guides/legends/transition.js +165 -16
- package/src/actions/guides/polar/axes/facade.js +8 -8
- package/src/actions/guides/polar/axes/labels.js +29 -10
- package/src/actions/guides/polar/axes/lines.js +19 -19
- package/src/actions/guides/polar/axes/shared.js +16 -0
- package/src/actions/guides/polar/axes/ticks.js +10 -16
- package/src/actions/guides/polar/axes/titles.js +6 -6
- package/src/actions/guides/polar/grids.js +12 -14
- package/src/actions/guides/polar/resolve.js +12 -8
- package/src/actions/index.js +16 -3
- package/src/actions/intervals/revision.js +126 -0
- package/src/actions/marks/arc/actions.js +80 -22
- package/src/actions/marks/area/actions.js +38 -13
- package/src/actions/marks/area/materialize.js +17 -1
- package/src/actions/marks/bar/create.js +12 -3
- package/src/actions/marks/bar/edit.js +21 -4
- package/src/actions/marks/bar/materialize.js +34 -40
- package/src/actions/marks/index.js +10 -1
- package/src/actions/marks/line/actions.js +40 -17
- package/src/actions/marks/line/materialize.js +29 -10
- package/src/actions/marks/point/create.js +9 -3
- package/src/actions/marks/point/edit.js +19 -7
- package/src/actions/marks/point/jitter.js +6 -8
- package/src/actions/marks/point/materialize.js +48 -22
- package/src/actions/marks/point/packing.js +6 -8
- package/src/actions/marks/rect/actions.js +36 -15
- package/src/actions/marks/references.js +602 -33
- package/src/actions/marks/remove.js +67 -41
- package/src/actions/marks/rule/actions.js +51 -14
- package/src/actions/marks/shared.js +1 -1
- package/src/actions/marks/text/actions.js +79 -14
- package/src/actions/marks/text/index.js +4 -0
- package/src/actions/marks/text/layout.js +157 -17
- package/src/actions/marks/text/removal.js +173 -0
- package/src/actions/marks/text/selection.js +72 -0
- package/src/actions/marks/tick/actions.js +25 -8
- package/src/actions/primitives/createGraphics.js +5 -4
- package/src/actions/primitives/editGraphics.js +31 -4
- package/src/actions/primitives/graphicProperties.js +6 -0
- package/src/actions/primitives/semantic.js +11 -3
- package/src/actions/primitives/semanticAction.js +90 -14
- package/src/actions/primitives/semanticValidation/dataset.js +2 -4
- package/src/actions/primitives/semanticValidation/guide.js +1 -1
- package/src/actions/primitives/semanticValidation/index.js +9 -1
- package/src/actions/primitives/semanticValidation/layer.js +5 -0
- package/src/actions/primitives/semanticValidation/scale.js +28 -7
- package/src/actions/regression/components.js +36 -25
- package/src/actions/regression/create.js +13 -6
- package/src/actions/regression/edit.js +24 -11
- package/src/actions/resources/index.js +7 -0
- package/src/actions/resources/remove.js +173 -0
- package/src/actions/scales/channels.js +212 -0
- package/src/actions/scales/consumers/common.js +1 -1
- package/src/actions/scales/consumers/families.js +3 -2
- package/src/actions/scales/consumers/index.js +19 -2
- package/src/actions/scales/consumers/seriesLayout.js +28 -14
- package/src/actions/scales/create.js +55 -23
- package/src/actions/scales/definitions.js +94 -40
- package/src/actions/scales/edit.js +67 -12
- package/src/actions/scales/editPolicy.js +81 -11
- package/src/actions/scales/index.js +6 -0
- package/src/actions/scales/materialize.js +5 -4
- package/src/actions/scales/offset.js +48 -0
- package/src/actions/scales/parallel.js +71 -0
- package/src/actions/scales/preview.js +111 -10
- package/src/actions/scales/quantitativeColor.js +4 -5
- package/src/actions/selection/actions.js +179 -66
- package/src/actions/selection/index.js +3 -0
- package/src/actions/textMetrics/index.js +56 -0
- package/src/actions/theme/actions.js +70 -15
- package/src/actions/theme/composition.js +238 -0
- package/src/actions/theme/index.js +9 -2
- package/src/actions/theme/reconcile.js +313 -121
- package/src/actions/theme/state.js +160 -0
- package/src/actions/titles/actions.js +8 -8
- package/src/actions/titles/resolve.js +3 -3
- package/src/actions/violinPlots/create.js +6 -3
- package/src/actions/violinPlots/edit.js +2 -1
- package/src/core/action.js +117 -35
- package/src/core/compositionState.js +6 -1
- 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 +21 -1
- package/src/core/resourceReferences.js +341 -0
- package/src/core/textMetricProfile.js +28 -0
- package/src/core/textMetrics.js +24 -3
- package/src/core/validation.js +22 -10
- package/src/core/vocabulary.js +16 -3
- package/src/diagnostics.js +1 -0
- package/src/grammar/bars/aggregate.js +4 -1
- package/src/grammar/bars/geometry.js +44 -0
- package/src/grammar/bin.js +54 -9
- package/src/grammar/complete.js +279 -0
- package/src/grammar/computed.js +265 -64
- package/src/grammar/coordinates.js +37 -0
- package/src/grammar/density.js +239 -37
- package/src/grammar/displayLabels.js +57 -0
- package/src/grammar/facets/dependencies.js +133 -1
- package/src/grammar/facets/guides.js +3 -0
- package/src/grammar/facets/index.js +7 -47
- package/src/grammar/facets/scales.js +15 -18
- package/src/grammar/impute.js +341 -0
- package/src/grammar/markLabelSelection.js +57 -0
- package/src/grammar/markLabels.js +18 -1
- package/src/grammar/normalize.js +366 -0
- package/src/grammar/pathSeries.js +26 -8
- package/src/grammar/pointShapes.js +13 -4
- package/src/grammar/polar.js +90 -8
- package/src/grammar/regression/index.js +1 -0
- package/src/grammar/regression/parameters.js +23 -0
- package/src/grammar/roundedRect.js +180 -0
- package/src/grammar/rules.js +1 -0
- package/src/grammar/scales/colorConsumers.js +20 -1
- package/src/grammar/scales/continuous.js +2 -2
- package/src/grammar/scales/definition.js +27 -4
- package/src/grammar/scales/index.js +1 -0
- package/src/grammar/scales/ordinal.js +12 -3
- package/src/grammar/scales/policies.js +2 -2
- package/src/grammar/scales/size.js +456 -0
- package/src/grammar/scales/types.js +8 -0
- package/src/grammar/schemas/concreteGraphic.js +14 -2
- package/src/grammar/schemas/graphic.js +15 -0
- package/src/grammar/schemas/graphicBounds.js +190 -41
- package/src/grammar/schemas/semanticPath.js +7 -2
- package/src/grammar/statisticalReference.js +103 -0
- package/src/grammar/strokeStyle.js +77 -0
- package/src/grammar/summary.js +78 -16
- package/src/grammar/timeUnit.js +216 -5
- package/src/grammar/transformTopology.js +4 -0
- package/src/grammar/transforms.js +394 -28
- package/src/grammar/weightedStatistics.js +374 -0
- package/src/grammar/window.js +221 -16
- package/src/layout/aspect.js +80 -0
- package/src/layout/facets.js +59 -5
- package/src/layout/labels.js +351 -7
- 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/bars/aggregate.js +25 -2
- package/src/materialization/bars/histogram.js +84 -24
- package/src/materialization/bars/ranged.js +19 -3
- package/src/materialization/bars/resolve.js +7 -4
- package/src/materialization/composition.js +3 -1
- package/src/materialization/coordinateBounds.js +204 -0
- package/src/materialization/dependencies.js +36 -0
- package/src/materialization/facetGuides/legacyCategorical.js +3 -0
- package/src/materialization/facetGuides/placement.js +9 -3
- package/src/materialization/facetGuides/preparation.js +13 -8
- package/src/materialization/facetHeaders.js +347 -0
- package/src/materialization/facets.js +15 -65
- package/src/materialization/guides/layout.js +3 -3
- package/src/materialization/guides/resources.js +26 -0
- package/src/materialization/legends.js +1 -1
- package/src/materialization/marks/index.js +11 -5
- package/src/materialization/marks/policies.js +2 -1
- package/src/materialization/rect.js +25 -12
- package/src/materialization/rectConfig.js +5 -1
- package/src/materialization/scaleGuideDependencies.js +10 -0
- package/src/materialization/scales/map.js +5 -3
- package/src/materialization/scales/policies/binnedPosition.js +2 -2
- package/src/materialization/scales/policies/offset.js +50 -8
- package/src/materialization/scales/policies/series.js +4 -1
- package/src/materialization/scales/resolve.js +22 -6
- package/src/materialization/selection/items/arc.js +28 -4
- package/src/materialization/selection/items/bar.js +30 -3
- package/src/materialization/selection/items/common.js +20 -5
- package/src/materialization/selection/items/rect.js +28 -4
- package/src/materialization/selection/path.js +1 -1
- package/src/materialization/selection/point.js +3 -1
- package/src/materialization/text.js +265 -14
- 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/circle.js +2 -3
- package/src/renderers/canvas/index.js +5 -4
- package/src/renderers/canvas/line.js +2 -3
- package/src/renderers/canvas/native.js +4 -4
- package/src/renderers/canvas/path.js +2 -3
- package/src/renderers/canvas/rect.js +2 -3
- package/src/renderers/canvas/stroke.js +11 -0
- 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 +29 -14
- package/src/renderers/text.js +1 -11
- package/src/selectors/coordinates.js +3 -1
- package/src/selectors/datasets.js +38 -5
- package/src/selectors/layers.js +10 -4
- package/src/selectors/markOwners.js +46 -0
- package/src/selectors/scales.js +6 -4
- package/src/theme/defaults.js +103 -1
- package/src/version.js +2 -0
- package/types/accessibility.d.ts +37 -0
- package/types/basic.d.ts +10 -2
- package/types/diagnostics.d.ts +15 -0
- package/types/index.d.ts +90 -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 +944 -118
|
@@ -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 {
|
|
@@ -11,6 +12,8 @@ import {
|
|
|
11
12
|
resolveFacetDefinition,
|
|
12
13
|
resolveFacetGridDefinition
|
|
13
14
|
} from "../../grammar/facets/index.js";
|
|
15
|
+
import { collectFacetScaleBindings, resolveFacetFamily } from
|
|
16
|
+
"../../grammar/facets/dependencies.js";
|
|
14
17
|
import {
|
|
15
18
|
FACET_SCALE_CHANNELS,
|
|
16
19
|
normalizeFacetScalePolicies
|
|
@@ -18,14 +21,21 @@ import {
|
|
|
18
21
|
import { resolveFacetLayout } from "../../layout/facets.js";
|
|
19
22
|
import { compositionChildDescriptor } from
|
|
20
23
|
"../../materialization/composition.js";
|
|
21
|
-
import { DEFAULT_COLORS, DEFAULT_FONT_FAMILY } from "../../theme/defaults.js";
|
|
22
24
|
import { deriveFacetChildren } from "./derive.js";
|
|
23
25
|
import { resolveFacetChildrenScales } from "./derive.js";
|
|
24
26
|
import { replayDerivedData } from "./replay.js";
|
|
25
27
|
import { composeFacetGuides } from "./guides.js";
|
|
26
28
|
import { applyCompositionState } from "../composition/actions.js";
|
|
29
|
+
import { replayCompositionThemeState } from "../theme/composition.js";
|
|
27
30
|
import { findDataset } from "../../selectors/datasets.js";
|
|
28
31
|
import { findLayer } from "../../selectors/layers.js";
|
|
32
|
+
import { findSemanticScale } from "../../selectors/scales.js";
|
|
33
|
+
import { normalizeDisplayLabelMap } from "../../grammar/displayLabels.js";
|
|
34
|
+
import {
|
|
35
|
+
createDefaultFacetHeaders,
|
|
36
|
+
normalizeFacetHeadersConfig,
|
|
37
|
+
resolveFacetHeaderConfig
|
|
38
|
+
} from "../../materialization/facetHeaders.js";
|
|
29
39
|
|
|
30
40
|
const FACET_OPTIONS = Object.freeze([
|
|
31
41
|
"id", "field", "data", "values", "columns", "gap", "align", "padding", "scales",
|
|
@@ -42,15 +52,12 @@ const REPEAT_OPTIONS = Object.freeze([
|
|
|
42
52
|
const SOURCE_EDIT_OPTIONS = Object.freeze(["program"]);
|
|
43
53
|
const GUIDE_OPTIONS = Object.freeze(["axes", "legend"]);
|
|
44
54
|
const HEADER_OPTIONS = Object.freeze([
|
|
45
|
-
"fontSize", "fontFamily", "fontWeight", "color", "offset"
|
|
55
|
+
"fontSize", "fontFamily", "fontWeight", "color", "offset", "role",
|
|
56
|
+
"labelMap", "side", "align"
|
|
57
|
+
]);
|
|
58
|
+
const HEADER_STYLE_OPTIONS = Object.freeze([
|
|
59
|
+
"fontSize", "fontFamily", "fontWeight", "color", "offset", "align"
|
|
46
60
|
]);
|
|
47
|
-
const DEFAULT_HEADERS = Object.freeze({
|
|
48
|
-
fontSize: 12,
|
|
49
|
-
fontFamily: DEFAULT_FONT_FAMILY,
|
|
50
|
-
fontWeight: 600,
|
|
51
|
-
color: DEFAULT_COLORS.strongText,
|
|
52
|
-
offset: 10
|
|
53
|
-
});
|
|
54
61
|
|
|
55
62
|
function normalizeGuides(guides) {
|
|
56
63
|
if (guides === undefined) return { axes: "each", legend: false };
|
|
@@ -74,11 +81,14 @@ function requireFacetProgram(program, operation) {
|
|
|
74
81
|
}
|
|
75
82
|
|
|
76
83
|
function usedFacetScalePolicies(program, policies) {
|
|
77
|
-
|
|
78
|
-
program.semanticSpec.
|
|
79
|
-
|
|
80
|
-
|
|
81
|
-
|
|
84
|
+
const used = new Set(
|
|
85
|
+
collectFacetScaleBindings(program.semanticSpec).map(binding => binding.policyKey)
|
|
86
|
+
);
|
|
87
|
+
return Object.fromEntries(
|
|
88
|
+
FACET_SCALE_CHANNELS.flatMap(channel =>
|
|
89
|
+
used.has(channel) ? [[channel, policies[channel]]] : []
|
|
90
|
+
)
|
|
91
|
+
);
|
|
82
92
|
}
|
|
83
93
|
|
|
84
94
|
function facetUnitTemplate(program) {
|
|
@@ -96,6 +106,9 @@ function facetUnitTemplate(program) {
|
|
|
96
106
|
resolvedScales: program.resolvedScales,
|
|
97
107
|
materializationConfigs: freezeOwned({
|
|
98
108
|
...unitConfigs,
|
|
109
|
+
...(seed.materializationConfigs.theme === undefined
|
|
110
|
+
? {}
|
|
111
|
+
: { theme: seed.materializationConfigs.theme }),
|
|
99
112
|
...(seed.materializationConfigs.guides === undefined
|
|
100
113
|
? {}
|
|
101
114
|
: { guides: seed.materializationConfigs.guides }),
|
|
@@ -145,11 +158,7 @@ function rederiveFacet(program, { scales, guides }) {
|
|
|
145
158
|
columns: current.facet.grid.columns,
|
|
146
159
|
combinations: current.facet.grid.combinations
|
|
147
160
|
});
|
|
148
|
-
const request =
|
|
149
|
-
program.semanticSpec.layers.some(
|
|
150
|
-
layer => layer.encoding?.[channel]?.scale !== undefined
|
|
151
|
-
) ? [[channel, scales[channel]]] : []
|
|
152
|
-
));
|
|
161
|
+
const request = usedFacetScalePolicies(program, scales);
|
|
153
162
|
const normalized = normalizeFacetScalePolicies(program.semanticSpec, request);
|
|
154
163
|
const template = facetUnitTemplate(program);
|
|
155
164
|
const derived = deriveFacetChildren(template, definition, {
|
|
@@ -175,15 +184,17 @@ function rederiveFacet(program, { scales, guides }) {
|
|
|
175
184
|
}, compositionSpec.children);
|
|
176
185
|
}
|
|
177
186
|
|
|
178
|
-
export const facet =
|
|
187
|
+
export const facet = /* @__PURE__ */ closedAction(
|
|
179
188
|
{
|
|
180
189
|
op: "facet",
|
|
181
190
|
description: "Repeat one direct-source chart by field value."
|
|
182
|
-
},
|
|
191
|
+
}, FACET_OPTIONS,
|
|
183
192
|
function (args = {}) {
|
|
184
|
-
validateOptionObject(args, FACET_OPTIONS, "facet");
|
|
185
193
|
const guides = normalizeGuides(args.guides);
|
|
186
194
|
const definition = resolveFacetDefinition(this.semanticSpec, args);
|
|
195
|
+
if (definition.family !== "cartesian" && guides.axes === "outer") {
|
|
196
|
+
throw new Error("Polar and Parallel facets do not support outer axes.");
|
|
197
|
+
}
|
|
187
198
|
const scalePolicies = normalizeFacetScalePolicies(
|
|
188
199
|
this.semanticSpec,
|
|
189
200
|
args.scales ?? {}
|
|
@@ -222,7 +233,7 @@ export const facet = action(
|
|
|
222
233
|
};
|
|
223
234
|
return applyCompositionState(
|
|
224
235
|
this._withMaterializationConfig(["facets", definition.id], {
|
|
225
|
-
headers:
|
|
236
|
+
headers: createDefaultFacetHeaders()
|
|
226
237
|
}),
|
|
227
238
|
{
|
|
228
239
|
children: derived.children,
|
|
@@ -238,8 +249,20 @@ function resolveRepeatDefinition(program, args) {
|
|
|
238
249
|
throw new TypeError("repeatCharts options must be a plain object.");
|
|
239
250
|
}
|
|
240
251
|
const id = validateUserId(args.id ?? "repeat", "Repeat id");
|
|
241
|
-
|
|
242
|
-
|
|
252
|
+
const parallelChannel = isPlainObject(args.channel);
|
|
253
|
+
if (parallelChannel) {
|
|
254
|
+
const keys = Object.keys(args.channel);
|
|
255
|
+
if (keys.length !== 1 || keys[0] !== "parallelDimension" ||
|
|
256
|
+
typeof args.channel.parallelDimension !== "string" ||
|
|
257
|
+
args.channel.parallelDimension.length === 0) {
|
|
258
|
+
throw new Error(
|
|
259
|
+
"repeatCharts Parallel channel must contain exactly one non-empty parallelDimension."
|
|
260
|
+
);
|
|
261
|
+
}
|
|
262
|
+
} else if (!["x", "y", "theta", "r"].includes(args.channel)) {
|
|
263
|
+
throw new Error(
|
|
264
|
+
'repeatCharts channel must be "x", "y", "theta", "r", or one parallelDimension.'
|
|
265
|
+
);
|
|
243
266
|
}
|
|
244
267
|
if (!Array.isArray(args.fields) || args.fields.length === 0 ||
|
|
245
268
|
args.fields.some(field => typeof field !== "string" || field.length === 0)) {
|
|
@@ -248,29 +271,53 @@ function resolveRepeatDefinition(program, args) {
|
|
|
248
271
|
if (new Set(args.fields).size !== args.fields.length) {
|
|
249
272
|
throw new Error("repeatCharts fields must be unique.");
|
|
250
273
|
}
|
|
251
|
-
const
|
|
252
|
-
|
|
253
|
-
|
|
254
|
-
|
|
255
|
-
|
|
256
|
-
|
|
274
|
+
const family = resolveFacetFamily(program.semanticSpec).family;
|
|
275
|
+
const semanticChannel = args.channel === "r" ? "radius" : args.channel;
|
|
276
|
+
const eligible = program.semanticSpec.layers.filter(layer => {
|
|
277
|
+
if (parallelChannel) {
|
|
278
|
+
const matches = (layer.encoding?.parallel?.dimensions ?? []).filter(
|
|
279
|
+
dimension => dimension.field === args.channel.parallelDimension
|
|
280
|
+
);
|
|
281
|
+
return family === "parallel" && layer.mark?.type === "line" && matches.length === 1;
|
|
282
|
+
}
|
|
283
|
+
if (["x", "y"].includes(args.channel)) {
|
|
284
|
+
return family === "cartesian" &&
|
|
285
|
+
layer.encoding?.x?.scale !== undefined &&
|
|
286
|
+
layer.encoding?.y?.scale !== undefined &&
|
|
287
|
+
layer.encoding?.[args.channel]?.field !== undefined &&
|
|
288
|
+
["point", "line", "area", "bar", "rule", "tick", "rect"].includes(layer.mark?.type);
|
|
289
|
+
}
|
|
290
|
+
const role = program.markConfigs[layer.id]?.compositionRole;
|
|
291
|
+
if (family !== "polar" || ["pie", "radar"].includes(role)) return false;
|
|
292
|
+
return ["point", "line", "arc"].includes(layer.mark?.type) &&
|
|
293
|
+
layer.encoding?.[semanticChannel]?.field !== undefined;
|
|
294
|
+
});
|
|
257
295
|
let target;
|
|
258
296
|
if (args.target !== undefined) {
|
|
259
297
|
target = validateUserId(args.target, "Repeat target");
|
|
260
298
|
if (!eligible.some(layer => layer.id === target)) {
|
|
261
|
-
throw new Error(
|
|
299
|
+
throw new Error(
|
|
300
|
+
`repeatCharts target "${target}" is not eligible for the requested field role.`
|
|
301
|
+
);
|
|
262
302
|
}
|
|
263
303
|
} else if (eligible.length === 1) {
|
|
264
304
|
target = eligible[0].id;
|
|
265
305
|
} else {
|
|
266
306
|
throw new Error(
|
|
267
307
|
eligible.length === 0
|
|
268
|
-
? "repeatCharts requires one complete
|
|
308
|
+
? "repeatCharts requires one eligible complete mark for the requested field role."
|
|
269
309
|
: "repeatCharts target is ambiguous; provide target."
|
|
270
310
|
);
|
|
271
311
|
}
|
|
272
|
-
|
|
273
|
-
|
|
312
|
+
const unrelatedLayers = program.semanticSpec.layers.filter(layer => {
|
|
313
|
+
if (layer.id === target) return false;
|
|
314
|
+
const attachedLabel = layer.mark?.type === "text" && layer.source === target;
|
|
315
|
+
const statisticalReference = program.markConfigs[layer.id]
|
|
316
|
+
?.statisticalReference?.source === target;
|
|
317
|
+
return !attachedLabel && !statisticalReference;
|
|
318
|
+
});
|
|
319
|
+
if (unrelatedLayers.length > 0) {
|
|
320
|
+
throw new Error("repeatCharts currently supports one direct mark only.");
|
|
274
321
|
}
|
|
275
322
|
const config = program.markConfigs[target] ?? {};
|
|
276
323
|
const composite = [
|
|
@@ -285,14 +332,23 @@ function resolveRepeatDefinition(program, args) {
|
|
|
285
332
|
if (dataset?.transform?.length > 0) {
|
|
286
333
|
throw new Error("repeatCharts does not rewrite a derived dataset dependency.");
|
|
287
334
|
}
|
|
288
|
-
const encoding =
|
|
335
|
+
const encoding = parallelChannel
|
|
336
|
+
? layer.encoding.parallel
|
|
337
|
+
: layer.encoding[semanticChannel];
|
|
338
|
+
const dimensionIndex = parallelChannel
|
|
339
|
+
? encoding.dimensions.findIndex(
|
|
340
|
+
dimension => dimension.field === args.channel.parallelDimension
|
|
341
|
+
)
|
|
342
|
+
: undefined;
|
|
289
343
|
return {
|
|
290
344
|
id,
|
|
291
345
|
target,
|
|
292
|
-
channel: args.channel,
|
|
346
|
+
channel: parallelChannel ? { ...args.channel } : args.channel,
|
|
347
|
+
policyKey: parallelChannel ? "parallelDimensions" : args.channel,
|
|
293
348
|
fields: [...args.fields],
|
|
294
349
|
data: layer.data,
|
|
295
350
|
encoding,
|
|
351
|
+
...(dimensionIndex === undefined ? {} : { dimensionIndex }),
|
|
296
352
|
cells: args.fields.map((field, index) => ({
|
|
297
353
|
id: `${id}-field-${index + 1}`,
|
|
298
354
|
field,
|
|
@@ -316,15 +372,52 @@ function repeatEncodingArgs(definition, field) {
|
|
|
316
372
|
};
|
|
317
373
|
}
|
|
318
374
|
|
|
375
|
+
function parallelRepeatDimensions(program, definition, field) {
|
|
376
|
+
return definition.encoding.dimensions.map((dimension, index) => {
|
|
377
|
+
const semanticScale = findSemanticScale(program, dimension.scale);
|
|
378
|
+
if (semanticScale === undefined) {
|
|
379
|
+
throw new Error(`repeatCharts Parallel dimension scale "${dimension.scale}" is missing.`);
|
|
380
|
+
}
|
|
381
|
+
const { id: _id, ...scale } = semanticScale;
|
|
382
|
+
void _id;
|
|
383
|
+
const replacement = index === definition.dimensionIndex;
|
|
384
|
+
return {
|
|
385
|
+
field: replacement ? field : dimension.field,
|
|
386
|
+
fieldType: dimension.fieldType,
|
|
387
|
+
title: replacement && dimension.title === dimension.field
|
|
388
|
+
? field
|
|
389
|
+
: dimension.title,
|
|
390
|
+
scale
|
|
391
|
+
};
|
|
392
|
+
});
|
|
393
|
+
}
|
|
394
|
+
|
|
395
|
+
function deriveRepeatedProgram(template, definition, field) {
|
|
396
|
+
if (isPlainObject(definition.channel)) {
|
|
397
|
+
return template.encodeParallelCoordinates({
|
|
398
|
+
target: definition.target,
|
|
399
|
+
coordinate: findLayer(template, definition.target).coordinate,
|
|
400
|
+
dimensions: parallelRepeatDimensions(template, definition, field),
|
|
401
|
+
...(definition.encoding.key === undefined ? {} : { key: definition.encoding.key }),
|
|
402
|
+
missing: definition.encoding.missing
|
|
403
|
+
});
|
|
404
|
+
}
|
|
405
|
+
const operation = {
|
|
406
|
+
x: "encodeX",
|
|
407
|
+
y: "encodeY",
|
|
408
|
+
theta: "encodeTheta",
|
|
409
|
+
r: "encodeR"
|
|
410
|
+
}[definition.channel];
|
|
411
|
+
return template[operation](repeatEncodingArgs(definition, field));
|
|
412
|
+
}
|
|
413
|
+
|
|
319
414
|
function deriveRepeatChildren(base, definition, scales, closeInheritedAction) {
|
|
320
415
|
const template = base.semanticSpec.title.text === undefined
|
|
321
416
|
? base
|
|
322
417
|
: base.removeTitle();
|
|
323
418
|
const independentlyResolved = Object.fromEntries(definition.cells.map(cell => [
|
|
324
419
|
cell.id,
|
|
325
|
-
template
|
|
326
|
-
repeatEncodingArgs(definition, cell.field)
|
|
327
|
-
)
|
|
420
|
+
deriveRepeatedProgram(template, definition, cell.field)
|
|
328
421
|
]));
|
|
329
422
|
return resolveFacetChildrenScales(
|
|
330
423
|
template,
|
|
@@ -335,13 +428,12 @@ function deriveRepeatChildren(base, definition, scales, closeInheritedAction) {
|
|
|
335
428
|
);
|
|
336
429
|
}
|
|
337
430
|
|
|
338
|
-
export const repeatCharts =
|
|
431
|
+
export const repeatCharts = /* @__PURE__ */ closedAction(
|
|
339
432
|
{
|
|
340
433
|
op: "repeatCharts",
|
|
341
|
-
description: "Repeat one direct
|
|
342
|
-
},
|
|
434
|
+
description: "Repeat one direct chart across an ordered field-role list."
|
|
435
|
+
}, REPEAT_OPTIONS,
|
|
343
436
|
function (args = {}) {
|
|
344
|
-
validateOptionObject(args, REPEAT_OPTIONS, "repeatCharts");
|
|
345
437
|
const guides = normalizeGuides(args.guides);
|
|
346
438
|
if (guides.axes === "outer") {
|
|
347
439
|
throw new Error("repeatCharts does not promote axes across different repeated fields.");
|
|
@@ -349,7 +441,7 @@ export const repeatCharts = action(
|
|
|
349
441
|
const definition = resolveRepeatDefinition(this, args);
|
|
350
442
|
const requestedScales = {
|
|
351
443
|
...(args.scales ?? {}),
|
|
352
|
-
[definition.
|
|
444
|
+
[definition.policyKey]: args.scales?.[definition.policyKey] ?? "independent"
|
|
353
445
|
};
|
|
354
446
|
const scalePolicies = normalizeFacetScalePolicies(
|
|
355
447
|
this.semanticSpec,
|
|
@@ -394,7 +486,7 @@ export const repeatCharts = action(
|
|
|
394
486
|
};
|
|
395
487
|
return applyCompositionState(
|
|
396
488
|
this._withMaterializationConfig(["facets", definition.id], {
|
|
397
|
-
headers:
|
|
489
|
+
headers: createDefaultFacetHeaders()
|
|
398
490
|
}),
|
|
399
491
|
{ children: derived.children, compositionSpec },
|
|
400
492
|
compositionSpec.children
|
|
@@ -402,15 +494,17 @@ export const repeatCharts = action(
|
|
|
402
494
|
}
|
|
403
495
|
);
|
|
404
496
|
|
|
405
|
-
export const facetGrid =
|
|
497
|
+
export const facetGrid = /* @__PURE__ */ closedAction(
|
|
406
498
|
{
|
|
407
499
|
op: "facetGrid",
|
|
408
500
|
description: "Repeat one direct-source Cartesian chart across a row and column field grid."
|
|
409
|
-
},
|
|
501
|
+
}, FACET_GRID_OPTIONS,
|
|
410
502
|
function (args = {}) {
|
|
411
|
-
validateOptionObject(args, FACET_GRID_OPTIONS, "facetGrid");
|
|
412
503
|
const guides = normalizeGuides(args.guides);
|
|
413
504
|
const definition = resolveFacetGridDefinition(this.semanticSpec, args);
|
|
505
|
+
if (definition.family !== "cartesian" && guides.axes === "outer") {
|
|
506
|
+
throw new Error("Polar and Parallel facets do not support outer axes.");
|
|
507
|
+
}
|
|
414
508
|
const scalePolicies = normalizeFacetScalePolicies(
|
|
415
509
|
this.semanticSpec,
|
|
416
510
|
args.scales ?? {}
|
|
@@ -461,7 +555,7 @@ export const facetGrid = action(
|
|
|
461
555
|
};
|
|
462
556
|
return applyCompositionState(
|
|
463
557
|
this._withMaterializationConfig(["facets", definition.id], {
|
|
464
|
-
headers:
|
|
558
|
+
headers: createDefaultFacetHeaders()
|
|
465
559
|
}),
|
|
466
560
|
{ children: derived.children, compositionSpec },
|
|
467
561
|
compositionSpec.children
|
|
@@ -469,7 +563,7 @@ export const facetGrid = action(
|
|
|
469
563
|
}
|
|
470
564
|
);
|
|
471
565
|
|
|
472
|
-
export const editFacetHeaders = action(
|
|
566
|
+
export const editFacetHeaders = /* @__PURE__ */ action(
|
|
473
567
|
{
|
|
474
568
|
op: "editFacetHeaders",
|
|
475
569
|
description: "Edit parent-owned facet header appearance.",
|
|
@@ -486,18 +580,73 @@ export const editFacetHeaders = action(
|
|
|
486
580
|
allowEmpty: false,
|
|
487
581
|
emptyMessage: "editFacetHeaders requires at least one change."
|
|
488
582
|
});
|
|
489
|
-
const
|
|
490
|
-
|
|
491
|
-
|
|
492
|
-
|
|
493
|
-
|
|
494
|
-
|
|
495
|
-
|
|
496
|
-
|
|
497
|
-
|
|
498
|
-
|
|
499
|
-
|
|
500
|
-
|
|
583
|
+
const role = args.role ?? "all";
|
|
584
|
+
if (!["all", "row", "column"].includes(role)) {
|
|
585
|
+
throw new Error(`Unknown facet header role "${role}".`);
|
|
586
|
+
}
|
|
587
|
+
if (role === "all" && Object.hasOwn(args, "side")) {
|
|
588
|
+
throw new Error("editFacetHeaders side requires an explicit row or column role.");
|
|
589
|
+
}
|
|
590
|
+
if (role === "row" && this.compositionSpec.facet.grid === undefined) {
|
|
591
|
+
throw new Error("editFacetHeaders row role requires a row-column facet grid.");
|
|
592
|
+
}
|
|
593
|
+
if (Object.hasOwn(args, "side")) {
|
|
594
|
+
const sides = role === "row" ? ["left", "right"] : ["top", "bottom"];
|
|
595
|
+
if (!sides.includes(args.side)) {
|
|
596
|
+
throw new Error(`editFacetHeaders ${role} side must be ${sides.join(" or ")}.`);
|
|
597
|
+
}
|
|
598
|
+
}
|
|
599
|
+
if (Object.hasOwn(args, "align") &&
|
|
600
|
+
!["start", "center", "end"].includes(args.align)) {
|
|
601
|
+
throw new Error("editFacetHeaders align must be start, center, or end.");
|
|
602
|
+
}
|
|
603
|
+
if (role === "all" && Object.keys(args).every(key => key === "role")) {
|
|
604
|
+
throw new Error("editFacetHeaders requires at least one change.");
|
|
605
|
+
}
|
|
606
|
+
const current = normalizeFacetHeadersConfig(config.headers);
|
|
607
|
+
const owner = role === "all" ? "common" : role;
|
|
608
|
+
const patch = { ...current[owner] };
|
|
609
|
+
for (const key of HEADER_STYLE_OPTIONS) {
|
|
610
|
+
if (Object.hasOwn(args, key)) patch[key] = args[key];
|
|
611
|
+
}
|
|
612
|
+
if (Object.hasOwn(args, "side")) patch.side = args.side;
|
|
613
|
+
if (Object.hasOwn(args, "labelMap")) {
|
|
614
|
+
if (args.labelMap === "auto") delete patch.labelMap;
|
|
615
|
+
else {
|
|
616
|
+
patch.labelMap = normalizeDisplayLabelMap(
|
|
617
|
+
args.labelMap,
|
|
618
|
+
`editFacetHeaders ${role} labelMap`
|
|
619
|
+
);
|
|
620
|
+
}
|
|
621
|
+
}
|
|
622
|
+
const headers = {
|
|
623
|
+
...current,
|
|
624
|
+
...(role === "all" ? {} : { mode: "roles" }),
|
|
625
|
+
[owner]: patch
|
|
626
|
+
};
|
|
627
|
+
for (const headerRole of ["all", "row", "column"]) {
|
|
628
|
+
const resolved = resolveFacetHeaderConfig(headers, headerRole);
|
|
629
|
+
validatePositiveFinite(resolved.fontSize, `Facet ${headerRole} header fontSize`);
|
|
630
|
+
validateNonEmptyString(resolved.fontFamily, `Facet ${headerRole} header fontFamily`);
|
|
631
|
+
validateNonEmptyString(resolved.color, `Facet ${headerRole} header color`);
|
|
632
|
+
validateNonNegativeFinite(resolved.offset, `Facet ${headerRole} header offset`);
|
|
633
|
+
if (!(
|
|
634
|
+
(typeof resolved.fontWeight === "string" && resolved.fontWeight.length > 0) ||
|
|
635
|
+
Number.isFinite(resolved.fontWeight)
|
|
636
|
+
)) {
|
|
637
|
+
throw new TypeError(
|
|
638
|
+
`Facet ${headerRole} header fontWeight must be a non-empty string or number.`
|
|
639
|
+
);
|
|
640
|
+
}
|
|
641
|
+
if (!["start", "center", "end"].includes(resolved.align)) {
|
|
642
|
+
throw new Error(`Facet ${headerRole} header align must be start, center, or end.`);
|
|
643
|
+
}
|
|
644
|
+
if (resolved.labelMap !== undefined) {
|
|
645
|
+
normalizeDisplayLabelMap(
|
|
646
|
+
resolved.labelMap,
|
|
647
|
+
`Facet ${headerRole} header labelMap`
|
|
648
|
+
);
|
|
649
|
+
}
|
|
501
650
|
}
|
|
502
651
|
return this
|
|
503
652
|
._withMaterializationConfig(["facets", id], { ...config, headers })
|
|
@@ -505,7 +654,7 @@ export const editFacetHeaders = action(
|
|
|
505
654
|
}
|
|
506
655
|
);
|
|
507
656
|
|
|
508
|
-
export const editFacetScales = action(
|
|
657
|
+
export const editFacetScales = /* @__PURE__ */ action(
|
|
509
658
|
{
|
|
510
659
|
op: "editFacetScales",
|
|
511
660
|
description: "Edit facet scale-resolution policies and rederive every cell.",
|
|
@@ -518,8 +667,8 @@ export const editFacetScales = action(
|
|
|
518
667
|
emptyMessage: "editFacetScales requires at least one channel policy change."
|
|
519
668
|
});
|
|
520
669
|
for (const channel of Object.keys(args)) {
|
|
521
|
-
if (!this.semanticSpec.
|
|
522
|
-
|
|
670
|
+
if (!collectFacetScaleBindings(this.semanticSpec).some(
|
|
671
|
+
binding => binding.policyKey === channel
|
|
523
672
|
)) {
|
|
524
673
|
throw new Error(
|
|
525
674
|
`Facet scale channel "${channel}" is not used by an affected layer.`
|
|
@@ -540,7 +689,7 @@ export const editFacetScales = action(
|
|
|
540
689
|
}
|
|
541
690
|
);
|
|
542
691
|
|
|
543
|
-
export const editFacetGuides = action(
|
|
692
|
+
export const editFacetGuides = /* @__PURE__ */ action(
|
|
544
693
|
{
|
|
545
694
|
op: "editFacetGuides",
|
|
546
695
|
description: "Edit facet guide ownership and rederive every cell.",
|
|
@@ -554,6 +703,10 @@ export const editFacetGuides = action(
|
|
|
554
703
|
});
|
|
555
704
|
const current = this.compositionSpec.facet;
|
|
556
705
|
const guides = normalizeGuides({ ...current.guides, ...args });
|
|
706
|
+
const family = resolveFacetFamily(this.semanticSpec).family;
|
|
707
|
+
if (family !== "cartesian" && guides.axes === "outer") {
|
|
708
|
+
throw new Error("Polar and Parallel facets do not support outer axes.");
|
|
709
|
+
}
|
|
557
710
|
if (current.repeat !== undefined && guides.axes === "outer") {
|
|
558
711
|
throw new Error("repeatCharts does not promote axes across different repeated fields.");
|
|
559
712
|
}
|
|
@@ -574,11 +727,33 @@ function adoptUnitState(program, actionOwner) {
|
|
|
574
727
|
if (program.actionStack.length !== 0) {
|
|
575
728
|
throw new Error("editFacetSource program has an unfinished action stack.");
|
|
576
729
|
}
|
|
730
|
+
const seedId = actionOwner.compositionSpec.children.find(id =>
|
|
731
|
+
actionOwner.children[id]?.semanticSpec.layers.length > 0
|
|
732
|
+
) ?? actionOwner.compositionSpec.children[0];
|
|
733
|
+
const retained = actionOwner.children[seedId]?.materializationConfigs ?? {};
|
|
734
|
+
const {
|
|
735
|
+
canvas: _retainedCanvas,
|
|
736
|
+
theme: _retainedTheme,
|
|
737
|
+
facets: _retainedFacets,
|
|
738
|
+
...retainedRecipe
|
|
739
|
+
} = retained;
|
|
740
|
+
void _retainedCanvas;
|
|
741
|
+
void _retainedTheme;
|
|
742
|
+
void _retainedFacets;
|
|
577
743
|
return new actionOwner.constructor({
|
|
578
744
|
semanticSpec: program.semanticSpec,
|
|
579
745
|
graphicSpec: program.graphicSpec,
|
|
580
746
|
resolvedScales: program.resolvedScales,
|
|
581
|
-
materializationConfigs:
|
|
747
|
+
materializationConfigs: freezeOwned({
|
|
748
|
+
...program.materializationConfigs,
|
|
749
|
+
...retainedRecipe,
|
|
750
|
+
...(program.materializationConfigs.canvas === undefined
|
|
751
|
+
? {}
|
|
752
|
+
: { canvas: program.materializationConfigs.canvas }),
|
|
753
|
+
...(program.materializationConfigs.theme === undefined
|
|
754
|
+
? {}
|
|
755
|
+
: { theme: program.materializationConfigs.theme })
|
|
756
|
+
}),
|
|
582
757
|
children: {},
|
|
583
758
|
context: program.context,
|
|
584
759
|
trace: actionOwner.trace,
|
|
@@ -587,14 +762,13 @@ function adoptUnitState(program, actionOwner) {
|
|
|
587
762
|
});
|
|
588
763
|
}
|
|
589
764
|
|
|
590
|
-
export const editFacetSource =
|
|
765
|
+
export const editFacetSource = /* @__PURE__ */ closedAction(
|
|
591
766
|
{
|
|
592
767
|
op: "editFacetSource",
|
|
593
768
|
description: "Reapply one facet, grid, or repeat recipe to a revised complete unit program.",
|
|
594
769
|
scope: "composition"
|
|
595
|
-
},
|
|
770
|
+
}, SOURCE_EDIT_OPTIONS,
|
|
596
771
|
function (args = {}) {
|
|
597
|
-
validateOptionObject(args, SOURCE_EDIT_OPTIONS, "editFacetSource");
|
|
598
772
|
requireFacetProgram(this, "editFacetSource");
|
|
599
773
|
const current = this.compositionSpec;
|
|
600
774
|
const facetConfig = this.materializationConfigs.facets?.[current.id];
|
|
@@ -653,11 +827,31 @@ export const editFacetSource = action(
|
|
|
653
827
|
...this.semanticSpec.title
|
|
654
828
|
});
|
|
655
829
|
}
|
|
656
|
-
return
|
|
830
|
+
return replayCompositionThemeState(
|
|
831
|
+
revised,
|
|
832
|
+
this.materializationConfigs.theme
|
|
833
|
+
);
|
|
657
834
|
}
|
|
658
835
|
);
|
|
659
836
|
|
|
660
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
|
+
});
|
|
661
855
|
ProgramClass.prototype.replayDerivedData = replayDerivedData;
|
|
662
856
|
ProgramClass.prototype.composeFacetGuides = composeFacetGuides;
|
|
663
857
|
ProgramClass.prototype.facet = facet;
|