ggaction 0.0.3 → 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 (108) hide show
  1. package/CHANGELOG.md +28 -3
  2. package/README.md +95 -83
  3. package/package.json +11 -6
  4. package/src/actions/data/regression.js +1 -1
  5. package/src/actions/encodings/appearance.js +1 -1
  6. package/src/actions/encodings/color/continuous.js +137 -0
  7. package/src/actions/encodings/color/index.js +151 -0
  8. package/src/actions/encodings/color/layout.js +91 -0
  9. package/src/actions/encodings/color/policy.js +88 -0
  10. package/src/actions/encodings/index.js +2 -2
  11. package/src/actions/encodings/offset.js +1 -1
  12. package/src/actions/encodings/{position.js → position/index.js} +6 -6
  13. package/src/actions/encodings/position/resolve.js +1 -1
  14. package/src/actions/encodings/ranged.js +2 -2
  15. package/src/actions/encodings/strokeDash.js +1 -1
  16. package/src/actions/encodings/text.js +1 -1
  17. package/src/actions/errorBands/options.js +1 -1
  18. package/src/actions/errorBars/options.js +1 -1
  19. package/src/actions/facets/actions.js +1 -1
  20. package/src/actions/facets/derive.js +2 -2
  21. package/src/actions/facets/guides.js +1 -1
  22. package/src/actions/guides/axes/labels.js +1 -1
  23. package/src/actions/guides/axes/ticks.js +1 -1
  24. package/src/actions/guides/axes/titles.js +1 -1
  25. package/src/actions/guides/grids/resolve.js +1 -1
  26. package/src/actions/guides/legends/categorical/layout.js +4 -2
  27. package/src/actions/guides/legends/continuous/interval.js +1 -1
  28. package/src/actions/guides/legends/continuous/opacity.js +1 -1
  29. package/src/actions/guides/legends/edit.js +2 -20
  30. package/src/actions/guides/legends/remove.js +2 -20
  31. package/src/actions/guides/legends/size.js +1 -1
  32. package/src/actions/guides/legends/target.js +25 -0
  33. package/src/actions/guides/polar/{axes.js → axes/index.js} +5 -5
  34. package/src/actions/guides/polar/index.js +1 -1
  35. package/src/actions/guides/polar/resolve.js +1 -1
  36. package/src/actions/guides/tickValues.js +1 -1
  37. package/src/actions/intervals/resolve.js +1 -1
  38. package/src/actions/marks/arc/actions.js +2 -2
  39. package/src/actions/marks/area/actions.js +2 -2
  40. package/src/actions/marks/bar/edit.js +1 -1
  41. package/src/actions/marks/line/actions.js +3 -3
  42. package/src/actions/marks/rect/actions.js +1 -1
  43. package/src/actions/marks/rule/actions.js +1 -1
  44. package/src/actions/marks/shared.js +1 -1
  45. package/src/actions/marks/text/actions.js +1 -1
  46. package/src/actions/primitives/semanticValue.js +1 -1
  47. package/src/actions/regression/components.js +1 -1
  48. package/src/actions/regression/create.js +1 -1
  49. package/src/actions/regression/edit.js +1 -1
  50. package/src/actions/scales/consumers/common.js +91 -0
  51. package/src/actions/scales/consumers/families.js +47 -0
  52. package/src/actions/scales/consumers/index.js +41 -0
  53. package/src/actions/scales/{consumers.js → consumers/seriesLayout.js} +10 -132
  54. package/src/actions/scales/create.js +1 -1
  55. package/src/actions/scales/definitions.js +2 -2
  56. package/src/actions/scales/edit.js +3 -3
  57. package/src/actions/scales/materialize.js +2 -2
  58. package/src/core/ChartProgram.js +22 -236
  59. package/src/core/compositionState.js +169 -0
  60. package/src/core/materializationState.js +65 -0
  61. package/src/core/programState.js +28 -0
  62. package/src/grammar/arcs.js +1 -1
  63. package/src/grammar/areaSeries.js +1 -1
  64. package/src/grammar/bars/aggregate.js +1 -1
  65. package/src/grammar/density.js +1 -1
  66. package/src/grammar/{facets.js → facets/index.js} +5 -5
  67. package/src/grammar/interval.js +2 -96
  68. package/src/grammar/lineSeries.js +1 -1
  69. package/src/grammar/palettes.js +5 -7
  70. package/src/grammar/polarLineCommands.js +1 -1
  71. package/src/grammar/regression/derive.js +97 -0
  72. package/src/grammar/regression/index.js +22 -0
  73. package/src/grammar/regression/models.js +282 -0
  74. package/src/grammar/regression/parameters.js +106 -0
  75. package/src/grammar/rules.js +1 -1
  76. package/src/grammar/scales/color.js +4 -2
  77. package/src/grammar/statistics/studentT.js +98 -0
  78. package/src/grammar/transforms.js +1 -1
  79. package/src/materialization/bars/aggregate.js +1 -1
  80. package/src/materialization/bars/grouped.js +1 -1
  81. package/src/materialization/bars/histogram.js +1 -1
  82. package/src/materialization/bars/ranged.js +1 -1
  83. package/src/materialization/density.js +1 -1
  84. package/src/materialization/dependencies.js +6 -87
  85. package/src/materialization/encodings.js +2 -2
  86. package/src/materialization/facetGuides/index.js +2 -0
  87. package/src/materialization/facetGuides/legacyCategorical.js +125 -0
  88. package/src/materialization/facetGuides/placement.js +126 -0
  89. package/src/materialization/facetGuides/preparation.js +188 -0
  90. package/src/materialization/facets.js +1 -1
  91. package/src/materialization/marks/capabilities.js +141 -0
  92. package/src/materialization/marks/index.js +105 -0
  93. package/src/materialization/marks/policies.js +87 -0
  94. package/src/materialization/rect.js +1 -1
  95. package/src/materialization/rowEncoding.js +1 -1
  96. package/src/materialization/scaleGuideDependencies.js +94 -0
  97. package/src/materialization/scales/map.js +1 -1
  98. package/src/materialization/scales/policies/series.js +1 -1
  99. package/src/materialization/scales/resolve.js +1 -1
  100. package/src/materialization/selection/items/bar.js +1 -1
  101. package/src/materialization/selection/styles.js +1 -1
  102. package/src/renderers/canvas/text.js +14 -1
  103. package/types/extension.d.ts +4 -1
  104. package/src/actions/encodings/color.js +0 -424
  105. package/src/grammar/regression.js +0 -578
  106. package/src/grammar/scales.js +0 -1
  107. package/src/materialization/facetGuides.js +0 -426
  108. package/src/materialization/marks.js +0 -316
