@internetstiftelsen/charts 0.13.0 → 0.13.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/dist/line.d.ts CHANGED
@@ -1,5 +1,5 @@
1
1
  import { type Selection } from 'd3';
2
- import type { LineConfig, DataItem, D3Scale, ScaleType, ChartTheme, LineValueLabelConfig, ExportHooks, LineConfigBase } from './types.js';
2
+ import type { LineConfig, DataItem, D3Scale, ScaleType, ChartTheme, LineValueLabelConfig, ExportHooks, LineConfigBase, LineCurveType, LinePointsConfig } from './types.js';
3
3
  import type { ChartComponent } from './chart-interface.js';
4
4
  import type { XYPointAnimationContext, XYPointSnapshot, XYSeriesRenderResult } from './xy-motion/types.js';
5
5
  export declare class Line implements ChartComponent<LineConfigBase> {
@@ -7,6 +7,8 @@ export declare class Line implements ChartComponent<LineConfigBase> {
7
7
  readonly dataKey: string;
8
8
  readonly stroke: string;
9
9
  readonly strokeWidth?: number;
10
+ readonly curve: LineCurveType;
11
+ readonly points: Required<LinePointsConfig>;
10
12
  readonly valueLabel?: LineValueLabelConfig;
11
13
  readonly exportHooks?: ExportHooks<LineConfigBase>;
12
14
  constructor(config: LineConfig);
package/dist/line.js CHANGED
@@ -1,7 +1,18 @@
1
- import { line } from 'd3';
1
+ import { curveBasis, curveCardinal, curveLinear, curveMonotoneX, curveNatural, curveStep, line, } from 'd3';
2
2
  import { sanitizeForCSS, mergeDeep } from './utils.js';
3
3
  import { getScalePosition } from './scale-utils.js';
4
4
  import { buildXYDatumSnapshotKeys, createTransitionCompletionPromise, createLeftToRightRevealTransition, getEnterStaggerTiming, } from './xy-motion/helpers.js';
5
+ const DEFAULT_LINE_POINTS = {
6
+ show: 'always',
7
+ };
8
+ const LINE_CURVE_FACTORIES = {
9
+ linear: curveLinear,
10
+ monotone: curveMonotoneX,
11
+ step: curveStep,
12
+ natural: curveNatural,
13
+ basis: curveBasis,
14
+ cardinal: curveCardinal,
15
+ };
5
16
  export class Line {
6
17
  constructor(config) {
7
18
  Object.defineProperty(this, "type", {
@@ -28,6 +39,18 @@ export class Line {
28
39
  writable: true,
29
40
  value: void 0
30
41
  });
42
+ Object.defineProperty(this, "curve", {
43
+ enumerable: true,
44
+ configurable: true,
45
+ writable: true,
46
+ value: void 0
47
+ });
48
+ Object.defineProperty(this, "points", {
49
+ enumerable: true,
50
+ configurable: true,
51
+ writable: true,
52
+ value: void 0
53
+ });
31
54
  Object.defineProperty(this, "valueLabel", {
32
55
  enumerable: true,
33
56
  configurable: true,
@@ -43,6 +66,10 @@ export class Line {
43
66
  this.dataKey = config.dataKey;
44
67
  this.stroke = config.stroke || '#8884d8';
45
68
  this.strokeWidth = config.strokeWidth;
69
+ this.curve = config.curve || 'linear';
70
+ this.points = {
71
+ show: config.points?.show ?? DEFAULT_LINE_POINTS.show,
72
+ };
46
73
  this.valueLabel = config.valueLabel;
47
74
  this.exportHooks = config.exportHooks;
48
75
  }
@@ -51,6 +78,8 @@ export class Line {
51
78
  dataKey: this.dataKey,
52
79
  stroke: this.stroke,
53
80
  strokeWidth: this.strokeWidth,
81
+ curve: this.curve,
82
+ points: this.points,
54
83
  valueLabel: this.valueLabel,
55
84
  };
56
85
  }
@@ -80,7 +109,9 @@ export class Line {
80
109
  });
81
110
  const transitions = [
82
111
  ...this.renderLinePath(plotGroup, lineData, animatedLineData, theme, sanitizeForCSS(this.dataKey), animation),
83
- ...this.renderLinePoints(plotGroup, validLineData, validAnimatedLineData, theme, animation),
112
+ ...(this.points.show === 'always'
113
+ ? this.renderLinePoints(plotGroup, validLineData, validAnimatedLineData, theme, animation)
114
+ : []),
84
115
  ];
85
116
  const snapshot = this.createSnapshot(validLineData);
86
117
  // Render value labels if enabled (only for valid values)
@@ -129,8 +160,10 @@ export class Line {
129
160
  }
130
161
  renderLinePath(plotGroup, lineData, animatedLineData, theme, sanitizedKey, animation) {
131
162
  const lineStrokeWidth = this.strokeWidth ?? theme.line.strokeWidth;
163
+ const curveFactory = LINE_CURVE_FACTORIES[this.curve] || curveLinear;
132
164
  const lineGenerator = line()
133
165
  .defined((entry) => entry.valid)
166
+ .curve(curveFactory)
134
167
  .x((entry) => entry.x)
135
168
  .y((entry) => entry.y);
136
169
  const finalPath = lineGenerator(lineData);
package/dist/tooltip.js CHANGED
@@ -269,7 +269,11 @@ export class Tooltip {
269
269
  .attr('aria-hidden', 'true')
270
270
  .style('fill', 'none')
271
271
  .style('pointer-events', 'all');
272
- const pointSeries = series.filter((currentSeries) => {
272
+ const focusCircleSeries = series.filter((currentSeries) => {
273
+ if (currentSeries.type === 'line' &&
274
+ currentSeries.points.show === 'never') {
275
+ return false;
276
+ }
273
277
  return (currentSeries.type === 'line' ||
274
278
  currentSeries.type === 'area' ||
275
279
  currentSeries.type === 'scatter');
@@ -278,7 +282,7 @@ export class Tooltip {
278
282
  return currentSeries.type === 'bar';
279
283
  });
280
284
  const hasBarSeries = barSeries.length > 0;
281
- const focusCircles = pointSeries.map((currentSeries) => {
285
+ const focusCircles = focusCircleSeries.map((currentSeries) => {
282
286
  const seriesColor = getSeriesColor(currentSeries);
283
287
  return svg
284
288
  .append('circle')
@@ -303,7 +307,7 @@ export class Tooltip {
303
307
  const updateVisualStateAtIndex = (closestIndex) => {
304
308
  const dataPoint = data[closestIndex];
305
309
  const dataPointPosition = dataPointPositions[closestIndex];
306
- pointSeries.forEach((currentSeries, seriesIndex) => {
310
+ focusCircleSeries.forEach((currentSeries, seriesIndex) => {
307
311
  const value = resolveSeriesValue(currentSeries, dataPoint, closestIndex);
308
312
  if (!Number.isFinite(value)) {
309
313
  focusCircles[seriesIndex].style('opacity', 0);
package/dist/types.d.ts CHANGED
@@ -184,16 +184,25 @@ export type ValueLabelConfig = {
184
184
  export type LineValueLabelConfig = ValueLabelConfig & {
185
185
  show?: boolean;
186
186
  };
187
+ export type LinePointVisibility = 'always' | 'hover' | 'never';
188
+ export type LinePointsConfig = {
189
+ show?: LinePointVisibility;
190
+ };
187
191
  export type BarValueLabelConfig = ValueLabelConfig & {
188
192
  show?: boolean;
189
193
  position?: 'inside' | 'outside';
190
194
  insidePosition?: 'top' | 'middle' | 'bottom';
191
195
  };
192
196
  export type BarSide = 'left' | 'right';
197
+ export type CurveType = 'linear' | 'monotone' | 'step' | 'natural' | 'basis' | 'cardinal';
198
+ export type LineCurveType = CurveType;
199
+ export type AreaCurveType = CurveType;
193
200
  export type LineConfigBase = {
194
201
  dataKey: string;
195
202
  stroke?: string;
196
203
  strokeWidth?: number;
204
+ curve?: LineCurveType;
205
+ points?: LinePointsConfig;
197
206
  valueLabel?: LineValueLabelConfig;
198
207
  };
199
208
  export type LineConfig = LineConfigBase & {
@@ -219,7 +228,6 @@ export type BarConfigBase = {
219
228
  export type BarConfig = BarConfigBase & {
220
229
  exportHooks?: ExportHooks<BarConfigBase>;
221
230
  };
222
- export type AreaCurveType = 'linear' | 'monotone' | 'step' | 'natural' | 'basis' | 'cardinal';
223
231
  export type AreaConfigBase = {
224
232
  dataKey: string;
225
233
  fill?: string;
package/docs/xy-chart.md CHANGED
@@ -338,6 +338,10 @@ new Line({
338
338
  dataKey: string, // Key in data objects for Y values (required)
339
339
  stroke?: string, // Line color (auto-assigned if omitted)
340
340
  strokeWidth?: number, // Line width in pixels (default: 2)
341
+ curve?: 'linear' | 'monotone' | 'step' | 'natural' | 'basis' | 'cardinal',
342
+ points?: {
343
+ show?: 'always' | 'hover' | 'never'
344
+ }, // Data point visibility (default: 'always')
341
345
  valueLabel?: {
342
346
  show?: boolean,
343
347
  formatter?: (dataKey, value, data) => string
@@ -355,8 +359,20 @@ chart.addChild(new Line({ dataKey: 'expenses' }));
355
359
  // Manual colors
356
360
  chart.addChild(new Line({ dataKey: 'revenue', stroke: '#00ff00' }));
357
361
  chart.addChild(new Line({ dataKey: 'expenses', stroke: '#ff0000' }));
362
+
363
+ // Smooth line interpolation
364
+ chart.addChild(new Line({ dataKey: 'revenue', curve: 'monotone' }));
365
+
366
+ // Show point circles only while hovering or focusing a tooltip target
367
+ chart
368
+ .addChild(new Line({ dataKey: 'revenue', points: { show: 'hover' } }))
369
+ .addChild(new Tooltip());
358
370
  ```
359
371
 
372
+ `points.show: 'hover'` uses `Tooltip` focus markers, so add a `Tooltip`
373
+ component when hover-only points should be visible. Use `'never'` to suppress
374
+ both static line points and tooltip focus markers for that line.
375
+
360
376
  ---
361
377
 
362
378
  ## Scatter
package/package.json CHANGED
@@ -1,5 +1,5 @@
1
1
  {
2
- "version": "0.13.0",
2
+ "version": "0.13.1",
3
3
  "name": "@internetstiftelsen/charts",
4
4
  "type": "module",
5
5
  "sideEffects": false,