ggaction 0.0.2 → 0.0.4

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 (242) hide show
  1. package/CHANGELOG.md +55 -2
  2. package/README.md +95 -72
  3. package/package.json +15 -5
  4. package/src/actions/boxPlots/components.js +3 -3
  5. package/src/actions/boxPlots/edit.js +277 -0
  6. package/src/actions/boxPlots/index.js +2 -0
  7. package/src/actions/boxPlots/materialize.js +12 -1
  8. package/src/actions/boxPlots/options.js +25 -14
  9. package/src/actions/canvas/actions.js +21 -17
  10. package/src/actions/composition/actions.js +247 -0
  11. package/src/actions/composition/index.js +1 -0
  12. package/src/actions/coordinates/actions.js +2 -5
  13. package/src/actions/data/density.js +7 -1
  14. package/src/actions/data/filter.js +3 -1
  15. package/src/actions/data/regression.js +1 -1
  16. package/src/actions/encodings/appearance.js +12 -1
  17. package/src/actions/encodings/barWidth.js +5 -3
  18. package/src/actions/encodings/color/continuous.js +137 -0
  19. package/src/actions/encodings/color/index.js +151 -0
  20. package/src/actions/encodings/color/layout.js +91 -0
  21. package/src/actions/encodings/color/policy.js +88 -0
  22. package/src/actions/encodings/index.js +4 -2
  23. package/src/actions/encodings/offset.js +91 -73
  24. package/src/actions/encodings/position/apply.js +66 -0
  25. package/src/actions/encodings/position/index.js +130 -0
  26. package/src/actions/encodings/position/policies/arc.js +26 -0
  27. package/src/actions/encodings/position/policies/bar.js +9 -5
  28. package/src/actions/encodings/position/policies/index.js +5 -1
  29. package/src/actions/encodings/position/policies/line.js +20 -3
  30. package/src/actions/encodings/position/resolve.js +58 -9
  31. package/src/actions/encodings/ranged.js +30 -8
  32. package/src/actions/encodings/shared.js +17 -21
  33. package/src/actions/encodings/strokeDash.js +1 -1
  34. package/src/actions/encodings/text.js +73 -0
  35. package/src/actions/errorBands/create.js +37 -29
  36. package/src/actions/errorBands/edit.js +206 -0
  37. package/src/actions/errorBands/index.js +9 -0
  38. package/src/actions/errorBands/options.js +39 -0
  39. package/src/actions/errorBars/create.js +50 -43
  40. package/src/actions/errorBars/edit.js +130 -0
  41. package/src/actions/errorBars/index.js +3 -0
  42. package/src/actions/errorBars/options.js +52 -0
  43. package/src/actions/facets/actions.js +162 -0
  44. package/src/actions/facets/derive.js +200 -0
  45. package/src/actions/facets/guides.js +16 -0
  46. package/src/actions/facets/index.js +1 -0
  47. package/src/actions/facets/replay.js +69 -0
  48. package/src/actions/guides/applicability.js +113 -0
  49. package/src/actions/guides/axes/axes.js +70 -16
  50. package/src/actions/guides/axes/edit.js +126 -0
  51. package/src/actions/guides/axes/index.js +12 -0
  52. package/src/actions/guides/axes/labels.js +22 -19
  53. package/src/actions/guides/axes/remove.js +60 -0
  54. package/src/actions/guides/axes/tickGroups.js +7 -5
  55. package/src/actions/guides/axes/ticks.js +10 -5
  56. package/src/actions/guides/axes/titles.js +8 -6
  57. package/src/actions/guides/grids/grid.js +144 -15
  58. package/src/actions/guides/grids/resolve.js +6 -14
  59. package/src/actions/guides/guides.js +17 -75
  60. package/src/actions/guides/index.js +6 -0
  61. package/src/actions/guides/legends/categorical/actions.js +48 -9
  62. package/src/actions/guides/legends/categorical/components.js +16 -16
  63. package/src/actions/guides/legends/categorical/index.js +14 -14
  64. package/src/actions/guides/legends/categorical/layout.js +7 -3
  65. package/src/actions/guides/legends/categorical/options.js +2 -5
  66. package/src/actions/guides/legends/categorical/resolve.js +2 -2
  67. package/src/actions/guides/legends/categorical/symbols.js +14 -14
  68. package/src/actions/guides/legends/continuous/common.js +7 -7
  69. package/src/actions/guides/legends/continuous/interval.js +6 -6
  70. package/src/actions/guides/legends/continuous/opacity.js +1 -1
  71. package/src/actions/guides/legends/edit.js +4 -26
  72. package/src/actions/guides/legends/focused.js +63 -0
  73. package/src/actions/guides/legends/index.js +4 -0
  74. package/src/actions/guides/legends/remove.js +46 -0
  75. package/src/actions/guides/legends/size.js +13 -15
  76. package/src/actions/guides/legends/target.js +25 -0
  77. package/src/actions/guides/polar/axes/facade.js +219 -0
  78. package/src/actions/guides/polar/axes/index.js +55 -0
  79. package/src/actions/guides/polar/axes/labels.js +188 -0
  80. package/src/actions/guides/polar/axes/lines.js +113 -0
  81. package/src/actions/guides/polar/axes/shared.js +112 -0
  82. package/src/actions/guides/polar/axes/ticks.js +164 -0
  83. package/src/actions/guides/polar/axes/titles.js +165 -0
  84. package/src/actions/guides/polar/grids.js +252 -0
  85. package/src/actions/guides/polar/index.js +2 -0
  86. package/src/actions/guides/polar/resolve.js +269 -0
  87. package/src/actions/guides/tickValues.js +1 -1
  88. package/src/actions/index.js +4 -0
  89. package/src/actions/intervals/resolve.js +1 -1
  90. package/src/actions/marks/arc/actions.js +239 -0
  91. package/src/actions/marks/arc/index.js +1 -0
  92. package/src/actions/marks/{area.js → area/actions.js} +51 -38
  93. package/src/actions/marks/area/index.js +4 -0
  94. package/src/actions/marks/bar/create.js +26 -5
  95. package/src/actions/marks/bar/edit.js +1 -1
  96. package/src/actions/marks/bar/materialize.js +25 -31
  97. package/src/actions/marks/index.js +12 -4
  98. package/src/actions/marks/lifecycle.js +27 -0
  99. package/src/actions/marks/line/actions.js +373 -0
  100. package/src/actions/marks/line/index.js +1 -0
  101. package/src/actions/marks/{point.js → point/actions.js} +67 -108
  102. package/src/actions/marks/point/index.js +1 -0
  103. package/src/actions/marks/rect/actions.js +165 -0
  104. package/src/actions/marks/rect/index.js +1 -0
  105. package/src/actions/marks/remove.js +214 -0
  106. package/src/actions/marks/{rule.js → rule/actions.js} +34 -28
  107. package/src/actions/marks/rule/index.js +1 -0
  108. package/src/actions/marks/shared.js +156 -25
  109. package/src/actions/marks/text/actions.js +192 -0
  110. package/src/actions/marks/text/index.js +1 -0
  111. package/src/actions/primitives/createGraphics.js +13 -6
  112. package/src/actions/primitives/editGraphics.js +10 -3
  113. package/src/actions/primitives/semantic.js +26 -3
  114. package/src/actions/primitives/semanticValue.js +26 -4
  115. package/src/actions/regression/components.js +2 -2
  116. package/src/actions/regression/create.js +19 -2
  117. package/src/actions/regression/edit.js +247 -0
  118. package/src/actions/regression/index.js +3 -0
  119. package/src/actions/regression/resolve.js +3 -1
  120. package/src/actions/scales/consumers/common.js +91 -0
  121. package/src/actions/scales/consumers/families.js +47 -0
  122. package/src/actions/scales/consumers/index.js +41 -0
  123. package/src/actions/scales/{consumers.js → consumers/seriesLayout.js} +14 -127
  124. package/src/actions/scales/create.js +1 -1
  125. package/src/actions/scales/definitions.js +15 -6
  126. package/src/actions/scales/edit.js +45 -22
  127. package/src/actions/scales/materialize.js +58 -409
  128. package/src/actions/selection/actions.js +38 -24
  129. package/src/actions/selection/index.js +2 -0
  130. package/src/actions/titles/actions.js +63 -2
  131. package/src/actions/titles/index.js +2 -0
  132. package/src/actions/titles/resolve.js +12 -17
  133. package/src/composition.js +10 -0
  134. package/src/core/ChartProgram.js +49 -65
  135. package/src/core/action.js +10 -0
  136. package/src/core/compositionState.js +169 -0
  137. package/src/core/materializationState.js +65 -0
  138. package/src/core/programState.js +28 -0
  139. package/src/core/validation.js +16 -0
  140. package/src/core/vocabulary.js +154 -4
  141. package/src/grammar/arcs.js +154 -0
  142. package/src/grammar/areaSeries.js +1 -1
  143. package/src/grammar/bars/aggregate.js +3 -3
  144. package/src/grammar/bars/geometry.js +3 -3
  145. package/src/grammar/bars/policy.js +7 -1
  146. package/src/grammar/coordinates.js +3 -7
  147. package/src/grammar/density.js +21 -2
  148. package/src/grammar/facets/dependencies.js +185 -0
  149. package/src/grammar/facets/guides.js +257 -0
  150. package/src/grammar/facets/index.js +122 -0
  151. package/src/grammar/facets/scales.js +254 -0
  152. package/src/grammar/interval.js +2 -96
  153. package/src/grammar/lineSeries.js +112 -4
  154. package/src/grammar/palettes.js +5 -7
  155. package/src/grammar/polar.js +102 -0
  156. package/src/grammar/polarGuides.js +243 -0
  157. package/src/grammar/polarLineCommands.js +43 -0
  158. package/src/grammar/polarPaths.js +161 -0
  159. package/src/grammar/positionCompatibility.js +18 -2
  160. package/src/grammar/rects.js +26 -0
  161. package/src/grammar/regression/derive.js +97 -0
  162. package/src/grammar/regression/index.js +22 -0
  163. package/src/grammar/regression/models.js +282 -0
  164. package/src/grammar/regression/parameters.js +106 -0
  165. package/src/grammar/rules.js +1 -1
  166. package/src/grammar/scales/color.js +4 -2
  167. package/src/grammar/scales/continuous.js +6 -1
  168. package/src/grammar/scales/fields.js +7 -0
  169. package/src/grammar/scales/ordinal.js +5 -2
  170. package/src/grammar/scales/policies.js +1 -1
  171. package/src/grammar/schemas/graphic.js +1 -1
  172. package/src/grammar/schemas/graphicBounds.js +64 -9
  173. package/src/grammar/schemas/graphicTree.js +44 -10
  174. package/src/grammar/schemas/semanticPath.js +31 -9
  175. package/src/grammar/seriesLayout.js +13 -2
  176. package/src/grammar/statistics/studentT.js +98 -0
  177. package/src/grammar/text.js +71 -0
  178. package/src/grammar/ticks.js +50 -13
  179. package/src/grammar/transforms.js +1 -1
  180. package/src/index.js +1 -0
  181. package/src/layout/composition.js +310 -0
  182. package/src/layout/facets.js +131 -0
  183. package/src/layout/title.js +6 -0
  184. package/src/materialization/bars/aggregate.js +6 -3
  185. package/src/materialization/bars/grouped.js +75 -37
  186. package/src/materialization/bars/histogram.js +1 -1
  187. package/src/materialization/bars/ranged.js +1 -1
  188. package/src/materialization/composition.js +152 -0
  189. package/src/materialization/compositionSnapshot.js +114 -0
  190. package/src/materialization/density.js +1 -1
  191. package/src/materialization/dependencies.js +47 -73
  192. package/src/materialization/encodings.js +14 -28
  193. package/src/materialization/facetGuides/index.js +2 -0
  194. package/src/materialization/facetGuides/legacyCategorical.js +125 -0
  195. package/src/materialization/facetGuides/placement.js +126 -0
  196. package/src/materialization/facetGuides/preparation.js +188 -0
  197. package/src/materialization/facets.js +214 -0
  198. package/src/materialization/graphicHierarchy.js +15 -5
  199. package/src/materialization/guides/resources.js +46 -0
  200. package/src/materialization/marks/capabilities.js +141 -0
  201. package/src/materialization/marks/index.js +105 -0
  202. package/src/materialization/marks/policies.js +87 -0
  203. package/src/materialization/planner.js +105 -12
  204. package/src/materialization/rect.js +138 -0
  205. package/src/materialization/rectConfig.js +38 -0
  206. package/src/materialization/rowEncoding.js +33 -0
  207. package/src/materialization/scaleGuideDependencies.js +94 -0
  208. package/src/materialization/scales/map.js +40 -0
  209. package/src/materialization/scales/policies/arc.js +37 -0
  210. package/src/materialization/scales/policies/bar.js +132 -0
  211. package/src/materialization/scales/policies/series.js +76 -0
  212. package/src/materialization/scales/resolve.js +326 -0
  213. package/src/materialization/selection/items/arc.js +29 -0
  214. package/src/materialization/selection/items/bar.js +255 -0
  215. package/src/materialization/selection/items/common.js +131 -0
  216. package/src/materialization/selection/items/index.js +6 -0
  217. package/src/materialization/selection/items/path.js +59 -0
  218. package/src/materialization/selection/items/point.js +55 -0
  219. package/src/materialization/selection/items/rect.js +23 -0
  220. package/src/materialization/selection/items/rule.js +25 -0
  221. package/src/materialization/selection/policies/arc.js +10 -0
  222. package/src/materialization/selection/policies/area.js +1 -1
  223. package/src/materialization/selection/policies/bar.js +1 -1
  224. package/src/materialization/selection/policies/index.js +5 -1
  225. package/src/materialization/selection/policies/line.js +1 -1
  226. package/src/materialization/selection/policies/point.js +1 -1
  227. package/src/materialization/selection/policies/rect.js +10 -0
  228. package/src/materialization/selection/policies/rule.js +1 -1
  229. package/src/materialization/selection/styles.js +25 -17
  230. package/src/materialization/text.js +156 -0
  231. package/src/renderers/canvas/index.js +68 -22
  232. package/src/renderers/canvas/text.js +14 -1
  233. package/types/extension.d.ts +5 -1
  234. package/types/index.d.ts +56 -1
  235. package/types/program.d.ts +664 -27
  236. package/src/actions/encodings/color.js +0 -329
  237. package/src/actions/encodings/position.js +0 -176
  238. package/src/actions/marks/line.js +0 -248
  239. package/src/grammar/regression.js +0 -578
  240. package/src/grammar/scales.js +0 -1
  241. package/src/materialization/marks.js +0 -110
  242. package/src/materialization/selection/items.js +0 -503
