@opendata-ai/openchart-engine 6.15.0 → 6.15.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@opendata-ai/openchart-engine",
3
- "version": "6.15.0",
3
+ "version": "6.15.1",
4
4
  "description": "Headless compiler for openchart: spec validation, data compilation, scales, and layout",
5
5
  "license": "Apache-2.0",
6
6
  "author": "Riley Hilliard",
@@ -45,7 +45,7 @@
45
45
  "typecheck": "tsc --noEmit"
46
46
  },
47
47
  "dependencies": {
48
- "@opendata-ai/openchart-core": "6.15.0",
48
+ "@opendata-ai/openchart-core": "6.15.1",
49
49
  "d3-array": "^3.2.0",
50
50
  "d3-format": "^3.1.2",
51
51
  "d3-interpolate": "^3.0.0",
@@ -12,18 +12,41 @@ import type {
12
12
  Encoding,
13
13
  GradientDef,
14
14
  LayoutStrategy,
15
+ LinearGradient,
15
16
  MarkAria,
16
17
  Rect,
17
18
  RectMark,
18
19
  } from '@opendata-ai/openchart-core';
19
20
  import { abbreviateNumber, formatNumber, isGradientDef } from '@opendata-ai/openchart-core';
20
21
  import type { ScaleBand, ScaleLinear } from 'd3-scale';
21
-
22
22
  import type { NormalizedChartSpec } from '../../compiler/types';
23
23
  import type { ResolvedScales } from '../../layout/scales';
24
24
  import { isConditionalValueDef, resolveConditionalValue } from '../../transforms/conditional';
25
25
  import { getColor, getSequentialColor, groupByField } from '../utils';
26
26
 
27
+ /**
28
+ * Auto-orient a gradient for horizontal bars.
29
+ *
30
+ * If the gradient uses the default top-to-bottom direction (no explicit
31
+ * x1/y1/x2/y2, or the defaults x1:0, y1:0, x2:0, y2:1), rotate it to
32
+ * left-to-right so the gradient follows the bar's data direction.
33
+ *
34
+ * Gradients with explicit non-default coordinates are left unchanged.
35
+ */
36
+ function orientGradientForHorizontalBar(grad: GradientDef): GradientDef {
37
+ if (grad.gradient !== 'linear') return grad;
38
+ const lg = grad as LinearGradient;
39
+ // Only auto-orient if using the default vertical direction.
40
+ // Default is x1:0, y1:0, x2:0, y2:1 (top-to-bottom).
41
+ const isDefaultVertical =
42
+ (lg.x1 === undefined || lg.x1 === 0) &&
43
+ (lg.y1 === undefined || lg.y1 === 0) &&
44
+ (lg.x2 === undefined || lg.x2 === 0) &&
45
+ (lg.y2 === undefined || lg.y2 === 1);
46
+ if (!isDefaultVertical) return grad;
47
+ return { ...lg, x1: 0, y1: 0, x2: 1, y2: 0 };
48
+ }
49
+
27
50
  // ---------------------------------------------------------------------------
28
51
  // Constants
29
52
  // ---------------------------------------------------------------------------
@@ -207,7 +230,7 @@ function computeStackedBars(
207
230
  y: bandY,
208
231
  width: barWidth,
209
232
  height: bandwidth,
210
- fill: color,
233
+ fill: isGradientDef(color) ? orientGradientForHorizontalBar(color) : color,
211
234
  cornerRadius: 0,
212
235
  data: row as Record<string, unknown>,
213
236
  aria,
@@ -277,7 +300,7 @@ function computeGroupedBars(
277
300
  y: subY,
278
301
  width: barWidth,
279
302
  height: subBandHeight,
280
- fill: color,
303
+ fill: isGradientDef(color) ? orientGradientForHorizontalBar(color) : color,
281
304
  cornerRadius: 2,
282
305
  data: row as Record<string, unknown>,
283
306
  aria,
@@ -327,7 +350,7 @@ function computeColoredBars(
327
350
  y: bandY,
328
351
  width: barWidth,
329
352
  height: bandwidth,
330
- fill: color,
353
+ fill: isGradientDef(color) ? orientGradientForHorizontalBar(color) : color,
331
354
  cornerRadius: 2,
332
355
  data: row as Record<string, unknown>,
333
356
  aria,
@@ -387,7 +410,7 @@ function computeSimpleBars(
387
410
  y: bandY,
388
411
  width: barWidth,
389
412
  height: bandwidth,
390
- fill: color,
413
+ fill: isGradientDef(color) ? orientGradientForHorizontalBar(color) : color,
391
414
  cornerRadius: 2,
392
415
  data: row as Record<string, unknown>,
393
416
  aria,
@@ -186,7 +186,7 @@ function validateChartSpec(spec: Record<string, unknown>, errors: ValidationErro
186
186
  message: `Spec error: encoding.${channel} must have a "field" string`,
187
187
  path: `encoding.${channel}.field`,
188
188
  code: 'MISSING_FIELD',
189
- suggestion: `Add a field name from your data columns: ${availableColumns}`,
189
+ suggestion: `For constant colors, use mark.fill (e.g., mark: { type: "bar", fill: "#1b7fa3" }) instead of encoding.${channel}. Encoding channels require a data field: ${availableColumns}`,
190
190
  });
191
191
  continue;
192
192
  }