@@ -0,0 +1,91 @@
1
+ import {
2
+ BAR_GRAINS,
3
+ resolveBarChannels,
4
+ resolveBarGrain,
5
+ resolveBarOffsetChannel
6
+ } from "../../../grammar/bars/policy.js";
7
+ import { resolveOffsetScaleDefinition } from "../../scales/definitions.js";
8
+ import { isRangedArea } from "./policy.js";
9
+
10
+ export function applyColorLayoutCompanion(
11
+ program,
12
+ { target, layer, layout, scale, field }
13
+ ) {
14
+ if (layout === undefined || layer.mark.type === "arc") return program;
15
+ if (
16
+ layer.mark.type === "bar" &&
17
+ resolveBarGrain(layer) === BAR_GRAINS.ranged
18
+ ) {
19
+ return program;
20
+ }
21
+ if (isRangedArea(layer)) return program;
22
+ const channels = layer.mark.type === "bar"
23
+ ? resolveBarChannels(layer)
24
+ : undefined;
25
+ const measureChannel = channels?.measure ?? "y";
26
+ const measure = layer.encoding?.[measureChannel];
27
+ if (measure?.field === undefined || measure.scale === undefined) {
28
+ throw new Error(`Color layout on mark "${target}" requires a measure encoding.`);
29
+ }
30
+ const stack = layout === "fill"
31
+ ? "normalize"
32
+ : layout === "overlay" || layout === "group"
33
+ ? null
34
+ : "zero";
35
+ let next = program;
36
+ if (layout === "group") {
37
+ const offsetChannel = resolveBarOffsetChannel(layer);
38
+ const method = offsetChannel === "xOffset" ? "encodeXOffset" : "encodeYOffset";
39
+ next = next[method]({
40
+ field,
41
+ target,
42
+ scale: {
43
+ ...(layer.encoding?.[offsetChannel]?.scale === undefined
44
+ ? {}
45
+ : { id: layer.encoding[offsetChannel].scale }),
46
+ domain: scale.domain
47
+ }
48
+ });
49
+ }
50
+ return next[measureChannel === "x" ? "encodeX" : "encodeY"]({
51
+ target,
52
+ field: measure.field,
53
+ fieldType: measure.fieldType,
54
+ ...(measure.aggregate === undefined ? {} : { aggregate: measure.aggregate }),
55
+ stack
56
+ });
57
+ }
58
+
59
+ export function preSynchronizeGroupedOffset(
60
+ program,
61
+ { target, layer, layout, field, fieldType, scale, requestedScale }
62
+ ) {
63
+ if (
64
+ layer.mark.type !== "bar" ||
65
+ layout !== "group" ||
66
+ layer.encoding?.color?.scale !== scale.id ||
67
+ !Object.keys(requestedScale).some(key => key !== "id")
68
+ ) {
69
+ return program;
70
+ }
71
+ const offsetChannel = resolveBarOffsetChannel(layer);
72
+ const offset = layer.encoding?.[offsetChannel];
73
+ if (offset?.scale === undefined) return program;
74
+ const offsetScale = resolveOffsetScaleDefinition(program, {
75
+ id: offset.scale,
76
+ domain: scale.domain
77
+ }, offsetChannel);
78
+ return program
79
+ .editSemantic({
80
+ property: `layer[${target}].encoding.${offsetChannel}.field`,
81
+ value: field
82
+ })
83
+ .editSemantic({
84
+ property: `layer[${target}].encoding.${offsetChannel}.fieldType`,
85
+ value: fieldType
86
+ })
87
+ .editSemantic({
88
+ property: `scale[${offsetScale.id}].domain`,
89
+ value: offsetScale.domain
90
+ });
91
+ }
@@ -0,0 +1,88 @@
1
+ import {
2
+ BAR_GRAINS,
3
+ inferBarColorLayout
4
+ } from "../../../grammar/bars/policy.js";
5
+ import { validateColorLayout } from "../../../grammar/seriesLayout.js";
6
+
7
+ export const COLOR_ENCODING_OPTIONS = Object.freeze([
8
+ "field", "target", "fieldType", "scale", "palette", "layout", "aggregate"
9
+ ]);
10
+
11
+ export function resolveColorScaleOptions(args) {
12
+ const options = args.scale ?? {};
13
+ if (args.palette === undefined) return options;
14
+ if (options.palette !== undefined || options.range !== undefined) {
15
+ throw new Error(
16
+ "encodeColor palette cannot be combined with scale.palette or scale.range."
17
+ );
18
+ }
19
+ return { ...options, palette: args.palette };
20
+ }
21
+
22
+ export function assertNoConstantColor(program, layer) {
23
+ const config = program.markConfigs[layer.id];
24
+ const hasConstant = {
25
+ point: config?.fill !== undefined,
26
+ line: config?.stroke !== undefined,
27
+ bar: config?.barAppearance?.fill !== undefined,
28
+ arc: config?.fill !== undefined,
29
+ rect: config?.fillExplicit === true
30
+ }[layer.mark.type] ?? false;
31
+ if (hasConstant) {
32
+ throw new Error(
33
+ `encodeColor cannot replace constant appearance on ${layer.mark.type} mark "${layer.id}".`
34
+ );
35
+ }
36
+ }
37
+
38
+ export function isRangedArea(layer) {
39
+ return layer.mark.type === "area" && (
40
+ layer.encoding?.x2 !== undefined ||
41
+ layer.encoding?.y2 !== undefined
42
+ );
43
+ }
44
+
45
+ export function resolveColorLayout(layer, requested, barGrain) {
46
+ const existing = layer.encoding?.color === undefined
47
+ ? undefined
48
+ : layer.encoding.color.layout ?? (
49
+ layer.mark.type === "bar"
50
+ ? inferBarColorLayout(layer)
51
+ : layer.mark.type === "area"
52
+ ? "overlay"
53
+ : undefined
54
+ );
55
+ if (requested !== undefined) validateColorLayout(requested);
56
+ if (existing !== undefined && requested !== undefined && requested !== existing) {
57
+ throw new Error(
58
+ `Color layout transition from "${existing}" to "${requested}" is not supported.`
59
+ );
60
+ }
61
+ const layout = requested ?? existing ?? (
62
+ layer.mark.type === "bar"
63
+ ? barGrain === BAR_GRAINS.histogram
64
+ ? "stack"
65
+ : barGrain === BAR_GRAINS.ranged ? "overlay" : "group"
66
+ : layer.mark.type === "area"
67
+ ? "overlay"
68
+ : undefined
69
+ );
70
+
71
+ if (["point", "line", "rect"].includes(layer.mark.type) && layout !== undefined) {
72
+ throw new Error(`Color layout is not supported for ${layer.mark.type} marks.`);
73
+ }
74
+ if (layer.mark.type === "area" && layout === "group") {
75
+ throw new Error('Area color layout does not support "group".');
76
+ }
77
+ if (
78
+ layer.mark.type === "arc" &&
79
+ layout !== undefined &&
80
+ layout !== "overlay"
81
+ ) {
82
+ throw new Error('Arc color layout currently supports only "overlay".');
83
+ }
84
+ if (isRangedArea(layer) && layout !== "overlay") {
85
+ throw new Error('Ranged area color encoding supports only "overlay" layout.');
86
+ }
87
+ return layout;
88
+ }
@@ -1,10 +1,10 @@
1
1
  import { registerAppearanceEncodingAction } from "./appearance.js";
