@internetstiftelsen/charts 0.12.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/README.md +10 -1
- package/dist/base-chart.d.ts +12 -1
- package/dist/base-chart.js +58 -18
- package/dist/chart-group.d.ts +15 -2
- package/dist/chart-group.js +181 -45
- package/dist/chart-interface.d.ts +3 -3
- package/dist/grouped-data.d.ts +1 -0
- package/dist/grouped-data.js +80 -40
- package/dist/grouped-tabular.js +12 -3
- package/dist/layout-manager.js +4 -4
- package/dist/line.d.ts +3 -1
- package/dist/line.js +35 -2
- package/dist/text.d.ts +40 -0
- package/dist/text.js +217 -0
- package/dist/theme.js +56 -0
- package/dist/title.d.ts +6 -12
- package/dist/title.js +29 -82
- package/dist/tooltip.js +7 -3
- package/dist/types.d.ts +43 -2
- package/docs/chart-group.md +24 -5
- package/docs/components.md +99 -15
- package/docs/donut-chart.md +2 -1
- package/docs/gauge-chart.md +2 -1
- package/docs/getting-started.md +1 -1
- package/docs/pie-chart.md +2 -1
- package/docs/theming.md +35 -0
- package/docs/word-cloud-chart.md +1 -0
- package/docs/xy-chart.md +16 -0
- package/package.json +1 -1
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.
|
|
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/text.d.ts
ADDED
|
@@ -0,0 +1,40 @@
|
|
|
1
|
+
import { type Selection } from 'd3';
|
|
2
|
+
import type { ChartTheme, ExportHooks, TextAlign, TextConfig, TextConfigBase, TextPosition } from './types.js';
|
|
3
|
+
import type { ComponentSpace, LayoutAwareComponent } from './chart-interface.js';
|
|
4
|
+
type TextComponentType = 'text' | 'title';
|
|
5
|
+
type ResolvedTextStyle = {
|
|
6
|
+
fontSize: number;
|
|
7
|
+
fontWeight: string;
|
|
8
|
+
fontFamily: string;
|
|
9
|
+
color: string;
|
|
10
|
+
lineHeight: number;
|
|
11
|
+
marginTop: number;
|
|
12
|
+
marginBottom: number;
|
|
13
|
+
};
|
|
14
|
+
export declare class Text implements LayoutAwareComponent<TextConfigBase> {
|
|
15
|
+
readonly type: TextComponentType;
|
|
16
|
+
readonly display: boolean;
|
|
17
|
+
readonly text: string;
|
|
18
|
+
readonly position: TextPosition;
|
|
19
|
+
readonly variant: string;
|
|
20
|
+
readonly align: TextAlign;
|
|
21
|
+
readonly exportHooks?: ExportHooks<TextConfigBase>;
|
|
22
|
+
protected readonly fontSize?: number;
|
|
23
|
+
protected readonly fontWeight?: string;
|
|
24
|
+
protected readonly fontFamily?: string;
|
|
25
|
+
protected readonly color?: string;
|
|
26
|
+
protected readonly lineHeight?: number;
|
|
27
|
+
protected readonly marginTop?: number;
|
|
28
|
+
protected readonly marginBottom?: number;
|
|
29
|
+
constructor(config: TextConfig, componentType?: TextComponentType);
|
|
30
|
+
getExportConfig(): TextConfigBase;
|
|
31
|
+
createExportComponent(override?: Partial<TextConfigBase>): LayoutAwareComponent<TextConfigBase>;
|
|
32
|
+
getRequiredSpace(theme?: ChartTheme): ComponentSpace;
|
|
33
|
+
render(svg: Selection<SVGSVGElement, undefined, null, undefined>, theme: ChartTheme, width: number, x?: number, y?: number): void;
|
|
34
|
+
protected resolveStyle(theme?: ChartTheme): ResolvedTextStyle;
|
|
35
|
+
private resolveStyleValue;
|
|
36
|
+
private getLines;
|
|
37
|
+
private resolveTextPosition;
|
|
38
|
+
private resolveClassName;
|
|
39
|
+
}
|
|
40
|
+
export {};
|
package/dist/text.js
ADDED
|
@@ -0,0 +1,217 @@
|
|
|
1
|
+
import { mergeDeep, sanitizeForCSS } from './utils.js';
|
|
2
|
+
export class Text {
|
|
3
|
+
constructor(config, componentType = 'text') {
|
|
4
|
+
Object.defineProperty(this, "type", {
|
|
5
|
+
enumerable: true,
|
|
6
|
+
configurable: true,
|
|
7
|
+
writable: true,
|
|
8
|
+
value: void 0
|
|
9
|
+
});
|
|
10
|
+
Object.defineProperty(this, "display", {
|
|
11
|
+
enumerable: true,
|
|
12
|
+
configurable: true,
|
|
13
|
+
writable: true,
|
|
14
|
+
value: void 0
|
|
15
|
+
});
|
|
16
|
+
Object.defineProperty(this, "text", {
|
|
17
|
+
enumerable: true,
|
|
18
|
+
configurable: true,
|
|
19
|
+
writable: true,
|
|
20
|
+
value: void 0
|
|
21
|
+
});
|
|
22
|
+
Object.defineProperty(this, "position", {
|
|
23
|
+
enumerable: true,
|
|
24
|
+
configurable: true,
|
|
25
|
+
writable: true,
|
|
26
|
+
value: void 0
|
|
27
|
+
});
|
|
28
|
+
Object.defineProperty(this, "variant", {
|
|
29
|
+
enumerable: true,
|
|
30
|
+
configurable: true,
|
|
31
|
+
writable: true,
|
|
32
|
+
value: void 0
|
|
33
|
+
});
|
|
34
|
+
Object.defineProperty(this, "align", {
|
|
35
|
+
enumerable: true,
|
|
36
|
+
configurable: true,
|
|
37
|
+
writable: true,
|
|
38
|
+
value: void 0
|
|
39
|
+
});
|
|
40
|
+
Object.defineProperty(this, "exportHooks", {
|
|
41
|
+
enumerable: true,
|
|
42
|
+
configurable: true,
|
|
43
|
+
writable: true,
|
|
44
|
+
value: void 0
|
|
45
|
+
});
|
|
46
|
+
Object.defineProperty(this, "fontSize", {
|
|
47
|
+
enumerable: true,
|
|
48
|
+
configurable: true,
|
|
49
|
+
writable: true,
|
|
50
|
+
value: void 0
|
|
51
|
+
});
|
|
52
|
+
Object.defineProperty(this, "fontWeight", {
|
|
53
|
+
enumerable: true,
|
|
54
|
+
configurable: true,
|
|
55
|
+
writable: true,
|
|
56
|
+
value: void 0
|
|
57
|
+
});
|
|
58
|
+
Object.defineProperty(this, "fontFamily", {
|
|
59
|
+
enumerable: true,
|
|
60
|
+
configurable: true,
|
|
61
|
+
writable: true,
|
|
62
|
+
value: void 0
|
|
63
|
+
});
|
|
64
|
+
Object.defineProperty(this, "color", {
|
|
65
|
+
enumerable: true,
|
|
66
|
+
configurable: true,
|
|
67
|
+
writable: true,
|
|
68
|
+
value: void 0
|
|
69
|
+
});
|
|
70
|
+
Object.defineProperty(this, "lineHeight", {
|
|
71
|
+
enumerable: true,
|
|
72
|
+
configurable: true,
|
|
73
|
+
writable: true,
|
|
74
|
+
value: void 0
|
|
75
|
+
});
|
|
76
|
+
Object.defineProperty(this, "marginTop", {
|
|
77
|
+
enumerable: true,
|
|
78
|
+
configurable: true,
|
|
79
|
+
writable: true,
|
|
80
|
+
value: void 0
|
|
81
|
+
});
|
|
82
|
+
Object.defineProperty(this, "marginBottom", {
|
|
83
|
+
enumerable: true,
|
|
84
|
+
configurable: true,
|
|
85
|
+
writable: true,
|
|
86
|
+
value: void 0
|
|
87
|
+
});
|
|
88
|
+
this.type = componentType;
|
|
89
|
+
this.display = config.display ?? true;
|
|
90
|
+
this.text = config.text;
|
|
91
|
+
this.position = config.position ?? 'top';
|
|
92
|
+
this.variant = config.variant ?? 'caption';
|
|
93
|
+
this.align = config.align ?? 'center';
|
|
94
|
+
this.fontSize = config.fontSize;
|
|
95
|
+
this.fontWeight = config.fontWeight;
|
|
96
|
+
this.fontFamily = config.fontFamily;
|
|
97
|
+
this.color = config.color;
|
|
98
|
+
this.lineHeight = config.lineHeight;
|
|
99
|
+
this.marginTop = config.marginTop;
|
|
100
|
+
this.marginBottom = config.marginBottom;
|
|
101
|
+
this.exportHooks = config.exportHooks;
|
|
102
|
+
}
|
|
103
|
+
getExportConfig() {
|
|
104
|
+
return {
|
|
105
|
+
display: this.display,
|
|
106
|
+
text: this.text,
|
|
107
|
+
position: this.position,
|
|
108
|
+
variant: this.variant,
|
|
109
|
+
align: this.align,
|
|
110
|
+
fontSize: this.fontSize,
|
|
111
|
+
fontWeight: this.fontWeight,
|
|
112
|
+
fontFamily: this.fontFamily,
|
|
113
|
+
color: this.color,
|
|
114
|
+
lineHeight: this.lineHeight,
|
|
115
|
+
marginTop: this.marginTop,
|
|
116
|
+
marginBottom: this.marginBottom,
|
|
117
|
+
};
|
|
118
|
+
}
|
|
119
|
+
createExportComponent(override) {
|
|
120
|
+
const merged = mergeDeep(this.getExportConfig(), override);
|
|
121
|
+
return new Text({
|
|
122
|
+
...merged,
|
|
123
|
+
exportHooks: this.exportHooks,
|
|
124
|
+
}, this.type);
|
|
125
|
+
}
|
|
126
|
+
getRequiredSpace(theme) {
|
|
127
|
+
if (!this.display) {
|
|
128
|
+
return {
|
|
129
|
+
width: 0,
|
|
130
|
+
height: 0,
|
|
131
|
+
position: this.position,
|
|
132
|
+
};
|
|
133
|
+
}
|
|
134
|
+
const style = this.resolveStyle(theme);
|
|
135
|
+
const lineCount = this.getLines().length;
|
|
136
|
+
const textHeight = style.fontSize +
|
|
137
|
+
Math.max(0, lineCount - 1) * style.fontSize * style.lineHeight;
|
|
138
|
+
return {
|
|
139
|
+
width: 0,
|
|
140
|
+
height: style.marginTop + textHeight + style.marginBottom,
|
|
141
|
+
position: this.position,
|
|
142
|
+
};
|
|
143
|
+
}
|
|
144
|
+
render(svg, theme, width, x = 0, y = 0) {
|
|
145
|
+
if (!this.display) {
|
|
146
|
+
return;
|
|
147
|
+
}
|
|
148
|
+
const style = this.resolveStyle(theme);
|
|
149
|
+
const { textX, textAnchor } = this.resolveTextPosition(theme, width);
|
|
150
|
+
const textGroup = svg
|
|
151
|
+
.append('g')
|
|
152
|
+
.attr('class', this.resolveClassName())
|
|
153
|
+
.attr('transform', `translate(${x}, ${y})`);
|
|
154
|
+
const text = textGroup
|
|
155
|
+
.append('text')
|
|
156
|
+
.attr('x', textX)
|
|
157
|
+
.attr('text-anchor', textAnchor)
|
|
158
|
+
.attr('font-size', `${style.fontSize}px`)
|
|
159
|
+
.attr('font-weight', style.fontWeight)
|
|
160
|
+
.attr('font-family', style.fontFamily)
|
|
161
|
+
.attr('fill', style.color);
|
|
162
|
+
this.getLines().forEach((line, index) => {
|
|
163
|
+
const tspan = text.append('tspan').attr('x', textX).text(line);
|
|
164
|
+
if (index === 0) {
|
|
165
|
+
tspan.attr('y', style.marginTop + style.fontSize);
|
|
166
|
+
return;
|
|
167
|
+
}
|
|
168
|
+
tspan.attr('dy', `${style.lineHeight}em`);
|
|
169
|
+
});
|
|
170
|
+
}
|
|
171
|
+
resolveStyle(theme) {
|
|
172
|
+
const variant = theme?.text.variants[this.variant] ?? {};
|
|
173
|
+
return {
|
|
174
|
+
fontSize: this.resolveStyleValue(this.fontSize, variant.fontSize, 12),
|
|
175
|
+
fontWeight: this.resolveStyleValue(this.fontWeight, variant.fontWeight, 'normal'),
|
|
176
|
+
fontFamily: this.fontFamily ??
|
|
177
|
+
variant.fontFamily ??
|
|
178
|
+
theme?.fontFamily ??
|
|
179
|
+
'',
|
|
180
|
+
color: this.resolveStyleValue(this.color, variant.color, '#1f2a36'),
|
|
181
|
+
lineHeight: this.resolveStyleValue(this.lineHeight, variant.lineHeight, 1.2),
|
|
182
|
+
marginTop: this.resolveStyleValue(this.marginTop, variant.marginTop, 0),
|
|
183
|
+
marginBottom: this.resolveStyleValue(this.marginBottom, variant.marginBottom, 0),
|
|
184
|
+
};
|
|
185
|
+
}
|
|
186
|
+
resolveStyleValue(configured, variant, fallback) {
|
|
187
|
+
return configured ?? variant ?? fallback;
|
|
188
|
+
}
|
|
189
|
+
getLines() {
|
|
190
|
+
return this.text.split('\n');
|
|
191
|
+
}
|
|
192
|
+
resolveTextPosition(theme, width) {
|
|
193
|
+
if (this.align === 'left') {
|
|
194
|
+
return {
|
|
195
|
+
textX: theme.margins.left,
|
|
196
|
+
textAnchor: 'start',
|
|
197
|
+
};
|
|
198
|
+
}
|
|
199
|
+
if (this.align === 'right') {
|
|
200
|
+
return {
|
|
201
|
+
textX: width - theme.margins.right,
|
|
202
|
+
textAnchor: 'end',
|
|
203
|
+
};
|
|
204
|
+
}
|
|
205
|
+
return {
|
|
206
|
+
textX: width / 2,
|
|
207
|
+
textAnchor: 'middle',
|
|
208
|
+
};
|
|
209
|
+
}
|
|
210
|
+
resolveClassName() {
|
|
211
|
+
const classes = ['text', `text--${sanitizeForCSS(this.variant)}`];
|
|
212
|
+
if (this.type === 'title') {
|
|
213
|
+
classes.unshift('title');
|
|
214
|
+
}
|
|
215
|
+
return classes.join(' ');
|
|
216
|
+
}
|
|
217
|
+
}
|
package/dist/theme.js
CHANGED
|
@@ -40,6 +40,34 @@ export const defaultTheme = {
|
|
|
40
40
|
itemSpacingX: 20,
|
|
41
41
|
itemSpacingY: 8,
|
|
42
42
|
},
|
|
43
|
+
text: {
|
|
44
|
+
variants: {
|
|
45
|
+
title: {
|
|
46
|
+
fontSize: 18,
|
|
47
|
+
fontWeight: 'bold',
|
|
48
|
+
color: '#1f2a36',
|
|
49
|
+
lineHeight: 1.2,
|
|
50
|
+
marginTop: 10,
|
|
51
|
+
marginBottom: 15,
|
|
52
|
+
},
|
|
53
|
+
subtitle: {
|
|
54
|
+
fontSize: 14,
|
|
55
|
+
fontWeight: 'normal',
|
|
56
|
+
color: '#4b5563',
|
|
57
|
+
lineHeight: 1.35,
|
|
58
|
+
marginTop: 0,
|
|
59
|
+
marginBottom: 12,
|
|
60
|
+
},
|
|
61
|
+
caption: {
|
|
62
|
+
fontSize: 12,
|
|
63
|
+
fontWeight: 'normal',
|
|
64
|
+
color: '#6b7280',
|
|
65
|
+
lineHeight: 1.3,
|
|
66
|
+
marginTop: 8,
|
|
67
|
+
marginBottom: 0,
|
|
68
|
+
},
|
|
69
|
+
},
|
|
70
|
+
},
|
|
43
71
|
tooltip: {
|
|
44
72
|
background: '#ffffff',
|
|
45
73
|
border: '#dddddd',
|
|
@@ -128,6 +156,34 @@ export const newspaperTheme = {
|
|
|
128
156
|
itemSpacingX: 20,
|
|
129
157
|
itemSpacingY: 8,
|
|
130
158
|
},
|
|
159
|
+
text: {
|
|
160
|
+
variants: {
|
|
161
|
+
title: {
|
|
162
|
+
fontSize: 18,
|
|
163
|
+
fontWeight: 'bold',
|
|
164
|
+
color: '#1a1a1a',
|
|
165
|
+
lineHeight: 1.2,
|
|
166
|
+
marginTop: 10,
|
|
167
|
+
marginBottom: 15,
|
|
168
|
+
},
|
|
169
|
+
subtitle: {
|
|
170
|
+
fontSize: 14,
|
|
171
|
+
fontWeight: 'normal',
|
|
172
|
+
color: '#4a4a4a',
|
|
173
|
+
lineHeight: 1.35,
|
|
174
|
+
marginTop: 0,
|
|
175
|
+
marginBottom: 12,
|
|
176
|
+
},
|
|
177
|
+
caption: {
|
|
178
|
+
fontSize: 12,
|
|
179
|
+
fontWeight: 'normal',
|
|
180
|
+
color: '#6b6b6b',
|
|
181
|
+
lineHeight: 1.3,
|
|
182
|
+
marginTop: 8,
|
|
183
|
+
marginBottom: 0,
|
|
184
|
+
},
|
|
185
|
+
},
|
|
186
|
+
},
|
|
131
187
|
tooltip: {
|
|
132
188
|
background: '#111111',
|
|
133
189
|
border: '#111111',
|
package/dist/title.d.ts
CHANGED
|
@@ -1,23 +1,17 @@
|
|
|
1
1
|
import { type Selection } from 'd3';
|
|
2
|
-
import type {
|
|
3
|
-
import type {
|
|
2
|
+
import type { ChartTheme, ExportHooks, TitleConfig, TitleConfigBase } from './types.js';
|
|
3
|
+
import type { ComponentSpace, LayoutAwareComponent } from './chart-interface.js';
|
|
4
4
|
export declare class Title implements LayoutAwareComponent<TitleConfigBase> {
|
|
5
5
|
readonly type: "title";
|
|
6
6
|
readonly display: boolean;
|
|
7
7
|
readonly text: string;
|
|
8
|
+
readonly position: "top";
|
|
9
|
+
readonly variant = "title";
|
|
8
10
|
readonly exportHooks?: ExportHooks<TitleConfigBase>;
|
|
9
|
-
private readonly
|
|
10
|
-
private readonly fontWeight;
|
|
11
|
-
private readonly fontFamily?;
|
|
12
|
-
private readonly align;
|
|
13
|
-
private readonly marginTop;
|
|
14
|
-
private readonly marginBottom;
|
|
11
|
+
private readonly textComponent;
|
|
15
12
|
constructor(config: TitleConfig);
|
|
16
13
|
getExportConfig(): TitleConfigBase;
|
|
17
14
|
createExportComponent(override?: Partial<TitleConfigBase>): LayoutAwareComponent<TitleConfigBase>;
|
|
18
|
-
|
|
19
|
-
* Returns the space required by the title
|
|
20
|
-
*/
|
|
21
|
-
getRequiredSpace(): ComponentSpace;
|
|
15
|
+
getRequiredSpace(theme?: ChartTheme): ComponentSpace;
|
|
22
16
|
render(svg: Selection<SVGSVGElement, undefined, null, undefined>, theme: ChartTheme, width: number, x?: number, y?: number): void;
|
|
23
17
|
}
|
package/dist/title.js
CHANGED
|
@@ -1,3 +1,4 @@
|
|
|
1
|
+
import { Text } from './text.js';
|
|
1
2
|
import { mergeDeep } from './utils.js';
|
|
2
3
|
export class Title {
|
|
3
4
|
constructor(config) {
|
|
@@ -19,68 +20,53 @@ export class Title {
|
|
|
19
20
|
writable: true,
|
|
20
21
|
value: void 0
|
|
21
22
|
});
|
|
22
|
-
Object.defineProperty(this, "
|
|
23
|
-
enumerable: true,
|
|
24
|
-
configurable: true,
|
|
25
|
-
writable: true,
|
|
26
|
-
value: void 0
|
|
27
|
-
});
|
|
28
|
-
Object.defineProperty(this, "fontSize", {
|
|
29
|
-
enumerable: true,
|
|
30
|
-
configurable: true,
|
|
31
|
-
writable: true,
|
|
32
|
-
value: void 0
|
|
33
|
-
});
|
|
34
|
-
Object.defineProperty(this, "fontWeight", {
|
|
35
|
-
enumerable: true,
|
|
36
|
-
configurable: true,
|
|
37
|
-
writable: true,
|
|
38
|
-
value: void 0
|
|
39
|
-
});
|
|
40
|
-
Object.defineProperty(this, "fontFamily", {
|
|
23
|
+
Object.defineProperty(this, "position", {
|
|
41
24
|
enumerable: true,
|
|
42
25
|
configurable: true,
|
|
43
26
|
writable: true,
|
|
44
|
-
value:
|
|
27
|
+
value: 'top'
|
|
45
28
|
});
|
|
46
|
-
Object.defineProperty(this, "
|
|
29
|
+
Object.defineProperty(this, "variant", {
|
|
47
30
|
enumerable: true,
|
|
48
31
|
configurable: true,
|
|
49
32
|
writable: true,
|
|
50
|
-
value:
|
|
33
|
+
value: 'title'
|
|
51
34
|
});
|
|
52
|
-
Object.defineProperty(this, "
|
|
35
|
+
Object.defineProperty(this, "exportHooks", {
|
|
53
36
|
enumerable: true,
|
|
54
37
|
configurable: true,
|
|
55
38
|
writable: true,
|
|
56
39
|
value: void 0
|
|
57
40
|
});
|
|
58
|
-
Object.defineProperty(this, "
|
|
41
|
+
Object.defineProperty(this, "textComponent", {
|
|
59
42
|
enumerable: true,
|
|
60
43
|
configurable: true,
|
|
61
44
|
writable: true,
|
|
62
45
|
value: void 0
|
|
63
46
|
});
|
|
64
|
-
this.
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
|
|
69
|
-
|
|
70
|
-
this.
|
|
71
|
-
this.
|
|
47
|
+
this.textComponent = new Text({
|
|
48
|
+
...config,
|
|
49
|
+
position: 'top',
|
|
50
|
+
variant: 'title',
|
|
51
|
+
exportHooks: config.exportHooks,
|
|
52
|
+
}, 'title');
|
|
53
|
+
this.display = this.textComponent.display;
|
|
54
|
+
this.text = this.textComponent.text;
|
|
72
55
|
this.exportHooks = config.exportHooks;
|
|
73
56
|
}
|
|
74
57
|
getExportConfig() {
|
|
58
|
+
const config = this.textComponent.getExportConfig();
|
|
75
59
|
return {
|
|
76
|
-
display:
|
|
77
|
-
text:
|
|
78
|
-
fontSize:
|
|
79
|
-
fontWeight:
|
|
80
|
-
fontFamily:
|
|
81
|
-
align:
|
|
82
|
-
|
|
83
|
-
|
|
60
|
+
display: config.display,
|
|
61
|
+
text: config.text,
|
|
62
|
+
fontSize: config.fontSize,
|
|
63
|
+
fontWeight: config.fontWeight,
|
|
64
|
+
fontFamily: config.fontFamily,
|
|
65
|
+
align: config.align,
|
|
66
|
+
color: config.color,
|
|
67
|
+
lineHeight: config.lineHeight,
|
|
68
|
+
marginTop: config.marginTop,
|
|
69
|
+
marginBottom: config.marginBottom,
|
|
84
70
|
};
|
|
85
71
|
}
|
|
86
72
|
createExportComponent(override) {
|
|
@@ -90,49 +76,10 @@ export class Title {
|
|
|
90
76
|
exportHooks: this.exportHooks,
|
|
91
77
|
});
|
|
92
78
|
}
|
|
93
|
-
|
|
94
|
-
|
|
95
|
-
*/
|
|
96
|
-
getRequiredSpace() {
|
|
97
|
-
if (!this.display) {
|
|
98
|
-
return {
|
|
99
|
-
width: 0,
|
|
100
|
-
height: 0,
|
|
101
|
-
position: 'top',
|
|
102
|
-
};
|
|
103
|
-
}
|
|
104
|
-
return {
|
|
105
|
-
width: 0, // Title spans full width
|
|
106
|
-
height: this.marginTop + this.fontSize + this.marginBottom,
|
|
107
|
-
position: 'top',
|
|
108
|
-
};
|
|
79
|
+
getRequiredSpace(theme) {
|
|
80
|
+
return this.textComponent.getRequiredSpace(theme);
|
|
109
81
|
}
|
|
110
82
|
render(svg, theme, width, x = 0, y = 0) {
|
|
111
|
-
|
|
112
|
-
return;
|
|
113
|
-
}
|
|
114
|
-
const titleGroup = svg
|
|
115
|
-
.append('g')
|
|
116
|
-
.attr('class', 'title')
|
|
117
|
-
.attr('transform', `translate(${x}, ${y})`);
|
|
118
|
-
let textX = width / 2;
|
|
119
|
-
let textAnchor = 'middle';
|
|
120
|
-
if (this.align === 'left') {
|
|
121
|
-
textX = theme.margins.left;
|
|
122
|
-
textAnchor = 'start';
|
|
123
|
-
}
|
|
124
|
-
else if (this.align === 'right') {
|
|
125
|
-
textX = width - theme.margins.right;
|
|
126
|
-
textAnchor = 'end';
|
|
127
|
-
}
|
|
128
|
-
titleGroup
|
|
129
|
-
.append('text')
|
|
130
|
-
.attr('x', textX)
|
|
131
|
-
.attr('y', this.marginTop + this.fontSize)
|
|
132
|
-
.attr('text-anchor', textAnchor)
|
|
133
|
-
.attr('font-size', `${this.fontSize}px`)
|
|
134
|
-
.attr('font-weight', this.fontWeight)
|
|
135
|
-
.attr('font-family', this.fontFamily || theme.fontFamily)
|
|
136
|
-
.text(this.text);
|
|
83
|
+
this.textComponent.render(svg, theme, width, x, y);
|
|
137
84
|
}
|
|
138
85
|
}
|
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
|
|
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 =
|
|
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
|
-
|
|
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);
|