@@ -1,329 +0,0 @@
1
- import { action } from "../../core/action.js";
2
- import {
3
- readNominalField,
4
- readQuantitativeField,
5
- readScaleField,
6
- readTemporalField,
7
- validateNominalFieldType
8
- } from "../../grammar/scales.js";
9
- import {
10
- BAR_GRAINS,
11
- inferBarColorLayout,
12
- resolveBarChannels,
13
- resolveBarGrain
14
- } from "../../grammar/bars/policy.js";
15
- import { validateColorLayout } from "../../grammar/seriesLayout.js";
16
- import {
17
- validateAggregate,
18
- validateAggregateFieldType,
19
- validateAggregateFieldValues
20
- } from "../../grammar/aggregate.js";
21
- import {
22
- resolveColorScaleDefinition,
23
- resolveQuantitativeColorScaleDefinition
24
- } from "../scales/definitions.js";
25
- import {
26
- applyEncodingScale,
27
- resolveReassignmentScaleOptions,
28
- resolveTarget,
29
- validateLineSeriesCompatibility,
30
- validateOptions
31
- } from "./shared.js";
32
- import { applyMaterializationPlan } from "../../materialization/dependencies.js";
33
- import { planEncodingRematerialization } from "../../materialization/encodings.js";
34
-
35
- const COLOR_ENCODING_OPTIONS = Object.freeze([
36
- "field", "target", "fieldType", "scale", "layout", "aggregate"
37
- ]);
38
-
39
- function resolveColorLayout(layer, requested, barGrain) {
40
- const existing = layer.encoding?.color === undefined
41
- ? undefined
42
- : layer.encoding.color.layout ?? (
43
- layer.mark.type === "bar"
44
- ? inferBarColorLayout(layer)
45
- : layer.mark.type === "area"
46
- ? "overlay"
47
- : undefined
48
- );
49
- if (requested !== undefined) validateColorLayout(requested);
50
- if (existing !== undefined && requested !== undefined && requested !== existing) {
51
- throw new Error(
52
- `Color layout transition from "${existing}" to "${requested}" is not supported.`
53
- );
54
- }
55
- const layout = requested ?? existing ?? (
56
- layer.mark.type === "bar"
57
- ? barGrain === BAR_GRAINS.histogram ? "stack" : barGrain === BAR_GRAINS.ranged ? "overlay" : "group"
58
- : layer.mark.type === "area"
59
- ? "overlay"
60
- : undefined
61
- );
62
-
63
- if (["point", "line"].includes(layer.mark.type) && layout !== undefined) {
64
- throw new Error(`Color layout is not supported for ${layer.mark.type} marks.`);
65
- }
66
- if (layer.mark.type === "area" && layout === "group") {
67
- throw new Error('Area color layout does not support "group".');
68
- }
69
- if (
70
- layer.mark.type === "area" &&
71
- layer.encoding?.y2 !== undefined &&
72
- layout !== "overlay"
73
- ) {
74
- throw new Error('Ranged area color encoding supports only "overlay" layout.');
75
- }
76
- return layout;
77
- }
78
-
79
- function applyColorLayoutCompanion(
80
- program,
81
- { target, layer, layout, scale, field }
82
- ) {
83
- if (layout === undefined) return program;
84
- if (layer.mark.type === "bar" && resolveBarGrain(layer) === BAR_GRAINS.ranged) return program;
85
- if (layer.mark.type === "area" && layer.encoding?.y2 !== undefined) {
86
- return program;
87
- }
88
- const channels = layer.mark.type === "bar" ? resolveBarChannels(layer) : undefined;
89
- const measureChannel = channels?.measure ?? "y";
90
- const measure = layer.encoding?.[measureChannel];
91
- if (measure?.field === undefined || measure.scale === undefined) {
92
- throw new Error(`Color layout on mark "${target}" requires a measure encoding.`);
93
- }
94
- const stack = layout === "fill"
95
- ? "normalize"
96
- : layout === "overlay" || layout === "group"
97
- ? null
98
- : "zero";
99
- let next = program;
100
- if (layout === "group") {
101
- if (channels?.orientation === "horizontal") {
102
- throw new Error('Horizontal bars do not support color layout "group" until yOffset is available.');
103
- }
104
- next = next.encodeXOffset({
105
- field,
106
- target,
107
- scale: {
108
- ...(layer.encoding?.xOffset?.scale === undefined
109
- ? {}
110
- : { id: layer.encoding.xOffset.scale }),
111
- domain: scale.domain
112
- }
113
- });
114
- }
115
- return next[measureChannel === "x" ? "encodeX" : "encodeY"]({
116
- target,
117
- field: measure.field,
118
- fieldType: measure.fieldType,
119
- ...(measure.aggregate === undefined ? {} : { aggregate: measure.aggregate }),
120
- stack
121
- });
122
- }
123
-
124
- function encodeContinuousColor(program, args) {
125
- if (!["quantitative", "temporal"].includes(args.fieldType)) {
126
- throw new Error(`Unsupported color field type "${args.fieldType}".`);
127
- }
128
- if (args.layout !== undefined) {
129
- throw new Error("Continuous color does not support layout.");
130
- }
131
- const { id: target, dataset, layer } = resolveTarget(
132
- program,
133
- args.target,
134
- ["point", "bar"],
135
- "continuous color mark"
136
- );
137
- const requestedScale = resolveReassignmentScaleOptions(
138
- layer.encoding?.color,
139
- args.scale ?? {}
140
- );
141
- const scale = resolveQuantitativeColorScaleDefinition(
142
- program,
143
- args.fieldType,
144
- requestedScale
145
- );
146
- if (Object.hasOwn(scale, "unknown") && layer.mark.type !== "point") {
147
- throw new Error(
148
- "Continuous color scale unknown currently requires a row-owned point mark."
149
- );
150
- }
151
- if (
152
- layer.mark.type === "bar" &&
153
- layer.encoding?.color?.fieldType === "nominal"
154
- ) {
155
- throw new Error(
156
- "Continuous bar color cannot replace an existing nominal color layout."
157
- );
158
- }
159
- let aggregate;
160
- if (layer.mark.type === "point") {
161
- if (args.aggregate !== undefined) {
162
- throw new Error("Point continuous color does not support aggregate.");
163
- }
164
- } else {
165
- if (args.fieldType !== "quantitative") {
166
- throw new Error("Aggregate bar color currently requires a quantitative field.");
167
- }
168
- if (resolveBarGrain(layer) !== BAR_GRAINS.aggregate) {
169
- throw new Error(
170
- "Continuous bar color requires a complete categorical aggregate bar."
171
- );
172
- }
173
- const channels = resolveBarChannels(layer);
174
- const measure = layer.encoding?.[channels.measure];
175
- aggregate = args.aggregate ?? (
176
- measure?.field === args.field ? measure.aggregate : undefined
177
- );
178
- if (aggregate === undefined) {
179
- throw new Error(
180
- "Continuous bar color requires aggregate when its field differs from the measure field."
181
- );
182
- }
183
- aggregate = validateAggregate(aggregate);
184
- validateAggregateFieldType(aggregate, args.fieldType);
185
- validateAggregateFieldValues(dataset.values, args.field, args.fieldType);
186
- }
187
- if (Object.hasOwn(scale, "unknown")) {
188
- readScaleField(dataset.values, args.field, args.fieldType, {
189
- allowUnknown: true
190
- });
191
- } else if (args.fieldType === "temporal") {
192
- readTemporalField(dataset.values, args.field);
193
- } else {
194
- readQuantitativeField(dataset.values, args.field);
195
- }
196
- const next = program
197
- .editSemantic({
198
- property: `layer[${target}].encoding.color.field`,
199
- value: args.field
200
- })
201
- .editSemantic({
202
- property: `layer[${target}].encoding.color.fieldType`,
203
- value: args.fieldType
204
- })
205
- .editSemantic({
206
- property: `layer[${target}].encoding.color.scale`,
207
- value: scale.id
208
- });
209
- const encoded = aggregate === undefined
210
- ? next
211
- : next.editSemantic({
212
- property: `layer[${target}].encoding.color.aggregate`,
213
- value: aggregate
214
- });
215
- const scaled = encoded.setQuantitativeColorScale(scale);
216
- return applyMaterializationPlan(
217
- scaled,
218
- planEncodingRematerialization(scaled, {
219
- target,
220
- channel: "color",
221
- scale: scale.id
222
- })
223
- );
224
- }
225
-
226
- const encodeColor = action(
227
- {
228
- op: "encodeColor",
229
- description: "Encode a field as graphical color."
230
- },
231
- function (args = {}) {
232
- validateOptions(args, COLOR_ENCODING_OPTIONS, "encodeColor");
233
- const requestedFieldType = args.fieldType ?? "nominal";
234
- if (requestedFieldType !== "nominal") {
235
- return encodeContinuousColor(this, {
236
- ...args,
237
- fieldType: requestedFieldType
238
- });
239
- }
240
- if (args.aggregate !== undefined) {
241
- throw new Error("Nominal color does not support aggregate.");
242
- }
243
- const fieldType = validateNominalFieldType(requestedFieldType);
244
- const { id: target, dataset, layer } = resolveTarget(
245
- this,
246
- args.target,
247
- ["point", "line", "bar", "area"],
248
- "color mark"
249
- );
250
- if (
251
- layer.mark.type === "area" &&
252
- (layer.encoding?.group?.field === undefined ||
253
- layer.encoding.group.field !== args.field)
254
- ) {
255
- throw new Error(
256
- "Area color encoding must match an existing group encoding."
257
- );
258
- }
259
- validateLineSeriesCompatibility(layer, "color", args.field);
260
-
261
- const barGrain = resolveBarGrain(layer);
262
- if (layer.mark.type === "bar" && barGrain === undefined) {
263
- throw new Error(
264
- "Bar color encoding requires a complete histogram encoding or a complete ordinal aggregate encoding."
265
- );
266
- }
267
- const layout = resolveColorLayout(layer, args.layout, barGrain);
268
- const requestedScale = resolveReassignmentScaleOptions(
269
- layer.encoding?.color,
270
- args.scale ?? {}
271
- );
272
- const scale = resolveColorScaleDefinition(this, requestedScale);
273
- if (Object.hasOwn(scale, "unknown") && layer.mark.type !== "point") {
274
- throw new Error(
275
- "Nominal color scale unknown currently requires a row-owned point mark."
276
- );
277
- }
278
- if (Object.hasOwn(scale, "unknown")) {
279
- readScaleField(dataset.values, args.field, fieldType, {
280
- allowUnknown: true
281
- });
282
- } else {
283
- readNominalField(dataset.values, args.field);
284
- }
285
-
286
- let next = this
287
- .editSemantic({
288
- property: `layer[${target}].encoding.color.field`,
289
- value: args.field
290
- })
291
- .editSemantic({
292
- property: `layer[${target}].encoding.color.fieldType`,
293
- value: fieldType
294
- })
295
- .editSemantic({
296
- property: `layer[${target}].encoding.color.scale`,
297
- value: scale.id
298
- });
299
- if (layout !== undefined) {
300
- next = next.editSemantic({
301
- property: `layer[${target}].encoding.color.layout`,
302
- value: layout
303
- });
304
- }
305
- next = applyEncodingScale(next, scale, requestedScale, {
306
- reassignment: layer.encoding?.color?.scale === scale.id
307
- });
308
- next = applyColorLayoutCompanion(next, {
309
- target,
310
- layer,
311
- layout,
312
- scale,
313
- field: args.field
314
- });
315
-
316
- return applyMaterializationPlan(
317
- next,
318
- planEncodingRematerialization(next, {
319
- target,
320
- channel: "color",
321
- scale: scale.id
322
- })
323
- );
324
- }
325
- );
326
-
327
- export function registerColorEncodingAction(ProgramClass) {
328
- ProgramClass.prototype.encodeColor = encodeColor;
329
- }
@@ -1,176 +0,0 @@
1
- import { action } from "../../core/action.js";
2
- import {
3
- canMaterializeArea,
4
- canMaterializeLine,
5
- } from "../../materialization/marks.js";
6
- import { resolveBarGrain } from "../../grammar/bars/policy.js";
7
- import { resolvePositionEncoding } from "./position/resolve.js";
8
- import { findLayer } from "../../selectors/layers.js";
9
- import {
10
- applyEncodingScale,
11
- rebindPositionGuides
12
- } from "./shared.js";
13
-
14
- function encodePosition(program, channel, args, operation) {
15
- const {
16
- target,
17
- layer,
18
- previous,
19
- requestedScale,
20
- field,
21
- datum,
22
- hasField,
23
- fieldType,
24
- scale,
25
- coordinate,
26
- bin,
27
- aggregate,
28
- stack
29
- } = resolvePositionEncoding(program, channel, args, operation);
30
-
31
- let next = program
32
- .createCoordinate({
33
- id: coordinate.id,
34
- type: coordinate.type,
35
- layers: [target]
36
- });
37
- if (previous !== undefined) {
38
- const alternate = hasField ? "datum" : "field";
39
- if (Object.hasOwn(previous, alternate)) {
40
- next = next.editSemantic({
41
- property: `layer[${target}].encoding.${channel}.${alternate}`,
42
- remove: true
43
- });
44
- }
45
- }
46
- next = next
47
- .editSemantic({
48
- property: `layer[${target}].encoding.${channel}.${hasField ? "field" : "datum"}`,
49
- value: hasField ? field : datum
50
- })
51
- .editSemantic({
52
- property: `layer[${target}].encoding.${channel}.fieldType`,
53
- value: fieldType
54
- });
55
-
56
- if (layer.mark.type === "line" && channel === "y" && args.aggregate !== undefined) {
57
- next = next.editSemantic({
58
- property: `layer[${target}].encoding.y.aggregate`,
59
- value: aggregate
60
- });
61
- }
62
-
63
- if (layer.mark.type === "bar" && channel === "x" && bin !== undefined) {
64
- const [mode] = Object.keys(bin);
65
- const previousModes = Object.keys(layer.encoding?.x?.bin ?? {});
66
- for (const previousMode of previousModes) {
67
- if (previousMode === mode) continue;
68
- next = next.editSemantic({
69
- property: `layer[${target}].encoding.x.bin.${previousMode}`,
70
- remove: true
71
- });
72
- }
73
- next = next.editSemantic({
74
- property: `layer[${target}].encoding.x.bin.${mode}`,
75
- value: bin[mode]
76
- });
77
- }
78
-
79
- if (layer.mark.type === "bar") {
80
- if (aggregate !== undefined) {
81
- next = next.editSemantic({
82
- property: `layer[${target}].encoding.${channel}.aggregate`,
83
- value: aggregate
84
- });
85
- }
86
- if (stack !== undefined) {
87
- next = next.editSemantic({
88
- property: `layer[${target}].encoding.${channel}.stack`,
89
- value: stack
90
- });
91
- }
92
- }
93
-
94
- if (layer.mark.type === "area" && channel === "y" && stack !== undefined) {
95
- next = next.editSemantic({
96
- property: `layer[${target}].encoding.y.stack`,
97
- value: stack
98
- });
99
- }
100
-
101
- next = next.editSemantic({
102
- property: `layer[${target}].encoding.${channel}.scale`,
103
- value: scale.id
104
- });
105
- next = applyEncodingScale(next, scale, requestedScale, {
106
- reassignment: previous?.scale === scale.id
107
- });
108
- next = rebindPositionGuides(
109
- next,
110
- channel,
111
- previous?.scale,
112
- scale.id,
113
- target
114
- );
115
-
116
- if (layer.mark.type === "line") {
117
- const updated = findLayer(next, target);
118
- return canMaterializeLine(next, updated)
119
- ? next.rematerializeLineMark({ id: target })
120
- : next.rematerializeScale({ id: scale.id });
121
- }
122
-
123
- if (layer.mark.type === "rule") {
124
- return next.rematerializeRuleMark({ id: target });
125
- }
126
-
127
- if (layer.mark.type === "bar") {
128
- const updated = findLayer(next, target);
129
- const pendingBox = next.markConfigs[target]?.boxPlot;
130
- if (pendingBox !== undefined && !pendingBox.materialized) {
131
- return updated.encoding?.x !== undefined && updated.encoding?.y !== undefined
132
- ? next.materializeBoxPlot({ id: target })
133
- : next;
134
- }
135
- const materialized = resolveBarGrain(updated) !== undefined
136
- ? next.rematerializeBarMark({ id: target })
137
- : next.rematerializeScale({ id: scale.id });
138
- return materialized;
139
- }
140
-
141
- next = next.rematerializeScale({ id: scale.id });
142
- if (layer.mark.type === "area") {
143
- const updated = findLayer(next, target);
144
- return canMaterializeArea(next, updated)
145
- ? next.rematerializeAreaMark({ id: target })
146
- : next;
147
- }
148
- return layer.mark.type === "point"
149
- ? next.rematerializePointMark({ id: target })
150
- : next;
151
- }
152
-
153
- const encodeX = action(
154
- {
155
- op: "encodeX",
156
- description: "Encode a field as horizontal position."
157
- },
158
- function (args = {}) {
159
- return encodePosition(this, "x", args, "encodeX");
160
- }
161
- );
162
-
163
- const encodeY = action(
164
- {
165
- op: "encodeY",
166
- description: "Encode a field as vertical position."
167
- },
168
- function (args = {}) {
169
- return encodePosition(this, "y", args, "encodeY");
170
- }
171
- );
172
-
173
- export function registerPositionEncodingActions(ProgramClass) {
174
- ProgramClass.prototype.encodeX = encodeX;
175
- ProgramClass.prototype.encodeY = encodeY;
176
- }