2
2
  import { registerBarWidthEncodingAction } from "./barWidth.js";
3
- import { registerColorEncodingAction } from "./color.js";
3
+ import { registerColorEncodingAction } from "./color/index.js";
4
4
  import { registerDensityEncodingAction } from "./density.js";
5
5
  import { registerHistogramEncodingAction } from "./histogram.js";
6
6
  import { registerOffsetEncodingAction } from "./offset.js";
7
- import { registerPositionEncodingActions } from "./position.js";
7
+ import { registerPositionEncodingActions } from "./position/index.js";
8
8
  import { registerRangedEncodingActions } from "./ranged.js";
9
9
  import { registerStrokeDashEncodingActions } from "./strokeDash.js";
10
10
  import { registerRuleAppearanceEncodingActions } from "./ruleAppearance.js";
@@ -2,7 +2,7 @@ import { action } from "../../core/action.js";
2
2
  import {
3
3
  readNominalField,
4
4
  validateCategoricalFieldType
5
- } from "../../grammar/scales.js";
5
+ } from "../../grammar/scales/index.js";
6
6
  import { resolveOffsetScaleDefinition } from "../scales/definitions.js";
7
7
  import {
8
8
  applyEncodingScale,
@@ -1,14 +1,14 @@
1
- import { action } from "../../core/action.js";
1
+ import { action } from "../../../core/action.js";
2
2
  import {
3
3
  getPositionEncodingMaterializationSteps
4
- } from "../../materialization/marks.js";
5
- import { resolvePositionEncoding } from "./position/resolve.js";
6
- import { findLayer } from "../../selectors/layers.js";
7
- import { applyPositionSemantics } from "./position/apply.js";
4
+ } from "../../../materialization/marks/index.js";
5
+ import { resolvePositionEncoding } from "./resolve.js";
6
+ import { findLayer } from "../../../selectors/layers.js";
7
+ import { applyPositionSemantics } from "./apply.js";
8
8
  import {
9
9
  applyEncodingScale,
10
10
  rebindPositionGuides
11
- } from "./shared.js";
11
+ } from "../shared.js";
12
12
 
