@opendata-ai/openchart-engine 7.5.0 → 7.6.0

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": "7.5.0",
3
+ "version": "7.6.0",
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",
@@ -48,7 +48,7 @@
48
48
  "typecheck": "tsc --noEmit"
49
49
  },
50
50
  "dependencies": {
51
- "@opendata-ai/openchart-core": "7.5.0",
51
+ "@opendata-ai/openchart-core": "7.6.0",
52
52
  "d3-array": "^3.2.0",
53
53
  "d3-format": "^3.1.2",
54
54
  "d3-interpolate": "^3.0.0",
@@ -3,6 +3,7 @@ import { describe, expect, it } from 'vitest';
3
3
  import type { NormalizedChartSpec } from '../../../compiler/types';
4
4
  import { computeScales } from '../../../layout/scales';
5
5
  import { computeScatterMarks } from '../compute';
6
+ import { scatterRenderer } from '../index';
6
7
  import { computeTrendLine } from '../trendline';
7
8
 
8
9
  // ---------------------------------------------------------------------------
@@ -462,3 +463,26 @@ describe('computeTrendLine', () => {
462
463
  expect(computeTrendLine([])).toBeNull();
463
464
  });
464
465
  });
466
+
467
+ describe('trendline opt-out', () => {
468
+ it('renders a trend line by default', () => {
469
+ const spec = makeBasicScatterSpec();
470
+ const scales = computeScales(spec, chartArea, spec.data);
471
+ const marks = scatterRenderer(spec, scales, chartArea, fullStrategy, undefined as never);
472
+
473
+ expect(marks.some((m) => m.type === 'line')).toBe(true);
474
+ });
475
+
476
+ it('suppresses the trend line when mark.trendline is false', () => {
477
+ const base = makeBasicScatterSpec();
478
+ const spec: NormalizedChartSpec = {
479
+ ...base,
480
+ markDef: { type: 'point', trendline: false },
481
+ };
482
+ const scales = computeScales(spec, chartArea, spec.data);
483
+ const marks = scatterRenderer(spec, scales, chartArea, fullStrategy, undefined as never);
484
+
485
+ expect(marks.some((m) => m.type === 'line')).toBe(false);
486
+ expect(marks.every((m) => m.type === 'point')).toBe(true);
487
+ });
488
+ });
@@ -23,11 +23,16 @@ export const scatterRenderer: ChartRenderer = (spec, scales, chartArea, strategy
23
23
  const pointMarks = computeScatterMarks(spec, scales, chartArea, strategy);
24
24
  const marks: Mark[] = [...pointMarks];
25
25
 
26
- // Add trend line if there are enough points
27
- const trendLine = computeTrendLine(pointMarks);
28
- if (trendLine) {
29
- // Trend line goes behind points
30
- marks.unshift(trendLine);
26
+ // Regression trend line renders by default but is opt-out via
27
+ // `mark: { type: 'point', trendline: false }`. Rendering it unconditionally
28
+ // competed with author-drawn reference lines (e.g. a manual x=y diagonal),
29
+ // so a chart could show two diagonals.
30
+ if (spec.markDef?.trendline !== false) {
31
+ const trendLine = computeTrendLine(pointMarks);
32
+ if (trendLine) {
33
+ // Trend line goes behind points
34
+ marks.unshift(trendLine);
35
+ }
31
36
  }
32
37
 
33
38
  return marks;