@rfprodz/client-d3-charts 1.0.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.
Files changed (54) hide show
  1. package/LICENSE +21 -0
  2. package/README.md +88 -0
  3. package/esm2020/index.mjs +5 -0
  4. package/esm2020/lib/client-d3-charts.module.mjs +47 -0
  5. package/esm2020/lib/components/bar-chart/bar-chart.component.mjs +87 -0
  6. package/esm2020/lib/components/chart-examples/chart-examples.component.mjs +181 -0
  7. package/esm2020/lib/components/force-directed-chart/force-directed-chart.component.mjs +92 -0
  8. package/esm2020/lib/components/index.mjs +7 -0
  9. package/esm2020/lib/components/line-chart/line-chart.component.mjs +91 -0
  10. package/esm2020/lib/components/pie-chart/pie-chart.component.mjs +90 -0
  11. package/esm2020/lib/components/radar-chart/radar-chart.component.mjs +102 -0
  12. package/esm2020/lib/interfaces/bar-chart.interface.mjs +2 -0
  13. package/esm2020/lib/interfaces/force-directed-chart.interface.mjs +2 -0
  14. package/esm2020/lib/interfaces/index.mjs +6 -0
  15. package/esm2020/lib/interfaces/line-chart.interface.mjs +2 -0
  16. package/esm2020/lib/interfaces/pie-chart.interface.mjs +2 -0
  17. package/esm2020/lib/interfaces/radar-chart.interface.mjs +2 -0
  18. package/esm2020/lib/providers/d3-chart-factory.provider.mjs +18 -0
  19. package/esm2020/lib/util/bar-chart.util.mjs +255 -0
  20. package/esm2020/lib/util/configuration.util.mjs +31 -0
  21. package/esm2020/lib/util/force-directed-chart.util.mjs +255 -0
  22. package/esm2020/lib/util/index.mjs +6 -0
  23. package/esm2020/lib/util/line-chart.util.mjs +266 -0
  24. package/esm2020/lib/util/pie-chart.util.mjs +89 -0
  25. package/esm2020/lib/util/radar-chart.util.mjs +295 -0
  26. package/esm2020/rfprodz-client-d3-charts.mjs +5 -0
  27. package/fesm2015/rfprodz-client-d3-charts.mjs +1868 -0
  28. package/fesm2015/rfprodz-client-d3-charts.mjs.map +1 -0
  29. package/fesm2020/rfprodz-client-d3-charts.mjs +1855 -0
  30. package/fesm2020/rfprodz-client-d3-charts.mjs.map +1 -0
  31. package/index.d.ts +4 -0
  32. package/lib/client-d3-charts.module.d.ts +13 -0
  33. package/lib/components/bar-chart/bar-chart.component.d.ts +49 -0
  34. package/lib/components/chart-examples/chart-examples.component.d.ts +60 -0
  35. package/lib/components/force-directed-chart/force-directed-chart.component.d.ts +49 -0
  36. package/lib/components/index.d.ts +6 -0
  37. package/lib/components/line-chart/line-chart.component.d.ts +49 -0
  38. package/lib/components/pie-chart/pie-chart.component.d.ts +49 -0
  39. package/lib/components/radar-chart/radar-chart.component.d.ts +49 -0
  40. package/lib/interfaces/bar-chart.interface.d.ts +25 -0
  41. package/lib/interfaces/force-directed-chart.interface.d.ts +50 -0
  42. package/lib/interfaces/index.d.ts +5 -0
  43. package/lib/interfaces/line-chart.interface.d.ts +28 -0
  44. package/lib/interfaces/pie-chart.interface.d.ts +19 -0
  45. package/lib/interfaces/radar-chart.interface.d.ts +30 -0
  46. package/lib/providers/d3-chart-factory.provider.d.ts +15 -0
  47. package/lib/util/bar-chart.util.d.ts +14 -0
  48. package/lib/util/configuration.util.d.ts +7 -0
  49. package/lib/util/force-directed-chart.util.d.ts +14 -0
  50. package/lib/util/index.d.ts +5 -0
  51. package/lib/util/line-chart.util.d.ts +14 -0
  52. package/lib/util/pie-chart.util.d.ts +14 -0
  53. package/lib/util/radar-chart.util.d.ts +14 -0
  54. package/package.json +53 -0
