ggaction 0.0.21 → 0.0.23

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.
Files changed (265) hide show
  1. package/CHANGELOG.md +90 -0
  2. package/README.md +83 -90
  3. package/knowledge/action-card.schema.json +1 -1
  4. package/knowledge/action-cards.json +1 -1
  5. package/knowledge/intent-taxonomy.json +1 -1
  6. package/knowledge/mcp-resources.json +1 -1
  7. package/package.json +11 -4
  8. package/src/BasicChartProgram.js +1 -1
  9. package/src/accessibility.js +1 -0
  10. package/src/actions/boxPlots/components.js +1 -96
  11. package/src/actions/boxPlots/create.js +6 -1
  12. package/src/actions/boxPlots/edit.js +8 -0
  13. package/src/actions/boxPlots/materialize.js +3 -0
  14. package/src/actions/boxPlots/options.js +1 -1
  15. package/src/actions/canvas/actions.js +2 -1
  16. package/src/actions/canvas/index.js +3 -0
  17. package/src/actions/canvas/plotBorder.js +2 -1
  18. package/src/actions/canvas/plotOrder.js +14 -0
  19. package/src/actions/charts/area.js +1 -1
  20. package/src/actions/charts/bar.js +4 -4
  21. package/src/actions/charts/density.js +1 -1
  22. package/src/actions/charts/ecdf.js +1 -1
  23. package/src/actions/charts/endpoints.js +54 -5
  24. package/src/actions/charts/heatmap.js +1 -1
  25. package/src/actions/charts/histogram.js +1 -1
  26. package/src/actions/charts/horizon.js +1 -1
  27. package/src/actions/charts/index.js +2 -1
  28. package/src/actions/charts/interval-regression.js +3 -3
  29. package/src/actions/charts/line.js +1 -1
  30. package/src/actions/charts/radar.js +63 -3
  31. package/src/actions/charts/raincloud.js +37 -6
  32. package/src/actions/charts/rug-strip.js +2 -2
  33. package/src/actions/charts/scatter.js +3 -3
  34. package/src/actions/charts/text.js +1 -1
  35. package/src/actions/composition/actions.js +10 -3
  36. package/src/actions/coordinates/actions.js +2 -0
  37. package/src/actions/data/basic.js +6 -0
  38. package/src/actions/data/derived.js +6 -2
  39. package/src/actions/data/edit.js +22 -36
  40. package/src/actions/data/filter.js +1 -376
  41. package/src/actions/data/flatten.js +19 -0
  42. package/src/actions/data/index.js +6 -0
  43. package/src/actions/data/lookup.js +50 -0
  44. package/src/actions/data/raincloudFilter.js +56 -0
  45. package/src/actions/data/shared.js +10 -0
  46. package/src/actions/data/timeUnit.js +1 -1
  47. package/src/actions/distributions/revision.js +3 -1
  48. package/src/actions/encodings/angle.js +2 -1
  49. package/src/actions/encodings/appearance.js +38 -13
  50. package/src/actions/encodings/channels.js +14 -3
  51. package/src/actions/encodings/color/continuous.js +26 -10
  52. package/src/actions/encodings/color/index.js +50 -20
  53. package/src/actions/encodings/color/policy.js +57 -4
  54. package/src/actions/encodings/parallel.js +4 -0
  55. package/src/actions/encodings/position/policies/bar.js +10 -6
  56. package/src/actions/encodings/position/policies/line.js +1 -152
  57. package/src/actions/encodings/position/resolve.js +4 -1
  58. package/src/actions/encodings/ranged.js +46 -0
  59. package/src/actions/encodings/remove.js +1 -1
  60. package/src/actions/encodings/ruleAppearance.js +7 -6
  61. package/src/actions/encodings/shared.js +14 -2
  62. package/src/actions/encodings/stroke.js +20 -14
  63. package/src/actions/encodings/strokeDash.js +9 -11
  64. package/src/actions/encodings/text.js +30 -2
  65. package/src/actions/errorBars/edit.js +24 -4
  66. package/src/actions/facets/actions.js +1 -793
  67. package/src/actions/facets/derive.js +34 -5
  68. package/src/actions/facets/replay.js +1 -38
  69. package/src/actions/gradientPlots/components.js +21 -9
  70. package/src/actions/gradientPlots/create.js +4 -2
  71. package/src/actions/gradientPlots/edit.js +18 -1
  72. package/src/actions/gradientPlots/materialize.js +35 -36
  73. package/src/actions/gradientPlots/options.js +1 -1
  74. package/src/actions/gradientPlots/paint.js +13 -7
  75. package/src/actions/guides/applicability.js +2 -0
  76. package/src/actions/guides/axes/axes.js +39 -0
  77. package/src/actions/guides/axes/axis.js +9 -5
  78. package/src/actions/guides/axes/edit.js +11 -8
  79. package/src/actions/guides/axes/labels.js +24 -8
  80. package/src/actions/guides/axes/parallel/policy.js +3 -5
  81. package/src/actions/guides/axes/parallel/resolve.js +4 -3
  82. package/src/actions/guides/axes/policy.js +22 -0
  83. package/src/actions/guides/axes/tickGroups.js +4 -2
  84. package/src/actions/guides/axes/ticks.js +22 -4
  85. package/src/actions/guides/axes/titles.js +19 -6
  86. package/src/actions/guides/facadeAxes.js +3 -0
  87. package/src/actions/guides/grids/grid.js +3 -1
  88. package/src/actions/guides/grids/resolve.js +7 -11
  89. package/src/actions/guides/guides.js +21 -1
  90. package/src/actions/guides/legends/categorical/actions.js +1 -515
  91. package/src/actions/guides/legends/categorical/components.js +1 -4
  92. package/src/actions/guides/legends/categorical/layout.js +5 -2
  93. package/src/actions/guides/legends/categorical/options.js +4 -0
  94. package/src/actions/guides/legends/categorical/resolve.js +8 -3
  95. package/src/actions/guides/legends/categorical/symbols.js +3 -3
  96. package/src/actions/guides/legends/colorSize.js +2 -0
  97. package/src/actions/guides/legends/continuous/common.js +1 -1
  98. package/src/actions/guides/legends/continuous/gradient.js +1 -360
  99. package/src/actions/guides/legends/continuous/interval.js +1 -1
  100. package/src/actions/guides/legends/continuous/opacity.js +15 -1
  101. package/src/actions/guides/legends/edit.js +1 -1
  102. package/src/actions/guides/legends/focused.js +1 -1
  103. package/src/actions/guides/legends/lane.js +1 -1
  104. package/src/actions/guides/legends/sampling.js +1 -140
  105. package/src/actions/guides/legends/strokeWidth.js +3 -2
  106. package/src/actions/guides/legends/transition.js +19 -2
  107. package/src/actions/guides/polar/axes/facade.js +5 -4
  108. package/src/actions/guides/polar/axes/labels.js +5 -4
  109. package/src/actions/guides/polar/axes/titles.js +5 -4
  110. package/src/actions/guides/polar/resolve.js +2 -1
  111. package/src/actions/guides/tickValues.js +7 -7
  112. package/src/actions/marks/arc/actions.js +5 -7
  113. package/src/actions/marks/area/actions.js +9 -3
  114. package/src/actions/marks/bar/create.js +4 -2
  115. package/src/actions/marks/bar/edit.js +9 -6
  116. package/src/actions/marks/bar/materialize.js +5 -3
  117. package/src/actions/marks/dependentReferences.js +87 -0
  118. package/src/actions/marks/index.js +2 -0
  119. package/src/actions/marks/lifecycle.js +2 -1
  120. package/src/actions/marks/line/actions.js +24 -6
  121. package/src/actions/marks/line/materialize.js +7 -3
  122. package/src/actions/marks/point/create.js +5 -4
  123. package/src/actions/marks/point/edit.js +6 -3
  124. package/src/actions/marks/point/jitter.js +6 -6
  125. package/src/actions/marks/point/materialize.js +36 -39
  126. package/src/actions/marks/rect/actions.js +16 -4
  127. package/src/actions/marks/references.js +183 -35
  128. package/src/actions/marks/rule/actions.js +20 -9
  129. package/src/actions/marks/shared.js +2 -1
  130. package/src/actions/marks/text/actions.js +10 -3
  131. package/src/actions/marks/tick/actions.js +11 -2
  132. package/src/actions/primitives/editGraphics.js +28 -3
  133. package/src/actions/primitives/index.js +9 -0
  134. package/src/actions/primitives/semanticAction.js +13 -7
  135. package/src/actions/primitives/semanticValidation/layer.js +20 -0
  136. package/src/actions/primitives/semanticValidation/scale.js +8 -1
  137. package/src/actions/regression/create.js +6 -1
  138. package/src/actions/regression/edit.js +10 -1
  139. package/src/actions/scales/channels.js +1 -1
  140. package/src/actions/scales/consumers/common.js +19 -1
  141. package/src/actions/scales/consumers/families.js +2 -2
  142. package/src/actions/scales/consumers/seriesLayout.js +4 -3
  143. package/src/actions/scales/edit.js +11 -0
  144. package/src/actions/scales/editPolicy.js +5 -3
  145. package/src/actions/scales/preview.js +2 -1
  146. package/src/actions/scales/quantitativeColor.js +2 -4
  147. package/src/actions/selection/actions.js +10 -1
  148. package/src/actions/theme/reconcile.js +37 -9
  149. package/src/core/compositionState.js +26 -7
  150. package/src/core/datasetReferences.js +17 -0
  151. package/src/core/facetAxisPolicy.js +30 -0
  152. package/src/core/immutable.js +1 -0
  153. package/src/core/resourceReferences.js +5 -3
  154. package/src/core/validation.js +4 -0
  155. package/src/core/vocabulary.js +24 -2
  156. package/src/grammar/aggregate.js +1 -0
  157. package/src/grammar/arcs.js +1 -1
  158. package/src/grammar/areaSeries.js +1 -1
  159. package/src/grammar/axisTextPlacement.js +1 -1
  160. package/src/grammar/bars/policy.js +2 -2
  161. package/src/grammar/curveCommands.js +35 -2
  162. package/src/grammar/datasetDependencies.js +97 -0
  163. package/src/grammar/datasetSchema.js +32 -2
  164. package/src/grammar/facetHeaders.js +1 -0
  165. package/src/grammar/facets/dependencies.js +6 -2
  166. package/src/grammar/facets/guides.js +7 -5
  167. package/src/grammar/facets/legendIntent.js +6 -2
  168. package/src/grammar/facets/scales.js +27 -7
  169. package/src/grammar/flatten.js +85 -0
  170. package/src/grammar/histogram.js +13 -1
  171. package/src/grammar/horizon.js +1 -494
  172. package/src/grammar/jitter.js +2 -2
  173. package/src/grammar/legendSpacing.js +45 -0
  174. package/src/grammar/lineMissing.js +90 -0
  175. package/src/grammar/lineSeries.js +1 -376
  176. package/src/grammar/lookup.js +97 -0
  177. package/src/grammar/markFilter.js +4 -2
  178. package/src/grammar/markLabels.js +8 -3
  179. package/src/grammar/numeric.js +1 -1
  180. package/src/grammar/pathCommands.js +1 -1
  181. package/src/grammar/pathSeries.js +1 -109
  182. package/src/grammar/pointPolygon.js +81 -0
  183. package/src/grammar/pointShapes.js +15 -15
  184. package/src/grammar/rects.js +1 -1
  185. package/src/grammar/regression/derive.js +1 -195
  186. package/src/grammar/regression/parameters.js +7 -0
  187. package/src/grammar/scales/appearance.js +1 -1
  188. package/src/grammar/scales/color.js +1 -1
  189. package/src/grammar/scales/colorConsumers.js +1 -63
  190. package/src/grammar/scales/continuous.js +58 -1
  191. package/src/grammar/scales/definition.js +1 -1
  192. package/src/grammar/scales/ordinal.js +5 -2
  193. package/src/grammar/scales/policies.js +3 -3
  194. package/src/grammar/schemas/graphicBounds.js +40 -12
  195. package/src/grammar/schemas/graphicClip.js +23 -0
  196. package/src/grammar/schemas/graphicTree.js +16 -0
  197. package/src/grammar/statisticalReference.js +22 -0
  198. package/src/grammar/text.js +65 -1
  199. package/src/grammar/ticks.js +92 -1
  200. package/src/grammar/timeUnit.js +9 -3
  201. package/src/grammar/transformTopology.js +3 -1
  202. package/src/grammar/transforms.js +24 -0
  203. package/src/inspection.js +1 -495
  204. package/src/inspectionDescriptors.js +1 -1
  205. package/src/layout/canvas.js +1 -1
  206. package/src/layout/facetContentFlow.js +101 -0
  207. package/src/layout/facetHeaderTitles.js +1 -0
  208. package/src/layout/facetTopLane.js +29 -0
  209. package/src/layout/facets.js +1 -1
  210. package/src/layout/guideCollisions.js +9 -3
  211. package/src/layout/legendGroup.js +1 -1
  212. package/src/layout/legendItems.js +26 -10
  213. package/src/layout/legendSpacing.js +66 -0
  214. package/src/layout/plotDrawOrder.js +17 -0
  215. package/src/materialization/bars/histogram.js +8 -2
  216. package/src/materialization/bars/resolve.js +1 -1
  217. package/src/materialization/composition.js +1 -0
  218. package/src/materialization/compositionSnapshot.js +22 -2
  219. package/src/materialization/dataProvenance.js +1 -1
  220. package/src/materialization/facetContentBounds.js +96 -0
  221. package/src/materialization/facetGuides/layout.js +1 -1
  222. package/src/materialization/facetGuides/placement.js +39 -11
  223. package/src/materialization/facetGuides/preparation.js +43 -24
  224. package/src/materialization/facetHeaders.js +1 -1
  225. package/src/materialization/facetTopLane.js +25 -0
  226. package/src/materialization/facets.js +1 -1
  227. package/src/materialization/graphicHierarchy.js +30 -1
  228. package/src/materialization/graphicTranslation.js +2 -0
  229. package/src/materialization/guides/layout.js +1 -1
  230. package/src/materialization/guides/resources.js +1 -1
  231. package/src/materialization/legends.js +1 -1
  232. package/src/materialization/markClip.js +26 -0
  233. package/src/materialization/marks/capabilities.js +3 -2
  234. package/src/materialization/marks/grouping.js +7 -5
  235. package/src/materialization/marks/index.js +4 -2
  236. package/src/materialization/marks/policies.js +4 -0
  237. package/src/materialization/plotDrawOrder.js +44 -0
  238. package/src/materialization/rect.js +11 -3
  239. package/src/materialization/scaleGuideDependencies.js +13 -5
  240. package/src/materialization/selection/items/common.js +1 -1
  241. package/src/materialization/selection/items/path.js +1 -0
  242. package/src/materialization/selection/policies/index.js +2 -1
  243. package/src/materialization/text.js +10 -5
  244. package/src/mcp/cli.js +0 -0
  245. package/src/persistence/validation.js +114 -18
  246. package/src/persistence.js +4 -2
  247. package/src/renderers/canvas/index.js +16 -0
  248. package/src/renderers/canvas/isolated.js +11 -1
  249. package/src/renderers/canvas/native.js +7 -0
  250. package/src/renderers/canvas/scene.js +66 -0
  251. package/src/renderers/canvas/text.js +3 -2
  252. package/src/renderers/svg.js +1 -617
  253. package/src/renderers/svgSerialization.js +643 -0
  254. package/src/renderers/transitionScene.js +67 -0
  255. package/src/scene.js +89 -0
  256. package/src/selectors/axes.js +1 -1
  257. package/src/selectors/datasets.js +1 -0
  258. package/src/selectors/grids.js +9 -0
  259. package/src/selectors/markClip.js +28 -0
  260. package/src/selectors/raincloud.js +7 -0
  261. package/src/version.js +1 -1
  262. package/types/basic.d.ts +7 -0
  263. package/types/index.d.ts +8 -0
  264. package/types/program.d.ts +286 -70
  265. package/types/scene.d.ts +35 -0