13
13
  function encodePosition(program, channel, args, operation) {
14
14
  const {
@@ -7,7 +7,7 @@ import {
7
7
  readTemporalField,
8
8
  validateFieldType,
9
9
  validatePositionChannel
10
- } from "../../../grammar/scales.js";
10
+ } from "../../../grammar/scales/index.js";
11
11
  import { resolvePositionScaleDefinition } from "../../scales/definitions.js";
12
12
  import { findCoordinate } from "../../../selectors/coordinates.js";
13
13
  import {
@@ -7,12 +7,12 @@ import {
7
7
  readScaleField,
8
8
  readTemporalField,
9
9
  validateSemanticFieldType
10
- } from "../../grammar/scales.js";
10
+ } from "../../grammar/scales/index.js";
11
11
  import { normalizeRuleDatum } from "../../grammar/rules.js";
12
12
  import {
13
13
  canMaterializeArea,
14
14
  canMaterializeLine
15
- } from "../../materialization/marks.js";
15
+ } from "../../materialization/marks/index.js";
16
16
  import { findLayer } from "../../selectors/layers.js";
17
17
  import {
18
18
  resolveTarget,
@@ -3,7 +3,7 @@ import {
3
3
  normalizeStrokeDashPattern,
4
4
  readNominalField,
5
5
  validateNominalFieldType
6
- } from "../../grammar/scales.js";
6
+ } from "../../grammar/scales/index.js";
7
7
  import { resolveStrokeDashScaleDefinition } from "../scales/definitions.js";
8
8
  import { applyMaterializationPlan } from "../../materialization/dependencies.js";
9
9
  import { planEncodingRematerialization } from "../../materialization/encodings.js";
@@ -1,6 +1,6 @@
1
1
  import { action } from "../../core/action.js";
2
2
  import { formatTextValue, validateTextFormat } from "../../grammar/text.js";
3
- import { canMaterializeText } from "../../materialization/marks.js";
3
+ import { canMaterializeText } from "../../materialization/marks/index.js";
4
4
  import { findLayer } from "../../selectors/layers.js";