@@ -0,0 +1,266 @@
1
+ import * as d3 from 'd3';
2
+ import { generateConfiguration } from './configuration.util';
3
+ /**
4
+ * The line chart default configuration.
5
+ */
6
+ export const defaultLineChartConfig = Object.freeze({
7
+ chartTitle: '',
8
+ width: 350,
9
+ height: 350,
10
+ margin: {
11
+ top: 70,
12
+ right: 50,
13
+ bottom: 50,
14
+ left: 50,
15
+ },
16
+ transitionDuration: 400,
17
+ dotRadius: 3.5,
18
+ xAxisTitle: '',
19
+ yAxisTitle: '',
20
+ ticks: {
21
+ x: 5,
22
+ y: 10,
23
+ },
24
+ displayAxisLabels: true,
25
+ labelTextWrapWidth: 20,
26
+ color: d3.scaleOrdinal(d3.schemeCategory10),
27
+ });
28
+ /**
29
+ * Creates a container for the line chart.
30
+ * @param container the chart container
31
+ * @param config the chart configuration
32
+ * @returns the object with the svg element and the g element
33
+ */
34
+ const createContainer = (container, config) => {
35
+ const id = container.nativeElement.id ?? 'line-0';
36
+ d3.select(`#${id}`).select('svg').remove();
37
+ const svg = d3
38
+ .select(`#${id}`)
39
+ .append('svg')
40
+ .attr('width', config.width + config.margin.left + config.margin.right)
41
+ .attr('height', config.height + config.margin.top + config.margin.bottom)
42
+ .attr('class', id);
43
+ const g = svg.append('g').attr('transform', `translate(${config.margin.left},${config.margin.top / 2})`);
44
+ return { svg, g };
45
+ };
46
+ /**
47
+ * Wraps the line chart axis labels text.
48
+ * @param svgText the svg text elements
49
+ * @param width the chart axis label width
50
+ */
51
+ const wrapSvgText = (svgText, width) => {
52
+ svgText.each(function () {
53
+ const text = d3.select(this);
54
+ const words = text.text().split(/\s+/).reverse();
55
+ let line = [];
56
+ let lineNumber = 0;
57
+ const lineHeight = 1.4;
58
+ const y = text.attr('y');
59
+ const x = text.attr('x');
60
+ const dy = parseFloat(text.attr('dy') ?? 0);
61
+ let tspan = text.text(null).append('tspan').attr('x', x).attr('y', y).attr('dy', `${dy}em`); // axis label
62
+ let word = words.pop();
63
+ while (typeof word !== 'undefined') {
64
+ line.push(word ?? '');
65
+ tspan.text(line.join(' '));
66
+ if ((tspan.node()?.getComputedTextLength() ?? 0) > width) {
67
+ line.pop();
68
+ tspan.text(line.join(' '));
69
+ line = [word ?? ''];
70
+ lineNumber += 1;
71
+ tspan = text
72
+ .append('tspan')
73
+ .attr('x', 0)
74
+ .attr('y', y)
75
+ .attr('dy', `${lineNumber * lineHeight + dy}em`)
76
+ .text(word ?? '');
77
+ }
78
+ word = words.pop();
79
+ }
80
+ });
81
+ };
82
+ /**
83
+ * Creates the legend.
84
+ * @param g the svg g element
85
+ * @param config the chart configuration
86
+ */
87
+ const createLegend = (g, config) => {
88
+ if (config.displayAxisLabels && config.xAxisTitle !== '') {
89
+ g.append('g')
90
+ .attr('transform', `translate(0, ${config.height + config.margin.bottom})`)
91
+ .append('text')
92
+ .style('font-size', '12px')
93
+ .attr('class', 'legend')
94
+ .attr('dx', '1.5em')
95
+ .attr('dy', '1em')
96
+ .text(`x - ${config.xAxisTitle}`);
97
+ }
98
+ if (config.displayAxisLabels && config.yAxisTitle !== '') {
99
+ g.append('g')
100
+ .attr('transform', `translate(0, ${config.height + config.margin.bottom})`)
101
+ .append('text')
102
+ .style('font-size', '12px')
103
+ .attr('class', 'legend')
104
+ .attr('dx', '1.5em')
105
+ .attr('dy', '2.5em')
106
+ .text(`y - ${config.yAxisTitle}`);
107
+ }
108
+ if (config.chartTitle !== '') {
109
+ g.append('g')
110
+ .attr('transform', `translate(0, 0)`)
111
+ .append('text')
112
+ .style('font-size', '12px')
113
+ .attr('class', 'legend')
114
+ .attr('dx', '1.5em')
115
+ .attr('dy', '-2em')
116
+ .text(config.chartTitle);
117
+ }
118
+ };
119
+ /**
120
+ * Creates the x axis.
121
+ * @param g the svg g element
122
+ * @param x the x axis scale
123
+ * @param config the chart configuration
124
+ */
125
+ const createAxisX = (g, x, config) => {
126
+ const xLabels = g
127
+ .append('g')
128
+ .attr('transform', `translate(0, ${config.height})`)
129
+ .call(d3
130
+ .axisBottom(x)
131
+ .ticks(config.ticks.x)
132
+ .tickFormat(d => {
133
+ const date = new Date(d.valueOf());
134
+ const formattingOffset = 10;
135
+ const day = date.getDate();
136
+ const dd = day < formattingOffset ? `0${day}` : day;
137
+ const month = date.getMonth() + 1;
138
+ const mm = month < formattingOffset ? `0${month}` : month;
139
+ const year = date.getFullYear().toString();
140
+ const yy = year.slice(2);
141
+ const hours = date.getHours();
142
+ const hour = hours < formattingOffset ? `0${hours}` : hours;
143
+ const minutes = date.getMinutes();
144
+ const minute = minutes < formattingOffset ? `0${minutes}` : minutes;
145
+ return `${dd}/${mm}/${yy} ${hour}:${minute}`;
146
+ }))
147
+ .append('text');
148
+ g.selectAll('text').call(wrapSvgText, config.labelTextWrapWidth);
149
+ if (config.displayAxisLabels) {
150
+ xLabels.attr('transform', `translate(${config.width}, 0)`).attr('class', 'legend').attr('dx', '1.5em').attr('dy', '0.7em').text('x');
151
+ }
152
+ };
153
+ /**
154
+ * Creates the y axis.
155
+ * @param g the svg g element
156
+ * @param y the y axis scale
157
+ * @param config the chart configuration
158
+ */
159
+ const createAxisY = (g, y, config) => {
160
+ const yLabels = g
161
+ .append('g')
162
+ .call(d3
163
+ .axisLeft(y)
164
+ .ticks(config.ticks.y)
165
+ .tickFormat(d => `${d}`))
166
+ .append('text');
167
+ if (config.displayAxisLabels) {
168
+ yLabels.attr('class', 'legend').attr('dy', '-1.5em').attr('class', 'legend').text('y');
169
+ }
170
+ };
171
+ /**
172
+ * The mouse over event handler.
173
+ * @param self an svg circle element
174
+ * @param d the chart data node
175
+ * @param g the svg g element
176
+ * @param config the chart configuration
177
+ */
178
+ const onMouseOver = (self, d, g, config) => {
179
+ const duration = 400;
180
+ d3.select(self)
181
+ .transition()
182
+ .duration(duration)
183
+ .attr('r', config.dotRadius * 2);
184
+ const tooltipShift = 4;
185
+ const tooltipDy = -10;
186
+ g.append('text')
187
+ .attr('class', 'val')
188
+ .style('font-size', '11px')
189
+ .attr('dx', () => (config.width - config.margin.left - config.margin.right) / tooltipShift)
190
+ .attr('dy', () => tooltipDy)
191
+ .text(() => `${d.value} (${new Date(d.timestamp).toUTCString()})`);
192
+ };
193
+ /**
194
+ * The mouse out event handler.
195
+ * @param self an svg circle element
196
+ * @param config the chart configuration
197
+ */
198
+ const onMouseOut = (self, config) => {
199
+ const duration = 400;
200
+ d3.select(self).attr('class', 'dot');
201
+ d3.select(self).transition().duration(duration).attr('r', config.dotRadius);
202
+ d3.selectAll('.val').remove();
203
+ };
204
+ /**
205
+ * Draws the chart lines, dots, and sets the mouse pointer events.
206
+ * @param g the svg g element
207
+ * @param x the x axis scale
208
+ * @param y the y axis scale
209
+ * @param config the chart configuration
210
+ * @param data the chart data
211
+ */
212
+ const drawLinesDotsAndSetPointerEvents = (g, x, y, config, data) => {
213
+ const line = d3
214
+ .line()
215
+ .x(d => x(d.timestamp))
216
+ .y(d => y(d.value))
217
+ .curve(d3.curveMonotoneX);
218
+ g.append('path').attr('id', 'line').style('fill', 'none').style('stroke', 'red').style('stroke-width', '2px').attr('d', line(data));
219
+ g.selectAll('.dot')
220
+ .data(data)
221
+ .enter()
222
+ .append('circle')
223
+ .attr('class', 'dot')
224
+ .style('pointer-events', 'all')
225
+ .style('fill', (d, i) => config.color(i.toString()))
226
+ .on('mouseover', function (event, d) {
227
+ return onMouseOver(this, d, g, config);
228
+ })
229
+ .on('mouseout', function () {
230
+ return onMouseOut(this, config);
231
+ })
232
+ .attr('cx', function (d) {
233
+ return x(d.timestamp);
234
+ })
235
+ .attr('cy', function (d) {
236
+ return y(d.value);
237
+ })
238
+ .attr('r', 0)
239
+ .transition()
240
+ .ease(d3.easeLinear)
241
+ .duration(config.transitionDuration)
242
+ .delay((d, i) => {
243
+ const multiplier = 50;
244
+ return i * multiplier;
245
+ })
246
+ .attr('r', config.dotRadius);
247
+ };
248
+ /**
249
+ * Draws the line chart.
250
+ * @param container the chart container
251
+ * @param data the chart data
252
+ * @param options the chart options
253
+ * @returns the chart configuration
254
+ */
255
+ export const drawLineChart = (container, data, options) => {
256
+ const config = generateConfiguration(defaultLineChartConfig, options, {});
257
+ const { g } = createContainer(container, config);
258
+ const x = d3.scaleTime([0, config.width]).domain([Math.min(...data.map(d => d.timestamp)), Math.max(...data.map(d => d.timestamp))]);
259
+ const y = d3.scaleLinear([config.height, 0]).domain([0, d3.max(data, d => d.value) ?? 1]);
260
+ createAxisX(g, x, config);
261
+ createAxisY(g, y, config);
262
+ createLegend(g, config);
263
+ drawLinesDotsAndSetPointerEvents(g, x, y, config, data);
264
+ return config;
265
+ };
266
+ //# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoibGluZS1jaGFydC51dGlsLmpzIiwic291cmNlUm9vdCI6IiIsInNvdXJjZXMiOlsiLi4vLi4vLi4vLi4vLi4vLi4vbGlicy9jbGllbnQtZDMtY2hhcnRzL3NyYy9saWIvdXRpbC9saW5lLWNoYXJ0LnV0aWwudHMiXSwibmFtZXMiOltdLCJtYXBwaW5ncyI6IkFBQ0EsT0FBTyxLQUFLLEVBQUUsTUFBTSxJQUFJLENBQUM7QUFHekIsT0FBTyxFQUFFLHFCQUFxQixFQUFFLE1BQU0sc0JBQXNCLENBQUM7QUFFN0Q7O0dBRUc7QUFDSCxNQUFNLENBQUMsTUFBTSxzQkFBc0IsR0FBc0IsTUFBTSxDQUFDLE1BQU0sQ0FBb0I7SUFDeEYsVUFBVSxFQUFFLEVBQUU7SUFDZCxLQUFLLEVBQUUsR0FBRztJQUNWLE1BQU0sRUFBRSxHQUFHO0lBQ1gsTUFBTSxFQUFFO1FBQ04sR0FBRyxFQUFFLEVBQUU7UUFDUCxLQUFLLEVBQUUsRUFBRTtRQUNULE1BQU0sRUFBRSxFQUFFO1FBQ1YsSUFBSSxFQUFFLEVBQUU7S0FDVDtJQUNELGtCQUFrQixFQUFFLEdBQUc7SUFDdkIsU0FBUyxFQUFFLEdBQUc7SUFDZCxVQUFVLEVBQUUsRUFBRTtJQUNkLFVBQVUsRUFBRSxFQUFFO0lBQ2QsS0FBSyxFQUFFO1FBQ0wsQ0FBQyxFQUFFLENBQUM7UUFDSixDQUFDLEVBQUUsRUFBRTtLQUNOO0lBQ0QsaUJBQWlCLEVBQUUsSUFBSTtJQUN2QixrQkFBa0IsRUFBRSxFQUFFO0lBQ3RCLEtBQUssRUFBRSxFQUFFLENBQUMsWUFBWSxDQUFDLEVBQUUsQ0FBQyxnQkFBZ0IsQ0FBQztDQUM1QyxDQUFDLENBQUM7QUFFSDs7Ozs7R0FLRztBQUNILE1BQU0sZUFBZSxHQUFHLENBQUMsU0FBcUMsRUFBRSxNQUF5QixFQUFFLEVBQUU7SUFDM0YsTUFBTSxFQUFFLEdBQUcsU0FBUyxDQUFDLGFBQWEsQ0FBQyxFQUFFLElBQUksUUFBUSxDQUFDO0lBRWxELEVBQUUsQ0FBQyxNQUFNLENBQUMsSUFBSSxFQUFFLEVB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LENBQUMsQ0FBQyxFQUFFLENBQUMsRUFBRSxDQUFDLEVBQUUsTUFBTSxFQUFFLElBQUksQ0FBQyxDQUFDO0lBRXhELE9BQU8sTUFBTSxDQUFDO0FBQ2hCLENBQUMsQ0FBQyIsInNvdXJjZXNDb250ZW50IjpbImltcG9ydCB7IEVsZW1lbnRSZWYgfSBmcm9tICdAYW5ndWxhci9jb3JlJztcbmltcG9ydCAqIGFzIGQzIGZyb20gJ2QzJztcblxuaW1wb3J0IHsgSUxpbmVDaGFydERhdGFOb2RlLCBJTGluZUNoYXJ0T3B0aW9ucywgVExpbmVDaGFydERhdGEgfSBmcm9tICcuLi9pbnRlcmZhY2VzL2xpbmUtY2hhcnQuaW50ZXJmYWNlJztcbmltcG9ydCB7IGdlbmVyYXRlQ29uZmlndXJhdGlvbiB9IGZyb20gJy4vY29uZmlndXJhdGlvbi51dGlsJztcblxuLyoqXG4gKiBUaGUgbGluZSBjaGFydCBkZWZhdWx0IGNvbmZpZ3VyYXRpb24uXG4gKi9cbmV4cG9ydCBjb25zdCBkZWZhdWx0TGluZUNoYXJ0Q29uZmlnOiBJTGluZUNoYXJ0T3B0aW9ucyA9IE9iamVjdC5mcmVlemUoPElMaW5lQ2hhcnRPcHRpb25zPntcbiAgY2hhcnRUaXRsZTogJycsXG4gIHdpZHRoOiAzNTAsXG4gIGhlaWdodDogMzUwLFxuICBtYXJnaW46IHtcbiAgICB0b3A6IDcwLFxuICAgIHJpZ2h0OiA1MCxcbiAgICBib3R0b206IDUwLFxuICAgIGxlZnQ6IDUwLFxuICB9LFxuICB0cmFuc2l0aW9uRHVyYXRpb246IDQwMCxcbiAgZG90UmFkaXVzOiAzLjUsXG4gIHhBeGlzVGl0bGU6ICcnLFxuICB5QXhpc1RpdGxlOiAnJyxcbiAgdGlja3M6IHtcbiAgICB4OiA1LFxuICAgIHk6IDEwLFxuICB9LFxuICBkaXNwbGF5QXhpc0xhYmVsczogdHJ1ZSxcbiAgbGFiZWxUZXh0V3JhcFdpZHRoOiAyMCwgLy8gdGhlIG51bWJlciBvZiBwaXhlbHMgYWZ0ZXIgd2hpY2ggYSBsYWJlbCBuZWVkcyB0byBiZSBnaXZlbiBhIG5ldyBsaW5lXG4gIGNvbG9yOiBkMy5zY2FsZU9yZGluYWwoZDMuc2NoZW1lQ2F0ZWdvcnkxMCksXG59KTtcblxuLyoqXG4gKiBDcmVhdGVzIGEgY29udGFpbmVyIGZvciB0aGUgbGluZSBjaGFydC5cbiAqIEBwYXJhbSBjb250YWluZXIgdGhlIGNoYXJ0IGNvbnRhaW5lclxuICogQHBhcmFtIGNvbmZpZyB0aGUgY2hhcnQgY29uZmlndXJhdGlvblxuICogQHJldHVybnMgdGhlIG9iamVjdCB3aXRoIHRoZSBzdmcgZWxlbWVudCBhbmQgdGhlIGcgZWxlbWVudFxuICovXG5jb25zdCBjcmVhdGVDb250YWluZXIgPSAoY29udGFpbmVyOiBFbGVtZW50UmVmPEhUTUxEaXZFbGVtZW50PiwgY29uZmlnOiBJTGluZUNoYXJ0T3B0aW9ucykgPT4ge1xuICBjb25zdCBpZCA9IGNvbnRhaW5lci5uYXRpdmVFbGVtZW50LmlkID8/ICdsaW5lLTAnO1xuXG4gIGQzLnNlbGVjdChgIyR7aWR9YCkuc2VsZWN0KCdzdmcnKS5yZW1vdmUoKTtcbiAgY29uc3Qgc3ZnID0gZDNcbiAgICAuc2VsZWN0KGAjJHtpZH1gKVxuICAgIC5hcHBlbmQoJ3N2ZycpXG4gICAgLmF0dHIoJ3dpZHRoJywgY29uZmlnLndpZHRoICsgY29uZmlnLm1hcmdpbi5sZWZ0ICsgY29uZmlnLm1hcmdpbi5yaWdodClcbiAgICAuYXR0cignaGVpZ2h0JywgY29uZmlnLmhlaWdodCArIGNvbmZpZy5tYXJnaW4udG9wICsgY29uZmlnLm1hcmdpbi5ib3R0b20pXG4gICAgLmF0dHIoJ2NsYXNzJywgaWQpO1xuICBjb25zdCBnID0gc3ZnLmFwcGVuZCgnZycpLmF0dHIoJ3RyYW5zZm9ybScsIGB0cmFuc2xhdGUoJHtjb25maWcubWFyZ2luLmxlZnR9LCR7Y29uZmlnLm1hcmdpbi50b3AgLyAyfSlgKTtcblxuICByZXR1cm4geyBzdmcsIGcgfTtcbn07XG5cbi8qKlxuICogV3JhcHMgdGhlIGxpbmUgY2hhcnQgYXhpcyBsYWJlbHMgdGV4dC5cbiAqIEBwYXJhbSBzdmdUZXh0IHRoZSBzdmcgdGV4dCBlbGVtZW50c1xuICogQHBhcmFtIHdpZHRoIHRoZSBjaGFydCBheGlzIGxhYmVsIHdpZHRoXG4gKi9cbmNvbnN0IHdyYXBTdmdUZXh0ID0gKHN2Z1RleHQ6IGQzLlNlbGVjdGlvbjxkMy5CYXNlVHlwZSwgdW5rbm93biwgU1ZHR0VsZW1lbnQsIHVua25vd24+LCB3aWR0aDogbnVtYmVyKSA9PiB7XG4gIHN2Z1RleHQuZWFjaChmdW5jdGlvbiAodGhpczogZDMuQmFzZVR5cGUpIHtcbiAgICBjb25zdCB0ZXh0ID0gZDMuc2VsZWN0PGQzLkJhc2VUeXBlLCBzdHJpbmc+KHRoaXMpO1xuICAgIGNvbnN0IHdvcmRzID0gdGV4dC50ZXh0KCkuc3BsaXQoL1xccysvKS5yZXZlcnNlKCk7XG4gICAgbGV0IGxpbmU6IHN0cmluZ1tdID0gW107XG4gICAgbGV0IGxpbmVOdW1iZXIgPSAwO1xuICAgIGNvbnN0IGxpbmVIZWlnaHQgPSAxLjQ7XG4gICAgY29uc3QgeSA9IHRleHQuYXR0cigneScpO1xuICAgIGNvbnN0IHggPSB0ZXh0LmF0dHIoJ3gnKTtcbiAgICBjb25zdCBkeSA9IHBhcnNlRmxvYXQodGV4dC5hdHRyKCdkeScpID8/IDApO1xuICAgIGxldCB0c3BhbiA9IHRleHQudGV4dChudWxsKS5hcHBlbmQoJ3RzcGFuJykuYXR0cigneCcsIHgpLmF0dHIoJ3knLCB5KS5hdHRyKCdkeScsIGAke2R5fWVtYCk7IC8vIGF4aXMgbGFiZWxcblxuICAgIGxldCB3b3JkID0gd29yZHMucG9wKCk7XG5cbiAgICB3aGlsZSAodHlwZW9mIHdvcmQgIT09ICd1bmRlZmluZWQnKSB7XG4gICAgICBsaW5lLnB1c2god29yZCA/PyAnJyk7XG4gICAgICB0c3Bhbi50ZXh0KGxpbmUuam9pbignICcpKTtcbiAgICAgIGlmICgodHNwYW4ubm9kZSgpPy5nZXRDb21wdXRlZFRleHRMZW5ndGgoKSA/PyAwKSA+IHdpZHRoKSB7XG4gICAgICAgIGxpbmUucG9wKCk7XG4gICAgICAgIHRzcGFuLnRleHQobGluZS5qb2luKCcgJykpO1xuICAgICAgICBsaW5lID0gW3dvcmQgPz8gJyddO1xuICAgICAgICBsaW5lTnVtYmVyICs9IDE7XG4gICAgICAgIHRzcGFuID0gdGV4dFxuICAgICAgICAgIC5hcHBlbmQoJ3RzcGFuJylcbiAgICAgICAgICAuYXR0cigneCcsIDApXG4gICAgICAgICAgLmF0dHIoJ3knLCB5KVxuICAgICAgICAgIC5hdHRyKCdkeScsIGAke2xpbmVOdW1iZXIgKiBsaW5lSGVpZ2h0ICsgZHl9ZW1gKVxuICAgICAgICAgIC50ZXh0KHdvcmQgPz8gJycpO1xuICAgICAgfVxuICAgICAgd29yZCA9IHdvcmRzLnBvcCgpO1xuICAgIH1cbiAgfSk7XG59O1xuXG4vKipcbiAqIENyZWF0ZXMgdGhlIGxlZ2VuZC5cbiAqIEBwYXJhbSBnIHRoZSBzdmcgZyBlbGVtZW50XG4gKiBAcGFyYW0gY29uZmlnIHRoZSBjaGFydCBjb25maWd1cmF0aW9uXG4gKi9cbmNvbnN0IGNyZWF0ZUxlZ2VuZCA9IChnOiBkMy5TZWxlY3Rpb248U1ZHR0VsZW1lbnQsIHVua25vd24sIEhUTUxFbGVtZW50LCB1bmtub3duPiwgY29uZmlnOiBJTGluZUNoYXJ0T3B0aW9ucykgPT4ge1xuICBpZiAoY29uZmlnLmRpc3BsYXlBeGlzTGFiZWxzICYmIGNvbmZpZy54QXhpc1RpdGxlICE9PSAnJykge1xuICAgIGcuYXBwZW5kKCdnJylcbiAgICAgIC5hdHRyKCd0cmFuc2Zvcm0nLCBgdHJhbnNsYXRlKDAsICR7Y29uZmlnLmhlaWdodCArIGNvbmZpZy5tYXJnaW4uYm90dG9tfSlgKVxuICAgICAgLmFwcGVuZCgndGV4dCcpXG4gICAgICAuc3R5bGUoJ2ZvbnQtc2l6ZScsICcxMnB4JylcbiAgICAgIC5hdHRyKCdjbGFzcycsICdsZWdlbmQnKVxuICAgICAgLmF0dHIoJ2R4JywgJzEuNWVtJylcbiAgICAgIC5hdHRyKCdkeScsICcxZW0nKVxuICAgICAgLnRleHQoYHggLSAke2NvbmZpZy54QXhpc1RpdGxlfWApO1xuICB9XG5cbiAgaWYgKGNvbmZpZy5kaXNwbGF5QXhpc0xhYmVscyAmJiBjb25maWcueUF4aXNUaXRsZSAhPT0gJycpIHtcbiAgICBnLmFwcGVuZCgnZycpXG4gICAgICAuYXR0cigndHJhbnNmb3JtJywgYHRyYW5zbGF0ZSgwLCAke2NvbmZpZy5oZWlnaHQgKyBjb25maWcubWFyZ2luLmJvdHRvbX0pYClcbiAgICAgIC5hcHBlbmQoJ3RleHQnKVxuICAgICAgLnN0eWxlKCdmb250LXNpemUnLCAnMTJweCcpXG4gICAgICAuYXR0cignY2xhc3MnLCAnbGVnZW5kJylcbiAgICAgIC5hdHRyKCdkeCcsICcxLjVlbScpXG4gICAgICAuYXR0cignZHknLCAnMi41ZW0nKVxuICAgICAgLnRleHQoYHkgLSAke2NvbmZpZy55QXhpc1RpdGxlfWApO1xuICB9XG5cbiAgaWYgKGNvbmZpZy5jaGFydFRpdGxlICE9PSAnJykge1xuICAgIGcuYXBwZW5kKCdnJylcbiAgICAgIC5hdHRyKCd0cmFuc2Zvcm0nLCBgdHJhbnNsYXRlKDAsIDApYClcbiAgICAgIC5hcHBlbmQoJ3RleHQnKVxuICAgICAgLnN0eWxlKCdmb250LXNpemUnLCAnMTJweCcpXG4gICAgICAuYXR0cignY2xhc3MnLCAnbGVnZW5kJylcbiAgICAgIC5hdHRyKCdkeCcsICcxLjVlbScpXG4gICAgICAuYXR0cignZHknLCAnLTJlbScpXG4gICAgICAudGV4dChjb25maWcuY2hhcnRUaXRsZSk7XG4gIH1cbn07XG5cbi8qKlxuICogQ3JlYXRlcyB0aGUgeCBheGlzLlxuICogQHBhcmFtIGcgdGhlIHN2ZyBnIGVsZW1lbnRcbiAqIEBwYXJhbSB4IHRoZSB4IGF4aXMgc2NhbGVcbiAqIEBwYXJhbSBjb25maWcgdGhlIGNoYXJ0IGNvbmZpZ3VyYXRpb25cbiAqL1xuY29uc3QgY3JlYXRlQXhpc1ggPSAoXG4gIGc6IGQzLlNlbGVjdGlvbjxTVkdHRWxlbWVudCwgdW5rbm93biwgSFRNTEVsZW1lbnQsIHVua25vd24+LFxuICB4OiBkMy5TY2FsZVRpbWU8bnVtYmVyLCBudW1iZXI+LFxuICBjb25maWc6IElMaW5lQ2hhcnRPcHRpb25zLFxuKSA9PiB7XG4gIGNvbnN0IHhMYWJlbHMgPSBnXG4gICAgLmFwcGVuZCgnZycpXG4gICAgLmF0dHIoJ3RyYW5zZm9ybScsIGB0cmFuc2xhdGUoMCwgJHtjb25maWcuaGVpZ2h0fSlgKVxuICAgIC5jYWxsKFxuICAgICAgZDNcbiAgICAgICAgLmF4aXNCb3R0b20oeClcbiAgICAgICAgLnRpY2tzKGNvbmZpZy50aWNrcy54KVxuICAgICAgICAudGlja0Zvcm1hdChkID0+IHtcbiAgICAgICAgICBjb25zdCBkYXRlID0gbmV3IERhdGUoZC52YWx1ZU9mKCkpO1xuICAgICAgICAgIGNvbnN0IGZvcm1hdHRpbmdPZmZzZXQgPSAxMDtcbiAgICAgICAgICBjb25zdCBkYXkgPSBkYXRlLmdldERhdGUoKTtcbiAgICAgICAgICBjb25zdCBkZCA9IGRheSA8IGZvcm1hdHRpbmdPZmZzZXQgPyBgMCR7ZGF5fWAgOiBkYXk7XG4gICAgICAgICAgY29uc3QgbW9udGggPSBkYXRlLmdldE1vbnRoKCkgKyAxO1xuICAgICAgICAgIGNvbnN0IG1tID0gbW9udGggPCBmb3JtYXR0aW5nT2Zmc2V0ID8gYDAke21vbnRofWAgOiBtb250aDtcbiAgICAgICAgICBjb25zdCB5ZWFyID0gZGF0ZS5nZXRGdWxsWWVhcigpLnRvU3RyaW5nKCk7XG4gICAgICAgICAgY29uc3QgeXkgPSB5ZWFyLnNsaWNlKDIpO1xuICAgICAgICAgIGNvbnN0IGhvdXJzID0gZGF0ZS5nZXRIb3VycygpO1xuICAgICAgICAgIGNvbnN0IGhvdXIgPSBob3VycyA8IGZvcm1hdHRpbmdPZmZzZXQgPyBgMCR7aG91cnN9YCA6IGhvdXJzO1xuICAgICAgICAgIGNvbnN0IG1pbnV0ZXMgPSBkYXRlLmdldE1pbnV0ZXMoKTtcbiAgICAgICAgICBjb25zdCBtaW51dGUgPSBtaW51dGVzIDwgZm9ybWF0dGluZ09mZnNldCA/IGAwJHttaW51dGVzfWAgOiBtaW51dGVzO1xuICAgICAgICAgIHJldHVybiBgJHtkZH0vJHttbX0vJHt5eX0gJHtob3VyfToke21pbnV0ZX1gO1xuICAgICAgICB9KSxcbiAgICApXG4gICAgLmFwcGVuZCgndGV4dCcpO1xuXG4gIGcuc2VsZWN0QWxsKCd0ZXh0JykuY2FsbCh3cmFwU3ZnVGV4dCwgY29uZmlnLmxhYmVsVGV4dFdyYXBXaWR0aCk7XG5cbiAgaWYgKGNvbmZpZy5kaXNwbGF5QXhpc0xhYmVscykge1xuICAgIHhMYWJlbHMuYXR0cigndHJhbnNmb3JtJywgYHRyYW5zbGF0ZSgke2NvbmZpZy53aWR0aH0sIDApYCkuYXR0cignY2xhc3MnLCAnbGVnZW5kJykuYXR0cignZHgnLCAnMS41ZW0nKS5hdHRyKCdkeScsICcwLjdlbScpLnRleHQoJ3gnKTtcbiAgfVxufTtcblxuLyoqXG4gKiBDcmVhdGVzIHRoZSB5IGF4aXMuXG4gKiBAcGFyYW0gZyB0aGUgc3ZnIGcgZWxlbWVudFxuICogQHBhcmFtIHkgdGhlIHkgYXhpcyBzY2FsZVxuICogQHBhcmFtIGNvbmZpZyB0aGUgY2hhcnQgY29uZmlndXJhdGlvblxuICovXG5jb25zdCBjcmVhdGVBeGlzWSA9IChcbiAgZzogZDMuU2VsZWN0aW9uPFNWR0dFbGVtZW50LCB1bmtub3duLCBIVE1MRWxlbWVudCwgdW5rbm93bj4sXG4gIHk6IGQzLlNjYWxlTGluZWFyPG51bWJlciwgbnVtYmVyPixcbiAgY29uZmlnOiBJTGluZUNoYXJ0T3B0aW9ucyxcbikgPT4ge1xuICBjb25zdCB5TGFiZWxzID0gZ1xuICAgIC5hcHBlbmQoJ2cnKVxuICAgIC5jYWxsKFxuICAgICAgZDNcbiAgICAgICAgLmF4aXNMZWZ0KHkpXG4gICAgICAgIC50aWNrcyhjb25maWcudGlja3MueSlcbiAgICAgICAgLnRpY2tGb3JtYXQoZCA9PiBgJHtkfWApLFxuICAgIClcbiAgICAuYXBwZW5kKCd0ZXh0Jyk7XG5cbiAgaWYgKGNvbmZpZy5kaXNwbGF5QXhpc0xhYmVscykge1xuICAgIHlMYWJlbHMuYXR0cignY2xhc3MnLCAnbGVnZW5kJykuYXR0cignZHknLCAnLTEuNWVtJykuYXR0cignY2xhc3MnLCAnbGVnZW5kJykudGV4dCgneScpO1xuICB9XG59O1xuXG4vKipcbiAqIFRoZSBtb3VzZSBvdmVyIGV2ZW50IGhhbmRsZXIuXG4gKiBAcGFyYW0gc2VsZiBhbiBzdmcgY2lyY2xlIGVsZW1lbnRcbiAqIEBwYXJhbSBkIHRoZSBjaGFydCBkYXRhIG5vZGVcbiAqIEBwYXJhbSBnIHRoZSBzdmcgZyBlbGVtZW50XG4gKiBAcGFyYW0gY29uZmlnIHRoZSBjaGFydCBjb25maWd1cmF0aW9uXG4gKi9cbmNvbnN0IG9uTW91c2VPdmVyID0gKFxuICBzZWxmOiBTVkdDaXJjbGVFbGVtZW50LFxuICBkOiBJTGluZUNoYXJ0RGF0YU5vZGUsXG4gIGc6IGQzLlNlbGVjdGlvbjxTVkdHRWxlbWVudCwgdW5rbm93biwgSFRNTEVsZW1lbnQsIHVua25vd24+LFxuICBjb25maWc6IElMaW5lQ2hhcnRPcHRpb25zLFxuKSA9PiB7XG4gIGNvbnN0IGR1cmF0aW9uID0gNDAwO1xuICBkMy5zZWxlY3Qoc2VsZilcbiAgICAudHJhbnNpdGlvbigpXG4gICAgLmR1cmF0aW9uKGR1cmF0aW9uKVxuICAgIC5hdHRyKCdyJywgY29uZmlnLmRvdFJhZGl1cyAqIDIpO1xuXG4gIGNvbnN0IHRvb2x0aXBTaGlmdCA9IDQ7XG4gIGNvbnN0IHRvb2x0aXBEeSA9IC0xMDtcbiAgZy5hcHBlbmQoJ3RleHQnKVxuICAgIC5hdHRyKCdjbGFzcycsICd2YWwnKVxuICAgIC5zdHlsZSgnZm9udC1zaXplJywgJzExcHgnKVxuICAgIC5hdHRyKCdkeCcsICgpID0+IChjb25maWcud2lkdGggLSBjb25maWcubWFyZ2luLmxlZnQgLSBjb25maWcubWFyZ2luLnJpZ2h0KSAvIHRvb2x0aXBTaGlmdClcbiAgICAuYXR0cignZHknLCAoKSA9PiB0b29sdGlwRHkpXG4gICAgLnRleHQoKCkgPT4gYCR7ZC52YWx1ZX0gKCR7bmV3IERhdGUoZC50aW1lc3RhbXApLnRvVVRDU3RyaW5nKCl9KWApO1xufTtcblxuLyoqXG4gKiBUaGUgbW91c2Ugb3V0IGV2ZW50IGhhbmRsZXIuXG4gKiBAcGFyYW0gc2VsZiBhbiBzdmcgY2lyY2xlIGVsZW1lbnRcbiAqIEBwYXJhbSBjb25maWcgdGhlIGNoYXJ0IGNvbmZpZ3VyYXRpb25cbiAqL1xuY29uc3Qgb25Nb3VzZU91dCA9IChzZWxmOiBTVkdDaXJjbGVFbGVtZW50LCBjb25maWc6IElMaW5lQ2hhcnRPcHRpb25zKSA9PiB7XG4gIGNvbnN0IGR1cmF0aW9uID0gNDAwO1xuICBkMy5zZWxlY3Qoc2VsZikuYXR0cignY2xhc3MnLCAnZG90Jyk7XG4gIGQzLnNlbGVjdChzZWxmKS50cmFuc2l0aW9uKCkuZHVyYXRpb24oZHVyYXRpb24pLmF0dHIoJ3InLCBjb25maWcuZG90UmFkaXVzKTtcblxuICBkMy5zZWxlY3RBbGwoJy52YWwnKS5yZW1vdmUoKTtcbn07XG5cbi8qKlxuICogRHJhd3MgdGhlIGNoYXJ0IGxpbmVzLCBkb3RzLCBhbmQgc2V0cyB0aGUgbW91c2UgcG9pbnRlciBldmVudHMuXG4gKiBAcGFyYW0gZyB0aGUgc3ZnIGcgZWxlbWVudFxuICogQHBhcmFtIHggdGhlIHggYXhpcyBzY2FsZVxuICogQHBhcmFtIHkgdGhlIHkgYXhpcyBzY2FsZVxuICogQHBhcmFtIGNvbmZpZyB0aGUgY2hhcnQgY29uZmlndXJhdGlvblxuICogQHBhcmFtIGRhdGEgdGhlIGNoYXJ0IGRhdGFcbiAqL1xuY29uc3QgZHJhd0xpbmVzRG90c0FuZFNldFBvaW50ZXJFdmVudHMgPSAoXG4gIGc6IGQzLlNlbGVjdGlvbjxTVkdHRWxlbWVudCwgdW5rbm93biwgSFRNTEVsZW1lbnQsIHVua25vd24+LFxuICB4OiBkMy5TY2FsZVRpbWU8bnVtYmVyLCBudW1iZXI+LFxuICB5OiBkMy5TY2FsZUxpbmVhcjxudW1iZXIsIG51bWJlcj4sXG4gIGNvbmZpZzogSUxpbmVDaGFydE9wdGlvbnMsXG4gIGRhdGE6IFRMaW5lQ2hhcnREYXRhLFxuKSA9PiB7XG4gIGNvbnN0IGxpbmUgPSBkM1xuICAgIC5saW5lPElMaW5lQ2hhcnREYXRhTm9kZT4oKVxuICAgIC54KGQgPT4geChkLnRpbWVzdGFtcCkpXG4gICAgLnkoZCA9PiB5KGQudmFsdWUpKVxuICAgIC5jdXJ2ZShkMy5jdXJ2ZU1vbm90b25lWCk7XG5cbiAgZy5hcHBlbmQoJ3BhdGgnKS5hdHRyKCdpZCcsICdsaW5lJykuc3R5bGUoJ2ZpbGwnLCAnbm9uZScpLnN0eWxlKCdzdHJva2UnLCAncmVkJykuc3R5bGUoJ3N0cm9rZS13aWR0aCcsICcycHgnKS5hdHRyKCdkJywgbGluZShkYXRhKSk7XG5cbiAgZy5zZWxlY3RBbGwoJy5kb3QnKVxuICAgIC5kYXRhKGRhdGEpXG4gICAgLmVudGVyKClcbiAgICAuYXBwZW5kKCdjaXJjbGUnKVxuICAgIC5hdHRyKCdjbGFzcycsICdkb3QnKVxuICAgIC5zdHlsZSgncG9pbnRlci1ldmVudHMnLCAnYWxsJylcbiAgICAuc3R5bGUoJ2ZpbGwnLCAoZCwgaSkgPT4gY29uZmlnLmNvbG9yKGkudG9TdHJpbmcoKSkpXG4gICAgLm9uKCdtb3VzZW92ZXInLCBmdW5jdGlvbiAodGhpcywgZXZlbnQsIGQpIHtcbiAgICAgIHJldHVybiBvbk1vdXNlT3Zlcih0aGlzLCBkLCBnLCBjb25maWcpO1xuICAgIH0pXG4gICAgLm9uKCdtb3VzZW91dCcsIGZ1bmN0aW9uICh0aGlzKSB7XG4gICAgICByZXR1cm4gb25Nb3VzZU91dCh0aGlzLCBjb25maWcpO1xuICAgIH0pXG4gICAgLmF0dHIoJ2N4JywgZnVuY3Rpb24gKHRoaXMsIGQpIHtcbiAgICAgIHJldHVybiB4KGQudGltZXN0YW1wKTtcbiAgICB9KVxuICAgIC5hdHRyKCdjeScsIGZ1bmN0aW9uICh0aGlzLCBkKSB7XG4gICAgICByZXR1cm4geShkLnZhbHVlKTtcbiAgICB9KVxuICAgIC5hdHRyKCdyJywgMClcbiAgICAudHJhbnNpdGlvbigpXG4gICAgLmVhc2UoZDMuZWFzZUxpbmVhcilcbiAgICAuZHVyYXRpb24oY29uZmlnLnRyYW5zaXRpb25EdXJhdGlvbilcbiAgICAuZGVsYXkoKGQsIGkpID0+IHtcbiAgICAgIGNvbnN0IG11bHRpcGxpZXIgPSA1MDtcbiAgICAgIHJldHVybiBpICogbXVsdGlwbGllcjtcbiAgICB9KVxuICAgIC5hdHRyKCdyJywgY29uZmlnLmRvdFJhZGl1cyk7XG59O1xuXG4vKipcbiAqIERyYXdzIHRoZSBsaW5lIGNoYXJ0LlxuICogQHBhcmFtIGNvbnRhaW5lciB0aGUgY2hhcnQgY29udGFpbmVyXG4gKiBAcGFyYW0gZGF0YSB0aGUgY2hhcnQgZGF0YVxuICogQHBhcmFtIG9wdGlvbnMgdGhlIGNoYXJ0IG9wdGlvbnNcbiAqIEByZXR1cm5zIHRoZSBjaGFydCBjb25maWd1cmF0aW9uXG4gKi9cbmV4cG9ydCBjb25zdCBkcmF3TGluZUNoYXJ0ID0gKGNvbnRhaW5lcjogRWxlbWVudFJlZjxIVE1MRGl2RWxlbWVudD4sIGRhdGE6IFRMaW5lQ2hhcnREYXRhLCBvcHRpb25zPzogUGFydGlhbDxJTGluZUNoYXJ0T3B0aW9ucz4pID0+IHtcbiAgY29uc3QgY29uZmlnOiBJTGluZUNoYXJ0T3B0aW9ucyA9IGdlbmVyYXRlQ29uZmlndXJhdGlvbjxJTGluZUNoYXJ0T3B0aW9ucz4oZGVmYXVsdExpbmVDaGFydENvbmZpZywgb3B0aW9ucywge30pO1xuXG4gIGNvbnN0IHsgZyB9ID0gY3JlYXRlQ29udGFpbmVyKGNvbnRhaW5lciwgY29uZmlnKTtcblxuICBjb25zdCB4ID0gZDMuc2NhbGVUaW1lKFswLCBjb25maWcud2lkdGhdKS5kb21haW4oW01hdGgubWluKC4uLmRhdGEubWFwKGQgPT4gZC50aW1lc3RhbXApKSwgTWF0aC5tYXgoLi4uZGF0YS5tYXAoZCA9PiBkLnRpbWVzdGFtcCkpXSk7XG4gIGNvbnN0IHkgPSBkMy5zY2FsZUxpbmVhcihbY29uZmlnLmhlaWdodCwgMF0pLmRvbWFpbihbMCwgZDMubWF4KGRhdGEsIGQgPT4gZC52YWx1ZSkgPz8gMV0pO1xuXG4gIGNyZWF0ZUF4aXNYKGcsIHgsIGNvbmZpZyk7XG5cbiAgY3JlYXRlQXhpc1koZywgeSwgY29uZmlnKTtcblxuICBjcmVhdGVMZWdlbmQoZywgY29uZmlnKTtcblxuICBkcmF3TGluZXNEb3RzQW5kU2V0UG9pbnRlckV2ZW50cyhnLCB4LCB5LCBjb25maWcsIGRhdGEpO1xuXG4gIHJldHVybiBjb25maWc7XG59O1xuIl19
@@ -0,0 +1,89 @@
1
+ import * as d3 from 'd3';
2
+ import { generateConfiguration } from './configuration.util';
3
+ /**
4
+ * The pie chart default configuration.
5
+ */
6
+ export const defaultPieChartConfig = Object.freeze({
7
+ chartTitle: '',
8
+ width: 600,
9
+ height: 600,
10
+ margin: {
11
+ top: 20,
12
+ right: 20,
13
+ bottom: 20,
14
+ left: 20,
15
+ },
16
+ innerRadius: 0,
17
+ labelRadiusModifier: 50,
18
+ labelTextWrapWidth: 60,
19
+ color: d3.scaleOrdinal(d3.schemeCategory10),
20
+ });
21
+ /**
22
+ * Creates a container for the pie chart.
23
+ * @param container the chart container
24
+ * @param config the chart configuration
25
+ * @returns the object with the svg element and the g element
26
+ */
27
+ const createContainer = (container, config) => {
28
+ const id = container.nativeElement.id ?? 'pie-0';
29
+ d3.select(`#${id}`).select('svg').remove();
30
+ const svg = d3
31
+ .select(`#${id}`)
32
+ .append('svg')
33
+ .attr('width', config.width + config.margin.left + config.margin.right)
34
+ .attr('height', config.height + config.margin.top + config.margin.bottom)
35
+ .attr('class', id);
36
+ const g = svg
37
+ .append('g')
38
+ .attr('transform', `translate(${config.width / 2 + config.margin.left},${config.height / 2 + config.margin.top})`);
39
+ return { svg, g };
40
+ };
41
+ /**
42
+ * Draws the pie chart.
43
+ * @param container the chart container
44
+ * @param data the chart data
45
+ * @param options the chart options
46
+ * @returns the chart configuration
47
+ */
48
+ export const drawPieChart = (container, data, options) => {
49
+ const config = generateConfiguration(defaultPieChartConfig, options, {});
50
+ const { g } = createContainer(container, config);
51
+ const pie = d3.pie().value(datum => datum.y);
52
+ const radius = Math.min(config.width, config.height) / 2;
53
+ const arc = d3.arc().innerRadius(config.innerRadius).outerRadius(radius);
54
+ const arcs = g
55
+ .selectAll('arc')
56
+ .data(pie(data))
57
+ .enter()
58
+ .append('g')
59
+ .attr('class', 'arc')
60
+ .on('mouseover', function (event, d) {
61
+ d3.select('#tooltip')
62
+ .style('left', `${event.pageX}px`)
63
+ .style('top', `${event.pageY}px`)
64
+ .style('opacity', 1)
65
+ .select('#value')
66
+ .text(d.value);
67
+ })
68
+ .on('mouseout', function (event, d) {
69
+ d3.select('#tooltip').style('opacity', 0);
70
+ });
71
+ const label = d3
72
+ .arc()
73
+ .innerRadius(radius)
74
+ .outerRadius(radius + config.labelRadiusModifier);
75
+ arcs
76
+ .append('path')
77
+ .attr('fill', (d, i) => config.color(i.toString()))
78
+ .attr('d', arc);
79
+ const textDy = 5;
80
+ arcs
81
+ .append('text')
82
+ .attr('class', 'legend')
83
+ .attr('text-anchor', 'middle')
84
+ .attr('dy', textDy)
85
+ .attr('transform', d => `translate(${label.centroid(d)})`)
86
+ .text(d => d.data.y);
87
+ return config;
88
+ };
89
+ //# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoicGllLWNoYXJ0LnV0aWwuanMiLCJzb3VyY2VSb290IjoiIiwic291cmNlcyI6WyIuLi8uLi8uLi8uLi8uLi8uLi9saWJzL2NsaWVudC1kMy1jaGFydHMvc3JjL2xpYi91dGlsL3BpZS1jaGFydC51dGlsLnRzIl0sIm5hbWVzIjpbXSwibWFwcGluZ3MiOiJBQUNBLE9BQU8sS0FBSyxFQUFFLE1BQU0sSUFBSSxDQUFDO0FBR3pCLE9BQU8sRUFBRSxxQkFBcUIsRUFBRSxNQUFNLHNCQUFzQixDQUFDO0FBRTdEOztHQUVHO0FBQ0gsTUFBTSxDQUFDLE1BQU0scUJBQXFCLEdBQXFCLE1BQU0sQ0FBQyxNQUFNLENBQUM7SUFDbkUsVUFBVSxFQUFFLEVBQUU7SUFDZCxLQUFLLEVBQUUsR0FBRztJQUNWLE1BQU0sRUFBRSxHQUFHO0lBQ1gsTUFBTSxFQUFFO1FBQ04sR0FBRyxFQUFFLEVBQUU7UUFDUCxLQUFLLEVBQUUsRUFBRTtRQUNULE1BQU0sRUFBRSxFQUFFO1FBQ1YsSUFBSSxFQUFFLEVBQUU7S0FDVDtJQUNELFdBQVcsRUFBRSxDQUFDO0lBQ2QsbUJBQW1CLEVBQUUsRUFBRTtJQUN2QixrQkFBa0IsRUFBRSxFQUFFO0lBQ3RCLEtBQUssRUFBRSxFQUFFLENBQUMsWUFBWSxDQUFDLEVBQUUsQ0FBQyxnQkFBZ0IsQ0FBQztDQUM1QyxDQUFDLENBQUM7QUFFSDs7Ozs7R0FLRztBQUNILE1BQU0sZUFBZSxHQUFHLENBQUMsU0FBcUMsRUFBRSxNQUF3QixFQUFFLEVBQUU7SUFDMUYsTUFBTSxFQUFFLEdBQUcsU0FBUyxDQUFDLGFBQWEsQ0FBQyxFQUFFLElBQUksT0FBTyxDQUFDO0lBRWpELEVBQUUsQ0FBQyxNQUFNLENBQUMsSUFBSSxFQUFFLEVBQUUsQ0FBQyxDQUFDLE1BQU0sQ0FBQyxLQUFLLENBQUMsQ0FBQyxNQUFNLEVBQUUsQ0FBQztJQUMzQyxNQUFNLEdBQUcsR0FBRyxFQUFFO1NBQ1gsTUFBTSxDQUFDLElBQUksRUFBRSxFQUFFLENBQUM7U0FDaEIsTUFBTSxD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Q0FBQyxDQUFDO0lBRXBELElBQUk7U0FDRCxNQUFNLENBQUMsTUFBTSxDQUFDO1NBQ2QsSUFBSSxDQUFDLE1BQU0sRUFBRSxDQUFDLENBQUMsRUFBRSxDQUFDLEVBQUUsRUFBRSxDQUFDLE1BQU0sQ0FBQyxLQUFLLENBQUMsQ0FBQyxDQUFDLFFBQVEsRUFBRSxDQUFDLENBQUM7U0FDbEQsSUFBSSxDQUFDLEdBQUcsRUFBRSxHQUFHLENBQUMsQ0FBQztJQUVsQixNQUFNLE1BQU0sR0FBRyxDQUFDLENBQUM7SUFDakIsSUFBSTtTQUNELE1BQU0sQ0FBQyxNQUFNLENBQUM7U0FDZCxJQUFJLENBQUMsT0FBTyxFQUFFLFFBQVEsQ0FBQztTQUN2QixJQUFJLENBQUMsYUFBYSxFQUFFLFFBQVEsQ0FBQztTQUM3QixJQUFJLENBQUMsSUFBSSxFQUFFLE1BQU0sQ0FBQztTQUNsQixJQUFJLENBQUMsV0FBVyxFQUFFLENBQUMsQ0FBQyxFQUFFLENBQUMsYUFBYSxLQUFLLENBQUMsUUFBUSxDQUFDLENBQUMsQ0FBQyxHQUFHLENBQUM7U0FDekQsSUFBSSxDQUFDLENBQUMsQ0FBQyxFQUFFLENBQUMsQ0FBQyxDQUFDLElBQUksQ0FBQyxDQUFDLENBQUMsQ0FBQztJQUV2QixPQUFPLE1BQU0sQ0FBQztBQUNoQixDQUFDLENBQUMiLCJzb3VyY2VzQ29udGVudCI6WyJpbXBvcnQgeyBFbGVtZW50UmVmIH0gZnJvbSAnQGFuZ3VsYXIvY29yZSc7XG5pbXBvcnQgKiBhcyBkMyBmcm9tICdkMyc7XG5cbmltcG9ydCB7IElQaWVDaGFydERhdGFOb2RlLCBJUGllQ2hhcnRPcHRpb25zIH0gZnJvbSAnLi4vaW50ZXJmYWNlcy9waWUtY2hhcnQuaW50ZXJmYWNlJztcbmltcG9ydCB7IGdlbmVyYXRlQ29uZmlndXJhdGlvbiB9IGZyb20gJy4vY29uZmlndXJhdGlvbi51dGlsJztcblxuLyoqXG4gKiBUaGUgcGllIGNoYXJ0IGRlZmF1bHQgY29uZmlndXJhdGlvbi5cbiAqL1xuZXhwb3J0IGNvbnN0IGRlZmF1bHRQaWVDaGFydENvbmZpZzogSVBpZUNoYXJ0T3B0aW9ucyA9IE9iamVjdC5mcmVlemUoe1xuICBjaGFydFRpdGxlOiAnJyxcbiAgd2lkdGg6IDYwMCxcbiAgaGVpZ2h0OiA2MDAsXG4gIG1hcmdpbjoge1xuICAgIHRvcDogMjAsXG4gICAgcmlnaHQ6IDIwLFxuICAgIGJvdHRvbTogMjAsXG4gICAgbGVmdDogMjAsXG4gIH0sXG4gIGlubmVyUmFkaXVzOiAwLCAvLyBpbmNyZWFzZSBpbm5lciByYWRpdXMgdG8gcmVuZGVyIGEgZG9udXQgY2hhcnRcbiAgbGFiZWxSYWRpdXNNb2RpZmllcjogNTAsXG4gIGxhYmVsVGV4dFdyYXBXaWR0aDogNjAsXG4gIGNvbG9yOiBkMy5zY2FsZU9yZGluYWwoZDMuc2NoZW1lQ2F0ZWdvcnkxMCksXG59KTtcblxuLyoqXG4gKiBDcmVhdGVzIGEgY29udGFpbmVyIGZvciB0aGUgcGllIGNoYXJ0LlxuICogQHBhcmFtIGNvbnRhaW5lciB0aGUgY2hhcnQgY29udGFpbmVyXG4gKiBAcGFyYW0gY29uZmlnIHRoZSBjaGFydCBjb25maWd1cmF0aW9uXG4gKiBAcmV0dXJucyB0aGUgb2JqZWN0IHdpdGggdGhlIHN2ZyBlbGVtZW50IGFuZCB0aGUgZyBlbGVtZW50XG4gKi9cbmNvbnN0IGNyZWF0ZUNvbnRhaW5lciA9IChjb250YWluZXI6IEVsZW1lbnRSZWY8SFRNTERpdkVsZW1lbnQ+LCBjb25maWc6IElQaWVDaGFydE9wdGlvbnMpID0+IHtcbiAgY29uc3QgaWQgPSBjb250YWluZXIubmF0aXZlRWxlbWVudC5pZCA/PyAncGllLTAnO1xuXG4gIGQzLnNlbGVjdChgIyR7aWR9YCkuc2VsZWN0KCdzdmcnKS5yZW1vdmUoKTtcbiAgY29uc3Qgc3ZnID0gZDNcbiAgICAuc2VsZWN0KGAjJHtpZH1gKVxuICAgIC5hcHBlbmQoJ3N2ZycpXG4gICAgLmF0dHIoJ3dpZHRoJywgY29uZmlnLndpZHRoICsgY29uZmlnLm1hcmdpbi5sZWZ0ICsgY29uZmlnLm1hcmdpbi5yaWdodClcbiAgICAuYXR0cignaGVpZ2h0JywgY29uZmlnLmhlaWdodCArIGNvbmZpZy5tYXJnaW4udG9wICsgY29uZmlnLm1hcmdpbi5ib3R0b20pXG4gICAgLmF0dHIoJ2NsYXNzJywgaWQpO1xuICBjb25zdCBnID0gc3ZnXG4gICAgLmFwcGVuZCgnZycpXG4gICAgLmF0dHIoJ3RyYW5zZm9ybScsIGB0cmFuc2xhdGUoJHtjb25maWcud2lkdGggLyAyICsgY29uZmlnLm1hcmdpbi5sZWZ0fSwke2NvbmZpZy5oZWlnaHQgLyAyICsgY29uZmlnLm1hcmdpbi50b3B9KWApO1xuXG4gIHJldHVybiB7IHN2ZywgZyB9O1xufTtcblxuLyoqXG4gKiBEcmF3cyB0aGUgcGllIGNoYXJ0LlxuICogQHBhcmFtIGNvbnRhaW5lciB0aGUgY2hhcnQgY29udGFpbmVyXG4gKiBAcGFyYW0gZGF0YSB0aGUgY2hhcnQgZGF0YVxuICogQHBhcmFtIG9wdGlvbnMgdGhlIGNoYXJ0IG9wdGlvbnNcbiAqIEByZXR1cm5zIHRoZSBjaGFydCBjb25maWd1cmF0aW9uXG4gKi9cbmV4cG9ydCBjb25zdCBkcmF3UGllQ2hhcnQgPSAoY29udGFpbmVyOiBFbGVtZW50UmVmPEhUTUxEaXZFbGVtZW50PiwgZGF0YTogSVBpZUNoYXJ0RGF0YU5vZGVbXSwgb3B0aW9ucz86IFBhcnRpYWw8SVBpZUNoYXJ0T3B0aW9ucz4pID0+IHtcbiAgY29uc3QgY29uZmlnOiBJUGllQ2hhcnRPcHRpb25zID0gZ2VuZXJhdGVDb25maWd1cmF0aW9uPElQaWVDaGFydE9wdGlvbnM+KGRlZmF1bHRQaWVDaGFydENvbmZpZywgb3B0aW9ucywge30pO1xuXG4gIGNvbnN0IHsgZyB9ID0gY3JlYXRlQ29udGFpbmVyKGNvbnRhaW5lciwgY29uZmlnKTtcblxuICBjb25zdCBwaWUgPSBkMy5waWU8SVBpZUNoYXJ0RGF0YU5vZGU+KCkudmFsdWUoZGF0dW0gPT4gZGF0dW0ueSk7XG5cbiAgY29uc3QgcmFkaXVzID0gTWF0aC5taW4oY29uZmlnLndpZHRoLCBjb25maWcuaGVpZ2h0KSAvIDI7XG5cbiAgY29uc3QgYXJjID0gZDMuYXJjPGQzLlBpZUFyY0RhdHVtPElQaWVDaGFydERhdGFOb2RlPj4oKS5pbm5lclJhZGl1cyhjb25maWcuaW5uZXJSYWRpdXMpLm91dGVyUmFkaXVzKHJhZGl1cyk7XG5cbiAgY29uc3QgYXJjcyA9IGdcbiAgICAuc2VsZWN0QWxsKCdhcmMnKVxuICAgIC5kYXRhKHBpZShkYXRhKSlcbiAgICAuZW50ZXIoKVxuICAgIC5hcHBlbmQoJ2cnKVxuICAgIC5hdHRyKCdjbGFzcycsICdhcmMnKVxuICAgIC5vbignbW91c2VvdmVyJywgZnVuY3Rpb24gKHRoaXMsIGV2ZW50OiBNb3VzZUV2ZW50LCBkKSB7XG4gICAgICBkMy5zZWxlY3QoJyN0b29sdGlwJylcbiAgICAgICAgLnN0eWxlKCdsZWZ0JywgYCR7ZXZlbnQucGFnZVh9cHhgKVxuICAgICAgICAuc3R5bGUoJ3RvcCcsIGAke2V2ZW50LnBhZ2VZfXB4YClcbiAgICAgICAgLnN0eWxlKCdvcGFjaXR5JywgMSlcbiAgICAgICAgLnNlbGVjdCgnI3ZhbHVlJylcbiAgICAgICAgLnRleHQoZC52YWx1ZSk7XG4gICAgfSlcbiAgICAub24oJ21vdXNlb3V0JywgZnVuY3Rpb24gKHRoaXMsIGV2ZW50LCBkKSB7XG4gICAgICBkMy5zZWxlY3QoJyN0b29sdGlwJykuc3R5bGUoJ29wYWNpdHknLCAwKTtcbiAgICB9KTtcblxuICBjb25zdCBsYWJlbCA9IGQzXG4gICAgLmFyYzxkMy5QaWVBcmNEYXR1bTxJUGllQ2hhcnREYXRhTm9kZT4+KClcbiAgICAuaW5uZXJSYWRpdXMocmFkaXVzKVxuICAgIC5vdXRlclJhZGl1cyhyYWRpdXMgKyBjb25maWcubGFiZWxSYWRpdXNNb2RpZmllcik7XG5cbiAgYXJjc1xuICAgIC5hcHBlbmQoJ3BhdGgnKVxuICAgIC5hdHRyKCdmaWxsJywgKGQsIGkpID0+IGNvbmZpZy5jb2xvcihpLnRvU3RyaW5nKCkpKVxuICAgIC5hdHRyKCdkJywgYXJjKTtcblxuICBjb25zdCB0ZXh0RHkgPSA1O1xuICBhcmNzXG4gICAgLmFwcGVuZCgndGV4dCcpXG4gICAgLmF0dHIoJ2NsYXNzJywgJ2xlZ2VuZCcpXG4gICAgLmF0dHIoJ3RleHQtYW5jaG9yJywgJ21pZGRsZScpXG4gICAgLmF0dHIoJ2R5JywgdGV4dER5KVxuICAgIC5hdHRyKCd0cmFuc2Zvcm0nLCBkID0+IGB0cmFuc2xhdGUoJHtsYWJlbC5jZW50cm9pZChkKX0pYClcbiAgICAudGV4dChkID0+IGQuZGF0YS55KTtcblxuICByZXR1cm4gY29uZmlnO1xufTtcbiJdfQ==