@@ -1,793 +1 @@
1
- import { resolveGraphicBounds } from "../../layout/canvas.js";
2
- import { action, closedAction } from "../../core/action.js";
3
- import { registerFacetDataRevision, reviseUnitData } from "../data/revise.js";
4
- import { freezeOwned, isPlainObject } from "../../core/immutable.js";
5
- import { validateUserId } from "../../core/identifiers.js";
6
- import {
7
- validateNonEmptyString,
8
- validateNonNegativeFinite,
9
- validateOptionObject,
10
- validatePositiveFinite
11
- } from "../../core/validation.js";
12
- import {
13
- resolveFacetDefinition,
14
- resolveFacetGridDefinition
15
- } from "../../grammar/facets/index.js";
16
- import { collectFacetScaleBindings, resolveFacetFamily } from
17
- "../../grammar/facets/dependencies.js";
18
- import {
19
- FACET_SCALE_CHANNELS,
20
- normalizeFacetScalePolicies
21
- } from "../../grammar/facets/scales.js";
22
- import { resolveFacetLayout } from "../../layout/facets.js";
23
- import { compositionChildDescriptor } from
24
- "../../materialization/composition.js";
25
- import { deriveFacetChildren } from "./derive.js";
26
- import { resolveFacetChildrenScales } from "./derive.js";
27
- import { replayDerivedData } from "./replay.js";
28
- import { composeFacetGuides } from "./guides.js";
29
- import { applyCompositionState } from "../composition/actions.js";
30
- import { replayCompositionThemeState } from "../theme/composition.js";
31
- import { findDataset } from "../../selectors/datasets.js";
32
- import { findLayer } from "../../selectors/layers.js";
33
- import { findSemanticScale } from "../../selectors/scales.js";
34
- import { normalizeDisplayLabelMap } from "../../grammar/displayLabels.js";
35
- import {
36
- createDefaultFacetHeaders,
37
- normalizeFacetHeadersConfig,
38
- resolveFacetHeaderConfig
39
- } from "../../materialization/facetHeaders.js";
40
-
41
- const FACET_OPTIONS = Object.freeze([
42
- "id", "field", "data", "values", "columns", "gap", "spacing", "align", "padding", "scales",
43
- "guides", "headers"
44
- ]);
45
- const FACET_GRID_OPTIONS = Object.freeze([
46
- "id", "data", "rows", "columns", "combinations", "gap", "spacing", "align",
47
- "padding", "scales", "guides", "headers"
48
- ]);
49
- const REPEAT_OPTIONS = Object.freeze([
50
- "id", "target", "channel", "fields", "columns", "gap", "spacing", "align",
51
- "padding", "scales", "guides", "headers"
52
- ]);
53
- const SOURCE_EDIT_OPTIONS = Object.freeze(["program"]);
54
- const GUIDE_OPTIONS = Object.freeze(["axes", "legend"]);
55
- const HEADER_OPTIONS = Object.freeze([
56
- "fontSize", "fontFamily", "fontWeight", "color", "offset", "role",
57
- "labelMap", "side", "align"
58
- ]);
59
- const HEADER_STYLE_OPTIONS = Object.freeze([
60
- "fontSize", "fontFamily", "fontWeight", "color", "offset", "align"
61
- ]);
62
-
63
- function normalizeGuides(guides, allowStored = false) {
64
- if (guides === undefined) return { axes: "each", legend: false };
65
- validateOptionObject(guides, GUIDE_OPTIONS, "facet.guides");
66
- const axes = guides.axes ?? "each";
67
- if (!["each", "outer"].includes(axes)) {
68
- throw new Error('facet guides.axes must be "each" or "outer".');
69
- }
70
- const legend = guides.legend ?? false;
71
- if (legend !== false && legend !== "shared" && !isPlainObject(legend)) {
72
- throw new Error('facet guides.legend must be false, "shared", or legend options.');
73
- }
74
- if (!allowStored && isPlainObject(legend) && Object.hasOwn(legend, "type")) {
75
- throw new Error("Facet legend options do not accept internal type tags.");
76
- }
77
- return { axes, legend };
78
- }
79
-
80
- function requireFacetProgram(program, operation) {
81
- program._assertCompositionProgram(operation);
82
- if (program.compositionSpec.type !== "facet") {
83
- throw new Error(`${operation} requires a facet composition.`);
84
- }
85
- }
86
-
87
- function usedFacetScalePolicies(program, policies) {
88
- const used = new Set(
89
- collectFacetScaleBindings(program.semanticSpec).map(binding => binding.policyKey)
90
- );
91
- return Object.fromEntries(
92
- FACET_SCALE_CHANNELS.flatMap(channel =>
93
- used.has(channel) ? [[channel, policies[channel]]] : []
94
- )
95
- );
96
- }
97
-
98
- function facetUnitTemplate(program) {
99
- const seedId = program.compositionSpec.children.find(id =>
100
- program.children[id]?.semanticSpec.layers.length > 0
101
- ) ?? program.compositionSpec.children[0];
102
- const seed = program.children[seedId];
103
- if (seed === undefined) {
104
- throw new Error(`Facet "${program.compositionSpec.id}" requires a retained child.`);
105
- }
106
- const { facets: _facets, guides: _guides, ...unitConfigs } = program.materializationConfigs;
107
- return new program.constructor({
108
- semanticSpec: program.semanticSpec,
109
- graphicSpec: seed.graphicSpec,
110
- resolvedScales: program.resolvedScales,
111
- materializationConfigs: freezeOwned({
112
- ...unitConfigs,
113
- ...(seed.materializationConfigs.theme === undefined
114
- ? {}
115
- : { theme: seed.materializationConfigs.theme }),
116
- ...(seed.materializationConfigs.guides === undefined
117
- ? {}
118
- : { guides: seed.materializationConfigs.guides }),
119
- canvas: seed.materializationConfigs.canvas
120
- }),
121
- children: {},
122
- context: program.context,
123
- trace: program.trace,
124
- actionStack: program.actionStack,
125
- actionSequence: program._actionSequence
126
- });
127
- }
128
-
129
- function rederiveFacet(program, { scales, guides }) {
130
- const current = program.compositionSpec;
131
- if (current.facet.repeat !== undefined) {
132
- const template = facetUnitTemplate(program);
133
- const definition = resolveRepeatDefinition(template, {
134
- id: current.id,
135
- ...current.facet.repeat
136
- });
137
- const derived = deriveRepeatChildren(
138
- template,
139
- definition,
140
- usedFacetScalePolicies(template, scales),
141
- true
142
- );
143
- return applyCompositionState(program, {
144
- children: derived.children,
145
- compositionSpec: {
146
- ...current,
147
- facet: { ...current.facet, scales, guides }
148
- }
149
- }, current.children);
150
- }
151
- const definition = current.facet.grid === undefined
152
- ? resolveFacetDefinition(program.semanticSpec, {
153
- id: current.id,
154
- data: current.facet.data,
155
- field: current.facet.field,
156
- values: current.facet.values
157
- })
158
- : resolveFacetGridDefinition(program.semanticSpec, {
159
- id: current.id,
160
- data: current.facet.data,
161
- rows: current.facet.grid.rows,
162
- columns: current.facet.grid.columns,
163
- combinations: current.facet.grid.combinations
164
- });
165
- const request = usedFacetScalePolicies(program, scales);
166
- const normalized = normalizeFacetScalePolicies(program.semanticSpec, request);
167
- const template = facetUnitTemplate(program);
168
- const derived = deriveFacetChildren(template, definition, {
169
- closeInheritedAction: true,
170
- stripTitle: true,
171
- scales: request
172
- });
173
- const compositionSpec = {
174
- ...current,
175
- facet: {
176
- ...current.facet,
177
- scales: normalized.channels,
178
- guides
179
- }
180
- };
181
- let parent = program._withoutMaterializationConfig(["guides", "legend"]);
182
- for (const [kind, config] of Object.entries(template.guideConfigs.legend ?? {})) {
183
- parent = parent._withLegendConfig(kind, config);
184
- }
185
- return applyCompositionState(parent, {
186
- children: derived.children,
187
- compositionSpec
188
- }, compositionSpec.children);
189
- }
190
-
191
- function resolveEditedFacetHeaders(currentHeaders, args, grid, operation = "editFacetHeaders") {
192
- validateOptionObject(args, HEADER_OPTIONS, operation, {
193
- allowEmpty: false,
194
- emptyMessage: `${operation} requires at least one change.`
195
- });
196
- const role = args.role ?? "all";
197
- if (!["all", "row", "column"].includes(role)) {
198
- throw new Error(`Unknown facet header role "${role}".`);
199
- }
200
- if (role === "all" && Object.hasOwn(args, "side")) {
201
- throw new Error(`${operation} side requires an explicit row or column role.`);
202
- }
203
- if (role === "row" && grid === undefined) {
204
- throw new Error(`${operation} row role requires a row-column facet grid.`);
205
- }
206
- if (Object.hasOwn(args, "side")) {
207
- const sides = role === "row" ? ["left", "right"]
208
- : grid === undefined
209
- ? ["top", "bottom", "left", "right"] : ["top", "bottom"];
210
- if (!sides.includes(args.side)) {
211
- throw new Error(`${operation} ${role} side must be ${sides.join(" or ")}.`);
212
- }
213
- }
214
- if (Object.hasOwn(args, "align") &&
215
- !["start", "center", "end"].includes(args.align)) {
216
- throw new Error(`${operation} align must be start, center, or end.`);
217
- }
218
- if (role === "all" && Object.keys(args).every(key => key === "role")) {
219
- throw new Error(`${operation} requires at least one change.`);
220
- }
221
- const current = normalizeFacetHeadersConfig(currentHeaders);
222
- const owner = role === "all" ? "common" : role;
223
- const patch = { ...current[owner] };
224
- for (const key of HEADER_STYLE_OPTIONS) {
225
- if (Object.hasOwn(args, key)) patch[key] = args[key];
226
- }
227
- if (Object.hasOwn(args, "side")) patch.side = args.side;
228
- if (Object.hasOwn(args, "labelMap")) {
229
- if (args.labelMap === "auto") delete patch.labelMap;
230
- else {
231
- patch.labelMap = normalizeDisplayLabelMap(
232
- args.labelMap,
233
- `${operation} ${role} labelMap`
234
- );
235
- }
236
- }
237
- const headers = {
238
- ...current,
239
- ...(role === "all" ? {} : { mode: "roles" }),
240
- [owner]: patch
241
- };
242
- for (const headerRole of ["all", "row", "column"]) {
243
- const resolved = resolveFacetHeaderConfig(headers, headerRole);
244
- validatePositiveFinite(resolved.fontSize, `Facet ${headerRole} header fontSize`);
245
- validateNonEmptyString(resolved.fontFamily, `Facet ${headerRole} header fontFamily`);
246
- validateNonEmptyString(resolved.color, `Facet ${headerRole} header color`);
247
- validateNonNegativeFinite(resolved.offset, `Facet ${headerRole} header offset`);
248
- if (!(
249
- (typeof resolved.fontWeight === "string" && resolved.fontWeight.length > 0) ||
250
- Number.isFinite(resolved.fontWeight)
251
- )) {
252
- throw new TypeError(
253
- `Facet ${headerRole} header fontWeight must be a non-empty string or number.`
254
- );
255
- }
256
- if (!["start", "center", "end"].includes(resolved.align)) {
257
- throw new Error(`Facet ${headerRole} header align must be start, center, or end.`);
258
- }
259
- if (resolved.labelMap !== undefined) {
260
- normalizeDisplayLabelMap(
261
- resolved.labelMap,
262
- `Facet ${headerRole} header labelMap`
263
- );
264
- }
265
- }
266
- return headers;
267
- }
268
-
269
- function initialFacetHeaders(value, grid) {
270
- let headers = createDefaultFacetHeaders();
271
- if (value === undefined) return headers;
272
- validateOptionObject(value, [...HEADER_STYLE_OPTIONS, "labelMap", "row", "column"], "facet.headers");
273
- const { row, column, ...common } = value;
274
- if (Object.keys(common).length > 0) headers = resolveEditedFacetHeaders(headers, common, grid, "facet.headers");
275
- for (const [role, patch] of [["row", row], ["column", column]]) {
276
- if (patch === undefined) continue;
277
- validateOptionObject(patch, HEADER_OPTIONS.filter(key => key !== "role"), `facet.headers.${role}`);
278
- headers = resolveEditedFacetHeaders(headers, { ...patch, role }, grid, `facet.headers.${role}`);
279
- }
280
- return headers;
281
- }
282
-
283
- function composeDerivedFacet(program, args, { definition, derived, guides, scalePolicies, facet }) {
284
- const headers = initialFacetHeaders(args.headers, definition.grid);
285
- const preflight = resolveFacetLayout({
286
- spacing: args.spacing,
287
- plots: Object.entries(derived.children).map(([id, child]) => ({ id, ...resolveGraphicBounds(child) })),
288
- children: definition.cells.map(cell => ({
289
- ...compositionChildDescriptor(cell.id, derived.children[cell.id]), value: cell.value,
290
- ...(definition.grid === undefined ? {} : { row: cell.row, column: cell.column })
291
- })),
292
- columns: definition.grid?.columns.values.length ?? args.columns,
293
- gap: args.gap, align: args.align, padding: args.padding,
294
- sharedLegend: guides.legend === "shared"
295
- });
296
- const compositionSpec = {
297
- id: definition.id, type: "facet", children: definition.cells.map(cell => cell.id),
298
- columns: preflight.columns, gap: preflight.gap, align: preflight.align, padding: preflight.padding,
299
- ...(preflight.spacing === undefined ? {} : { spacing: preflight.spacing }),
300
- facet: { data: definition.data, ...facet, scales: scalePolicies.channels, guides }
301
- };
302
- return applyCompositionState(
303
- program._withMaterializationConfig(["facets", definition.id], { headers }),
304
- { children: derived.children, compositionSpec }, compositionSpec.children
305
- );
306
- }
307
-
308
- function partitionFacetAction(op, description, definitionResolver) {
309
- return closedAction({ op, description }, op === "facet" ? FACET_OPTIONS : FACET_GRID_OPTIONS,
310
- function (args = {}) {
311
- const guides = normalizeGuides(args.guides);
312
- const definition = definitionResolver(this.semanticSpec, args);
313
- if (definition.family !== "cartesian" && guides.axes === "outer") {
314
- throw new Error("Polar and Parallel facets do not support outer axes.");
315
- }
316
- const scalePolicies = normalizeFacetScalePolicies(this.semanticSpec, args.scales ?? {});
317
- const derived = deriveFacetChildren(this, definition, {
318
- closeInheritedAction: true, stripTitle: true, scales: args.scales ?? {}
319
- });
320
- const facet = definition.grid === undefined
321
- ? { field: definition.field, values: definition.values }
322
- : { values: definition.cells.map(cell => cell.value), grid: {
323
- ...definition.grid, cells: definition.cells.map(cell => ({
324
- id: cell.id, row: cell.row, column: cell.column,
325
- rowValue: cell.rowValue, columnValue: cell.columnValue, empty: cell.empty
326
- }))
327
- } };
328
- return composeDerivedFacet(this, args, { definition, derived, guides, scalePolicies, facet });
329
- });
330
- }
331
-
332
- export const facet = /* @__PURE__ */ partitionFacetAction("facet",
333
- "Repeat one direct-source chart by field value.", resolveFacetDefinition);
334
-
335
- function resolveRepeatDefinition(program, args) {
336
- if (!isPlainObject(args)) {
337
- throw new TypeError("repeatCharts options must be a plain object.");
338
- }
339
- const id = validateUserId(args.id ?? "repeat", "Repeat id");
340
- const parallelChannel = isPlainObject(args.channel);
341
- if (parallelChannel) {
342
- const keys = Object.keys(args.channel);
343
- if (keys.length !== 1 || keys[0] !== "parallelDimension" ||
344
- typeof args.channel.parallelDimension !== "string" ||
345
- args.channel.parallelDimension.length === 0) {
346
- throw new Error(
347
- "repeatCharts Parallel channel must contain exactly one non-empty parallelDimension."
348
- );
349
- }
350
- } else if (!["x", "y", "theta", "r"].includes(args.channel)) {
351
- throw new Error(
352
- 'repeatCharts channel must be "x", "y", "theta", "r", or one parallelDimension.'
353
- );
354
- }
355
- if (!Array.isArray(args.fields) || args.fields.length === 0 ||
356
- args.fields.some(field => typeof field !== "string" || field.length === 0)) {
357
- throw new TypeError("repeatCharts fields must be a non-empty array of field names.");
358
- }
359
- if (new Set(args.fields).size !== args.fields.length) {
360
- throw new Error("repeatCharts fields must be unique.");
361
- }
362
- const family = resolveFacetFamily(program.semanticSpec).family;
363
- const semanticChannel = args.channel === "r" ? "radius" : args.channel;
364
- const eligible = program.semanticSpec.layers.filter(layer => {
365
- if (parallelChannel) {
366
- const matches = (layer.encoding?.parallel?.dimensions ?? []).filter(
367
- dimension => dimension.field === args.channel.parallelDimension
368
- );
369
- return family === "parallel" && layer.mark?.type === "line" && matches.length === 1;
370
- }
371
- if (["x", "y"].includes(args.channel)) {
372
- return family === "cartesian" &&
373
- layer.encoding?.x?.scale !== undefined &&
374
- layer.encoding?.y?.scale !== undefined &&
375
- layer.encoding?.[args.channel]?.field !== undefined &&
376
- ["point", "line", "area", "bar", "rule", "tick", "rect"].includes(layer.mark?.type);
377
- }
378
- const role = program.markConfigs[layer.id]?.compositionRole;
379
- if (family !== "polar" || ["pie", "radar"].includes(role)) return false;
380
- return ["point", "line", "arc"].includes(layer.mark?.type) &&
381
- layer.encoding?.[semanticChannel]?.field !== undefined;
382
- });
383
- let target;
384
- if (args.target !== undefined) {
385
- target = validateUserId(args.target, "Repeat target");
386
- if (!eligible.some(layer => layer.id === target)) {
387
- throw new Error(
388
- `repeatCharts target "${target}" is not eligible for the requested field role.`
389
- );
390
- }
391
- } else if (eligible.length === 1) {
392
- target = eligible[0].id;
393
- } else {
394
- throw new Error(
395
- eligible.length === 0
396
- ? "repeatCharts requires one eligible complete mark for the requested field role."
397
- : "repeatCharts target is ambiguous; provide target."
398
- );
399
- }
400
- const unrelatedLayers = program.semanticSpec.layers.filter(layer => {
401
- if (layer.id === target) return false;
402
- const attachedLabel = layer.mark?.type === "text" && layer.source === target;
403
- const statisticalReference = program.markConfigs[layer.id]
404
- ?.statisticalReference?.source === target;
405
- return !attachedLabel && !statisticalReference;
406
- });
407
- if (unrelatedLayers.length > 0) {
408
- throw new Error("repeatCharts currently supports one direct mark only.");
409
- }
410
- const config = program.markConfigs[target] ?? {};
411
- const composite = [
412
- "boxPlot", "gradientPlot", "violinPlot", "regressionPlot", "endpointPlot",
413
- "ecdfPlot", "raincloudPlot", "intervalPlot"
414
- ].find(key => config[key] !== undefined);
415
- if (composite !== undefined) {
416
- throw new Error(`repeatCharts does not replace the ${composite} composite role.`);
417
- }
418
- const layer = findLayer(program, target);
419
- const dataset = findDataset(program, layer.data);
420
- if (dataset?.transform?.length > 0) {
421
- throw new Error("repeatCharts does not rewrite a derived dataset dependency.");
422
- }
423
- const encoding = parallelChannel
424
- ? layer.encoding.parallel
425
- : layer.encoding[semanticChannel];
426
- const dimensionIndex = parallelChannel
427
- ? encoding.dimensions.findIndex(
428
- dimension => dimension.field === args.channel.parallelDimension
429
- )
430
- : undefined;
431
- return {
432
- id,
433
- target,
434
- channel: parallelChannel ? { ...args.channel } : args.channel,
435
- policyKey: parallelChannel ? "parallelDimensions" : args.channel,
436
- fields: [...args.fields],
437
- data: layer.data,
438
- encoding,
439
- ...(dimensionIndex === undefined ? {} : { dimensionIndex }),
440
- cells: args.fields.map((field, index) => ({
441
- id: `${id}-field-${index + 1}`,
442
- field,
443
- value: field
444
- }))
445
- };
446
- }
447
-
448
- function repeatEncodingArgs(definition, field) {
449
- const encoding = definition.encoding;
450
- return {
451
- target: definition.target,
452
- field,
453
- fieldType: encoding.fieldType,
454
- ...(encoding.temporalUnit === undefined ? {} : { temporalUnit: encoding.temporalUnit }),
455
- ...(encoding.aggregate === undefined ? {} : { aggregate: encoding.aggregate }),
456
- ...(encoding.bin === undefined ? {} : { bin: encoding.bin }),
457
- ...(encoding.stack === undefined ? {} : { stack: encoding.stack }),
458
- ...(encoding.weight === undefined ? {} : { weight: encoding.weight }),
459
- scale: { id: encoding.scale }
460
- };
461
- }
462
-
463
- function parallelRepeatDimensions(program, definition, field) {
464
- return definition.encoding.dimensions.map((dimension, index) => {
465
- const semanticScale = findSemanticScale(program, dimension.scale);
466
- if (semanticScale === undefined) {
467
- throw new Error(`repeatCharts Parallel dimension scale "${dimension.scale}" is missing.`);
468
- }
469
- const { id: _id, ...scale } = semanticScale;
470
- void _id;
471
- const replacement = index === definition.dimensionIndex;
472
- return {
473
- field: replacement ? field : dimension.field,
474
- fieldType: dimension.fieldType,
475
- title: replacement && dimension.title === dimension.field
476
- ? field
477
- : dimension.title,
478
- scale
479
- };
480
- });
481
- }
482
-
483
- function deriveRepeatedProgram(template, definition, field) {
484
- if (isPlainObject(definition.channel)) {
485
- return template.encodeParallelCoordinates({
486
- target: definition.target,
487
- coordinate: findLayer(template, definition.target).coordinate,
488
- dimensions: parallelRepeatDimensions(template, definition, field),
489
- ...(definition.encoding.key === undefined ? {} : { key: definition.encoding.key }),
490
- missing: definition.encoding.missing
491
- });
492
- }
493
- const operation = {
494
- x: "encodeX",
495
- y: "encodeY",
496
- theta: "encodeTheta",
497
- r: "encodeR"
498
- }[definition.channel];
499
- return template[operation](repeatEncodingArgs(definition, field));
500
- }
501
-
502
- function deriveRepeatChildren(base, definition, scales, closeInheritedAction) {
503
- const template = base.semanticSpec.title.text === undefined
504
- ? base
505
- : base.removeTitle();
506
- const independentlyResolved = Object.fromEntries(definition.cells.map(cell => [
507
- cell.id,
508
- deriveRepeatedProgram(template, definition, cell.field)
509
- ]));
510
- return resolveFacetChildrenScales(
511
- template,
512
- definition.cells.map(cell => cell.id),
513
- independentlyResolved,
514
- scales,
515
- closeInheritedAction
516
- );
517
- }
518
-
519
- export const repeatCharts = /* @__PURE__ */ closedAction(
520
- {
521
- op: "repeatCharts",
522
- description: "Repeat one direct chart across an ordered field-role list."
523
- }, REPEAT_OPTIONS,
524
- function (args = {}) {
525
- const guides = normalizeGuides(args.guides);
526
- if (guides.axes === "outer") {
527
- throw new Error("repeatCharts does not promote axes across different repeated fields.");
528
- }
529
- const definition = resolveRepeatDefinition(this, args);
530
- const requestedScales = {
531
- ...(args.scales ?? {}),
532
- [definition.policyKey]: args.scales?.[definition.policyKey] ?? "independent"
533
- };
534
- const scalePolicies = normalizeFacetScalePolicies(
535
- this.semanticSpec,
536
- requestedScales
537
- );
538
- const derived = deriveRepeatChildren(
539
- this,
540
- definition,
541
- requestedScales,
542
- true
543
- );
544
- return composeDerivedFacet(this, args, {
545
- definition, derived, guides, scalePolicies,
546
- facet: { values: definition.fields,
547
- repeat: { target: definition.target, channel: definition.channel, fields: definition.fields } }
548
- });
549
- }
550
- );
551
-
552
- export const facetGrid = /* @__PURE__ */ partitionFacetAction("facetGrid",
553
- "Repeat one direct-source Cartesian chart across a row and column field grid.", resolveFacetGridDefinition);
554
-
555
- export const editFacetHeaders = /* @__PURE__ */ action(
556
- {
557
- op: "editFacetHeaders",
558
- description: "Edit parent-owned facet header appearance.",
559
- scope: "composition"
560
- },
561
- function (args = {}) {
562
- requireFacetProgram(this, "editFacetHeaders");
563
- const id = this.compositionSpec.id;
564
- const config = this.materializationConfigs.facets?.[id];
565
- if (!isPlainObject(config?.headers)) {
566
- throw new Error(`Facet "${id}" requires header configuration.`);
567
- }
568
- const headers = resolveEditedFacetHeaders(config.headers, args, this.compositionSpec.facet.grid);
569
- return this
570
- ._withMaterializationConfig(["facets", id], { ...config, headers })
571
- .materializeComposition();
572
- }
573
- );
574
-
575
- export const editFacetScales = /* @__PURE__ */ action(
576
- {
577
- op: "editFacetScales",
578
- description: "Edit facet scale-resolution policies and rederive every cell.",
579
- scope: "composition"
580
- },
581
- function (args = {}) {
582
- requireFacetProgram(this, "editFacetScales");
583
- validateOptionObject(args, FACET_SCALE_CHANNELS, "editFacetScales", {
584
- allowEmpty: false,
585
- emptyMessage: "editFacetScales requires at least one channel policy change."
586
- });
587
- for (const channel of Object.keys(args)) {
588
- if (!collectFacetScaleBindings(this.semanticSpec).some(
589
- binding => binding.policyKey === channel
590
- )) {
591
- throw new Error(
592
- `Facet scale channel "${channel}" is not used by an affected layer.`
593
- );
594
- }
595
- }
596
- const current = this.compositionSpec.facet;
597
- const scales = { ...current.scales, ...args };
598
- if (FACET_SCALE_CHANNELS.every(
599
- channel => scales[channel] === current.scales[channel]
600
- )) {
601
- throw new Error("editFacetScales requires at least one channel policy change.");
602
- }
603
- return rederiveFacet(this, {
604
- scales,
605
- guides: current.guides
606
- });
607
- }
608
- );
609
-
610
- export const editFacetGuides = /* @__PURE__ */ action(
611
- {
612
- op: "editFacetGuides",
613
- description: "Edit facet guide ownership and rederive every cell.",
614
- scope: "composition"
615
- },
616
- function (args = {}) {
617
- requireFacetProgram(this, "editFacetGuides");
618
- validateOptionObject(args, GUIDE_OPTIONS, "editFacetGuides", {
619
- allowEmpty: false,
620
- emptyMessage: "editFacetGuides requires at least one guide policy."
621
- });
622
- const current = this.compositionSpec.facet;
623
- if (Object.hasOwn(args, "legend")) normalizeGuides({ legend: args.legend });
624
- const guides = normalizeGuides({ ...current.guides, ...args }, true);
625
- const family = resolveFacetFamily(this.semanticSpec).family;
626
- if (family !== "cartesian" && guides.axes === "outer") {
627
- throw new Error("Polar and Parallel facets do not support outer axes.");
628
- }
629
- if (current.repeat !== undefined && guides.axes === "outer") {
630
- throw new Error("repeatCharts does not promote axes across different repeated fields.");
631
- }
632
- return rederiveFacet(this, {
633
- scales: current.scales,
634
- guides
635
- });
636
- }
637
- );
638
-
639
- function adoptUnitState(program, actionOwner) {
640
- if (!(program instanceof actionOwner.constructor)) {
641
- throw new TypeError("editFacetSource program must be a ChartProgram.");
642
- }
643
- if (program.compositionSpec !== undefined) {
644
- throw new Error("editFacetSource program must be a complete unit ChartProgram.");
645
- }
646
- if (program.actionStack.length !== 0) {
647
- throw new Error("editFacetSource program has an unfinished action stack.");
648
- }
649
- const seedId = actionOwner.compositionSpec.children.find(id =>
650
- actionOwner.children[id]?.semanticSpec.layers.length > 0
651
- ) ?? actionOwner.compositionSpec.children[0];
652
- const retained = actionOwner.children[seedId]?.materializationConfigs ?? {};
653
- const {
654
- canvas: _retainedCanvas,
655
- theme: _retainedTheme,
656
- facets: _retainedFacets,
657
- ...retainedRecipe
658
- } = retained;
659
- void _retainedCanvas;
660
- void _retainedTheme;
661
- void _retainedFacets;
662
- return new actionOwner.constructor({
663
- semanticSpec: program.semanticSpec,
664
- graphicSpec: program.graphicSpec,
665
- resolvedScales: program.resolvedScales,
666
- materializationConfigs: freezeOwned({
667
- ...program.materializationConfigs,
668
- ...retainedRecipe,
669
- ...(program.materializationConfigs.canvas === undefined
670
- ? {}
671
- : { canvas: program.materializationConfigs.canvas }),
672
- ...(program.materializationConfigs.theme === undefined
673
- ? {}
674
- : { theme: program.materializationConfigs.theme })
675
- }),
676
- children: {},
677
- context: program.context,
678
- trace: actionOwner.trace,
679
- actionStack: actionOwner.actionStack,
680
- actionSequence: actionOwner._actionSequence
681
- });
682
- }
683
-
684
- export const editFacetSource = /* @__PURE__ */ closedAction(
685
- {
686
- op: "editFacetSource",
687
- description: "Reapply one facet, grid, or repeat recipe to a revised complete unit program.",
688
- scope: "composition"
689
- }, SOURCE_EDIT_OPTIONS,
690
- function (args = {}) {
691
- requireFacetProgram(this, "editFacetSource");
692
- const current = this.compositionSpec;
693
- const facetConfig = this.materializationConfigs.facets?.[current.id];
694
- const base = adoptUnitState(args.program, this);
695
- const authored = isPlainObject(current.facet.guides.legend);
696
- const guides = authored ? { ...current.facet.guides, legend: false } : current.facet.guides;
697
- let revised;
698
- const scales = usedFacetScalePolicies(base, current.facet.scales);
699
- if (current.facet.grid !== undefined) {
700
- revised = base.facetGrid({
701
- id: current.id,
702
- data: current.facet.data,
703
- rows: current.facet.grid.rows,
704
- columns: current.facet.grid.columns,
705
- combinations: current.facet.grid.combinations,
706
- gap: current.gap,
707
- ...(current.spacing === undefined ? {} : { spacing: current.spacing }),
708
- align: current.align,
709
- padding: current.padding,
710
- scales,
711
- guides
712
- });
713
- } else if (current.facet.repeat !== undefined) {
714
- revised = base.repeatCharts({
715
- id: current.id,
716
- ...current.facet.repeat,
717
- columns: current.columns,
718
- gap: current.gap,
719
- ...(current.spacing === undefined ? {} : { spacing: current.spacing }),
720
- align: current.align,
721
- padding: current.padding,
722
- scales,
723
- guides
724
- });
725
- } else {
726
- revised = base.facet({
727
- id: current.id,
728
- data: current.facet.data,
729
- field: current.facet.field,
730
- values: current.facet.values,
731
- columns: current.columns,
732
- gap: current.gap,
733
- ...(current.spacing === undefined ? {} : { spacing: current.spacing }),
734
- align: current.align,
735
- padding: current.padding,
736
- scales,
737
- guides
738
- });
739
- }
740
- if (authored) {
741
- const spec = revised.compositionSpec;
742
- revised = revised._withCompositionState({ children: revised.children,
743
- compositionSpec: { ...spec, facet: { ...spec.facet, guides: current.facet.guides } } });
744
- }
745
- if (facetConfig !== undefined) {
746
- revised = revised
747
- ._withMaterializationConfig(["facets", current.id], facetConfig)
748
- .materializeComposition();
749
- }
750
- if (revised.semanticSpec.title.text !== undefined) {
751
- revised = revised.removeTitle();
752
- }
753
- if (this.semanticSpec.title.text !== undefined) {
754
- revised = revised.createTitle({
755
- ...this.titleConfig,
756
- ...this.semanticSpec.title
757
- });
758
- }
759
- return replayCompositionThemeState(
760
- revised,
761
- this.materializationConfigs.theme
762
- );
763
- }
764
- );
765
-
766
- export function registerFacetActions(ProgramClass) {
767
- registerFacetDataRevision((program, args) => {
768
- const { program: unit, plan } = reviseUnitData(facetUnitTemplate(program), args);
769
- const current = program.compositionSpec;
770
- // Adopt an already-materialized unit revision into the retained parent.
771
- const revised = new program.constructor({
772
- ...unit,
773
- graphicSpec: program.graphicSpec,
774
- children: program.children,
775
- materializationConfigs: { ...unit.materializationConfigs,
776
- facets: program.materializationConfigs.facets,
777
- ...(program.titleConfig === undefined ? {} : { title: program.titleConfig }) },
778
- actionSequence: unit._actionSequence,
779
- compositionSpec: { ...current, facet: { ...current.facet,
780
- data: plan.replacements.get(current.facet.data) ?? current.facet.data } }
781
- });
782
- return rederiveFacet(revised, current.facet);
783
- });
784
- ProgramClass.prototype.replayDerivedData = replayDerivedData;
785
- ProgramClass.prototype.composeFacetGuides = composeFacetGuides;
786
- ProgramClass.prototype.facet = facet;
787
- ProgramClass.prototype.facetGrid = facetGrid;
788
- ProgramClass.prototype.repeatCharts = repeatCharts;
789
- ProgramClass.prototype.editFacetHeaders = editFacetHeaders;
790
- ProgramClass.prototype.editFacetScales = editFacetScales;
791
- ProgramClass.prototype.editFacetGuides = editFacetGuides;
792
- ProgramClass.prototype.editFacetSource = editFacetSource;
793
- }
1
+ import{normalizeFacetAxes as R,validateFacetAxisPolicy as x}from"../../core/facetAxisPolicy.js";import{DEFAULT_ACTION_METHODS as te}from"../../core/vocabulary.js";import{axisGraphicIds as ie}from"../../materialization/guides/resources.js";import{cartesianAxisOwners as ne,axisTargetArgs as ae}from"../../selectors/axes.js";import{resolveGraphicBounds as oe}from"../../layout/canvas.js";import{action as z,closedAction as T,getWrappedActionMetadata as ce}from"../../core/action.js";import{registerFacetDataRevision as se,reviseUnitData as re}from"../data/revise.js";import{applyMaterializationPlan as de}from"../../materialization/dependencies.js";import{getMarkMaterializationStep as le}from"../../materialization/marks/index.js";import{buildMaterializationPlan as fe}from"../../materialization/planner.js";import{freezeOwned as A,isPlainObject as S}from"../../core/immutable.js";import{validateUserId as P}from"../../core/identifiers.js";import{validateNonEmptyString as $,validateNonNegativeFinite as pe,validateOptionObject as w,validatePositiveFinite as ue}from"../../core/validation.js";import{resolveFacetDefinition as G,resolveFacetGridDefinition as I}from"../../grammar/facets/index.js";import{collectFacetScaleBindings as N,resolveFacetFamily as k}from"../../grammar/facets/dependencies.js";import{FACET_SCALE_CHANNELS as _,normalizeFacetScalePolicies as j}from"../../grammar/facets/scales.js";import{resolveFacetLayout as he}from"../../layout/facets.js";import{compositionChildDescriptor as me}from"../../materialization/composition.js";import{deriveFacetChildren as H}from"./derive.js";import{resolveFacetChildrenScales as ge}from"./derive.js";import{replayDerivedData as Se}from"./replay.js";import{composeFacetGuides as we}from"./guides.js";import{applyCompositionState as q}from"../composition/actions.js";import{replayCompositionThemeState as ye}from"../theme/composition.js";import{findDataset as Fe}from"../../selectors/datasets.js";import{findLayer as U}from"../../selectors/layers.js";import{findSemanticScale as be}from"../../selectors/scales.js";import{normalizeDisplayLabelMap as W}from"../../grammar/displayLabels.js";import{resolveRotation as ve}from"../../grammar/rotation.js";import{normalizeFacetHeaderTitle as Ce}from"../../grammar/facetHeaders.js";import{createDefaultFacetHeaders as Ee,normalizeFacetHeadersConfig as K,resolveFacetHeaderConfig as Oe}from"../../materialization/facetHeaders.js";const xe=Object.freeze(["id","field","data","values","columns","gap","spacing","topLane","align","padding","scales","guides","headers"]),ze=Object.freeze(["id","data","rows","columns","combinations","gap","spacing","topLane","align","padding","scales","guides","headers"]),Te=Object.freeze(["id","target","channel","fields","columns","gap","spacing","topLane","align","padding","scales","guides","headers"]),$e=new Set(te),ke=Object.freeze(["program","action"]),V=Object.freeze(["axes","legend"]),B=Object.freeze(["fontSize","fontFamily","fontWeight","color","offset","role","labelMap","side","align","rotation","title","anchor"]),Y=Object.freeze(["fontSize","fontFamily","fontWeight","color","offset","align","rotation","anchor"]);function b(t,e=!1){if(t===void 0)return{axes:"each",legend:!1};w(t,V,"facet.guides");const n=R(t.axes),i=t.legend??!1;if(i!==!1&&i!=="shared"&&!S(i))throw new Error('facet guides.legend must be false, "shared", or legend options.');if(!e&&S(i)&&Object.hasOwn(i,"type"))throw new Error("Facet legend options do not accept internal type tags.");return{axes:n,legend:i}}function v(t,e){if(t._assertCompositionProgram(e),t.compositionSpec.type!=="facet")throw new Error(`${e} requires a facet composition.`)}function C(t,e){const n=new Set(N(t.semanticSpec).map(i=>i.policyKey));return Object.fromEntries(_.flatMap(i=>n.has(i)&&e[i]!==void 0?[[i,e[i]]]:[]))}function E(t,e=!1){const n=t.compositionSpec.children.find(l=>t.children[l]?.semanticSpec.layers.length>0)??t.compositionSpec.children[0],i=t.children[n];if(i===void 0)throw new Error(`Facet "${t.compositionSpec.id}" requires a retained child.`);const{facets:c,guides:o,...d}=t.materializationConfigs,{legend:s,...r}=t.semanticSpec.guides,a={...i.materializationConfigs.guides,axis:o?.axis??i.guideConfigs.axis,grid:o?.grid??i.guideConfigs.grid};return e&&delete d.title,new t.constructor({semanticSpec:e?{...t.semanticSpec,title:{},guides:{...r,...i.semanticSpec.guides.legend===void 0?{}:{legend:i.semanticSpec.guides.legend}}}:t.semanticSpec,graphicSpec:i.graphicSpec,resolvedScales:t.resolvedScales,materializationConfigs:A({...d,...i.materializationConfigs.theme===void 0?{}:{theme:i.materializationConfigs.theme},...a===void 0?{}:{guides:a},canvas:i.materializationConfigs.canvas}),children:{},context:t.context,trace:t.trace,actionStack:t.actionStack,actionSequence:t._actionSequence})}function D(t,{scales:e,guides:n}){const i=t.compositionSpec;if(i.facet.repeat!==void 0){const f=E(t),u=Q(f,{id:i.id,...i.facet.repeat}),m=Z(f,u,C(f,e),!0);return q(t,{children:m.children,compositionSpec:{...i,facet:{...i.facet,scales:e,guides:n}}},i.children)}const c=i.facet.grid===void 0?G(t.semanticSpec,{id:i.id,data:i.facet.data,field:i.facet.field,values:i.facet.values}):I(t.semanticSpec,{id:i.id,data:i.facet.data,rows:i.facet.grid.rows,columns:i.facet.grid.columns,combinations:i.facet.grid.combinations}),o=C(t,e),d=j(t.semanticSpec,o),s=E(t),r=H(s,c,{closeInheritedAction:!0,stripTitle:!0,scales:o}),a={...i,facet:{...i.facet,scales:d.channels,guides:n}};let l=t._withoutMaterializationConfig(["guides","legend"]);for(const[f,u]of Object.entries(s.guideConfigs.legend??{}))l=l._withLegendConfig(f,u);return q(l,{children:r.children,compositionSpec:a},a.children)}function L(t,e,n,i="editFacetHeaders"){w(e,B,i,{allowEmpty:!1,emptyMessage:`${i} requires at least one change.`});const c=e.role??"all";if(!["all","row","column"].includes(c))throw new Error(`Unknown facet header role "${c}".`);if(c==="all"&&Object.hasOwn(e,"side"))throw new Error(`${i} side requires an explicit row or column role.`);if(c==="all"&&Object.hasOwn(e,"title"))throw new Error(`${i} title requires an explicit row or column role.`);if(c==="row"&&n===void 0)throw new Error(`${i} row role requires a row-column facet grid.`);if(Object.hasOwn(e,"side")){const a=c==="row"?["left","right"]:n===void 0?["top","bottom","left","right"]:["top","bottom"];if(!a.includes(e.side))throw new Error(`${i} ${c} side must be ${a.join(" or ")}.`)}if(Object.hasOwn(e,"align")&&!["start","center","end"].includes(e.align))throw new Error(`${i} align must be start, center, or end.`);if(c==="all"&&Object.keys(e).every(a=>a==="role"))throw new Error(`${i} requires at least one change.`);const o=K(t),d=c==="all"?"common":c,s={...o[d]};if(Object.hasOwn(e,"title")){const a=Ce(s.title,e.title);a===void 0?delete s.title:s.title=a}for(const a of Y)Object.hasOwn(e,a)&&(s[a]=e[a]);Object.hasOwn(e,"rotation")&&(s.rotation=ve(e.rotation,`${i} ${c} rotation`)),Object.hasOwn(e,"side")&&(s.side=e.side),Object.hasOwn(e,"labelMap")&&(e.labelMap==="auto"?delete s.labelMap:s.labelMap=W(e.labelMap,`${i} ${c} labelMap`));const r={...o,...c==="all"?{}:{mode:"roles"},[d]:s};for(const a of["all","row","column"]){const l=Oe(r,a);if(ue(l.fontSize,`Facet ${a} header fontSize`),$(l.fontFamily,`Facet ${a} header fontFamily`),$(l.color,`Facet ${a} header color`),pe(l.offset,`Facet ${a} header offset`),l.rotation!==void 0&&!Number.isFinite(l.rotation))throw new TypeError(`Facet ${a} header rotation must resolve to finite radians.`);if(!(typeof l.fontWeight=="string"&&l.fontWeight.length>0||Number.isFinite(l.fontWeight)))throw new TypeError(`Facet ${a} header fontWeight must be a non-empty string or number.`);if(!["start","center","end"].includes(l.align))throw new Error(`Facet ${a} header align must be start, center, or end.`);l.labelMap!==void 0&&W(l.labelMap,`Facet ${a} header labelMap`)}return r}function _e(t,e){let n=Ee();if(t===void 0)return n;w(t,[...Y,"labelMap","row","column"],"facet.headers");const{row:i,column:c,...o}=t;Object.keys(o).length>0&&(n=L(n,o,e,"facet.headers"));for(const[d,s]of[["row",i],["column",c]])s!==void 0&&(w(s,B.filter(r=>r!=="role"),`facet.headers.${d}`),n=L(n,{...s,role:d},e,`facet.headers.${d}`));return n}function X(t,e,{definition:n,derived:i,guides:c,scalePolicies:o,facet:d}){const s=t.materializationConfigs.facets?.[n.id]?.headers,r=e.headers===void 0&&s!==void 0?K(s):_e(e.headers,n.grid),a=he({spacing:e.spacing,topLane:e.topLane,plots:Object.entries(i.children).map(([f,u])=>({id:f,...oe(u)})),children:n.cells.map(f=>({...me(f.id,i.children[f.id]),value:f.value,...n.grid===void 0?{}:{row:f.row,column:f.column}})),columns:n.grid?.columns.values.length??e.columns,gap:e.gap,align:e.align,padding:e.padding,sharedLegend:c.legend==="shared"}),l={id:n.id,type:"facet",children:n.cells.map(f=>f.id),columns:a.columns,gap:a.gap,align:a.align,padding:a.padding,...a.spacing===void 0?{}:{spacing:a.spacing},...a.topLane===void 0?{}:{topLane:a.topLane},facet:{data:n.data,...d,scales:o.channels,guides:c}};return q(t._withMaterializationConfig(["facets",n.id],{headers:r}),{children:i.children,compositionSpec:l},l.children)}function J(t,e,n){return T({op:t,description:e},t==="facet"?xe:ze,function(i={}){const c=b(i.guides),o=n(this.semanticSpec,i);x(c.axes,o.family);const d=j(this.semanticSpec,i.scales??{}),s=H(this,o,{closeInheritedAction:!0,stripTitle:!0,scales:i.scales??{}}),r=o.grid===void 0?{field:o.field,values:o.values}:{values:o.cells.map(a=>a.value),grid:{...o.grid,cells:o.cells.map(a=>({id:a.id,row:a.row,column:a.column,rowValue:a.rowValue,columnValue:a.columnValue,empty:a.empty}))}};return X(this,i,{definition:o,derived:s,guides:c,scalePolicies:d,facet:r})})}const je=J("facet","Repeat one direct-source chart by field value.",G);function Q(t,e){if(!S(e))throw new TypeError("repeatCharts options must be a plain object.");const n=P(e.id??"repeat","Repeat id"),i=S(e.channel);if(i){const p=Object.keys(e.channel);if(p.length!==1||p[0]!=="parallelDimension"||typeof e.channel.parallelDimension!="string"||e.channel.parallelDimension.length===0)throw new Error("repeatCharts Parallel channel must contain exactly one non-empty parallelDimension.")}else if(!["x","y","theta","r"].includes(e.channel))throw new Error('repeatCharts channel must be "x", "y", "theta", "r", or one parallelDimension.');if(!Array.isArray(e.fields)||e.fields.length===0||e.fields.some(p=>typeof p!="string"||p.length===0))throw new TypeError("repeatCharts fields must be a non-empty array of field names.");if(new Set(e.fields).size!==e.fields.length)throw new Error("repeatCharts fields must be unique.");const c=k(t.semanticSpec).family,o=e.channel==="r"?"radius":e.channel,d=t.semanticSpec.layers.filter(p=>{if(i){const F=(p.encoding?.parallel?.dimensions??[]).filter(y=>y.field===e.channel.parallelDimension);return c==="parallel"&&p.mark?.type==="line"&&F.length===1}if(["x","y"].includes(e.channel))return c==="cartesian"&&p.encoding?.x?.scale!==void 0&&p.encoding?.y?.scale!==void 0&&p.encoding?.[e.channel]?.field!==void 0&&["point","line","area","bar","rule","tick","rect"].includes(p.mark?.type);const g=t.markConfigs[p.id]?.compositionRole;return c!=="polar"||["pie","radar"].includes(g)?!1:["point","line","arc"].includes(p.mark?.type)&&p.encoding?.[o]?.field!==void 0});let s;if(e.target!==void 0){if(s=P(e.target,"Repeat target"),!d.some(p=>p.id===s))throw new Error(`repeatCharts target "${s}" is not eligible for the requested field role.`)}else if(d.length===1)s=d[0].id;else throw new Error(d.length===0?"repeatCharts requires one eligible complete mark for the requested field role.":"repeatCharts target is ambiguous; provide target.");if(t.semanticSpec.layers.filter(p=>{if(p.id===s)return!1;const g=p.mark?.type==="text"&&p.source===s,F=t.markConfigs[p.id]?.statisticalReference?.source===s;return!g&&!F}).length>0)throw new Error("repeatCharts currently supports one direct mark only.");const a=t.markConfigs[s]??{},l=["boxPlot","gradientPlot","violinPlot","regressionPlot","endpointPlot","ecdfPlot","raincloudPlot","intervalPlot"].find(p=>a[p]!==void 0);if(l!==void 0)throw new Error(`repeatCharts does not replace the ${l} composite role.`);const f=U(t,s),u=Fe(t,f.data);if(u?.transform?.length>0&&u.transform[0].type!=="lookup")throw new Error("repeatCharts does not rewrite a derived dataset dependency.");const m=i?f.encoding.parallel:f.encoding[o],h=i?m.dimensions.findIndex(p=>p.field===e.channel.parallelDimension):void 0;return{id:n,target:s,channel:i?{...e.channel}:e.channel,policyKey:i?"parallelDimensions":e.channel,fields:[...e.fields],data:f.data,encoding:m,...h===void 0?{}:{dimensionIndex:h},cells:e.fields.map((p,g)=>({id:`${n}-field-${g+1}`,field:p,value:p}))}}function qe(t,e){const n=t.encoding;return{target:t.target,field:e,fieldType:n.fieldType,...n.temporalUnit===void 0?{}:{temporalUnit:n.temporalUnit},...n.aggregate===void 0?{}:{aggregate:n.aggregate},...n.bin===void 0?{}:{bin:n.bin},...n.stack===void 0?{}:{stack:n.stack},...n.weight===void 0?{}:{weight:n.weight},scale:{id:n.scale}}}function De(t,e,n){return e.encoding.dimensions.map((i,c)=>{const o=be(t,i.scale);if(o===void 0)throw new Error(`repeatCharts Parallel dimension scale "${i.scale}" is missing.`);const{id:d,...s}=o,r=c===e.dimensionIndex;return{field:r?n:i.field,fieldType:i.fieldType,title:r&&i.title===i.field?n:i.title,scale:s}})}function Le(t,e,n){if(S(e.channel))return t.encodeParallelCoordinates({target:e.target,coordinate:U(t,e.target).coordinate,dimensions:De(t,e,n),...e.encoding.key===void 0?{}:{key:e.encoding.key},missing:e.encoding.missing});const i={x:"encodeX",y:"encodeY",theta:"encodeTheta",r:"encodeR"}[e.channel];return t[i](qe(e,n))}function Z(t,e,n,i){const c=t.semanticSpec.title.text===void 0?t:t.removeTitle(),o=Object.fromEntries(e.cells.map(d=>[d.id,Le(c,e,d.field)]));return ge(c,e.cells.map(d=>d.id),o,n,i)}const Me=T({op:"repeatCharts",description:"Repeat one direct chart across an ordered field-role list."},Te,function(t={}){const e=b(t.guides),n=Q(this,t);x(e.axes,k(this.semanticSpec).family,!0);const i={...t.scales??{},[n.policyKey]:t.scales?.[n.policyKey]??"independent"},c=j(this.semanticSpec,i),o=Z(this,n,i,!0);return X(this,t,{definition:n,derived:o,guides:e,scalePolicies:c,facet:{values:n.fields,repeat:{target:n.target,channel:n.channel,fields:n.fields}}})}),Re=J("facetGrid","Repeat one direct-source Cartesian chart across a row and column field grid.",I),Ae=z({op:"editFacetHeaders",description:"Edit parent-owned facet header appearance.",scope:"composition"},function(t={}){v(this,"editFacetHeaders");const e=this.compositionSpec.id,n=this.materializationConfigs.facets?.[e];if(!S(n?.headers))throw new Error(`Facet "${e}" requires header configuration.`);const i=L(n.headers,t,this.compositionSpec.facet.grid);return this._withMaterializationConfig(["facets",e],{...n,headers:i}).materializeComposition()}),Pe=z({op:"editFacetScales",description:"Edit facet scale-resolution policies and rederive every cell.",scope:"composition"},function(t={}){v(this,"editFacetScales"),w(t,_,"editFacetScales",{allowEmpty:!1,emptyMessage:"editFacetScales requires at least one channel policy change."});for(const i of Object.keys(t))if(!N(this.semanticSpec).some(c=>c.policyKey===i))throw new Error(`Facet scale channel "${i}" is not used by an affected layer.`);const e=this.compositionSpec.facet,n={...e.scales,...t};if(_.every(i=>n[i]===e.scales[i]))throw new Error("editFacetScales requires at least one channel policy change.");return D(this,{scales:n,guides:e.guides})}),Ge=z({op:"editFacetGuides",description:"Edit facet guide ownership and rederive every cell.",scope:"composition"},function(t={}){v(this,"editFacetGuides"),w(t,V,"editFacetGuides",{allowEmpty:!1,emptyMessage:"editFacetGuides requires at least one guide policy."});const e=this.compositionSpec.facet;Object.hasOwn(t,"legend")&&b({legend:t.legend});const n=b({...e.guides,...t,...Object.hasOwn(t,"axes")?{axes:R(t.axes,e.guides.axes)}:{}},!0),i=k(this.semanticSpec).family;return x(n.axes,i,e.repeat!==void 0),D(this,{scales:e.scales,guides:n})});function Ie(t,e,n=!1){if(!(t instanceof e.constructor))throw new TypeError("editFacetSource program must be a ChartProgram.");if(t.compositionSpec!==void 0)throw new Error("editFacetSource program must be a complete unit ChartProgram.");if(t.actionStack.length!==0)throw new Error("editFacetSource program has an unfinished action stack.");const i=e.compositionSpec.children.find(a=>e.children[a]?.semanticSpec.layers.length>0)??e.compositionSpec.children[0],c=e.children[i]?.materializationConfigs??{},{canvas:o,theme:d,facets:s,...r}=c;return new e.constructor({semanticSpec:t.semanticSpec,graphicSpec:t.graphicSpec,resolvedScales:t.resolvedScales,materializationConfigs:A({...n?{...r,...t.materializationConfigs}:{...t.materializationConfigs,...r},...t.materializationConfigs.canvas===void 0?{}:{canvas:t.materializationConfigs.canvas},...t.materializationConfigs.theme===void 0?{}:{theme:t.materializationConfigs.theme}}),children:{},context:t.context,trace:e.trace,actionStack:e.actionStack,actionSequence:e._actionSequence})}const Ne=T({op:"editFacetSource",description:"Reapply one facet, grid, or repeat recipe to a revised complete unit program.",scope:"composition"},ke,function(t={}){v(this,"editFacetSource");const e=this.compositionSpec,n=this.materializationConfigs.facets?.[e.id];if(Object.hasOwn(t,"program")===Object.hasOwn(t,"action"))throw new Error("editFacetSource requires exactly one of program or action.");let i=t.program,c=this;if(t.action!==void 0){w(t.action,["method","options"],"editFacetSource action");const l=$(t.action.method,"editFacetSource action method");let f=E(this,!0);const u=typeof f[l]=="function"?ce(f[l]):void 0;if(!u||!$e.has(l)||u.scope==="composition"||/^(?:_|materialize|rematerialize|replay|editSemantic$|editGraphics$|createGraphics$)/.test(l))throw new Error("editFacetSource action requires a unit chart-authoring action.");f=de(f,fe({marks:f.semanticSpec.layers.map(h=>le(f,h))}));for(const h of ne(f)){const p=f.guideConfigs.axis?.[h.id]??{},g=ie(h.channel,h.id);for(const[F,y]of["line","ticks","labels","title"].entries()){if(!p[y]||f.graphicSpec.objects[g[F]])continue;const{mode:M,inferredValues:He,inferredText:Ue,inferredRotation:We,inferredOffset:Ke,...O}=p[y];M==="values"&&delete O.count,M==="count"&&delete O.values;const ee=y[0].toUpperCase()+y.slice(1);f=f[`create${h.channel.toUpperCase()}Axis${ee}`]({...O,...ae(h.id,h.channel)})}}const m=f[l](t.action.options??{});c=new this.constructor({...this,trace:m.trace,actionStack:m.actionStack,actionSequence:m._actionSequence}),i=new this.constructor({...m,actionStack:[],actionSequence:m._actionSequence})}let o=Ie(i,c,t.action!==void 0);n!==void 0&&(o=o._withMaterializationConfig(["facets",e.id],n));const d=S(e.facet.guides.legend),s=d?{...e.facet.guides,legend:!1}:e.facet.guides;let r;const a=C(o,C(this,e.facet.scales));if(e.facet.grid!==void 0?r=o.facetGrid({id:e.id,data:e.facet.data,rows:e.facet.grid.rows,columns:e.facet.grid.columns,combinations:e.facet.grid.combinations,gap:e.gap,...e.spacing===void 0?{}:{spacing:e.spacing},...e.topLane===void 0?{}:{topLane:e.topLane},align:e.align,padding:e.padding,scales:a,guides:s}):e.facet.repeat!==void 0?r=o.repeatCharts({id:e.id,...e.facet.repeat,columns:e.columns,gap:e.gap,...e.spacing===void 0?{}:{spacing:e.spacing},...e.topLane===void 0?{}:{topLane:e.topLane},align:e.align,padding:e.padding,scales:a,guides:s}):r=o.facet({id:e.id,data:e.facet.data,field:e.facet.field,values:e.facet.values,columns:e.columns,gap:e.gap,...e.spacing===void 0?{}:{spacing:e.spacing},...e.topLane===void 0?{}:{topLane:e.topLane},align:e.align,padding:e.padding,scales:a,guides:s}),d){const l=r.compositionSpec;r=r._withCompositionState({children:r.children,compositionSpec:{...l,facet:{...l.facet,guides:e.facet.guides}}})}return n!==void 0&&(r=r._withMaterializationConfig(["facets",e.id],n).materializeComposition()),r.semanticSpec.title.text!==void 0&&(r=r.removeTitle()),this.semanticSpec.title.text!==void 0&&(r=r.createTitle({...this.titleConfig,...this.semanticSpec.title})),ye(r,this.materializationConfigs.theme)});function Et(t){se((e,n)=>{const{program:i,plan:c}=re(E(e),n),o=e.compositionSpec,d=new e.constructor({...i,graphicSpec:e.graphicSpec,children:e.children,materializationConfigs:{...i.materializationConfigs,facets:e.materializationConfigs.facets,...e.titleConfig===void 0?{}:{title:e.titleConfig}},actionSequence:i._actionSequence,compositionSpec:{...o,facet:{...o.facet,data:c.replacements.get(o.facet.data)??o.facet.data}}});return D(d,o.facet)}),t.prototype.replayDerivedData=Se,t.prototype.composeFacetGuides=we,t.prototype.facet=je,t.prototype.facetGrid=Re,t.prototype.repeatCharts=Me,t.prototype.editFacetHeaders=Ae,t.prototype.editFacetScales=Pe,t.prototype.editFacetGuides=Ge,t.prototype.editFacetSource=Ne}export{Ge as editFacetGuides,Ae as editFacetHeaders,Pe as editFacetScales,Ne as editFacetSource,je as facet,Re as facetGrid,Et as registerFacetActions,Me as repeatCharts};