5
5
  import { resolveTarget, validateOptions } from "./shared.js";
6
6
 
@@ -6,7 +6,7 @@ import {
6
6
  validateUnitInterval
7
7
  } from "../../core/validation.js";
8
8
  import { validateCurveInterpolation } from "../../grammar/curveCommands.js";
9
- import { normalizeStrokeDashPattern } from "../../grammar/scales.js";
9
+ import { normalizeStrokeDashPattern } from "../../grammar/scales/index.js";
10
10
 
11
11
  export const ERROR_BAND_BOUNDARY_OPTIONS = Object.freeze([
12
12
  "stroke", "strokeWidth", "strokeDash", "opacity", "curve"
@@ -5,7 +5,7 @@ import {
5
5
  import {
6
6
  normalizeStrokeDashPattern,
7
7
  validateOpacityValue
8
- } from "../../grammar/scales.js";
8
+ } from "../../grammar/scales/index.js";
9
9
  import {
10
10
  validateRuleStroke,
11
11
  validateRuleStrokeWidth
@@ -6,7 +6,7 @@ import {
6
6
  validateOptionObject,
7
7
  validatePositiveFinite
8
8
  } from "../../core/validation.js";
9
- import { resolveFacetDefinition } from "../../grammar/facets.js";
9
+ import { resolveFacetDefinition } from "../../grammar/facets/index.js";
10
10
  import { normalizeFacetScalePolicies } from
11
11
  "../../grammar/facets/scales.js";
12
12
  import { resolveFacetLayout } from "../../layout/facets.js";
@@ -1,13 +1,13 @@
1
1
  import { freezeOwned } from "../../core/immutable.js";
2
2
  import { resolveHistogramBins } from "../../grammar/histogram.js";
3
- import { readQuantitativeField } from "../../grammar/scales.js";
3
+ import { readQuantitativeField } from "../../grammar/scales/index.js";
4
4
  import { BAR_GRAINS, resolveBarGrain } from "../../grammar/bars/policy.js";
5
5
  import { resolveFacetScaleDomains } from "../../grammar/facets/scales.js";
6
6
  import {
7
7
  applyMaterializationPlan,
8
8
  planScaleGuideRematerialization
9
9
  } from "../../materialization/dependencies.js";
10
- import { getMarkMaterializationStep } from "../../materialization/marks.js";
10
+ import { getMarkMaterializationStep } from "../../materialization/marks/index.js";
11
11
  import { buildMaterializationPlan } from "../../materialization/planner.js";
12
12
  import { requireDataset } from "../../selectors/datasets.js";
13
13
  import { requireLayer } from "../../selectors/layers.js";
@@ -1,7 +1,7 @@
1
1
  import { action } from "../../core/action.js";
2
2
  import { validateKeys } from "../../core/validation.js";
3
3
  import { applyFacetGuideComposition } from
4
- "../../materialization/facetGuides.js";
4
+ "../../materialization/facetGuides/index.js";
5
5
 
6
6
  export const composeFacetGuides = action(
7
7
  {
@@ -13,7 +13,7 @@ import {
13
13
  mapContinuousScaleValues,
14
14
  formatTransformedTick,
15
15
  mapOrdinalPositionValues
16
- } from "../../../grammar/scales.js";
16
+ } from "../../../grammar/scales/index.js";
17
17
  import { formatTimeTick, formatTimeTicks } from "../../../grammar/ticks.js";
18
18
  import { valuesFromTickConfig } from "../tickValues.js";
19
19
  import { DEFAULT_COLORS, DEFAULT_FONT_FAMILY } from
@@ -10,7 +10,7 @@ import {
10
10
  isTransformedScaleType,
11
11
  mapContinuousScaleValues,
12
12
  mapOrdinalPositionValues
13
- } from "../../../grammar/scales.js";
13
+ } from "../../../grammar/scales/index.js";
14
14
  import {
15
15
  DEFAULT_TICK_COUNT,
16
16
  inferHistogramBoundaries,
@@ -11,7 +11,7 @@ import {
11
11
  isTransformedScaleType,
12
12
  mapContinuousScaleValues,
13
13
  mapOrdinalPositionValues
14
- } from "../../../grammar/scales.js";
14
+ } from "../../../grammar/scales/index.js";
15
15
  import { DEFAULT_COLORS, DEFAULT_FONT_FAMILY } from
16
16
  "../../../theme/defaults.js";
17
17
  import { findDataset } from "../../../selectors/datasets.js";
@@ -7,7 +7,7 @@ import {
7
7
  import {
8
8
  isTransformedScaleType,
9
9
  mapContinuousScaleValues
10
- } from "../../../grammar/scales.js";
10
+ } from "../../../grammar/scales/index.js";
11
11
  import { resolveGraphicBounds } from "../../../layout/canvas.js";
12
12
  import { resolveGridLineGeometry } from "../../../layout/grid.js";
13
13
  import { DEFAULT_COLORS } from "../../../theme/defaults.js";
@@ -1,6 +1,6 @@
1
1
  import { isPlainObject } from "../../../../core/immutable.js";
2
2
  import { noOptions } from "../../../../core/validation.js";
3
- import { mapOrdinalValues } from "../../../../grammar/scales.js";
3
+ import { mapOrdinalValues } from "../../../../grammar/scales/index.js";
4
4
  import { resolveGraphicBounds } from "../../../../layout/canvas.js";
5
5
  import { unionConcreteGraphicBounds } from "../../../../grammar/schemas/graphicBounds.js";
6
6
  import { DEFAULT_COLORS } from "../../../../theme/defaults.js";
@@ -382,7 +382,9 @@ export function resolveLayout(program, config) {
382
382
  const count = config.domain.length;
383
383
  const width = symbolWidth(config);
384
384
  if (config.position === "right") {
385
- const symbolX = Array(count).fill(bounds.x + bounds.width + 30);
385
+ const symbolX = Array(count).fill(
386
+ bounds.x + bounds.width + config.offset
387
+ );
386
388
  const itemY = Array.from(
387
389
  { length: count },
388
390
  (_, index) => bounds.y + 52 + index * config.itemGap
@@ -4,7 +4,7 @@ import {
4
4
  validateKeys,
5
5
  validateOptionObject
6
6
  } from "../../../../core/validation.js";
7
- import { formatDiscretizedIntervals } from "../../../../grammar/scales.js";
7
+ import { formatDiscretizedIntervals } from "../../../../grammar/scales/index.js";
8
8
  import { DEFAULT_COLORS, DEFAULT_FONT_FAMILY } from
9
9
  "../../../../theme/defaults.js";
10
10
  import {
@@ -1,7 +1,7 @@
1
1
  import { action } from "../../../../core/action.js";
2
2
  import { isPlainObject } from "../../../../core/immutable.js";
3
3
  import { validateKeys } from "../../../../core/validation.js";
4
- import { mapLinearValues } from "../../../../grammar/scales.js";
4
+ import { mapLinearValues } from "../../../../grammar/scales/index.js";
5
5
  import { DEFAULT_COLORS } from "../../../../theme/defaults.js";
6
6
  import {
7
7
  assertLegendInsideCanvas,
@@ -1,5 +1,4 @@
1
1
  import { action } from "../../../core/action.js";
2
- import { validateUserId } from "../../../core/identifiers.js";
3
2
  import { validateOptionObject } from "../../../core/validation.js";
4
3
  import { normalizeOptions } from "./categorical/options.js";
5
4
  import { symbolGraphic } from "./categorical/layout.js";
@@ -12,6 +11,7 @@ import { normalizeIntervalLegend } from "./continuous/interval.js";
12
11
  import { findLayer } from "../../../selectors/layers.js";
13
12
  import { resolveLegendGraphicPlacement } from
14
13
  "../../../materialization/graphicHierarchy.js";
14
+ import { resolveLegendTarget } from "./target.js";
15
15
 
16
16
  const OPTIONS = Object.freeze([
17
17
  "target", "position", "align", "direction", "columns", "offset",
@@ -31,24 +31,6 @@ function mergeBorder(previous, patch) {
31
31
  return previous === false ? patch : { ...previous, ...patch };
32
32
  }
33
33
 
34
- function resolveTarget(program, requested) {
35
- const configs = program.guideConfigs.legend ?? {};
36
- const targets = [...new Set(Object.values(configs)
37
- .map(config => config?.target)
38
- .filter(Boolean))];
39
- if (requested !== undefined) {
40
- const target = validateUserId(requested, "Legend target id");
41
- if (!targets.includes(target)) {
42
- throw new Error(`Unknown legend target "${target}".`);
43
- }
44
- return target;
45
- }
46
- if (targets.length !== 1) {
47
- throw new Error("editLegend requires target when the legend is ambiguous.");
48
- }
49
- return targets[0];
50
- }
51
-
52
34
  function reconcileGraphic(program, id, shouldExist, definition) {
53
35
  const exists = program.graphicSpec.objects[id] !== undefined;
54
36
  if (exists && !shouldExist) return program.editGraphics({ target: id, remove: true });
@@ -285,7 +267,7 @@ export const editLegend = action(
285
267
  )) {
286
268
  throw new TypeError('editLegend title must be a non-empty string, "auto", or false.');
287
269
  }
288
- const target = resolveTarget(this, args.target);
270
+ const target = resolveLegendTarget(this, args.target, "editLegend");
289
271
  const configs = this.guideConfigs.legend ?? {};
290
272
  const categoricalKind = ["series", "color"].find(
291
273
  kind => configs[kind]?.target === target
@@ -1,29 +1,11 @@
1
1
  import { action } from "../../../core/action.js";
2
- import { validateUserId } from "../../../core/identifiers.js";
3
2
  import { validateKeys } from "../../../core/validation.js";
4
3
  import { legendGraphicIds } from
5
4
  "../../../materialization/guides/resources.js";
5
+ import { resolveLegendTarget } from "./target.js";
6
6
 
7
7
  const OPTIONS = Object.freeze(["target"]);
8
8
 
9
- function resolveTarget(program, requested) {
10
- const targets = [...new Set(Object.values(program.guideConfigs.legend ?? {})
11
- .map(config => config?.target)
12
- .filter(Boolean))];
13
- if (requested !== undefined) {
14
- const target = validateUserId(requested, "Legend target id");
15
- if (!targets.includes(target)) {
16
- throw new Error(`Unknown legend target "${target}".`);
17
- }
18
- return target;
19
- }
20
- if (targets.length === 0) throw new Error("removeLegend requires an existing legend.");
21
- if (targets.length > 1) {
22
- throw new Error("removeLegend requires target when the legend is ambiguous.");
23
- }
24
- return targets[0];
25
- }
26
-
27
9
  const SEMANTIC_KIND = Object.freeze({
28
10
  series: "series",
29
11
  color: "color",
@@ -37,7 +19,7 @@ export const removeLegend = action(
37
19
  { op: "removeLegend", description: "Remove every legend block owned by one mark." },
38
20
  function (args = {}) {
39
21
  validateKeys(args, OPTIONS, "removeLegend");
40
- const target = resolveTarget(this, args.target);
22
+ const target = resolveLegendTarget(this, args.target, "removeLegend");
41
23
  const kinds = Object.entries(this.guideConfigs.legend ?? {})
42
24
  .filter(([, config]) => config?.target === target)
43
25
  .map(([kind]) => kind);
@@ -1,6 +1,6 @@
1
1
  import { action } from "../../../core/action.js";
2
2
  import { validateKeys } from "../../../core/validation.js";
3
- import { mapLinearValues } from "../../../grammar/scales.js";
3
+ import { mapLinearValues } from "../../../grammar/scales/index.js";
4
4
  import { resolveGraphicBounds } from "../../../layout/canvas.js";
5
5
  import { DEFAULT_COLORS, DEFAULT_FONT_FAMILY } from
6
6
  "../../../theme/defaults.js";
@@ -0,0 +1,25 @@
1
+ import { validateUserId } from "../../../core/identifiers.js";
2
+
3
+ export function legendTargets(program) {
4
+ return [...new Set(Object.values(program.guideConfigs.legend ?? {})
5
+ .map(config => config?.target)
6
+ .filter(Boolean))];
7
+ }
8
+
9
+ export function resolveLegendTarget(program, requested, operation) {
10
+ const targets = legendTargets(program);
11
+ if (requested !== undefined) {
12
+ const target = validateUserId(requested, "Legend target id");
13
+ if (!targets.includes(target)) {
14
+ throw new Error(`Unknown legend target "${target}".`);
15
+ }
16
+ return target;
17
+ }
18
+ if (operation === "removeLegend" && targets.length === 0) {
19
+ throw new Error("removeLegend requires an existing legend.");
20
+ }
21
+ if (targets.length !== 1) {
22
+ throw new Error(`${operation} requires target when the legend is ambiguous.`);
23
+ }
24
+ return targets[0];
25
+ }
@@ -3,31 +3,31 @@ import {
3
3
  createThetaAxis,
4
4
  editRadialAxis,
5
5
  editThetaAxis
6
- } from "./axes/facade.js";
6
+ } from "./facade.js";
7
7
  import {
8
8
  createRadialAxisLabels,
9
9
  createThetaAxisLabels,
10
10
  editRadialAxisLabels,
11
11
  editThetaAxisLabels
12
- } from "./axes/labels.js";
12
+ } from "./labels.js";
13
13
  import {
14
14
  createRadialAxisLine,
15
15
  createThetaAxisLine,
16
16
  editRadialAxisLine,
17
17
  editThetaAxisLine
18
- } from "./axes/lines.js";
18
+ } from "./lines.js";
19
19
  import {
20
20
  createRadialAxisTicks,
21
21
  createThetaAxisTicks,
22
22
  editRadialAxisTicks,
23
23
  editThetaAxisTicks
24
- } from "./axes/ticks.js";
24
+ } from "./ticks.js";
25
25
  import {
26
26
  createRadialAxisTitle,
27
27
  createThetaAxisTitle,
28
28
  editRadialAxisTitle,
29
29
  editThetaAxisTitle
30
- } from "./axes/titles.js";
30
+ } from "./titles.js";
31
31
 
32
32
  export function registerPolarAxisActions(ProgramClass) {
33
33
  Object.assign(ProgramClass.prototype, {
@@ -1,2 +1,2 @@
1
1
  export { registerPolarGridActions } from "./grids.js";
2
- export { registerPolarAxisActions } from "./axes.js";
2
+ export { registerPolarAxisActions } from "./axes/index.js";
@@ -10,7 +10,7 @@ import {
10
10
  isTransformedScaleType,
11
11
  mapContinuousScaleValues,
12
12
  mapOrdinalPositionValues
13
- } from "../../../grammar/scales.js";
13
+ } from "../../../grammar/scales/index.js";
14
14
  import { formatTimeTick, formatTimeTicks } from "../../../grammar/ticks.js";
15
15
  import { resolveGraphicBounds } from "../../../layout/canvas.js";
16
16
  import { findCoordinate } from "../../../selectors/coordinates.js";
@@ -3,7 +3,7 @@ import {
3
3
  isTransformedScaleType,
4
4
  readQuantitativeField,
5
5
  transformedTicks
6
- } from "../../grammar/scales.js";
6
+ } from "../../grammar/scales/index.js";
7
7
  import { niceTicks, timeTicks } from "../../grammar/ticks.js";
8
8
  import { findDataset } from "../../selectors/datasets.js";
9
9
  import { findSemanticScale } from "../../selectors/scales.js";
@@ -3,7 +3,7 @@ import {
3
3
  resolveOptionalUserId,
4
4
  validateUserId
5
5
  } from "../../core/identifiers.js";
6
- import { readQuantitativeField } from "../../grammar/scales.js";
6
+ import { readQuantitativeField } from "../../grammar/scales/index.js";
7
7
  import { findDataset } from "../../selectors/datasets.js";
8
8
  import { hasLayer, resolveEligibleLayer } from "../../selectors/layers.js";
9
9
  import { findSemanticScale } from "../../selectors/scales.js";
@@ -8,9 +8,9 @@ import {
8
8
  import { deriveArcSectors } from "../../../grammar/arcs.js";
9
9
  import { buildAnnularSectorCommands } from "../../../grammar/polarPaths.js";
10
10
  import { resolvePolarFrame } from "../../../grammar/polar.js";
11
- import { mapOrdinalValues } from "../../../grammar/scales.js";
11
+ import { mapOrdinalValues } from "../../../grammar/scales/index.js";
12
12
  import { resolveGraphicBounds } from "../../../layout/canvas.js";
13
- import { canMaterializeArc } from "../../../materialization/marks.js";
13
+ import { canMaterializeArc } from "../../../materialization/marks/index.js";
14
14
  import { findDataset } from "../../../selectors/datasets.js";
15
15
  import { findLayer, resolveEligibleLayer } from "../../../selectors/layers.js";
16
16
  import { DEFAULT_COLORS } from "../../../theme/defaults.js";
@@ -10,7 +10,7 @@ import {
10
10
  deriveDensityAreaSeries,
11
11
  layoutDensityAreaSeries
12
12
  } from "../../../grammar/areaSeries.js";
13
- import { mapContinuousScaleValues, mapOrdinalValues } from "../../../grammar/scales.js";
13
+ import { mapContinuousScaleValues, mapOrdinalValues } from "../../../grammar/scales/index.js";
14
14
  import {
15
15
  assertMarkAvailable,
16
16
  applyLayeredMarkInheritance,
@@ -29,7 +29,7 @@ import {
29
29
  } from "../../../grammar/curveCommands.js";
30
30
  import { buildLinearPathCommands } from "../../../grammar/pathCommands.js";
31
31
  import { resolveEligibleLayer } from "../../../selectors/layers.js";
32
- import { canMaterializeArea } from "../../../materialization/marks.js";
32
+ import { canMaterializeArea } from "../../../materialization/marks/index.js";
33
33
  import { findUpstreamTransform } from "../../../materialization/dataProvenance.js";
34
34
  import { resolveMarkGraphicPlacement } from
35
35
  "../../../materialization/graphicHierarchy.js";