@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,1868 @@
1
+ import * as i2 from '@angular/common';
2
+ import { DOCUMENT, CommonModule } from '@angular/common';
3
+ import * as i0 from '@angular/core';
4
+ import { InjectionToken, Component, ChangeDetectionStrategy, Inject, Input, ViewChild, NgModule } from '@angular/core';
5
+ import * as d3 from 'd3';
6
+ import * as i1 from '@angular/cdk/layout';
7
+ import { Breakpoints } from '@angular/cdk/layout';
8
+ import { map, switchMap, timer, first } from 'rxjs';
9
+
10
+ /**
11
+ * Generates a configuration object based on a defaut configuration and an options object.
12
+ * @param config the default object with all properties
13
+ * @param options the input object
14
+ * @param result the output object
15
+ */
16
+ const generateConfiguration = (config, options, result) => {
17
+ const defaultConfiguration = config;
18
+ if (typeof options === 'undefined') {
19
+ return config;
20
+ }
21
+ const keys = Object.keys(defaultConfiguration);
22
+ for (const key of keys) {
23
+ const defaultValue = defaultConfiguration[key];
24
+ const value = options[key];
25
+ const typedKey = key;
26
+ if (typeof defaultValue === 'string' || typeof defaultValue === 'number' || typeof defaultValue === 'boolean') {
27
+ result[typedKey] = typeof value !== 'undefined' ? value : defaultValue;
28
+ }
29
+ else if (defaultValue instanceof Function) {
30
+ result[typedKey] = defaultValue;
31
+ }
32
+ else if (typeof defaultValue === 'object' && defaultValue !== null) {
33
+ const nestedDefaultObject = defaultValue;
34
+ const nestedObject = value;
35
+ result[typedKey] = generateConfiguration(nestedDefaultObject, nestedObject, {});
36
+ }
37
+ }
38
+ return result;
39
+ };
40
+
41
+ /**
42
+ * The bar chart default configuration.
43
+ */
44
+ const defaultBarChartConfig = Object.freeze({
45
+ chartTitle: '',
46
+ width: 350,
47
+ height: 350,
48
+ margin: {
49
+ top: 70,
50
+ right: 50,
51
+ bottom: 50,
52
+ left: 50,
53
+ },
54
+ transitionDuration: 400,
55
+ xAxisPadding: 0.4,
56
+ xAxisTitle: '',
57
+ yAxisTitle: '',
58
+ yAxisTicks: 10,
59
+ displayAxisLabels: true,
60
+ labelTextWrapWidth: 60,
61
+ color: d3.scaleOrdinal(d3.schemeCategory10),
62
+ });
63
+ /**
64
+ * Creates a container for the bar chart.
65
+ * @param container the chart container
66
+ * @param config the chart configuration
67
+ * @returns the object with the svg element and the g element
68
+ */
69
+ const createContainer$4 = (container, config) => {
70
+ var _a;
71
+ const id = (_a = container.nativeElement.id) !== null && _a !== void 0 ? _a : 'bar-0';
72
+ d3.select(`#${id}`).select('svg').remove();
73
+ const svg = d3
74
+ .select(`#${id}`)
75
+ .append('svg')
76
+ .attr('width', config.width + config.margin.left + config.margin.right)
77
+ .attr('height', config.height + config.margin.top + config.margin.bottom)
78
+ .attr('class', id);
79
+ const g = svg.append('g').attr('transform', `translate(${config.margin.left},${config.margin.top / 2})`);
80
+ return { svg, g };
81
+ };
82
+ /**
83
+ * Wraps the bar chart axis labels text.
84
+ * @param svgText the svg text elements
85
+ * @param width the chart axis label width
86
+ */
87
+ const wrapSvgText$2 = (svgText, width) => {
88
+ svgText.each(function () {
89
+ var _a, _b, _c;
90
+ const text = d3.select(this);
91
+ const words = text.text().split(/\s+/).reverse();
92
+ let line = [];
93
+ let lineNumber = 0;
94
+ const lineHeight = 1.4;
95
+ const y = text.attr('y');
96
+ const x = text.attr('x');
97
+ const dy = parseFloat((_a = text.attr('dy')) !== null && _a !== void 0 ? _a : 0);
98
+ let tspan = text.text(null).append('tspan').attr('x', x).attr('y', y).attr('dy', `${dy}em`); // axis label
99
+ let word = words.pop();
100
+ while (typeof word !== 'undefined') {
101
+ line.push(word !== null && word !== void 0 ? word : '');
102
+ tspan.text(line.join(' '));
103
+ if (((_c = (_b = tspan.node()) === null || _b === void 0 ? void 0 : _b.getComputedTextLength()) !== null && _c !== void 0 ? _c : 0) > width) {
104
+ line.pop();
105
+ tspan.text(line.join(' '));
106
+ line = [word !== null && word !== void 0 ? word : ''];
107
+ lineNumber += 1;
108
+ tspan = text
109
+ .append('tspan')
110
+ .attr('x', 0)
111
+ .attr('y', y)
112
+ .attr('dy', `${lineNumber * lineHeight + dy}em`)
113
+ .text(word !== null && word !== void 0 ? word : '');
114
+ }
115
+ word = words.pop();
116
+ }
117
+ });
118
+ };
119
+ /**
120
+ * Creates the legend.
121
+ * @param g the svg g element
122
+ * @param config the chart configuration
123
+ */
124
+ const createLegend$2 = (g, config) => {
125
+ if (config.displayAxisLabels && config.xAxisTitle !== '') {
126
+ g.append('g')
127
+ .attr('transform', `translate(0, ${config.height + config.margin.bottom})`)
128
+ .append('text')
129
+ .style('font-size', '12px')
130
+ .attr('class', 'legend')
131
+ .attr('dx', '1.5em')
132
+ .attr('dy', '1em')
133
+ .text(`x - ${config.xAxisTitle}`);
134
+ }
135
+ if (config.displayAxisLabels && config.yAxisTitle !== '') {
136
+ g.append('g')
137
+ .attr('transform', `translate(0, ${config.height + config.margin.bottom})`)
138
+ .append('text')
139
+ .style('font-size', '12px')
140
+ .attr('class', 'legend')
141
+ .attr('dx', '1.5em')
142
+ .attr('dy', '2.5em')
143
+ .text(`y - ${config.yAxisTitle}`);
144
+ }
145
+ if (config.chartTitle !== '') {
146
+ g.append('g')
147
+ .attr('transform', `translate(0, 0)`)
148
+ .append('text')
149
+ .style('font-size', '12px')
150
+ .attr('class', 'legend')
151
+ .attr('dx', '1.5em')
152
+ .attr('dy', '-2em')
153
+ .text(config.chartTitle);
154
+ }
155
+ };
156
+ /**
157
+ * Creates the x axis.
158
+ * @param g the svg g element
159
+ * @param x the x axis scale
160
+ * @param config the chart configuration
161
+ */
162
+ const createAxisX$1 = (g, x, config) => {
163
+ const xLabels = g.append('g').attr('transform', `translate(0, ${config.height})`).call(d3.axisBottom(x)).append('text');
164
+ g.selectAll('text').call(wrapSvgText$2, config.labelTextWrapWidth);
165
+ if (config.displayAxisLabels) {
166
+ xLabels.attr('transform', `translate(${config.width}, 0)`).attr('class', 'legend').attr('dx', '1.5em').attr('dy', '0.7em').text('x');
167
+ }
168
+ };
169
+ /**
170
+ * Creates the y axis.
171
+ * @param g the svg g element
172
+ * @param y the y axis scale
173
+ * @param config the chart configuration
174
+ */
175
+ const createAxisY$1 = (g, y, config) => {
176
+ const yLabels = g
177
+ .append('g')
178
+ .call(d3
179
+ .axisLeft(y)
180
+ .tickFormat(function (d) {
181
+ return `${d}`;
182
+ })
183
+ .ticks(config.yAxisTicks))
184
+ .append('text');
185
+ if (config.displayAxisLabels) {
186
+ yLabels.attr('dy', '-1.5em').attr('class', 'legend').text('y');
187
+ }
188
+ };
189
+ /**
190
+ * The mouse over event handler.
191
+ * @param self an svg rect element
192
+ * @param d the chart data node
193
+ * @param g the svg g element
194
+ * @param x the x axis scale
195
+ * @param y the y axis scale
196
+ * @param config the chart configuration
197
+ */
198
+ const onMouseOver$1 = (self, d, g, x, y, config) => {
199
+ const widthModifier = 5;
200
+ d3.select(self)
201
+ .transition()
202
+ .duration(config.transitionDuration)
203
+ .attr('width', x.bandwidth() + widthModifier)
204
+ .attr('y', function () {
205
+ const modifier = 10;
206
+ return y(d.value) - modifier;
207
+ })
208
+ .attr('height', function () {
209
+ const modifier = 10;
210
+ return config.height - y(d.value) + modifier;
211
+ });
212
+ g.append('text')
213
+ .attr('class', 'val')
214
+ .style('font-size', '11px')
215
+ .attr('x', () => { var _a; return (_a = x(d.title)) !== null && _a !== void 0 ? _a : ''; })
216
+ .attr('y', function () {
217
+ const modifier = 15;
218
+ return y(d.value) - modifier;
219
+ })
220
+ .text(() => d.value);
221
+ };
222
+ /**
223
+ * The mouse out event handler.
224
+ * @param self an svg rect element
225
+ * @param d the chart data node
226
+ * @param x the x axis scale
227
+ * @param y the y axis scale
228
+ * @param config the chart configuration
229
+ */
230
+ const onMouseOut$1 = (self, d, x, y, config) => {
231
+ d3.select(self).attr('class', 'bar');
232
+ d3.select(self)
233
+ .transition()
234
+ .duration(config.transitionDuration)
235
+ .attr('width', x.bandwidth())
236
+ .attr('y', () => { var _a; return (_a = y(d.value)) !== null && _a !== void 0 ? _a : 0; })
237
+ .attr('height', () => { var _a; return config.height - ((_a = y(d.value)) !== null && _a !== void 0 ? _a : 0); });
238
+ d3.selectAll('.val').remove();
239
+ };
240
+ /**
241
+ * Draws the chart bars, and sets the mouse pointer events.
242
+ * @param g the svg g element
243
+ * @param x the x axis scale
244
+ * @param y the y axis scale
245
+ * @param config the chart configuration
246
+ * @param data the chart data
247
+ */
248
+ const drawBarsAndSetPointerEvents = (g, x, y, config, data) => {
249
+ const duration = 400;
250
+ g.selectAll('.bar')
251
+ .data(data)
252
+ .enter()
253
+ .append('rect')
254
+ .attr('class', 'bar')
255
+ .style('fill', (d, i) => config.color(i.toString()))
256
+ .on('mouseover', function (event, d) {
257
+ return onMouseOver$1(this, d, g, x, y, config);
258
+ })
259
+ .on('mouseout', function (event, d) {
260
+ return onMouseOut$1(this, d, x, y, config);
261
+ })
262
+ .attr('x', d => { var _a; return (_a = x(d.title)) !== null && _a !== void 0 ? _a : ''; })
263
+ .attr('y', d => y(d.value))
264
+ .attr('width', x.bandwidth())
265
+ .transition()
266
+ .ease(d3.easeLinear)
267
+ .duration(duration)
268
+ .delay(function (d, i) {
269
+ const multiplier = 50;
270
+ return i * multiplier;
271
+ })
272
+ .attr('height', d => config.height - y(d.value));
273
+ };
274
+ /**
275
+ * Draws the bar chart.
276
+ * @param container the chart container
277
+ * @param data the chart data
278
+ * @param options the chart options
279
+ * @returns the chart configuration
280
+ */
281
+ const drawBarChart = (container, data, options) => {
282
+ var _a;
283
+ const config = generateConfiguration(defaultBarChartConfig, options, {});
284
+ const { g } = createContainer$4(container, config);
285
+ const x = d3
286
+ .scaleBand([0, config.width])
287
+ .padding(config.xAxisPadding)
288
+ .domain(data.map(d => d.title));
289
+ const y = d3.scaleLinear([config.height, 0]).domain([0, (_a = d3.max(data, d => d.value)) !== null && _a !== void 0 ? _a : 1]);
290
+ createAxisX$1(g, x, config);
291
+ createAxisY$1(g, y, config);
292
+ createLegend$2(g, config);
293
+ drawBarsAndSetPointerEvents(g, x, y, config, data);
294
+ return config;
295
+ };
296
+
297
+ /**
298
+ * The force directed chart default configuration.
299
+ */
300
+ const defaultForceDirectedChartConfig = Object.freeze({
301
+ chartTitle: '',
302
+ width: 600,
303
+ height: 600,
304
+ centerCalcMod: 1.6,
305
+ charge: {
306
+ strength: -10,
307
+ theta: 0.6,
308
+ distanceMax: 2000,
309
+ },
310
+ distance: 75,
311
+ fontSize: 10,
312
+ collisionRadius: 30,
313
+ margin: {
314
+ top: 20,
315
+ right: 20,
316
+ bottom: 20,
317
+ left: 20,
318
+ },
319
+ strokeWidth: 1.5,
320
+ labelTextWrapWidth: 60,
321
+ color: d3.scaleOrdinal(d3.schemeCategory10),
322
+ });
323
+ /**
324
+ * The force durected chart tick handler.
325
+ * @param link chart links
326
+ * @param node chart nodes
327
+ * @param text chart text
328
+ * @returns rotation angle
329
+ */
330
+ const ticked = (link, node, text) => {
331
+ if (typeof link !== 'undefined') {
332
+ link
333
+ .attr('x1', d => { var _a; return (_a = d.source.x) !== null && _a !== void 0 ? _a : 0; })
334
+ .attr('y1', d => { var _a; return (_a = d.source.y) !== null && _a !== void 0 ? _a : 0; })
335
+ .attr('x2', d => { var _a; return (_a = d.target.x) !== null && _a !== void 0 ? _a : 0; })
336
+ .attr('y2', d => { var _a; return (_a = d.target.y) !== null && _a !== void 0 ? _a : 0; });
337
+ }
338
+ if (typeof node !== 'undefined') {
339
+ node.attr('cx', d => { var _a; return (_a = d.x) !== null && _a !== void 0 ? _a : 0; }).attr('cy', d => { var _a; return (_a = d.y) !== null && _a !== void 0 ? _a : 0; });
340
+ }
341
+ if (typeof text !== 'undefined') {
342
+ const dx = 10;
343
+ const dy = 5;
344
+ text.attr('x', d => { var _a; return ((_a = d.x) !== null && _a !== void 0 ? _a : 0) + dx; }).attr('y', d => { var _a; return ((_a = d.y) !== null && _a !== void 0 ? _a : 0) - dy; });
345
+ }
346
+ return 'rotate(0)';
347
+ };
348
+ /**
349
+ * Creates a container for the force directed chart.
350
+ * @param container the chart container
351
+ * @param config the chart configuration
352
+ * @returns the object with the svg element and the g element
353
+ */
354
+ const createContainer$3 = (container, config) => {
355
+ var _a;
356
+ const id = (_a = container.nativeElement.id) !== null && _a !== void 0 ? _a : 'force-directed-0';
357
+ d3.select(`#${id}`).select('svg').remove();
358
+ const svg = d3
359
+ .select(`#${id}`)
360
+ .append('svg')
361
+ .attr('width', config.width + config.margin.left + config.margin.right)
362
+ .attr('height', config.height + config.margin.top + config.margin.bottom)
363
+ .attr('class', id);
364
+ const g = svg
365
+ .append('g')
366
+ .attr('transform', `translate(${config.width / 2 + config.margin.left},${config.height / 2 + config.margin.top})`);
367
+ return { svg, g };
368
+ };
369
+ /**
370
+ * Applies the force directed chart data.
371
+ * @param g the svg g element
372
+ * @param data the chart data
373
+ */
374
+ const applyChartData = (g, data) => {
375
+ const imageXY = 10;
376
+ g.append('defs')
377
+ .selectAll('pattern')
378
+ .data(data.entities)
379
+ .enter()
380
+ .append('pattern')
381
+ .attr('id', (val, i) => `img-${val.index}`)
382
+ .attr('x', 0)
383
+ .attr('y', 0)
384
+ .attr('height', val => {
385
+ const baseValue = 30;
386
+ return baseValue + val.linksCount * 2;
387
+ })
388
+ .attr('width', val => {
389
+ const baseValue = 30;
390
+ return baseValue + val.linksCount * 2;
391
+ })
392
+ .append('image')
393
+ .attr('x', imageXY)
394
+ .attr('y', imageXY)
395
+ .attr('height', val => {
396
+ const baseValue = 30;
397
+ return baseValue + val.linksCount * 2;
398
+ })
399
+ .attr('width', val => {
400
+ const baseValue = 30;
401
+ return baseValue + val.linksCount * 2;
402
+ })
403
+ .attr('xlink:href', val => val.img);
404
+ };
405
+ /**
406
+ * Creates the force directed chart links.
407
+ * @param svg the svg element
408
+ * @param config the chart configuration
409
+ * @param data the chart data
410
+ * @returns the chart links
411
+ */
412
+ const createLinks = (svg, config, data) => {
413
+ return svg
414
+ .selectAll('.link')
415
+ .data(data.links)
416
+ .enter()
417
+ .append('line')
418
+ .attr('class', 'link')
419
+ .style('stroke', '#000000')
420
+ .style('stroke-width', config.strokeWidth);
421
+ };
422
+ /**
423
+ * Creates the force directed chart forces.
424
+ * @param config the chart configuration
425
+ * @param data the chart data
426
+ * @returns the chart forces
427
+ */
428
+ const createForces = (config, data) => {
429
+ return d3
430
+ .forceSimulation(data.nodes)
431
+ .force('link', d3.forceLink().id(d => { var _a; return (_a = d.index) !== null && _a !== void 0 ? _a : 0; }))
432
+ .force('charge', d3.forceManyBody().strength(config.charge.strength).theta(config.charge.theta).distanceMax(config.charge.distanceMax))
433
+ .force('center', d3.forceCenter(config.width / config.centerCalcMod, config.height / config.centerCalcMod))
434
+ .force('collision', d3.forceCollide().radius(d => config.collisionRadius))
435
+ .force('link', d3
436
+ .forceLink(data.links)
437
+ .id(d => { var _a; return (_a = d.index) !== null && _a !== void 0 ? _a : 0; })
438
+ .distance(config.distance)
439
+ .links(data.links));
440
+ };
441
+ /**
442
+ * The force directed chart node drag start handler.
443
+ * @param event a drag event
444
+ * @param datum the chart data
445
+ * @param force the chart forces
446
+ */
447
+ const nodeDragStartHandler = (event, datum, force) => {
448
+ if (!event.active && typeof force !== 'undefined') {
449
+ const alphaTarget = 0.3;
450
+ force.alphaTarget(alphaTarget).restart();
451
+ }
452
+ datum.fx = event.x;
453
+ datum.fy = event.y;
454
+ };
455
+ /**
456
+ * The force directed chart node drag handler.
457
+ * @param event a drag event
458
+ * @param datum the chart data
459
+ * @param config the chart configuration
460
+ */
461
+ const nodeDragHandler = (event, datum, config) => {
462
+ datum.fx = event.x > config.margin.left && event.x < config.width + config.margin.right ? event.x : datum.fx;
463
+ datum.fy = event.y > config.margin.top && event.y < config.width + config.margin.bottom ? event.y : datum.fy;
464
+ };
465
+ /**
466
+ * The force directed chart node drag end handler.
467
+ * @param event a drag event
468
+ * @param datum the chart data
469
+ * @param force the chart forces
470
+ */
471
+ const nodeDragEndHandler = (event, datum, force) => {
472
+ if (!event.active && typeof force !== 'undefined') {
473
+ force.alphaTarget(0);
474
+ }
475
+ datum.fx = null;
476
+ datum.fy = null;
477
+ };
478
+ /**
479
+ * Creates the force directed chart nodes.
480
+ * @param svg the svg element
481
+ * @param data the chart data
482
+ * @param force the chart forces
483
+ * @param config the chart configuration
484
+ * @returns the chart nodes
485
+ */
486
+ const createNodes = (svg, data, force, config) => {
487
+ return svg
488
+ .selectAll('.node')
489
+ .data(data.nodes)
490
+ .enter()
491
+ .append('circle')
492
+ .attr('class', 'node')
493
+ .attr('r', val => {
494
+ var _a, _b;
495
+ const base = 5;
496
+ return base + ((_a = val.value) !== null && _a !== void 0 ? _a : 0) + ((_b = val.linksCount) !== null && _b !== void 0 ? _b : 0) * 2;
497
+ })
498
+ .style('stroke-width', val => {
499
+ var _a, _b;
500
+ const base = 5;
501
+ return base + ((_a = val.value) !== null && _a !== void 0 ? _a : 0) + ((_b = val.linksCount) !== null && _b !== void 0 ? _b : 0) * 2;
502
+ })
503
+ .style('fill', val => (typeof val.img === 'undefined' || val.img === '' ? '#f00000' : `url(${val.img})`))
504
+ .call(d3
505
+ .drag()
506
+ .on('start', function (event, datum) {
507
+ nodeDragStartHandler(event, datum, force);
508
+ })
509
+ .on('drag', function (event, datum) {
510
+ nodeDragHandler(event, datum, config);
511
+ })
512
+ .on('end', function (event, datum) {
513
+ nodeDragEndHandler(event, datum, force);
514
+ }));
515
+ };
516
+ /**
517
+ * Creates the force directed chart text labels.
518
+ * @param svg the svg element
519
+ * @param data the chart data
520
+ * @returns the chart text labels
521
+ */
522
+ const createText = (svg, data) => {
523
+ return svg
524
+ .append('g')
525
+ .selectAll('text')
526
+ .data(data.nodes)
527
+ .enter()
528
+ .append('text')
529
+ .attr('class', 'legend')
530
+ .text(val => { var _a; return (_a = val.name) !== null && _a !== void 0 ? _a : `N/A (id. ${val.index})`; });
531
+ };
532
+ /**
533
+ * Draws the force directed chart.
534
+ * @param container the chart container
535
+ * @param data the chart data
536
+ * @param options the chart options
537
+ * @returns the chart configuration
538
+ */
539
+ const drawForceDirectedChart = (container, data, options) => {
540
+ const config = generateConfiguration(defaultForceDirectedChartConfig, options, {});
541
+ const { svg, g } = createContainer$3(container, config);
542
+ applyChartData(g, data);
543
+ const link = createLinks(svg, config, data);
544
+ const force = createForces(config, data);
545
+ const node = createNodes(svg, data, force, config);
546
+ const text = createText(svg, data);
547
+ force.on('tick', () => {
548
+ ticked(link, node, text);
549
+ });
550
+ return config;
551
+ };
552
+
553
+ /**
554
+ * The line chart default configuration.
555
+ */
556
+ const defaultLineChartConfig = Object.freeze({
557
+ chartTitle: '',
558
+ width: 350,
559
+ height: 350,
560
+ margin: {
561
+ top: 70,
562
+ right: 50,
563
+ bottom: 50,
564
+ left: 50,
565
+ },
566
+ transitionDuration: 400,
567
+ dotRadius: 3.5,
568
+ xAxisTitle: '',
569
+ yAxisTitle: '',
570
+ ticks: {
571
+ x: 5,
572
+ y: 10,
573
+ },
574
+ displayAxisLabels: true,
575
+ labelTextWrapWidth: 20,
576
+ color: d3.scaleOrdinal(d3.schemeCategory10),
577
+ });
578
+ /**
579
+ * Creates a container for the line chart.
580
+ * @param container the chart container
581
+ * @param config the chart configuration
582
+ * @returns the object with the svg element and the g element
583
+ */
584
+ const createContainer$2 = (container, config) => {
585
+ var _a;
586
+ const id = (_a = container.nativeElement.id) !== null && _a !== void 0 ? _a : 'line-0';
587
+ d3.select(`#${id}`).select('svg').remove();
588
+ const svg = d3
589
+ .select(`#${id}`)
590
+ .append('svg')
591
+ .attr('width', config.width + config.margin.left + config.margin.right)
592
+ .attr('height', config.height + config.margin.top + config.margin.bottom)
593
+ .attr('class', id);
594
+ const g = svg.append('g').attr('transform', `translate(${config.margin.left},${config.margin.top / 2})`);
595
+ return { svg, g };
596
+ };
597
+ /**
598
+ * Wraps the line chart axis labels text.
599
+ * @param svgText the svg text elements
600
+ * @param width the chart axis label width
601
+ */
602
+ const wrapSvgText$1 = (svgText, width) => {
603
+ svgText.each(function () {
604
+ var _a, _b, _c;
605
+ const text = d3.select(this);
606
+ const words = text.text().split(/\s+/).reverse();
607
+ let line = [];
608
+ let lineNumber = 0;
609
+ const lineHeight = 1.4;
610
+ const y = text.attr('y');
611
+ const x = text.attr('x');
612
+ const dy = parseFloat((_a = text.attr('dy')) !== null && _a !== void 0 ? _a : 0);
613
+ let tspan = text.text(null).append('tspan').attr('x', x).attr('y', y).attr('dy', `${dy}em`); // axis label
614
+ let word = words.pop();
615
+ while (typeof word !== 'undefined') {
616
+ line.push(word !== null && word !== void 0 ? word : '');
617
+ tspan.text(line.join(' '));
618
+ if (((_c = (_b = tspan.node()) === null || _b === void 0 ? void 0 : _b.getComputedTextLength()) !== null && _c !== void 0 ? _c : 0) > width) {
619
+ line.pop();
620
+ tspan.text(line.join(' '));
621
+ line = [word !== null && word !== void 0 ? word : ''];
622
+ lineNumber += 1;
623
+ tspan = text
624
+ .append('tspan')
625
+ .attr('x', 0)
626
+ .attr('y', y)
627
+ .attr('dy', `${lineNumber * lineHeight + dy}em`)
628
+ .text(word !== null && word !== void 0 ? word : '');
629
+ }
630
+ word = words.pop();
631
+ }
632
+ });
633
+ };
634
+ /**
635
+ * Creates the legend.
636
+ * @param g the svg g element
637
+ * @param config the chart configuration
638
+ */
639
+ const createLegend$1 = (g, config) => {
640
+ if (config.displayAxisLabels && config.xAxisTitle !== '') {
641
+ g.append('g')
642
+ .attr('transform', `translate(0, ${config.height + config.margin.bottom})`)
643
+ .append('text')
644
+ .style('font-size', '12px')
645
+ .attr('class', 'legend')
646
+ .attr('dx', '1.5em')
647
+ .attr('dy', '1em')
648
+ .text(`x - ${config.xAxisTitle}`);
649
+ }
650
+ if (config.displayAxisLabels && config.yAxisTitle !== '') {
651
+ g.append('g')
652
+ .attr('transform', `translate(0, ${config.height + config.margin.bottom})`)
653
+ .append('text')
654
+ .style('font-size', '12px')
655
+ .attr('class', 'legend')
656
+ .attr('dx', '1.5em')
657
+ .attr('dy', '2.5em')
658
+ .text(`y - ${config.yAxisTitle}`);
659
+ }
660
+ if (config.chartTitle !== '') {
661
+ g.append('g')
662
+ .attr('transform', `translate(0, 0)`)
663
+ .append('text')
664
+ .style('font-size', '12px')
665
+ .attr('class', 'legend')
666
+ .attr('dx', '1.5em')
667
+ .attr('dy', '-2em')
668
+ .text(config.chartTitle);
669
+ }
670
+ };
671
+ /**
672
+ * Creates the x axis.
673
+ * @param g the svg g element
674
+ * @param x the x axis scale
675
+ * @param config the chart configuration
676
+ */
677
+ const createAxisX = (g, x, config) => {
678
+ const xLabels = g
679
+ .append('g')
680
+ .attr('transform', `translate(0, ${config.height})`)
681
+ .call(d3
682
+ .axisBottom(x)
683
+ .ticks(config.ticks.x)
684
+ .tickFormat(d => {
685
+ const date = new Date(d.valueOf());
686
+ const formattingOffset = 10;
687
+ const day = date.getDate();
688
+ const dd = day < formattingOffset ? `0${day}` : day;
689
+ const month = date.getMonth() + 1;
690
+ const mm = month < formattingOffset ? `0${month}` : month;
691
+ const year = date.getFullYear().toString();
692
+ const yy = year.slice(2);
693
+ const hours = date.getHours();
694
+ const hour = hours < formattingOffset ? `0${hours}` : hours;
695
+ const minutes = date.getMinutes();
696
+ const minute = minutes < formattingOffset ? `0${minutes}` : minutes;
697
+ return `${dd}/${mm}/${yy} ${hour}:${minute}`;
698
+ }))
699
+ .append('text');
700
+ g.selectAll('text').call(wrapSvgText$1, config.labelTextWrapWidth);
701
+ if (config.displayAxisLabels) {
702
+ xLabels.attr('transform', `translate(${config.width}, 0)`).attr('class', 'legend').attr('dx', '1.5em').attr('dy', '0.7em').text('x');
703
+ }
704
+ };
705
+ /**
706
+ * Creates the y axis.
707
+ * @param g the svg g element
708
+ * @param y the y axis scale
709
+ * @param config the chart configuration
710
+ */
711
+ const createAxisY = (g, y, config) => {
712
+ const yLabels = g
713
+ .append('g')
714
+ .call(d3
715
+ .axisLeft(y)
716
+ .ticks(config.ticks.y)
717
+ .tickFormat(d => `${d}`))
718
+ .append('text');
719
+ if (config.displayAxisLabels) {
720
+ yLabels.attr('class', 'legend').attr('dy', '-1.5em').attr('class', 'legend').text('y');
721
+ }
722
+ };
723
+ /**
724
+ * The mouse over event handler.
725
+ * @param self an svg circle element
726
+ * @param d the chart data node
727
+ * @param g the svg g element
728
+ * @param config the chart configuration
729
+ */
730
+ const onMouseOver = (self, d, g, config) => {
731
+ const duration = 400;
732
+ d3.select(self)
733
+ .transition()
734
+ .duration(duration)
735
+ .attr('r', config.dotRadius * 2);
736
+ const tooltipShift = 4;
737
+ const tooltipDy = -10;
738
+ g.append('text')
739
+ .attr('class', 'val')
740
+ .style('font-size', '11px')
741
+ .attr('dx', () => (config.width - config.margin.left - config.margin.right) / tooltipShift)
742
+ .attr('dy', () => tooltipDy)
743
+ .text(() => `${d.value} (${new Date(d.timestamp).toUTCString()})`);
744
+ };
745
+ /**
746
+ * The mouse out event handler.
747
+ * @param self an svg circle element
748
+ * @param config the chart configuration
749
+ */
750
+ const onMouseOut = (self, config) => {
751
+ const duration = 400;
752
+ d3.select(self).attr('class', 'dot');
753
+ d3.select(self).transition().duration(duration).attr('r', config.dotRadius);
754
+ d3.selectAll('.val').remove();
755
+ };
756
+ /**
757
+ * Draws the chart lines, dots, and sets the mouse pointer events.
758
+ * @param g the svg g element
759
+ * @param x the x axis scale
760
+ * @param y the y axis scale
761
+ * @param config the chart configuration
762
+ * @param data the chart data
763
+ */
764
+ const drawLinesDotsAndSetPointerEvents = (g, x, y, config, data) => {
765
+ const line = d3
766
+ .line()
767
+ .x(d => x(d.timestamp))
768
+ .y(d => y(d.value))
769
+ .curve(d3.curveMonotoneX);
770
+ g.append('path').attr('id', 'line').style('fill', 'none').style('stroke', 'red').style('stroke-width', '2px').attr('d', line(data));
771
+ g.selectAll('.dot')
772
+ .data(data)
773
+ .enter()
774
+ .append('circle')
775
+ .attr('class', 'dot')
776
+ .style('pointer-events', 'all')
777
+ .style('fill', (d, i) => config.color(i.toString()))
778
+ .on('mouseover', function (event, d) {
779
+ return onMouseOver(this, d, g, config);
780
+ })
781
+ .on('mouseout', function () {
782
+ return onMouseOut(this, config);
783
+ })
784
+ .attr('cx', function (d) {
785
+ return x(d.timestamp);
786
+ })
787
+ .attr('cy', function (d) {
788
+ return y(d.value);
789
+ })
790
+ .attr('r', 0)
791
+ .transition()
792
+ .ease(d3.easeLinear)
793
+ .duration(config.transitionDuration)
794
+ .delay((d, i) => {
795
+ const multiplier = 50;
796
+ return i * multiplier;
797
+ })
798
+ .attr('r', config.dotRadius);
799
+ };
800
+ /**
801
+ * Draws the line chart.
802
+ * @param container the chart container
803
+ * @param data the chart data
804
+ * @param options the chart options
805
+ * @returns the chart configuration
806
+ */
807
+ const drawLineChart = (container, data, options) => {
808
+ var _a;
809
+ const config = generateConfiguration(defaultLineChartConfig, options, {});
810
+ const { g } = createContainer$2(container, config);
811
+ const x = d3.scaleTime([0, config.width]).domain([Math.min(...data.map(d => d.timestamp)), Math.max(...data.map(d => d.timestamp))]);
812
+ const y = d3.scaleLinear([config.height, 0]).domain([0, (_a = d3.max(data, d => d.value)) !== null && _a !== void 0 ? _a : 1]);
813
+ createAxisX(g, x, config);
814
+ createAxisY(g, y, config);
815
+ createLegend$1(g, config);
816
+ drawLinesDotsAndSetPointerEvents(g, x, y, config, data);
817
+ return config;
818
+ };
819
+
820
+ /**
821
+ * The pie chart default configuration.
822
+ */
823
+ const defaultPieChartConfig = Object.freeze({
824
+ chartTitle: '',
825
+ width: 600,
826
+ height: 600,
827
+ margin: {
828
+ top: 20,
829
+ right: 20,
830
+ bottom: 20,
831
+ left: 20,
832
+ },
833
+ innerRadius: 0,
834
+ labelRadiusModifier: 50,
835
+ labelTextWrapWidth: 60,
836
+ color: d3.scaleOrdinal(d3.schemeCategory10),
837
+ });
838
+ /**
839
+ * Creates a container for the pie chart.
840
+ * @param container the chart container
841
+ * @param config the chart configuration
842
+ * @returns the object with the svg element and the g element
843
+ */
844
+ const createContainer$1 = (container, config) => {
845
+ var _a;
846
+ const id = (_a = container.nativeElement.id) !== null && _a !== void 0 ? _a : 'pie-0';
847
+ d3.select(`#${id}`).select('svg').remove();
848
+ const svg = d3
849
+ .select(`#${id}`)
850
+ .append('svg')
851
+ .attr('width', config.width + config.margin.left + config.margin.right)
852
+ .attr('height', config.height + config.margin.top + config.margin.bottom)
853
+ .attr('class', id);
854
+ const g = svg
855
+ .append('g')
856
+ .attr('transform', `translate(${config.width / 2 + config.margin.left},${config.height / 2 + config.margin.top})`);
857
+ return { svg, g };
858
+ };
859
+ /**
860
+ * Draws the pie chart.
861
+ * @param container the chart container
862
+ * @param data the chart data
863
+ * @param options the chart options
864
+ * @returns the chart configuration
865
+ */
866
+ const drawPieChart = (container, data, options) => {
867
+ const config = generateConfiguration(defaultPieChartConfig, options, {});
868
+ const { g } = createContainer$1(container, config);
869
+ const pie = d3.pie().value(datum => datum.y);
870
+ const radius = Math.min(config.width, config.height) / 2;
871
+ const arc = d3.arc().innerRadius(config.innerRadius).outerRadius(radius);
872
+ const arcs = g
873
+ .selectAll('arc')
874
+ .data(pie(data))
875
+ .enter()
876
+ .append('g')
877
+ .attr('class', 'arc')
878
+ .on('mouseover', function (event, d) {
879
+ d3.select('#tooltip')
880
+ .style('left', `${event.pageX}px`)
881
+ .style('top', `${event.pageY}px`)
882
+ .style('opacity', 1)
883
+ .select('#value')
884
+ .text(d.value);
885
+ })
886
+ .on('mouseout', function (event, d) {
887
+ d3.select('#tooltip').style('opacity', 0);
888
+ });
889
+ const label = d3
890
+ .arc()
891
+ .innerRadius(radius)
892
+ .outerRadius(radius + config.labelRadiusModifier);
893
+ arcs
894
+ .append('path')
895
+ .attr('fill', (d, i) => config.color(i.toString()))
896
+ .attr('d', arc);
897
+ const textDy = 5;
898
+ arcs
899
+ .append('text')
900
+ .attr('class', 'legend')
901
+ .attr('text-anchor', 'middle')
902
+ .attr('dy', textDy)
903
+ .attr('transform', d => `translate(${label.centroid(d)})`)
904
+ .text(d => d.data.y);
905
+ return config;
906
+ };
907
+
908
+ /**
909
+ * The radar chart default configuration.
910
+ */
911
+ const defaultRadarChartConfig = Object.freeze({
912
+ chartTitle: '',
913
+ width: 350,
914
+ height: 350,
915
+ margin: {
916
+ top: 50,
917
+ right: 50,
918
+ bottom: 50,
919
+ left: 50,
920
+ },
921
+ levels: 3,
922
+ maxValue: 0,
923
+ lineFactor: 1.1,
924
+ labelFactor: 1.15,
925
+ labelTextWrapWidth: 60,
926
+ opacityArea: 0.35,
927
+ dotRadius: 4,
928
+ opacityCircles: 0.1,
929
+ strokeWidth: 2,
930
+ roundStrokes: false,
931
+ transitionDuration: 200,
932
+ color: d3.scaleOrdinal(d3.schemeCategory10),
933
+ });
934
+ /**
935
+ * Creates a container for the radar chart.
936
+ * @param container the chart container
937
+ * @param config the chart configuration
938
+ * @returns the object with the svg element and the g element
939
+ */
940
+ const createContainer = (container, config) => {
941
+ var _a;
942
+ const id = (_a = container.nativeElement.id) !== null && _a !== void 0 ? _a : 'radar-0';
943
+ d3.select(`#${id}`).select('svg').remove();
944
+ const svg = d3
945
+ .select(`#${id}`)
946
+ .append('svg')
947
+ .attr('width', config.width + config.margin.left + config.margin.right)
948
+ .attr('height', config.height + config.margin.top + config.margin.bottom)
949
+ .attr('class', id);
950
+ const g = svg
951
+ .append('g')
952
+ .attr('transform', `translate(${config.width / 2 + config.margin.left},${config.height / 2 + config.margin.top})`);
953
+ return { svg, g };
954
+ };
955
+ /**
956
+ * Draws the radar chart circular grid.
957
+ * @param axisGrid the chart axis grid
958
+ * @param radius the chart radius value
959
+ * @param maxValue the maximum value of the chart axis
960
+ * @param config the chart configuration
961
+ */
962
+ const drawCircularGrid = (axisGrid, radius, maxValue, config) => {
963
+ // background circles
964
+ axisGrid
965
+ .selectAll('.levels')
966
+ .data(d3.range(1, config.levels + 1).reverse())
967
+ .enter()
968
+ .append('circle')
969
+ .attr('class', 'grid-circle')
970
+ .attr('r', (d, i) => (radius / config.levels) * d)
971
+ .style('fill', '#CDCDCD')
972
+ .style('stroke', '#CDCDCD')
973
+ .style('fill-opacity', config.opacityCircles)
974
+ .style('filter', 'url(#glow)');
975
+ // text indicating at what % each level is
976
+ const axisGridX = 4;
977
+ axisGrid
978
+ .selectAll('.axis-label')
979
+ .data(d3.range(1, config.levels + 1).reverse())
980
+ .enter()
981
+ .append('text')
982
+ .attr('class', 'axis-label')
983
+ .attr('x', axisGridX)
984
+ .attr('y', d => (-d * radius) / config.levels)
985
+ .attr('dy', '0.4em')
986
+ .style('font-size', '10px')
987
+ .attr('fill', '#737373')
988
+ .text((d, i) => (maxValue * d) / config.levels);
989
+ };
990
+ /**
991
+ * Wraps the chart axis labels text.
992
+ * @param svgText the svg text elements
993
+ * @param width the chart axis label width
994
+ */
995
+ const wrapSvgText = (svgText, width) => {
996
+ svgText.each(function () {
997
+ var _a, _b, _c;
998
+ const text = d3.select(this);
999
+ const words = text.text().split(/\s+/).reverse();
1000
+ let line = [];
1001
+ let lineNumber = 0;
1002
+ const lineHeight = 1.4;
1003
+ const y = text.attr('y');
1004
+ const x = text.attr('x');
1005
+ const dy = parseFloat((_a = text.attr('dy')) !== null && _a !== void 0 ? _a : 0);
1006
+ let tspan = text.text(null).append('tspan').attr('x', x).attr('y', y).attr('dy', `${dy}em`);
1007
+ let word = words.pop();
1008
+ while (typeof word !== 'undefined') {
1009
+ line.push(word !== null && word !== void 0 ? word : '');
1010
+ tspan.text(line.join(' '));
1011
+ if (((_c = (_b = tspan.node()) === null || _b === void 0 ? void 0 : _b.getComputedTextLength()) !== null && _c !== void 0 ? _c : 0) > width) {
1012
+ line.pop();
1013
+ tspan.text(line.join(' '));
1014
+ line = [word !== null && word !== void 0 ? word : ''];
1015
+ lineNumber += 1;
1016
+ tspan = text
1017
+ .append('tspan')
1018
+ .attr('x', x)
1019
+ .attr('y', y)
1020
+ .attr('dy', `${lineNumber * lineHeight + dy}em`)
1021
+ .text(word !== null && word !== void 0 ? word : '');
1022
+ }
1023
+ word = words.pop();
1024
+ }
1025
+ });
1026
+ };
1027
+ /**
1028
+ * Creates the legend.
1029
+ * @param g the svg g element
1030
+ * @param config the chart configuration
1031
+ */
1032
+ const createLegend = (g, config) => {
1033
+ if (config.chartTitle !== '') {
1034
+ g.append('g')
1035
+ .attr('transform', `translate(-${config.width / 2 + config.margin.left / 2}, -${config.height / 2 + config.margin.top / 2})`)
1036
+ .append('text')
1037
+ .style('font-size', '12px')
1038
+ .attr('class', 'legend')
1039
+ .text(config.chartTitle);
1040
+ }
1041
+ };
1042
+ /**
1043
+ * Draws the radar chart axis.
1044
+ * @param axisGrid the chart axis grid
1045
+ * @param axisNames the chart axis names
1046
+ * @param radiusScale the chart radius scale
1047
+ * @param maxValue the maximum value of the chart axis
1048
+ * @param angleSlice the chart angle slice value
1049
+ * @param config the chart configuration
1050
+ */
1051
+ const drawAxis = (axisGrid, axisNames, radiusScale, maxValue, angleSlice, config) => {
1052
+ // create the straight lines radiating outward from the center
1053
+ const axis = axisGrid.selectAll('.axis').data(axisNames).enter().append('g').attr('class', 'axis');
1054
+ // append the lines
1055
+ axis
1056
+ .append('line')
1057
+ .attr('x1', 0)
1058
+ .attr('y1', 0)
1059
+ .attr('x2', (d, i) => radiusScale(maxValue * config.lineFactor) * Math.cos(angleSlice * i - Math.PI / 2))
1060
+ .attr('y2', (d, i) => radiusScale(maxValue * config.lineFactor) * Math.sin(angleSlice * i - Math.PI / 2))
1061
+ .attr('class', 'line')
1062
+ .style('stroke', 'white')
1063
+ .style('stroke-width', '2px');
1064
+ // append the labels at each axis
1065
+ axis
1066
+ .append('text')
1067
+ .attr('class', 'legend')
1068
+ .style('font-size', '11px')
1069
+ .attr('text-anchor', 'middle')
1070
+ .attr('dy', '0.35em')
1071
+ .attr('x', (d, i) => radiusScale(maxValue * config.labelFactor) * Math.cos(angleSlice * i - Math.PI / 2))
1072
+ .attr('y', (d, i) => radiusScale(maxValue * config.labelFactor) * Math.sin(angleSlice * i - Math.PI / 2))
1073
+ .text(d => d)
1074
+ .call(wrapSvgText, config.labelTextWrapWidth);
1075
+ };
1076
+ /**
1077
+ * Draws the radar chart blobs.
1078
+ * @param radiusScale the chart radius scale
1079
+ * @param angleSlice the chart angle slice value
1080
+ * @param g the svg g element
1081
+ * @param data the chart data
1082
+ * @param config the chart configuration
1083
+ */
1084
+ const drawRadarChartBlobs = (radiusScale, angleSlice, g, data, config) => {
1085
+ // the radial line function
1086
+ const radarLine = d3
1087
+ .lineRadial()
1088
+ .radius(d => radiusScale(d.value))
1089
+ .angle((d, i) => i * angleSlice);
1090
+ // create a wrapper for the blobs
1091
+ const blobWrapper = g.selectAll('.radar-wrapper').data(data).enter().append('g').attr('class', 'radar-wrapper');
1092
+ // append the backgrounds
1093
+ blobWrapper
1094
+ .append('path')
1095
+ .attr('class', 'radar-area')
1096
+ .attr('d', (d, i) => radarLine(d))
1097
+ .style('fill', (d, i) => config.color(i.toString()))
1098
+ .style('fill-opacity', config.opacityArea)
1099
+ .on('mouseover', function (d, i) {
1100
+ // dim all blobs
1101
+ const radarAreaFillOpacity = 0.1;
1102
+ d3.selectAll('.radar-area').transition().duration(config.transitionDuration).style('fill-opacity', radarAreaFillOpacity);
1103
+ // bring back the hovered over blob
1104
+ const fillOpacity = 0.7;
1105
+ d3.select(this).transition().duration(config.transitionDuration).style('fill-opacity', fillOpacity);
1106
+ })
1107
+ .on('mouseout', () => {
1108
+ // bring back all blobs
1109
+ d3.selectAll('.radar-area').transition().duration(config.transitionDuration).style('fill-opacity', config.opacityArea);
1110
+ });
1111
+ // create the outlines
1112
+ blobWrapper
1113
+ .append('path')
1114
+ .attr('class', 'radar-stroke')
1115
+ .attr('d', (d, i) => radarLine(d))
1116
+ .style('stroke-width', `${config.strokeWidth}px`)
1117
+ .style('stroke', (d, i) => config.color(i.toString()))
1118
+ .style('fill', 'none')
1119
+ .style('filter', 'url(#glow)');
1120
+ // append the circles
1121
+ const blobWrapperFillOpacity = 0.8;
1122
+ blobWrapper
1123
+ .selectAll('.radar-circle')
1124
+ .data((d, i) => d)
1125
+ .enter()
1126
+ .append('circle')
1127
+ .attr('class', 'radar-circle')
1128
+ .attr('r', config.dotRadius)
1129
+ .attr('cx', (d, i) => radiusScale(d.value) * Math.cos(angleSlice * i - Math.PI / 2))
1130
+ .attr('cy', (d, i) => radiusScale(d.value) * Math.sin(angleSlice * i - Math.PI / 2))
1131
+ .style('fill', (d, i, j) => config.color(j.toString()))
1132
+ .style('fill-opacity', blobWrapperFillOpacity);
1133
+ };
1134
+ /**
1135
+ * Appends the invisible tooltip circles.
1136
+ * @param g the svg g element
1137
+ * @param data the chart data
1138
+ * @param radiusScale the chart radius scale
1139
+ * @param angleSlice the chart angle slice value
1140
+ * @param config the chart configuration
1141
+ */
1142
+ const appendInvisibleTooltipCircles = (g, data, radiusScale, angleSlice, config) => {
1143
+ // wrapper for the invisible circles on top
1144
+ const blobCircleWrapper = g.selectAll('.radar-circle-wrapper').data(data).enter().append('g').attr('class', 'radar-circle-wrapper');
1145
+ // set up the small tooltip for when you hover over a circle
1146
+ const tooltip = g.append('text').attr('class', 'tooltip').style('opacity', 0);
1147
+ // append a set of invisible circles on top for the mouseover pop-up
1148
+ const blobCircleWrapperRadiusMultiplier = 1.5;
1149
+ blobCircleWrapper
1150
+ .selectAll('.radar-invisible-circle')
1151
+ .data((d, i) => d)
1152
+ .enter()
1153
+ .append('circle')
1154
+ .attr('class', 'radar-invisible-circle')
1155
+ .attr('r', config.dotRadius * blobCircleWrapperRadiusMultiplier)
1156
+ .attr('cx', (d, i) => radiusScale(d.value) * Math.cos(angleSlice * i - Math.PI / 2))
1157
+ .attr('cy', (d, i) => radiusScale(d.value) * Math.sin(angleSlice * i - Math.PI / 2))
1158
+ .style('fill', 'none')
1159
+ .style('pointer-events', 'all')
1160
+ .on('mouseover', function (event, i) {
1161
+ const modifier = 10;
1162
+ const newX = parseFloat(d3.select(this).attr('cx')) - modifier;
1163
+ const newY = parseFloat(d3.select(this).attr('cy')) - modifier;
1164
+ const nodeData = event.target['__data__'];
1165
+ const tooltipText = `${nodeData.value} ${nodeData.unit}`;
1166
+ tooltip.attr('x', newX).attr('y', newY).text(tooltipText).transition().duration(config.transitionDuration).style('opacity', 1);
1167
+ })
1168
+ .on('mouseout', () => {
1169
+ tooltip.transition().duration(config.transitionDuration).style('opacity', 0);
1170
+ });
1171
+ };
1172
+ /**
1173
+ * Draws the radar chart.
1174
+ * @param container the chart container
1175
+ * @param data the chart data
1176
+ * @param options the chart options
1177
+ * @returns the hart configuration
1178
+ */
1179
+ const drawRadarChart = (container, data, options) => {
1180
+ var _a;
1181
+ const config = generateConfiguration(defaultRadarChartConfig, options, {});
1182
+ const maxValue = Math.max(config.maxValue, (_a = d3.max(data, i => d3.max(i.map(o => o.value)))) !== null && _a !== void 0 ? _a : 0);
1183
+ const axisNames = data[0].map((i, j) => i.axis);
1184
+ const totalAxis = axisNames.length;
1185
+ const radius = Math.min(config.width / 2 - config.margin.left / 2, config.height / 2 - config.margin.top / 2);
1186
+ const angleSlice = (Math.PI * 2) / totalAxis;
1187
+ const radiusScale = d3.scaleLinear([0, radius]).domain([0, maxValue]);
1188
+ const { g } = createContainer(container, config);
1189
+ // filter for the outside glow
1190
+ const filter = g.append('defs').append('filter').attr('id', 'glow');
1191
+ filter.append('feGaussianBlur').attr('stdDeviation', '2.5').attr('result', 'coloredBlur');
1192
+ const feMerge = filter.append('feMerge');
1193
+ feMerge.append('feMergeNode').attr('in', 'coloredBlur');
1194
+ feMerge.append('feMergeNode').attr('in', 'SourceGraphic');
1195
+ const axisGrid = g.append('g').attr('class', 'axis-wrapper');
1196
+ drawCircularGrid(axisGrid, radius, maxValue, config);
1197
+ drawAxis(axisGrid, axisNames, radiusScale, maxValue, angleSlice, config);
1198
+ createLegend(g, config);
1199
+ drawRadarChartBlobs(radiusScale, angleSlice, g, data, config);
1200
+ appendInvisibleTooltipCircles(g, data, radiusScale, angleSlice, config);
1201
+ return config;
1202
+ };
1203
+
1204
+ const d3ChartFactory = () => ({
1205
+ drawPieChart,
1206
+ drawRadarChart,
1207
+ drawBarChart,
1208
+ drawLineChart,
1209
+ drawForceDirectedChart,
1210
+ });
1211
+ const D3_CHART_FACTORY = new InjectionToken('D3_CHART_FACTORY', {
1212
+ providedIn: 'root',
1213
+ factory: d3ChartFactory,
1214
+ });
1215
+
1216
+ class AppBarChartComponent {
1217
+ constructor(doc, d3Factory) {
1218
+ this.doc = doc;
1219
+ this.d3Factory = d3Factory;
1220
+ /**
1221
+ * The chart id.
1222
+ */
1223
+ this.chartId = 'bar-0';
1224
+ /**
1225
+ * The chart data.
1226
+ */
1227
+ this.data = [];
1228
+ /**
1229
+ * The chart options.
1230
+ */
1231
+ this.options = {};
1232
+ }
1233
+ /**
1234
+ * The chart options constructor.
1235
+ * @returns chart options
1236
+ */
1237
+ chartOptions() {
1238
+ var _a, _b;
1239
+ const bodyWidthAdjustment = 10;
1240
+ const width = Math.min((_a = this.options.width) !== null && _a !== void 0 ? _a : defaultBarChartConfig.width, this.doc.body.clientWidth - defaultBarChartConfig.margin.left - defaultBarChartConfig.margin.right - bodyWidthAdjustment);
1241
+ const height = Math.min((_b = this.options.height) !== null && _b !== void 0 ? _b : width, this.doc.body.clientWidth - defaultBarChartConfig.margin.top - defaultBarChartConfig.margin.bottom - bodyWidthAdjustment);
1242
+ const yAxisTicks = Math.max(...this.data.map(item => item.value));
1243
+ const options = Object.assign({ width,
1244
+ height,
1245
+ yAxisTicks }, this.options);
1246
+ return options;
1247
+ }
1248
+ /**
1249
+ * Draws the chart.
1250
+ */
1251
+ drawChart() {
1252
+ if (typeof this.container !== 'undefined') {
1253
+ const options = this.chartOptions();
1254
+ this.d3Factory.drawBarChart(this.container, this.data, options);
1255
+ }
1256
+ }
1257
+ /**
1258
+ * Actually draws the chart after the component view is initialized.
1259
+ */
1260
+ ngAfterViewInit() {
1261
+ this.drawChart();
1262
+ }
1263
+ /**
1264
+ * Redraws the chart on changes.
1265
+ */
1266
+ ngOnChanges(changes) {
1267
+ var _a, _b;
1268
+ const data = (_a = changes.data) === null || _a === void 0 ? void 0 : _a.currentValue;
1269
+ const options = (_b = changes.options) === null || _b === void 0 ? void 0 : _b.currentValue;
1270
+ if ((typeof data !== 'undefined' && data !== null) || (typeof options !== 'undefined' && options !== null)) {
1271
+ this.drawChart();
1272
+ }
1273
+ }
1274
+ }
1275
+ /** @nocollapse */ AppBarChartComponent.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "14.0.6", ngImport: i0, type: AppBarChartComponent, deps: [{ token: DOCUMENT }, { token: D3_CHART_FACTORY }], target: i0.ɵɵFactoryTarget.Component });
1276
+ /** @nocollapse */ AppBarChartComponent.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "14.0.0", version: "14.0.6", type: AppBarChartComponent, selector: "app-bar-chart", inputs: { chartId: "chartId", data: "data", options: "options" }, viewQueries: [{ propertyName: "container", first: true, predicate: ["container"], descendants: true }], usesOnChanges: true, ngImport: i0, template: "<div class=\"container\" id=\"{{ chartId }}\" #container></div>\n", styles: [":host{display:flex;flex-direction:row;flex-wrap:nowrap;justify-content:center}:host .container{flex:0 1 auto}\n"], changeDetection: i0.ChangeDetectionStrategy.OnPush });
1277
+ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "14.0.6", ngImport: i0, type: AppBarChartComponent, decorators: [{
1278
+ type: Component,
1279
+ args: [{ selector: 'app-bar-chart', changeDetection: ChangeDetectionStrategy.OnPush, template: "<div class=\"container\" id=\"{{ chartId }}\" #container></div>\n", styles: [":host{display:flex;flex-direction:row;flex-wrap:nowrap;justify-content:center}:host .container{flex:0 1 auto}\n"] }]
1280
+ }], ctorParameters: function () {
1281
+ return [{ type: Document, decorators: [{
1282
+ type: Inject,
1283
+ args: [DOCUMENT]
1284
+ }] }, { type: undefined, decorators: [{
1285
+ type: Inject,
1286
+ args: [D3_CHART_FACTORY]
1287
+ }] }];
1288
+ }, propDecorators: { chartId: [{
1289
+ type: Input
1290
+ }], data: [{
1291
+ type: Input
1292
+ }], options: [{
1293
+ type: Input
1294
+ }], container: [{
1295
+ type: ViewChild,
1296
+ args: ['container']
1297
+ }] } });
1298
+
1299
+ class AppPieChartComponent {
1300
+ constructor(doc, d3Factory) {
1301
+ this.doc = doc;
1302
+ this.d3Factory = d3Factory;
1303
+ /**
1304
+ * The chart id.
1305
+ */
1306
+ this.chartId = 'pie-0';
1307
+ /**
1308
+ * The chart data.
1309
+ */
1310
+ this.data = [];
1311
+ /**
1312
+ * The chart options.
1313
+ */
1314
+ this.options = {};
1315
+ }
1316
+ /**
1317
+ * The chart options constructor.
1318
+ * @returns chart options
1319
+ */
1320
+ chartOptions() {
1321
+ const margin = { top: 50, right: 50, bottom: 50, left: 50 };
1322
+ const minWidth = 350;
1323
+ const modifiers = {
1324
+ width: 10,
1325
+ height: 20,
1326
+ };
1327
+ const width = Math.min(minWidth, this.doc.body.clientWidth - modifiers.width) - margin.left - margin.right;
1328
+ const height = Math.min(width, this.doc.body.clientHeight - margin.top - margin.bottom - modifiers.height);
1329
+ const options = Object.assign({ width,
1330
+ height,
1331
+ margin }, this.options);
1332
+ return options;
1333
+ }
1334
+ /**
1335
+ * Draws the chart.
1336
+ */
1337
+ drawChart() {
1338
+ if (typeof this.container !== 'undefined') {
1339
+ const options = this.chartOptions();
1340
+ this.d3Factory.drawPieChart(this.container, this.data, options);
1341
+ }
1342
+ }
1343
+ /**
1344
+ * Actually draws the chart after the component view is initialized.
1345
+ */
1346
+ ngAfterViewInit() {
1347
+ this.drawChart();
1348
+ }
1349
+ /**
1350
+ * Redraws the chart on changes.
1351
+ */
1352
+ ngOnChanges(changes) {
1353
+ var _a, _b;
1354
+ const data = (_a = changes.data) === null || _a === void 0 ? void 0 : _a.currentValue;
1355
+ const options = (_b = changes.options) === null || _b === void 0 ? void 0 : _b.currentValue;
1356
+ if ((typeof data !== 'undefined' && data !== null) || (typeof options !== 'undefined' && options !== null)) {
1357
+ this.drawChart();
1358
+ }
1359
+ }
1360
+ }
1361
+ /** @nocollapse */ AppPieChartComponent.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "14.0.6", ngImport: i0, type: AppPieChartComponent, deps: [{ token: DOCUMENT }, { token: D3_CHART_FACTORY }], target: i0.ɵɵFactoryTarget.Component });
1362
+ /** @nocollapse */ AppPieChartComponent.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "14.0.0", version: "14.0.6", type: AppPieChartComponent, selector: "app-pie-chart", inputs: { chartId: "chartId", data: "data", options: "options" }, viewQueries: [{ propertyName: "container", first: true, predicate: ["container"], descendants: true }], usesOnChanges: true, ngImport: i0, template: "<div class=\"container\">\n <div id=\"{{ chartId }}\" #container></div>\n\n <small class=\"container--chart-title\">{{ options.chartTitle }}</small>\n</div>\n", styles: [":host{display:flex;flex-direction:row;flex-wrap:nowrap;justify-content:center}:host canvas{width:auto!important;height:150px}:host .container{flex:0 1 auto}:host .container--chart-title{display:block;text-align:center}\n"], changeDetection: i0.ChangeDetectionStrategy.OnPush });
1363
+ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "14.0.6", ngImport: i0, type: AppPieChartComponent, decorators: [{
1364
+ type: Component,
1365
+ args: [{ selector: 'app-pie-chart', changeDetection: ChangeDetectionStrategy.OnPush, template: "<div class=\"container\">\n <div id=\"{{ chartId }}\" #container></div>\n\n <small class=\"container--chart-title\">{{ options.chartTitle }}</small>\n</div>\n", styles: [":host{display:flex;flex-direction:row;flex-wrap:nowrap;justify-content:center}:host canvas{width:auto!important;height:150px}:host .container{flex:0 1 auto}:host .container--chart-title{display:block;text-align:center}\n"] }]
1366
+ }], ctorParameters: function () {
1367
+ return [{ type: Document, decorators: [{
1368
+ type: Inject,
1369
+ args: [DOCUMENT]
1370
+ }] }, { type: undefined, decorators: [{
1371
+ type: Inject,
1372
+ args: [D3_CHART_FACTORY]
1373
+ }] }];
1374
+ }, propDecorators: { chartId: [{
1375
+ type: Input
1376
+ }], data: [{
1377
+ type: Input
1378
+ }], options: [{
1379
+ type: Input
1380
+ }], container: [{
1381
+ type: ViewChild,
1382
+ args: ['container']
1383
+ }] } });
1384
+
1385
+ class AppRadarChartComponent {
1386
+ constructor(doc, d3Factory) {
1387
+ this.doc = doc;
1388
+ this.d3Factory = d3Factory;
1389
+ /**
1390
+ * The chart id.
1391
+ */
1392
+ this.chartId = 'radar-0';
1393
+ /**
1394
+ * The chart data.
1395
+ */
1396
+ this.data = [[]];
1397
+ /**
1398
+ * The chart options.
1399
+ */
1400
+ this.options = {};
1401
+ }
1402
+ /**
1403
+ * The chart options constructor.
1404
+ * @returns chart options
1405
+ */
1406
+ chartOptions() {
1407
+ var _a;
1408
+ const xsOffset = 500;
1409
+ const smOffset = 800;
1410
+ const mdOffset = 1024;
1411
+ const labelFactorDefault = 1.15;
1412
+ const labelFactorMd = 1.15;
1413
+ const labelFactorSm = 1.15;
1414
+ const labelFactorXs = 1.4;
1415
+ const wrapWidthDefault = 85;
1416
+ const wrapWidthMd = 80;
1417
+ const wrapWidthXs = 70;
1418
+ const bodyWidthAdjustment = 10;
1419
+ const width = Math.min((_a = this.options.width) !== null && _a !== void 0 ? _a : defaultRadarChartConfig.width, this.doc.body.clientWidth - defaultRadarChartConfig.margin.left - defaultRadarChartConfig.margin.right - bodyWidthAdjustment);
1420
+ const height = Math.min(width, this.doc.body.clientHeight - defaultRadarChartConfig.margin.top - defaultRadarChartConfig.margin.bottom - bodyWidthAdjustment);
1421
+ const labelFactor = width <= xsOffset ? labelFactorXs : width <= smOffset ? labelFactorSm : width <= mdOffset ? labelFactorMd : labelFactorDefault;
1422
+ const labelTextWrapWidth = width <= xsOffset ? wrapWidthXs : width <= mdOffset ? wrapWidthMd : wrapWidthDefault;
1423
+ const options = Object.assign({ width,
1424
+ height, maxValue: this.data[0].reduce((accumulator, item) => (item.value > accumulator ? item.value : accumulator), 0) + 1, levels: 5, roundStrokes: true, labelFactor,
1425
+ labelTextWrapWidth }, this.options);
1426
+ return options;
1427
+ }
1428
+ /**
1429
+ * Draws the chart.
1430
+ */
1431
+ drawChart() {
1432
+ if (typeof this.container !== 'undefined') {
1433
+ const options = this.chartOptions();
1434
+ this.d3Factory.drawRadarChart(this.container, this.data, options);
1435
+ }
1436
+ }
1437
+ /**
1438
+ * Actually draws the chart after the component view is initialized.
1439
+ */
1440
+ ngAfterViewInit() {
1441
+ this.drawChart();
1442
+ }
1443
+ /**
1444
+ * Redraws the chart on changes.
1445
+ */
1446
+ ngOnChanges(changes) {
1447
+ var _a, _b;
1448
+ const currentValue = (_a = changes.data) === null || _a === void 0 ? void 0 : _a.currentValue;
1449
+ const options = (_b = changes.options) === null || _b === void 0 ? void 0 : _b.currentValue;
1450
+ if ((typeof currentValue !== 'undefined' && currentValue !== null) || (typeof options !== 'undefined' && options !== null)) {
1451
+ this.drawChart();
1452
+ }
1453
+ }
1454
+ }
1455
+ /** @nocollapse */ AppRadarChartComponent.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "14.0.6", ngImport: i0, type: AppRadarChartComponent, deps: [{ token: DOCUMENT }, { token: D3_CHART_FACTORY }], target: i0.ɵɵFactoryTarget.Component });
1456
+ /** @nocollapse */ AppRadarChartComponent.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "14.0.0", version: "14.0.6", type: AppRadarChartComponent, selector: "app-radar-chart", inputs: { chartId: "chartId", data: "data", options: "options" }, viewQueries: [{ propertyName: "container", first: true, predicate: ["container"], descendants: true }], usesOnChanges: true, ngImport: i0, template: "<div class=\"container\" id=\"{{ chartId }}\" #container></div>\n", styles: [":host{display:flex;flex-direction:row;flex-wrap:nowrap;justify-content:center}:host .container{flex:0 1 auto}\n"], changeDetection: i0.ChangeDetectionStrategy.OnPush });
1457
+ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "14.0.6", ngImport: i0, type: AppRadarChartComponent, decorators: [{
1458
+ type: Component,
1459
+ args: [{ selector: 'app-radar-chart', changeDetection: ChangeDetectionStrategy.OnPush, template: "<div class=\"container\" id=\"{{ chartId }}\" #container></div>\n", styles: [":host{display:flex;flex-direction:row;flex-wrap:nowrap;justify-content:center}:host .container{flex:0 1 auto}\n"] }]
1460
+ }], ctorParameters: function () {
1461
+ return [{ type: Document, decorators: [{
1462
+ type: Inject,
1463
+ args: [DOCUMENT]
1464
+ }] }, { type: undefined, decorators: [{
1465
+ type: Inject,
1466
+ args: [D3_CHART_FACTORY]
1467
+ }] }];
1468
+ }, propDecorators: { chartId: [{
1469
+ type: Input
1470
+ }], data: [{
1471
+ type: Input
1472
+ }], options: [{
1473
+ type: Input
1474
+ }], container: [{
1475
+ type: ViewChild,
1476
+ args: ['container']
1477
+ }] } });
1478
+
1479
+ class AppForceDirectedChartComponent {
1480
+ constructor(doc, d3Factory) {
1481
+ this.doc = doc;
1482
+ this.d3Factory = d3Factory;
1483
+ /**
1484
+ * The chart identifier.
1485
+ */
1486
+ this.chartId = 'force-0';
1487
+ /**
1488
+ * The chart data.
1489
+ */
1490
+ this.data = {
1491
+ domains: [],
1492
+ entities: [],
1493
+ links: [],
1494
+ nodes: [],
1495
+ };
1496
+ /**
1497
+ * The chart options.
1498
+ */
1499
+ this.options = {};
1500
+ }
1501
+ /**
1502
+ * The chart options constructor.
1503
+ * @returns chart options
1504
+ */
1505
+ chartOptions() {
1506
+ const margin = { top: 50, right: 50, bottom: 50, left: 50 };
1507
+ const minWidth = 350;
1508
+ const modifiers = {
1509
+ width: 10,
1510
+ height: 20,
1511
+ };
1512
+ const width = Math.min(minWidth, this.doc.body.clientWidth - modifiers.width) - margin.left - margin.right;
1513
+ const height = Math.min(width, this.doc.body.clientHeight - margin.top - margin.bottom - modifiers.height);
1514
+ const options = Object.assign({ width, height, margin }, this.options);
1515
+ return options;
1516
+ }
1517
+ /**
1518
+ * Draws the chart.
1519
+ */
1520
+ drawChart() {
1521
+ if (typeof this.container !== 'undefined') {
1522
+ const options = this.chartOptions();
1523
+ this.d3Factory.drawForceDirectedChart(this.container, this.data, options);
1524
+ }
1525
+ }
1526
+ /**
1527
+ * Actually draws the chart after the component view is initialized.
1528
+ */
1529
+ ngAfterViewInit() {
1530
+ this.drawChart();
1531
+ }
1532
+ /**
1533
+ * Redraws the chart on changes.
1534
+ */
1535
+ ngOnChanges(changes) {
1536
+ var _a, _b, _c, _d, _e, _f;
1537
+ const prevData = (_a = changes.data) === null || _a === void 0 ? void 0 : _a.previousValue;
1538
+ const nextData = (_b = changes.data) === null || _b === void 0 ? void 0 : _b.currentValue;
1539
+ const options = (_c = changes.options) === null || _c === void 0 ? void 0 : _c.currentValue;
1540
+ if ((Boolean((_d = changes.data) === null || _d === void 0 ? void 0 : _d.currentValue) && ((_e = prevData === null || prevData === void 0 ? void 0 : prevData.nodes) !== null && _e !== void 0 ? _e : []).length !== ((_f = nextData === null || nextData === void 0 ? void 0 : nextData.nodes) !== null && _f !== void 0 ? _f : []).length) ||
1541
+ (typeof options !== 'undefined' && options !== null)) {
1542
+ this.drawChart();
1543
+ }
1544
+ }
1545
+ }
1546
+ /** @nocollapse */ AppForceDirectedChartComponent.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "14.0.6", ngImport: i0, type: AppForceDirectedChartComponent, deps: [{ token: DOCUMENT }, { token: D3_CHART_FACTORY }], target: i0.ɵɵFactoryTarget.Component });
1547
+ /** @nocollapse */ AppForceDirectedChartComponent.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "14.0.0", version: "14.0.6", type: AppForceDirectedChartComponent, selector: "app-force-directed-chart", inputs: { chartId: "chartId", data: "data", options: "options" }, viewQueries: [{ propertyName: "container", first: true, predicate: ["container"], descendants: true }], usesOnChanges: true, ngImport: i0, template: "<div class=\"container\">\n <div id=\"{{ chartId }}\" #container></div>\n\n <small class=\"container--chart-title\">{{ options.chartTitle }}</small>\n</div>\n", styles: [":host{display:flex;flex-direction:row;flex-wrap:nowrap;justify-content:center}:host .container{flex:0 1 auto}:host .container--chart-title{display:block;text-align:center}\n"], changeDetection: i0.ChangeDetectionStrategy.OnPush });
1548
+ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "14.0.6", ngImport: i0, type: AppForceDirectedChartComponent, decorators: [{
1549
+ type: Component,
1550
+ args: [{ selector: 'app-force-directed-chart', changeDetection: ChangeDetectionStrategy.OnPush, template: "<div class=\"container\">\n <div id=\"{{ chartId }}\" #container></div>\n\n <small class=\"container--chart-title\">{{ options.chartTitle }}</small>\n</div>\n", styles: [":host{display:flex;flex-direction:row;flex-wrap:nowrap;justify-content:center}:host .container{flex:0 1 auto}:host .container--chart-title{display:block;text-align:center}\n"] }]
1551
+ }], ctorParameters: function () {
1552
+ return [{ type: Document, decorators: [{
1553
+ type: Inject,
1554
+ args: [DOCUMENT]
1555
+ }] }, { type: undefined, decorators: [{
1556
+ type: Inject,
1557
+ args: [D3_CHART_FACTORY]
1558
+ }] }];
1559
+ }, propDecorators: { chartId: [{
1560
+ type: Input
1561
+ }], data: [{
1562
+ type: Input
1563
+ }], options: [{
1564
+ type: Input
1565
+ }], container: [{
1566
+ type: ViewChild,
1567
+ args: ['container']
1568
+ }] } });
1569
+
1570
+ class AppLineChartComponent {
1571
+ constructor(doc, d3Factory) {
1572
+ this.doc = doc;
1573
+ this.d3Factory = d3Factory;
1574
+ /**
1575
+ * The chart id.
1576
+ */
1577
+ this.chartId = 'line-0';
1578
+ /**
1579
+ * The chart data.
1580
+ */
1581
+ this.data = [];
1582
+ /**
1583
+ * The chart options.
1584
+ */
1585
+ this.options = {};
1586
+ }
1587
+ /**
1588
+ * The chart options constructor.
1589
+ * @returns chart options
1590
+ */
1591
+ chartOptions() {
1592
+ var _a, _b;
1593
+ const bodyWidthAdjustment = 10;
1594
+ const width = Math.min((_a = this.options.width) !== null && _a !== void 0 ? _a : defaultLineChartConfig.width, this.doc.body.clientWidth - defaultLineChartConfig.margin.left - defaultLineChartConfig.margin.right - bodyWidthAdjustment);
1595
+ const xTicksScale = 50;
1596
+ const ticks = {
1597
+ x: width / xTicksScale,
1598
+ y: Math.max(...this.data.map(item => item.value)),
1599
+ };
1600
+ const height = Math.min((_b = this.options.height) !== null && _b !== void 0 ? _b : width, this.doc.body.clientWidth - defaultLineChartConfig.margin.top - defaultLineChartConfig.margin.bottom - bodyWidthAdjustment);
1601
+ const options = Object.assign({ width,
1602
+ height,
1603
+ ticks }, this.options);
1604
+ return options;
1605
+ }
1606
+ /**
1607
+ * Draws the chart.
1608
+ */
1609
+ drawChart() {
1610
+ if (typeof this.container !== 'undefined') {
1611
+ const options = this.chartOptions();
1612
+ this.d3Factory.drawLineChart(this.container, this.data, options);
1613
+ }
1614
+ }
1615
+ /**
1616
+ * Actually draws the chart after the component view is initialized.
1617
+ */
1618
+ ngAfterViewInit() {
1619
+ this.drawChart();
1620
+ }
1621
+ /**
1622
+ * Redraws the chart on changes.
1623
+ */
1624
+ ngOnChanges(changes) {
1625
+ var _a, _b;
1626
+ const data = (_a = changes.data) === null || _a === void 0 ? void 0 : _a.currentValue;
1627
+ const options = (_b = changes.options) === null || _b === void 0 ? void 0 : _b.currentValue;
1628
+ if ((typeof data !== 'undefined' && data !== null) || (typeof options !== 'undefined' && options !== null)) {
1629
+ this.drawChart();
1630
+ }
1631
+ }
1632
+ }
1633
+ /** @nocollapse */ AppLineChartComponent.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "14.0.6", ngImport: i0, type: AppLineChartComponent, deps: [{ token: DOCUMENT }, { token: D3_CHART_FACTORY }], target: i0.ɵɵFactoryTarget.Component });
1634
+ /** @nocollapse */ AppLineChartComponent.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "14.0.0", version: "14.0.6", type: AppLineChartComponent, selector: "app-line-chart", inputs: { chartId: "chartId", data: "data", options: "options" }, viewQueries: [{ propertyName: "container", first: true, predicate: ["container"], descendants: true }], usesOnChanges: true, ngImport: i0, template: "<div class=\"container\" id=\"{{ chartId }}\" #container></div>\n", styles: [":host{display:flex;flex-direction:row;flex-wrap:nowrap;justify-content:center}:host .container{flex:0 1 auto}\n"], changeDetection: i0.ChangeDetectionStrategy.OnPush });
1635
+ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "14.0.6", ngImport: i0, type: AppLineChartComponent, decorators: [{
1636
+ type: Component,
1637
+ args: [{ selector: 'app-line-chart', changeDetection: ChangeDetectionStrategy.OnPush, template: "<div class=\"container\" id=\"{{ chartId }}\" #container></div>\n", styles: [":host{display:flex;flex-direction:row;flex-wrap:nowrap;justify-content:center}:host .container{flex:0 1 auto}\n"] }]
1638
+ }], ctorParameters: function () {
1639
+ return [{ type: Document, decorators: [{
1640
+ type: Inject,
1641
+ args: [DOCUMENT]
1642
+ }] }, { type: undefined, decorators: [{
1643
+ type: Inject,
1644
+ args: [D3_CHART_FACTORY]
1645
+ }] }];
1646
+ }, propDecorators: { chartId: [{
1647
+ type: Input
1648
+ }], data: [{
1649
+ type: Input
1650
+ }], options: [{
1651
+ type: Input
1652
+ }], container: [{
1653
+ type: ViewChild,
1654
+ args: ['container']
1655
+ }] } });
1656
+
1657
+ class AppChartExamplesComponent {
1658
+ constructor(breakpointObserver) {
1659
+ this.breakpointObserver = breakpointObserver;
1660
+ this.breakpoint$ = this.breakpointObserver
1661
+ .observe([Breakpoints.XSmall, Breakpoints.Small, Breakpoints.Medium, Breakpoints.Large, Breakpoints.XLarge])
1662
+ .pipe(map(result => { var _a; return (_a = Object.keys(result.breakpoints).find(item => result.breakpoints[item])) !== null && _a !== void 0 ? _a : 'unknown'; }));
1663
+ this.barChartConfig$ = this.breakpoint$.pipe(switchMap(() => timer(this.timeout).pipe(first(), map(() => ({ data: this.barChartData, options: this.barChartOptions() })))));
1664
+ this.lineChartConfig$ = this.breakpoint$.pipe(switchMap(() => timer(this.timeout).pipe(first(), map(() => ({ data: this.lineChartData, options: this.lineChartOptions() })))));
1665
+ this.radarChartConfig$ = this.breakpoint$.pipe(switchMap(() => timer(this.timeout).pipe(first(), map(() => ({ data: this.radarChartData, options: this.radarChartOptions() })))));
1666
+ this.pieChartConfig$ = this.breakpoint$.pipe(switchMap(() => timer(this.timeout).pipe(first(), map(() => ({ data: this.pieChartData, options: this.pieChartOptions() })))));
1667
+ this.forceDirectedChartConfig$ = this.breakpoint$.pipe(switchMap(() => timer(this.timeout).pipe(first(), map(() => ({ data: this.forceDirectedChartData, options: this.forceDirectedChartOptions() })))));
1668
+ this.timeout = 100;
1669
+ }
1670
+ /**
1671
+ * Sample bar chart data.
1672
+ */
1673
+ get barChartData() {
1674
+ return [
1675
+ { title: 'one', value: 1 },
1676
+ { title: 'two', value: 2 },
1677
+ { title: 'three', value: 3 },
1678
+ { title: 'four', value: 4 },
1679
+ { title: 'five', value: 5 },
1680
+ ];
1681
+ }
1682
+ /**
1683
+ * Sample line chart data.
1684
+ */
1685
+ get lineChartData() {
1686
+ const increment = 10000;
1687
+ const multiplier = 2;
1688
+ return [
1689
+ { timestamp: new Date().getTime(), value: 1 },
1690
+ { timestamp: new Date().getTime() + increment, value: 10 },
1691
+ { timestamp: new Date().getTime() + increment * multiplier, value: 3 },
1692
+ { timestamp: new Date().getTime() + increment * Math.pow(multiplier, multiplier), value: 5 },
1693
+ { timestamp: new Date().getTime() + increment * Math.pow(multiplier, multiplier) * multiplier, value: 4 },
1694
+ { timestamp: new Date().getTime() + increment * Math.pow(multiplier, multiplier) * Math.pow(multiplier, multiplier), value: 7 },
1695
+ {
1696
+ timestamp: new Date().getTime() + increment * Math.pow(multiplier, multiplier) * Math.pow(multiplier, multiplier) * multiplier,
1697
+ value: 8,
1698
+ },
1699
+ ];
1700
+ }
1701
+ /**
1702
+ * Sample radar chart data.
1703
+ */
1704
+ get radarChartData() {
1705
+ return [
1706
+ [
1707
+ { axis: 'one', value: 1, unit: 'x' },
1708
+ { axis: 'two', value: 2, unit: 'x' },
1709
+ { axis: 'three', value: 3, unit: 'x' },
1710
+ { axis: 'four', value: 4, unit: 'x' },
1711
+ { axis: 'five', value: 5, unit: 'x' },
1712
+ { axis: 'six', value: 6, unit: 'x' },
1713
+ { axis: 'seven', value: 7, unit: 'x' },
1714
+ { axis: 'eight', value: 8, unit: 'x' },
1715
+ { axis: 'nine (long labels are wrapped)', value: 9, unit: 'x' },
1716
+ ],
1717
+ [
1718
+ { axis: 'one', value: 9, unit: 'y' },
1719
+ { axis: 'two', value: 8, unit: 'y' },
1720
+ { axis: 'three', value: 7, unit: 'y' },
1721
+ { axis: 'four', value: 6, unit: 'y' },
1722
+ { axis: 'five', value: 5, unit: 'y' },
1723
+ { axis: 'six', value: 4, unit: 'y' },
1724
+ { axis: 'seven', value: 3, unit: 'y' },
1725
+ { axis: 'eight', value: 2, unit: 'y' },
1726
+ { axis: 'nine (long labels are wrapped)', value: 1, unit: 'y' },
1727
+ ],
1728
+ ];
1729
+ }
1730
+ /**
1731
+ * Sample pie chart data.
1732
+ */
1733
+ get pieChartData() {
1734
+ return [
1735
+ { key: 'one', y: 1 },
1736
+ { key: 'two', y: 2 },
1737
+ { key: 'three', y: 3 },
1738
+ { key: 'four', y: 4 },
1739
+ { key: 'five', y: 5 },
1740
+ { key: 'six', y: 6 },
1741
+ ];
1742
+ }
1743
+ /**
1744
+ * Sample force directed chart data.
1745
+ */
1746
+ get forceDirectedChartData() {
1747
+ const input = {
1748
+ domains: ['first', 'second', 'third'],
1749
+ entities: [
1750
+ { name: 'one', domains: ['first'], img: '' },
1751
+ { name: 'two', domains: ['second'], img: '' },
1752
+ { name: 'three', domains: ['third'], img: '' },
1753
+ { name: 'four', domains: ['first', 'second'], img: '' },
1754
+ { name: 'five', domains: ['second'], img: '' },
1755
+ { name: 'six', domains: ['third', 'second'], img: '' },
1756
+ { name: 'seven', domains: ['second'], img: '' },
1757
+ { name: 'eight', domains: ['third'], img: '' },
1758
+ ],
1759
+ };
1760
+ const domains = input.domains.map((name, index) => ({ index, name, value: 1 }));
1761
+ const entities = input.entities.map((app, index) => ({
1762
+ index: index,
1763
+ name: app.name,
1764
+ domains: [...app.domains],
1765
+ img: app.img,
1766
+ linksCount: 0,
1767
+ }));
1768
+ const nodes = [...entities];
1769
+ const links = entities
1770
+ .map(entity => {
1771
+ return entity.domains.map(domain => {
1772
+ var _a, _b;
1773
+ const source = (_b = (_a = domains.find(value => domain === value.name)) === null || _a === void 0 ? void 0 : _a.index) !== null && _b !== void 0 ? _b : -1;
1774
+ const target = entity.index;
1775
+ return { source, target };
1776
+ });
1777
+ })
1778
+ .reduce((accumulator, item) => (Array.isArray(item) ? [...accumulator, ...item] : [...accumulator, item]), [])
1779
+ .filter(link => link.source !== -1 && link.target !== -1 && typeof link.target !== 'undefined');
1780
+ const chartData = {
1781
+ domains,
1782
+ entities: entities.map(item => (Object.assign(Object.assign({}, item), { linksCount: links.reduce((acc, link) => (link.target === item.index ? acc + 1 : acc), 0) }))),
1783
+ links,
1784
+ nodes,
1785
+ };
1786
+ return chartData;
1787
+ }
1788
+ barChartOptions() {
1789
+ return {
1790
+ chartTitle: 'Example bar chart',
1791
+ xAxisTitle: 'long x axis title',
1792
+ yAxisTitle: 'long y axis title',
1793
+ };
1794
+ }
1795
+ lineChartOptions() {
1796
+ return {
1797
+ chartTitle: 'Example line chart',
1798
+ xAxisTitle: 'Date range',
1799
+ yAxisTitle: 'Value range',
1800
+ };
1801
+ }
1802
+ radarChartOptions() {
1803
+ return {
1804
+ chartTitle: 'Example radar chart',
1805
+ };
1806
+ }
1807
+ pieChartOptions() {
1808
+ return {
1809
+ chartTitle: 'Example pie chart',
1810
+ };
1811
+ }
1812
+ forceDirectedChartOptions() {
1813
+ return {
1814
+ chartTitle: 'Example force directed chart',
1815
+ };
1816
+ }
1817
+ }
1818
+ /** @nocollapse */ AppChartExamplesComponent.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "14.0.6", ngImport: i0, type: AppChartExamplesComponent, deps: [{ token: i1.BreakpointObserver }], target: i0.ɵɵFactoryTarget.Component });
1819
+ /** @nocollapse */ AppChartExamplesComponent.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "14.0.0", version: "14.0.6", type: AppChartExamplesComponent, selector: "app-chart-examples", ngImport: i0, template: "<div class=\"container\" *ngIf=\"barChartConfig$ | async as config\">\n <app-bar-chart [chartId]=\"'bar-example-1'\" [data]=\"config.data\" [options]=\"config.options\"></app-bar-chart>\n</div>\n\n<hr [ngStyle]=\"{ width: '100%' }\" />\n\n<div class=\"container\" *ngIf=\"lineChartConfig$ | async as config\">\n <app-line-chart [chartId]=\"'line-example-1'\" [data]=\"config.data\" [options]=\"config.options\"></app-line-chart>\n</div>\n\n<hr [ngStyle]=\"{ width: '100%' }\" />\n\n<div class=\"container\" *ngIf=\"radarChartConfig$ | async as config\">\n <app-radar-chart [chartId]=\"'radar-example-1'\" [data]=\"config.data\" [options]=\"config.options\"></app-radar-chart>\n</div>\n\n<hr [ngStyle]=\"{ width: '100%' }\" />\n\n<div class=\"container\" *ngIf=\"pieChartConfig$ | async as config\">\n <app-pie-chart [chartId]=\"'pie-example-1'\" [data]=\"config.data\" [options]=\"config.options\"></app-pie-chart>\n</div>\n\n<hr [ngStyle]=\"{ width: '100%' }\" />\n\n<div class=\"container\" *ngIf=\"forceDirectedChartConfig$ | async as config\">\n <app-force-directed-chart\n [chartId]=\"'force-directed-example-1'\"\n [data]=\"config.data\"\n [options]=\"config.options\"\n ></app-force-directed-chart>\n</div>\n", styles: [":host{display:flex;flex-direction:row;flex-wrap:wrap;justify-content:center}:host .container{flex:1 1 auto;width:100%}\n"], dependencies: [{ kind: "directive", type: i2.NgIf, selector: "[ngIf]", inputs: ["ngIf", "ngIfThen", "ngIfElse"] }, { kind: "directive", type: i2.NgStyle, selector: "[ngStyle]", inputs: ["ngStyle"] }, { kind: "component", type: AppPieChartComponent, selector: "app-pie-chart", inputs: ["chartId", "data", "options"] }, { kind: "component", type: AppRadarChartComponent, selector: "app-radar-chart", inputs: ["chartId", "data", "options"] }, { kind: "component", type: AppForceDirectedChartComponent, selector: "app-force-directed-chart", inputs: ["chartId", "data", "options"] }, { kind: "component", type: AppBarChartComponent, selector: "app-bar-chart", inputs: ["chartId", "data", "options"] }, { kind: "component", type: AppLineChartComponent, selector: "app-line-chart", inputs: ["chartId", "data", "options"] }, { kind: "pipe", type: i2.AsyncPipe, name: "async" }], changeDetection: i0.ChangeDetectionStrategy.OnPush });
1820
+ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "14.0.6", ngImport: i0, type: AppChartExamplesComponent, decorators: [{
1821
+ type: Component,
1822
+ args: [{ selector: 'app-chart-examples', changeDetection: ChangeDetectionStrategy.OnPush, template: "<div class=\"container\" *ngIf=\"barChartConfig$ | async as config\">\n <app-bar-chart [chartId]=\"'bar-example-1'\" [data]=\"config.data\" [options]=\"config.options\"></app-bar-chart>\n</div>\n\n<hr [ngStyle]=\"{ width: '100%' }\" />\n\n<div class=\"container\" *ngIf=\"lineChartConfig$ | async as config\">\n <app-line-chart [chartId]=\"'line-example-1'\" [data]=\"config.data\" [options]=\"config.options\"></app-line-chart>\n</div>\n\n<hr [ngStyle]=\"{ width: '100%' }\" />\n\n<div class=\"container\" *ngIf=\"radarChartConfig$ | async as config\">\n <app-radar-chart [chartId]=\"'radar-example-1'\" [data]=\"config.data\" [options]=\"config.options\"></app-radar-chart>\n</div>\n\n<hr [ngStyle]=\"{ width: '100%' }\" />\n\n<div class=\"container\" *ngIf=\"pieChartConfig$ | async as config\">\n <app-pie-chart [chartId]=\"'pie-example-1'\" [data]=\"config.data\" [options]=\"config.options\"></app-pie-chart>\n</div>\n\n<hr [ngStyle]=\"{ width: '100%' }\" />\n\n<div class=\"container\" *ngIf=\"forceDirectedChartConfig$ | async as config\">\n <app-force-directed-chart\n [chartId]=\"'force-directed-example-1'\"\n [data]=\"config.data\"\n [options]=\"config.options\"\n ></app-force-directed-chart>\n</div>\n", styles: [":host{display:flex;flex-direction:row;flex-wrap:wrap;justify-content:center}:host .container{flex:1 1 auto;width:100%}\n"] }]
1823
+ }], ctorParameters: function () { return [{ type: i1.BreakpointObserver }]; } });
1824
+
1825
+ class AppClientD3ChartsModule {
1826
+ }
1827
+ /** @nocollapse */ AppClientD3ChartsModule.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "14.0.6", ngImport: i0, type: AppClientD3ChartsModule, deps: [], target: i0.ɵɵFactoryTarget.NgModule });
1828
+ /** @nocollapse */ AppClientD3ChartsModule.ɵmod = i0.ɵɵngDeclareNgModule({ minVersion: "14.0.0", version: "14.0.6", ngImport: i0, type: AppClientD3ChartsModule, declarations: [AppPieChartComponent,
1829
+ AppRadarChartComponent,
1830
+ AppForceDirectedChartComponent,
1831
+ AppBarChartComponent,
1832
+ AppLineChartComponent,
1833
+ AppChartExamplesComponent], imports: [CommonModule], exports: [AppPieChartComponent,
1834
+ AppRadarChartComponent,
1835
+ AppForceDirectedChartComponent,
1836
+ AppBarChartComponent,
1837
+ AppLineChartComponent,
1838
+ AppChartExamplesComponent] });
1839
+ /** @nocollapse */ AppClientD3ChartsModule.ɵinj = i0.ɵɵngDeclareInjector({ minVersion: "12.0.0", version: "14.0.6", ngImport: i0, type: AppClientD3ChartsModule, imports: [CommonModule] });
1840
+ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "14.0.6", ngImport: i0, type: AppClientD3ChartsModule, decorators: [{
1841
+ type: NgModule,
1842
+ args: [{
1843
+ imports: [CommonModule],
1844
+ declarations: [
1845
+ AppPieChartComponent,
1846
+ AppRadarChartComponent,
1847
+ AppForceDirectedChartComponent,
1848
+ AppBarChartComponent,
1849
+ AppLineChartComponent,
1850
+ AppChartExamplesComponent,
1851
+ ],
1852
+ exports: [
1853
+ AppPieChartComponent,
1854
+ AppRadarChartComponent,
1855
+ AppForceDirectedChartComponent,
1856
+ AppBarChartComponent,
1857
+ AppLineChartComponent,
1858
+ AppChartExamplesComponent,
1859
+ ],
1860
+ }]
1861
+ }] });
1862
+
1863
+ /**
1864
+ * Generated bundle index. Do not edit.
1865
+ */
1866
+
1867
+ export { AppBarChartComponent, AppChartExamplesComponent, AppClientD3ChartsModule, AppForceDirectedChartComponent, AppLineChartComponent, AppPieChartComponent, AppRadarChartComponent, defaultBarChartConfig, defaultForceDirectedChartConfig, defaultLineChartConfig, defaultPieChartConfig, defaultRadarChartConfig, drawBarChart, drawForceDirectedChart, drawLineChart, drawPieChart, drawRadarChart };
1868
+ //# sourceMappingURL=rfprodz-client-d3-charts.mjs.map