@fluentui/react-charting 5.19.17 → 5.19.19
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/CHANGELOG.json +45 -1
- package/CHANGELOG.md +21 -2
- package/dist/react-charting.js +1 -1
- package/dist/react-charting.min.js +1 -1
- package/lib/components/HeatMapChart/HeatMapChart.base.js +43 -43
- package/lib/components/HeatMapChart/HeatMapChart.base.js.map +1 -1
- package/lib/components/SankeyChart/SankeyChart.base.d.ts +1 -27
- package/lib/components/SankeyChart/SankeyChart.base.js +246 -260
- package/lib/components/SankeyChart/SankeyChart.base.js.map +1 -1
- package/lib/version.js +1 -1
- package/lib/version.js.map +1 -1
- package/lib-amd/components/HeatMapChart/HeatMapChart.base.js +43 -43
- package/lib-amd/components/HeatMapChart/HeatMapChart.base.js.map +1 -1
- package/lib-amd/components/SankeyChart/SankeyChart.base.d.ts +1 -27
- package/lib-amd/components/SankeyChart/SankeyChart.base.js +241 -255
- package/lib-amd/components/SankeyChart/SankeyChart.base.js.map +1 -1
- package/lib-amd/version.js +1 -1
- package/lib-amd/version.js.map +1 -1
- package/lib-commonjs/components/HeatMapChart/HeatMapChart.base.js +43 -43
- package/lib-commonjs/components/HeatMapChart/HeatMapChart.base.js.map +1 -1
- package/lib-commonjs/components/SankeyChart/SankeyChart.base.d.ts +1 -27
- package/lib-commonjs/components/SankeyChart/SankeyChart.base.js +245 -259
- package/lib-commonjs/components/SankeyChart/SankeyChart.base.js.map +1 -1
- package/lib-commonjs/version.js +1 -1
- package/lib-commonjs/version.js.map +1 -1
- package/package.json +3 -3
|
@@ -1,13 +1,13 @@
|
|
|
1
1
|
import { __assign, __extends } from "tslib";
|
|
2
|
-
import
|
|
2
|
+
import { FocusZone, FocusZoneDirection, FocusZoneTabbableElements } from '@fluentui/react-focus';
|
|
3
|
+
import { Callout, DirectionalHint } from '@fluentui/react/lib/Callout';
|
|
3
4
|
import { classNamesFunction, getId, getRTL, memoizeFunction } from '@fluentui/react/lib/Utilities';
|
|
4
|
-
import { sankey as d3Sankey, sankeyRight, sankeyJustify } from 'd3-sankey';
|
|
5
|
-
import { area as d3Area, curveBumpX as d3CurveBasis } from 'd3-shape';
|
|
6
5
|
import { sum as d3Sum } from 'd3-array';
|
|
7
|
-
import {
|
|
8
|
-
import { Callout, DirectionalHint } from '@fluentui/react/lib/Callout';
|
|
6
|
+
import { sankey as d3Sankey, sankeyJustify, sankeyRight } from 'd3-sankey';
|
|
9
7
|
import { select, selectAll } from 'd3-selection';
|
|
10
|
-
import {
|
|
8
|
+
import { area as d3Area, curveBumpX as d3CurveBasis } from 'd3-shape';
|
|
9
|
+
import * as React from 'react';
|
|
10
|
+
import { ChartHoverCard } from '../../index';
|
|
11
11
|
var getClassNames = classNamesFunction();
|
|
12
12
|
var PADDING_PERCENTAGE = 0.3;
|
|
13
13
|
var NON_SELECTED_NODE_AND_STREAM_COLOR = '#757575';
|
|
@@ -31,12 +31,167 @@ var SELECTED_STREAM_OPACITY = 0.3;
|
|
|
31
31
|
var NON_SELECTED_STREAM_BORDER_OPACITY = 0.5;
|
|
32
32
|
var DEFAULT_TEXT_COLOR = '#323130';
|
|
33
33
|
var NON_SELECTED_TEXT_COLOR = '#FFFFFF';
|
|
34
|
+
// eslint-disable-next-line @typescript-eslint/no-explicit-any
|
|
35
|
+
function getSelectedNodes(selectedLinks) {
|
|
36
|
+
var nodes = [];
|
|
37
|
+
selectedLinks.forEach(function (link) {
|
|
38
|
+
nodes.push(link.target);
|
|
39
|
+
if (nodes.indexOf(link.source) === -1) {
|
|
40
|
+
nodes.push(link.source);
|
|
41
|
+
}
|
|
42
|
+
});
|
|
43
|
+
return nodes;
|
|
44
|
+
}
|
|
45
|
+
function getSelectedLinks(singleNode) {
|
|
46
|
+
// eslint-disable-next-line @typescript-eslint/no-explicit-any, no-array-constructor
|
|
47
|
+
var q = new Array();
|
|
48
|
+
var finalLinks = new Set();
|
|
49
|
+
singleNode.sourceLinks.forEach(function (link) {
|
|
50
|
+
q.push(link);
|
|
51
|
+
finalLinks.add(link);
|
|
52
|
+
});
|
|
53
|
+
while (q.length > 0) {
|
|
54
|
+
var poppedLink = q.shift();
|
|
55
|
+
var node = poppedLink.target;
|
|
56
|
+
if (node && node.sourceLinks) {
|
|
57
|
+
node.sourceLinks.forEach(function (link) {
|
|
58
|
+
finalLinks.add(link);
|
|
59
|
+
q.push(link);
|
|
60
|
+
});
|
|
61
|
+
}
|
|
62
|
+
}
|
|
63
|
+
if (singleNode.targetLinks) {
|
|
64
|
+
singleNode.targetLinks.forEach(function (link) {
|
|
65
|
+
q.push(link);
|
|
66
|
+
finalLinks.add(link);
|
|
67
|
+
});
|
|
68
|
+
}
|
|
69
|
+
while (q.length > 0) {
|
|
70
|
+
var poppedLink = q.shift();
|
|
71
|
+
var node = poppedLink.source;
|
|
72
|
+
if (node && node.targetLinks) {
|
|
73
|
+
node.targetLinks.forEach(function (link) {
|
|
74
|
+
finalLinks.add(link);
|
|
75
|
+
q.push(link);
|
|
76
|
+
});
|
|
77
|
+
}
|
|
78
|
+
}
|
|
79
|
+
return finalLinks;
|
|
80
|
+
}
|
|
81
|
+
function getSelectedLinksforStreamHover(singleLink) {
|
|
82
|
+
// eslint-disable-next-line @typescript-eslint/no-explicit-any, no-array-constructor
|
|
83
|
+
var q = new Array();
|
|
84
|
+
var finalLinks = new Set();
|
|
85
|
+
var finalNodes = new Set();
|
|
86
|
+
q.push(singleLink.source);
|
|
87
|
+
finalLinks.add(singleLink);
|
|
88
|
+
while (q.length > 0) {
|
|
89
|
+
var poppedNode = q.shift();
|
|
90
|
+
finalNodes.add(poppedNode);
|
|
91
|
+
if (poppedNode.targetLinks && poppedNode.targetLinks.length > 0) {
|
|
92
|
+
poppedNode.targetLinks.forEach(function (link) {
|
|
93
|
+
q.push(link.source);
|
|
94
|
+
finalLinks.add(link);
|
|
95
|
+
});
|
|
96
|
+
}
|
|
97
|
+
}
|
|
98
|
+
q.push(singleLink.target);
|
|
99
|
+
while (q.length > 0) {
|
|
100
|
+
var poppedNode = q.shift();
|
|
101
|
+
finalNodes.add(poppedNode);
|
|
102
|
+
if (poppedNode.sourceLinks && poppedNode.sourceLinks.length > 0) {
|
|
103
|
+
poppedNode.sourceLinks.forEach(function (link) {
|
|
104
|
+
q.push(link.target);
|
|
105
|
+
finalLinks.add(link);
|
|
106
|
+
});
|
|
107
|
+
}
|
|
108
|
+
}
|
|
109
|
+
return {
|
|
110
|
+
selectedLinks: finalLinks,
|
|
111
|
+
selectedNodes: finalNodes,
|
|
112
|
+
};
|
|
113
|
+
}
|
|
114
|
+
/**
|
|
115
|
+
* This is used to group nodes by column index.
|
|
116
|
+
*/
|
|
117
|
+
function populateNodeInColumns(graph, sankey) {
|
|
118
|
+
sankey(graph);
|
|
119
|
+
var nodesInColumn = {};
|
|
120
|
+
graph.nodes.forEach(function (node) {
|
|
121
|
+
var columnId = node.layer;
|
|
122
|
+
if (nodesInColumn[columnId]) {
|
|
123
|
+
nodesInColumn[columnId].push(node);
|
|
124
|
+
}
|
|
125
|
+
else {
|
|
126
|
+
nodesInColumn[columnId] = [node];
|
|
127
|
+
}
|
|
128
|
+
});
|
|
129
|
+
return nodesInColumn;
|
|
130
|
+
}
|
|
131
|
+
/**
|
|
132
|
+
* This is used to normalize the nodes value whose value is less than 1% of the total column value.
|
|
133
|
+
*/
|
|
134
|
+
function adjustOnePercentHeightNodes(nodesInColumn) {
|
|
135
|
+
var totalColumnValue = Object.values(nodesInColumn).map(function (column) {
|
|
136
|
+
return d3Sum(column, function (node) { return node.value; });
|
|
137
|
+
});
|
|
138
|
+
totalColumnValue.forEach(function (columnValue, index) {
|
|
139
|
+
var totalPercentage = 0;
|
|
140
|
+
nodesInColumn[index].forEach(function (node) {
|
|
141
|
+
var nodePercentage = (node.value / columnValue) * 100;
|
|
142
|
+
node.actualValue = node.value;
|
|
143
|
+
//if the value is less than 1% then we are making it as 1% of total .
|
|
144
|
+
if (nodePercentage < 1) {
|
|
145
|
+
node.value = 0.01 * columnValue;
|
|
146
|
+
totalPercentage = totalPercentage + 1;
|
|
147
|
+
}
|
|
148
|
+
else {
|
|
149
|
+
totalPercentage = totalPercentage + nodePercentage;
|
|
150
|
+
}
|
|
151
|
+
});
|
|
152
|
+
//since we have adjusted the value to be 1% but we need to keep the sum of the percentage value under 100.
|
|
153
|
+
var scalingRatio = totalPercentage !== 0 ? totalPercentage / 100 : 1;
|
|
154
|
+
if (scalingRatio > 1) {
|
|
155
|
+
nodesInColumn[index].forEach(function (node) {
|
|
156
|
+
node.value = node.value / scalingRatio;
|
|
157
|
+
changeColumnValue(node, node.actualValue, node.value);
|
|
158
|
+
});
|
|
159
|
+
}
|
|
160
|
+
});
|
|
161
|
+
}
|
|
162
|
+
/**
|
|
163
|
+
* This is used for normalizing each links value for reflecting the normalized node value.
|
|
164
|
+
*/
|
|
165
|
+
function changeColumnValue(node, originalValue, normalizedValue) {
|
|
166
|
+
node.sourceLinks.forEach(function (link) {
|
|
167
|
+
link.unnormalizedValue = link.value;
|
|
168
|
+
var linkRatio = link.value / originalValue;
|
|
169
|
+
link.value = normalizedValue * linkRatio;
|
|
170
|
+
});
|
|
171
|
+
node.targetLinks.forEach(function (link) {
|
|
172
|
+
link.unnormalizedValue = link.value;
|
|
173
|
+
var linkRatio = link.value / originalValue;
|
|
174
|
+
link.value = normalizedValue * linkRatio;
|
|
175
|
+
});
|
|
176
|
+
}
|
|
177
|
+
/**
|
|
178
|
+
* This is used for calculating the node non normalized value based on link non normalized value.
|
|
179
|
+
*/
|
|
180
|
+
function populateNodeActualValue(data) {
|
|
181
|
+
data.links.forEach(function (link) {
|
|
182
|
+
if (!link.unnormalizedValue) {
|
|
183
|
+
link.unnormalizedValue = link.value;
|
|
184
|
+
}
|
|
185
|
+
});
|
|
186
|
+
data.nodes.forEach(function (node) {
|
|
187
|
+
node.actualValue = Math.max(d3Sum(node.sourceLinks, function (link) { return link.unnormalizedValue; }), d3Sum(node.targetLinks, function (link) { return link.unnormalizedValue; }));
|
|
188
|
+
});
|
|
189
|
+
}
|
|
34
190
|
var SankeyChartBase = /** @class */ (function (_super) {
|
|
35
191
|
__extends(SankeyChartBase, _super);
|
|
36
192
|
function SankeyChartBase(props) {
|
|
37
193
|
var _this = _super.call(this, props) || this;
|
|
38
194
|
_this._isRtl = getRTL();
|
|
39
|
-
// eslint-disable-next-line @typescript-eslint/no-explicit-any
|
|
40
195
|
_this._onCloseCallout = function () {
|
|
41
196
|
_this.setState({
|
|
42
197
|
isCalloutVisible: false,
|
|
@@ -47,27 +202,27 @@ var SankeyChartBase = /** @class */ (function (_super) {
|
|
|
47
202
|
_this._onBlur = function () {
|
|
48
203
|
/**/
|
|
49
204
|
};
|
|
50
|
-
// eslint-disable-next-line @typescript-eslint/no-explicit-any
|
|
51
205
|
_this._fillNodeColors = function (singleNode) {
|
|
52
|
-
|
|
206
|
+
var state = _this.state;
|
|
207
|
+
if (!state.selectedState) {
|
|
53
208
|
return singleNode.color;
|
|
54
209
|
}
|
|
55
|
-
else if (
|
|
56
|
-
return
|
|
210
|
+
else if (state.selectedState && state.selectedNodes.has(singleNode.index) && state.selectedNode) {
|
|
211
|
+
return state.selectedNode.color;
|
|
57
212
|
}
|
|
58
|
-
else if (
|
|
213
|
+
else if (state.selectedState && !state.selectedNode) {
|
|
59
214
|
return singleNode.color;
|
|
60
215
|
}
|
|
61
216
|
};
|
|
62
|
-
// eslint-disable-next-line @typescript-eslint/no-explicit-any
|
|
63
217
|
_this._fillNodeBorder = function (singleNode) {
|
|
64
|
-
|
|
218
|
+
var state = _this.state;
|
|
219
|
+
if (!state.selectedState) {
|
|
65
220
|
return singleNode.borderColor;
|
|
66
221
|
}
|
|
67
|
-
else if (
|
|
68
|
-
return
|
|
222
|
+
else if (state.selectedState && state.selectedNodes.has(singleNode.index) && state.selectedNode) {
|
|
223
|
+
return state.selectedNode.borderColor;
|
|
69
224
|
}
|
|
70
|
-
else if (
|
|
225
|
+
else if (state.selectedState && state.selectedNodes.has(singleNode.index)) {
|
|
71
226
|
return singleNode.borderColor;
|
|
72
227
|
}
|
|
73
228
|
return singleNode.borderColor;
|
|
@@ -104,148 +259,70 @@ var SankeyChartBase = /** @class */ (function (_super) {
|
|
|
104
259
|
var _this = this;
|
|
105
260
|
if (!this._isChartEmpty()) {
|
|
106
261
|
var _a = this.props, theme = _a.theme, className = _a.className, styles = _a.styles, pathColor = _a.pathColor;
|
|
107
|
-
|
|
262
|
+
var state = this.state;
|
|
263
|
+
var classNames = getClassNames(styles, {
|
|
108
264
|
theme: theme,
|
|
109
|
-
width:
|
|
110
|
-
height:
|
|
265
|
+
width: state.containerWidth,
|
|
266
|
+
height: state.containerHeight,
|
|
111
267
|
pathColor: pathColor,
|
|
112
268
|
className: className,
|
|
113
269
|
});
|
|
114
270
|
// We are using the this._margins.left and this._margins.top in sankey extent while constructing the layout
|
|
115
271
|
var _b = this._preRenderLayout(), height = _b.height, width = _b.width;
|
|
116
|
-
this.
|
|
272
|
+
var sankeyChartData = this.props.data.SankeyChartData;
|
|
273
|
+
this._normalizeData(sankeyChartData);
|
|
117
274
|
var nodePadding = 8;
|
|
118
275
|
nodePadding = this._adjustPadding(this._sankey, height - 6, this._nodesInColumn);
|
|
119
276
|
this._sankey.nodePadding(nodePadding);
|
|
120
|
-
this._sankey(
|
|
121
|
-
|
|
277
|
+
this._sankey(sankeyChartData);
|
|
278
|
+
populateNodeActualValue(sankeyChartData);
|
|
122
279
|
this._assignNodeColors();
|
|
123
|
-
var nodeData = this._createNodes(
|
|
280
|
+
var nodeData = this._createNodes(classNames);
|
|
124
281
|
var linkData = this._createLinks();
|
|
125
282
|
var calloutProps = {
|
|
126
|
-
isCalloutVisible:
|
|
283
|
+
isCalloutVisible: state.isCalloutVisible,
|
|
127
284
|
directionalHint: DirectionalHint.topAutoEdge,
|
|
128
285
|
id: "toolTip".concat(this._calloutId),
|
|
129
|
-
target:
|
|
130
|
-
color:
|
|
131
|
-
XValue:
|
|
132
|
-
YValue:
|
|
133
|
-
descriptionMessage:
|
|
286
|
+
target: state.refSelected,
|
|
287
|
+
color: state.color,
|
|
288
|
+
XValue: state.xCalloutValue,
|
|
289
|
+
YValue: state.yCalloutValue ? state.yCalloutValue : state.dataForHoverCard,
|
|
290
|
+
descriptionMessage: state.descriptionMessage,
|
|
134
291
|
isBeakVisible: false,
|
|
135
292
|
gapSpace: 15,
|
|
136
293
|
onDismiss: this._onCloseCallout,
|
|
137
|
-
className:
|
|
294
|
+
className: classNames.calloutContentRoot,
|
|
138
295
|
preventDismissOnLostFocus: true,
|
|
139
296
|
};
|
|
140
|
-
return (React.createElement("div", { className:
|
|
297
|
+
return (React.createElement("div", { className: classNames.root, role: 'presentation', ref: function (rootElem) { return (_this.chartContainer = rootElem); }, onMouseLeave: this._onCloseCallout },
|
|
141
298
|
React.createElement(FocusZone, { direction: FocusZoneDirection.bidirectional, isCircularNavigation: true, handleTabKey: FocusZoneTabbableElements.all },
|
|
142
299
|
React.createElement("svg", { width: width, height: height, id: getId('sankeyChart') },
|
|
143
|
-
React.createElement("g", { className:
|
|
144
|
-
React.createElement("g", { className:
|
|
300
|
+
React.createElement("g", { className: classNames.links, strokeOpacity: 1 }, linkData),
|
|
301
|
+
React.createElement("g", { className: classNames.nodes }, nodeData),
|
|
145
302
|
calloutProps.isCalloutVisible && (React.createElement(Callout, __assign({}, calloutProps),
|
|
146
303
|
React.createElement(ChartHoverCard, { XValue: calloutProps.XValue, YValue: calloutProps.YValue, color: calloutProps.color, descriptionMessage: calloutProps.descriptionMessage ? calloutProps.descriptionMessage : '' })))))));
|
|
147
304
|
}
|
|
148
305
|
return (React.createElement("div", { id: this._emptyChartId, role: 'alert', style: { opacity: '0' }, "aria-label": 'Graph has no data to display' }));
|
|
149
306
|
};
|
|
150
307
|
SankeyChartBase.prototype._preRenderLayout = function () {
|
|
151
|
-
var
|
|
152
|
-
var
|
|
308
|
+
var _a = this.state, containerHeight = _a.containerHeight, containerWidth = _a.containerWidth;
|
|
309
|
+
var _b = this._margins, left = _b.left, right = _b.right, top = _b.top, bottom = _b.bottom;
|
|
310
|
+
var width = containerWidth - right;
|
|
311
|
+
var height = containerHeight - bottom > 0 ? containerHeight - bottom : 0;
|
|
153
312
|
this._sankey = d3Sankey()
|
|
154
313
|
.nodeWidth(124)
|
|
155
314
|
.extent([
|
|
156
|
-
[
|
|
315
|
+
[left, top],
|
|
157
316
|
[width - 1, height - 6],
|
|
158
317
|
])
|
|
159
318
|
.nodeAlign(this._isRtl ? sankeyRight : sankeyJustify);
|
|
160
319
|
return { height: height, width: width };
|
|
161
320
|
};
|
|
162
|
-
/**
|
|
163
|
-
* This is used for calculating the node non normalized value based on link non normalized value.
|
|
164
|
-
*
|
|
165
|
-
*/
|
|
166
|
-
SankeyChartBase.prototype._populateNodeActualValue = function (data) {
|
|
167
|
-
data.links.forEach(function (link) {
|
|
168
|
-
if (!link.unnormalizedValue) {
|
|
169
|
-
link.unnormalizedValue = link.value;
|
|
170
|
-
}
|
|
171
|
-
});
|
|
172
|
-
data.nodes.forEach(function (node) {
|
|
173
|
-
node.actualValue = Math.max(d3Sum(node.sourceLinks, function (link) { return link.unnormalizedValue; }), d3Sum(node.targetLinks, function (link) { return link.unnormalizedValue; }));
|
|
174
|
-
});
|
|
175
|
-
};
|
|
176
321
|
SankeyChartBase.prototype._normalizeSankeyData = function (data) {
|
|
177
|
-
this._nodesInColumn =
|
|
178
|
-
|
|
322
|
+
var nodesInColumn = (this._nodesInColumn = populateNodeInColumns(data, this._sankey));
|
|
323
|
+
adjustOnePercentHeightNodes(nodesInColumn);
|
|
179
324
|
};
|
|
180
325
|
/**
|
|
181
|
-
*
|
|
182
|
-
* This is used to group nodes by column index.
|
|
183
|
-
*/
|
|
184
|
-
SankeyChartBase.prototype._populateNodeInColumns = function (graph, sankey) {
|
|
185
|
-
sankey(graph);
|
|
186
|
-
var nodesInColumn = {};
|
|
187
|
-
graph.nodes.forEach(function (node) {
|
|
188
|
-
var columnId = node.layer;
|
|
189
|
-
if (nodesInColumn[columnId]) {
|
|
190
|
-
nodesInColumn[columnId].push(node);
|
|
191
|
-
}
|
|
192
|
-
else {
|
|
193
|
-
nodesInColumn[columnId] = [node];
|
|
194
|
-
}
|
|
195
|
-
});
|
|
196
|
-
return nodesInColumn;
|
|
197
|
-
};
|
|
198
|
-
/**
|
|
199
|
-
* This is used to normalize the nodes value whose value is less than 1% of the total column value.
|
|
200
|
-
*
|
|
201
|
-
*/
|
|
202
|
-
SankeyChartBase.prototype._adjustOnePercentHeightNodes = function (nodesInColumn) {
|
|
203
|
-
var _this = this;
|
|
204
|
-
var totalColumnValue = Object.values(nodesInColumn).map(function (column) {
|
|
205
|
-
return d3Sum(column, function (node) { return node.value; });
|
|
206
|
-
});
|
|
207
|
-
totalColumnValue.forEach(function (columnValue, index) {
|
|
208
|
-
var totalPercentage = 0;
|
|
209
|
-
nodesInColumn[index].forEach(function (node) {
|
|
210
|
-
var nodePercentage = (node.value / columnValue) * 100;
|
|
211
|
-
node.actualValue = node.value;
|
|
212
|
-
//if the value is less than 1% then we are making it as 1% of total .
|
|
213
|
-
if (nodePercentage < 1) {
|
|
214
|
-
node.value = 0.01 * columnValue;
|
|
215
|
-
totalPercentage = totalPercentage + 1;
|
|
216
|
-
}
|
|
217
|
-
else {
|
|
218
|
-
totalPercentage = totalPercentage + nodePercentage;
|
|
219
|
-
}
|
|
220
|
-
});
|
|
221
|
-
//since we have adjusted the value to be 1% but we need to keep the sum of the percentage value under 100.
|
|
222
|
-
var scalingRatio = totalPercentage !== 0 ? totalPercentage / 100 : 1;
|
|
223
|
-
if (scalingRatio > 1) {
|
|
224
|
-
nodesInColumn[index].forEach(function (node) {
|
|
225
|
-
node.value = node.value / scalingRatio;
|
|
226
|
-
_this._changeColumnValue(node, node.actualValue, node.value);
|
|
227
|
-
});
|
|
228
|
-
}
|
|
229
|
-
});
|
|
230
|
-
};
|
|
231
|
-
/**
|
|
232
|
-
*
|
|
233
|
-
* This is used for normalizing each links value for reflecting the normalized node value.
|
|
234
|
-
*/
|
|
235
|
-
SankeyChartBase.prototype._changeColumnValue = function (node, originalValue, normalizedValue) {
|
|
236
|
-
node.sourceLinks.forEach(function (link) {
|
|
237
|
-
link.unnormalizedValue = link.value;
|
|
238
|
-
var linkRatio = link.value / originalValue;
|
|
239
|
-
link.value = normalizedValue * linkRatio;
|
|
240
|
-
});
|
|
241
|
-
node.targetLinks.forEach(function (link) {
|
|
242
|
-
link.unnormalizedValue = link.value;
|
|
243
|
-
var linkRatio = link.value / originalValue;
|
|
244
|
-
link.value = normalizedValue * linkRatio;
|
|
245
|
-
});
|
|
246
|
-
};
|
|
247
|
-
/**
|
|
248
|
-
*
|
|
249
326
|
* This is used to introduce dynamic padding for cases where the number of nodes in a column is huge
|
|
250
327
|
* so that we maintain a node to space ratio for such columns as if we fail to do so the
|
|
251
328
|
* chart is devoid of nodes and only shows links.
|
|
@@ -267,8 +344,10 @@ var SankeyChartBase = /** @class */ (function (_super) {
|
|
|
267
344
|
SankeyChartBase.prototype._createLinks = function () {
|
|
268
345
|
var _this = this;
|
|
269
346
|
var links = [];
|
|
270
|
-
|
|
271
|
-
|
|
347
|
+
var sankeyChartData = this.props.data.SankeyChartData;
|
|
348
|
+
if (sankeyChartData) {
|
|
349
|
+
var linkId_1 = this._linkId;
|
|
350
|
+
sankeyChartData.links.forEach(function (singleLink, index) {
|
|
272
351
|
var onMouseOut = function () {
|
|
273
352
|
_this._onStreamLeave(singleLink);
|
|
274
353
|
};
|
|
@@ -289,10 +368,10 @@ var SankeyChartBase = /** @class */ (function (_super) {
|
|
|
289
368
|
// eslint-disable-next-line @typescript-eslint/no-explicit-any
|
|
290
369
|
.y1(function (p) { return p.y1; })
|
|
291
370
|
.curve(d3CurveBasis);
|
|
292
|
-
var gradientUrl = "url(#gradient-".concat(
|
|
293
|
-
var link = (React.createElement("g", { key: "".concat(
|
|
371
|
+
var gradientUrl = "url(#gradient-".concat(linkId_1, "-").concat(index, ")");
|
|
372
|
+
var link = (React.createElement("g", { key: "".concat(linkId_1, "-").concat(index) },
|
|
294
373
|
React.createElement("defs", null,
|
|
295
|
-
React.createElement("linearGradient", { id: "gradient-".concat(
|
|
374
|
+
React.createElement("linearGradient", { id: "gradient-".concat(linkId_1, "-").concat(index), x1: "0%", y1: "0%", x2: "100%", y2: "0%" },
|
|
296
375
|
React.createElement("stop", { offset: "0", stopColor: singleLink.source.color }),
|
|
297
376
|
React.createElement("stop", { offset: "100%", stopColor: singleLink.target.color }))),
|
|
298
377
|
React.createElement("path", { d: linkArea(dataPoints), id: getId('link'), fill: _this._fillStreamColors(singleLink, gradientUrl), stroke: _this._fillStreamBorder(singleLink, gradientUrl), strokeWidth: "2", strokeOpacity: _this._getOpacityStreamBorder(singleLink), onMouseOver: _this._onStreamHover.bind(_this, singleLink), onMouseOut: onMouseOut, onFocus: _this._onFocusLink.bind(_this, singleLink), onBlur: _this._onBlur, fillOpacity: _this._getOpacityStream(singleLink), "data-is-focusable": true, "aria-label": 'link from' +
|
|
@@ -306,12 +385,13 @@ var SankeyChartBase = /** @class */ (function (_super) {
|
|
|
306
385
|
}
|
|
307
386
|
return links;
|
|
308
387
|
};
|
|
309
|
-
SankeyChartBase.prototype._createNodes = function (
|
|
388
|
+
SankeyChartBase.prototype._createNodes = function (classNames) {
|
|
310
389
|
var _this = this;
|
|
311
390
|
var nodes = [];
|
|
312
|
-
|
|
313
|
-
|
|
314
|
-
|
|
391
|
+
var sankeyChartData = this.props.data.SankeyChartData;
|
|
392
|
+
if (sankeyChartData) {
|
|
393
|
+
var state_1 = this.state;
|
|
394
|
+
sankeyChartData.nodes.forEach(function (singleNode, index) {
|
|
315
395
|
var onMouseOut = function () {
|
|
316
396
|
_this._onLeave(singleNode);
|
|
317
397
|
};
|
|
@@ -336,28 +416,21 @@ var SankeyChartBase = /** @class */ (function (_super) {
|
|
|
336
416
|
var truncatedname = _this._truncateText(singleNode.name, 116, padding);
|
|
337
417
|
var isTruncated = truncatedname.slice(-3) === '...';
|
|
338
418
|
var id = getId('tooltip');
|
|
339
|
-
var div = select('body')
|
|
340
|
-
.append('div')
|
|
341
|
-
.attr('id', id)
|
|
342
|
-
.attr('class', _this._classNames.toolTip)
|
|
343
|
-
.style('opacity', 0);
|
|
419
|
+
var div = select('body').append('div').attr('id', id).attr('class', classNames.toolTip).style('opacity', 0);
|
|
344
420
|
var nodeId = getId('nodeBar');
|
|
421
|
+
// TODO: Should the `aria-label` be localized?
|
|
345
422
|
var node = (React.createElement("g", { key: index, id: getId('nodeGElement') },
|
|
346
423
|
React.createElement("rect", { x: singleNode.x0, y: singleNode.y0, height: height, width: singleNode.x1 - singleNode.x0, fill: _this._fillNodeColors(singleNode), id: nodeId, onMouseOver: _this._onHover.bind(_this, singleNode), onMouseOut: onMouseOut, onFocus: _this._onCloseCallout.bind(_this), stroke: _this._fillNodeBorder(singleNode), strokeWidth: "2", opacity: "1", "data-is-focusable": true, "aria-label": 'node' + "".concat(singleNode.name) + 'with weight' + "".concat(singleNode.actualValue), role: "img" }),
|
|
347
|
-
singleNode.y1 - singleNode.y0 > MIN_HEIGHT_FOR_TYPE && (React.createElement("g", { className:
|
|
424
|
+
singleNode.y1 - singleNode.y0 > MIN_HEIGHT_FOR_TYPE && (React.createElement("g", { className: classNames.nodeTextContainer },
|
|
348
425
|
React.createElement("g", { className: "nodeName" },
|
|
349
|
-
React.createElement("text", { id: "".concat(nodeId, "-name"), x: singleNode.x0, y: singleNode.y0, dy: '1.2em', dx: '0.4em', textAnchor: _this._isRtl ? 'end' : 'start', fontWeight: "regular", "aria-hidden": "true", fill: !(!
|
|
350
|
-
(
|
|
351
|
-
|
|
352
|
-
_this.state.selectedNode) ||
|
|
353
|
-
(_this.state.selectedState && !_this.state.selectedNode))
|
|
426
|
+
React.createElement("text", { id: "".concat(nodeId, "-name"), x: singleNode.x0, y: singleNode.y0, dy: '1.2em', dx: '0.4em', textAnchor: _this._isRtl ? 'end' : 'start', fontWeight: "regular", "aria-hidden": "true", fill: !(!state_1.selectedState ||
|
|
427
|
+
(state_1.selectedState && state_1.selectedNodes.has(singleNode.index) && state_1.selectedNode) ||
|
|
428
|
+
(state_1.selectedState && !state_1.selectedNode))
|
|
354
429
|
? DEFAULT_TEXT_COLOR
|
|
355
430
|
: NON_SELECTED_TEXT_COLOR, fontSize: 10, onMouseOver: _this._showTooltip.bind(_this, singleNode.name, isTruncated, div), onMouseOut: _this._hideTooltip.bind(_this, div) }, truncatedname)),
|
|
356
|
-
React.createElement("text", { x: height > MIN_HEIGHT_FOR_DOUBLINE_TYPE ? singleNode.x0 : singleNode.x1 - textLengthForNodeWeight - 8, y: singleNode.y0, dy: height > MIN_HEIGHT_FOR_DOUBLINE_TYPE ? '2em' : '1em', dx: height > MIN_HEIGHT_FOR_DOUBLINE_TYPE ? '0.4em' : '0em', textAnchor: _this._isRtl ? 'end' : 'start', fontWeight: "bold", "aria-hidden": "true", fill: !(!
|
|
357
|
-
(
|
|
358
|
-
|
|
359
|
-
_this.state.selectedNode) ||
|
|
360
|
-
(_this.state.selectedState && !_this.state.selectedNode))
|
|
431
|
+
React.createElement("text", { x: height > MIN_HEIGHT_FOR_DOUBLINE_TYPE ? singleNode.x0 : singleNode.x1 - textLengthForNodeWeight - 8, y: singleNode.y0, dy: height > MIN_HEIGHT_FOR_DOUBLINE_TYPE ? '2em' : '1em', dx: height > MIN_HEIGHT_FOR_DOUBLINE_TYPE ? '0.4em' : '0em', textAnchor: _this._isRtl ? 'end' : 'start', fontWeight: "bold", "aria-hidden": "true", fill: !(!state_1.selectedState ||
|
|
432
|
+
(state_1.selectedState && state_1.selectedNodes.has(singleNode.index) && state_1.selectedNode) ||
|
|
433
|
+
(state_1.selectedState && !state_1.selectedNode))
|
|
361
434
|
? DEFAULT_TEXT_COLOR
|
|
362
435
|
: NON_SELECTED_TEXT_COLOR, fontSize: 14 }, singleNode.actualValue)))));
|
|
363
436
|
nodes.push(node);
|
|
@@ -365,7 +438,6 @@ var SankeyChartBase = /** @class */ (function (_super) {
|
|
|
365
438
|
return nodes;
|
|
366
439
|
}
|
|
367
440
|
};
|
|
368
|
-
// eslint-disable-next-line @typescript-eslint/no-explicit-any
|
|
369
441
|
SankeyChartBase.prototype._onLeave = function (singleNode) {
|
|
370
442
|
if (this.state.selectedState) {
|
|
371
443
|
this.setState({
|
|
@@ -376,13 +448,12 @@ var SankeyChartBase = /** @class */ (function (_super) {
|
|
|
376
448
|
});
|
|
377
449
|
}
|
|
378
450
|
};
|
|
379
|
-
// eslint-disable-next-line @typescript-eslint/no-explicit-any
|
|
380
451
|
SankeyChartBase.prototype._onHover = function (singleNode, mouseEvent) {
|
|
381
452
|
mouseEvent.persist();
|
|
382
453
|
this._onCloseCallout();
|
|
383
454
|
if (!this.state.selectedState) {
|
|
384
|
-
var selectedLinks =
|
|
385
|
-
var selectedNodes =
|
|
455
|
+
var selectedLinks = getSelectedLinks(singleNode);
|
|
456
|
+
var selectedNodes = getSelectedNodes(selectedLinks);
|
|
386
457
|
selectedNodes.push(singleNode);
|
|
387
458
|
this.setState({
|
|
388
459
|
selectedState: true,
|
|
@@ -398,12 +469,11 @@ var SankeyChartBase = /** @class */ (function (_super) {
|
|
|
398
469
|
});
|
|
399
470
|
}
|
|
400
471
|
};
|
|
401
|
-
// eslint-disable-next-line @typescript-eslint/no-explicit-any
|
|
402
472
|
SankeyChartBase.prototype._onStreamHover = function (singleLink, mouseEvent) {
|
|
403
473
|
mouseEvent.persist();
|
|
404
474
|
this._onCloseCallout();
|
|
405
475
|
if (!this.state.selectedState) {
|
|
406
|
-
var _a =
|
|
476
|
+
var _a = getSelectedLinksforStreamHover(singleLink), selectedLinks = _a.selectedLinks, selectedNodes = _a.selectedNodes;
|
|
407
477
|
this.setState({
|
|
408
478
|
selectedState: true,
|
|
409
479
|
selectedNodes: new Set(Array.from(selectedNodes).map(function (node) { return node.index; })),
|
|
@@ -414,7 +484,7 @@ var SankeyChartBase = /** @class */ (function (_super) {
|
|
|
414
484
|
color: singleLink.source.color,
|
|
415
485
|
xCalloutValue: singleLink.target.name,
|
|
416
486
|
yCalloutValue: singleLink.unnormalizedValue.toString(),
|
|
417
|
-
descriptionMessage: 'from ' + singleLink.source.name,
|
|
487
|
+
descriptionMessage: 'from ' + singleLink.source.name, // TODO: Does this need to be localized?
|
|
418
488
|
});
|
|
419
489
|
}
|
|
420
490
|
};
|
|
@@ -439,7 +509,7 @@ var SankeyChartBase = /** @class */ (function (_super) {
|
|
|
439
509
|
xCalloutValue: singleLink.target.name,
|
|
440
510
|
// eslint-disable-next-line @typescript-eslint/no-explicit-any
|
|
441
511
|
yCalloutValue: singleLink.source.actualValue,
|
|
442
|
-
descriptionMessage: 'from ' + singleLink.source.name,
|
|
512
|
+
descriptionMessage: 'from ' + singleLink.source.name, // TODO: Does this need to be localized?
|
|
443
513
|
});
|
|
444
514
|
};
|
|
445
515
|
/**
|
|
@@ -449,9 +519,10 @@ var SankeyChartBase = /** @class */ (function (_super) {
|
|
|
449
519
|
SankeyChartBase.prototype._assignNodeColors = function () {
|
|
450
520
|
var colors;
|
|
451
521
|
var borders;
|
|
452
|
-
|
|
453
|
-
|
|
454
|
-
|
|
522
|
+
var _a = this.props, colorsForNodes = _a.colorsForNodes, borderColorsForNodes = _a.borderColorsForNodes;
|
|
523
|
+
if (colorsForNodes && borderColorsForNodes) {
|
|
524
|
+
colors = colorsForNodes;
|
|
525
|
+
borders = borderColorsForNodes;
|
|
455
526
|
}
|
|
456
527
|
else {
|
|
457
528
|
colors = DEFAULT_NODE_COLORS.map(function (color) { return color.fillColor; });
|
|
@@ -472,126 +543,43 @@ var SankeyChartBase = /** @class */ (function (_super) {
|
|
|
472
543
|
currentIndex = (currentIndex + 1) % colors.length;
|
|
473
544
|
});
|
|
474
545
|
};
|
|
475
|
-
// eslint-disable-next-line @typescript-eslint/no-explicit-any
|
|
476
546
|
SankeyChartBase.prototype._fillStreamColors = function (singleLink, gradientUrl) {
|
|
477
|
-
|
|
478
|
-
|
|
547
|
+
var state = this.state;
|
|
548
|
+
if (state.selectedState && state.selectedLinks.has(singleLink.index) && state.selectedNode) {
|
|
549
|
+
return state.selectedNode.color;
|
|
479
550
|
}
|
|
480
|
-
else if (
|
|
551
|
+
else if (state.selectedState && state.selectedLinks.has(singleLink.index)) {
|
|
481
552
|
return gradientUrl;
|
|
482
553
|
}
|
|
483
554
|
};
|
|
484
|
-
// eslint-disable-next-line @typescript-eslint/no-explicit-any
|
|
485
555
|
SankeyChartBase.prototype._fillStreamBorder = function (singleLink, gradientUrl) {
|
|
486
|
-
|
|
556
|
+
var state = this.state;
|
|
557
|
+
if (!state.selectedState) {
|
|
487
558
|
return NON_SELECTED_NODE_AND_STREAM_COLOR;
|
|
488
559
|
}
|
|
489
|
-
else if (
|
|
490
|
-
return
|
|
560
|
+
else if (state.selectedState && state.selectedLinks.has(singleLink.index) && state.selectedNode) {
|
|
561
|
+
return state.selectedNode.borderColor;
|
|
491
562
|
}
|
|
492
|
-
else if (
|
|
563
|
+
else if (state.selectedState && state.selectedLinks.has(singleLink.index)) {
|
|
493
564
|
return gradientUrl;
|
|
494
565
|
}
|
|
495
566
|
return NON_SELECTED_NODE_AND_STREAM_COLOR;
|
|
496
567
|
};
|
|
497
|
-
// eslint-disable-next-line @typescript-eslint/no-explicit-any
|
|
498
|
-
SankeyChartBase.prototype._getSelectedNodes = function (selectedLinks) {
|
|
499
|
-
// eslint-disable-next-line @typescript-eslint/no-explicit-any
|
|
500
|
-
var nodes = [];
|
|
501
|
-
selectedLinks.forEach(function (link) {
|
|
502
|
-
nodes.push(link.target);
|
|
503
|
-
if (nodes.indexOf(link.source) === -1) {
|
|
504
|
-
nodes.push(link.source);
|
|
505
|
-
}
|
|
506
|
-
});
|
|
507
|
-
return nodes;
|
|
508
|
-
};
|
|
509
|
-
// eslint-disable-next-line @typescript-eslint/no-explicit-any
|
|
510
|
-
SankeyChartBase.prototype._getSelectedLinks = function (singleNode) {
|
|
511
|
-
// eslint-disable-next-line @typescript-eslint/no-explicit-any, no-array-constructor
|
|
512
|
-
var q = new Array();
|
|
513
|
-
var finalLinks = new Set();
|
|
514
|
-
singleNode.sourceLinks.forEach(function (link) {
|
|
515
|
-
q.push(link);
|
|
516
|
-
finalLinks.add(link);
|
|
517
|
-
});
|
|
518
|
-
while (q.length > 0) {
|
|
519
|
-
var poppedLink = q.shift();
|
|
520
|
-
var node = poppedLink.target;
|
|
521
|
-
if (node && node.sourceLinks) {
|
|
522
|
-
node.sourceLinks.forEach(function (link) {
|
|
523
|
-
finalLinks.add(link);
|
|
524
|
-
q.push(link);
|
|
525
|
-
});
|
|
526
|
-
}
|
|
527
|
-
}
|
|
528
|
-
if (singleNode.targetLinks) {
|
|
529
|
-
singleNode.targetLinks.forEach(function (link) {
|
|
530
|
-
q.push(link);
|
|
531
|
-
finalLinks.add(link);
|
|
532
|
-
});
|
|
533
|
-
}
|
|
534
|
-
while (q.length > 0) {
|
|
535
|
-
var poppedLink = q.shift();
|
|
536
|
-
var node = poppedLink.source;
|
|
537
|
-
if (node && node.targetLinks) {
|
|
538
|
-
node.targetLinks.forEach(function (link) {
|
|
539
|
-
finalLinks.add(link);
|
|
540
|
-
q.push(link);
|
|
541
|
-
});
|
|
542
|
-
}
|
|
543
|
-
}
|
|
544
|
-
return finalLinks;
|
|
545
|
-
};
|
|
546
|
-
// eslint-disable-next-line @typescript-eslint/no-explicit-any
|
|
547
|
-
SankeyChartBase.prototype._getSelectedLinksforStreamHover = function (singleLink) {
|
|
548
|
-
// eslint-disable-next-line @typescript-eslint/no-explicit-any, no-array-constructor
|
|
549
|
-
var q = new Array();
|
|
550
|
-
var finalLinks = new Set();
|
|
551
|
-
var finalNodes = new Set();
|
|
552
|
-
q.push(singleLink.source);
|
|
553
|
-
finalLinks.add(singleLink);
|
|
554
|
-
while (q.length > 0) {
|
|
555
|
-
var poppedNode = q.shift();
|
|
556
|
-
finalNodes.add(poppedNode);
|
|
557
|
-
if (poppedNode.targetLinks && poppedNode.targetLinks.length > 0) {
|
|
558
|
-
poppedNode.targetLinks.forEach(function (link) {
|
|
559
|
-
q.push(link.source);
|
|
560
|
-
finalLinks.add(link);
|
|
561
|
-
});
|
|
562
|
-
}
|
|
563
|
-
}
|
|
564
|
-
q.push(singleLink.target);
|
|
565
|
-
while (q.length > 0) {
|
|
566
|
-
var poppedNode = q.shift();
|
|
567
|
-
finalNodes.add(poppedNode);
|
|
568
|
-
if (poppedNode.sourceLinks && poppedNode.sourceLinks.length > 0) {
|
|
569
|
-
poppedNode.sourceLinks.forEach(function (link) {
|
|
570
|
-
q.push(link.target);
|
|
571
|
-
finalLinks.add(link);
|
|
572
|
-
});
|
|
573
|
-
}
|
|
574
|
-
}
|
|
575
|
-
return {
|
|
576
|
-
selectedLinks: finalLinks,
|
|
577
|
-
selectedNodes: finalNodes,
|
|
578
|
-
};
|
|
579
|
-
};
|
|
580
568
|
SankeyChartBase.prototype._getOpacityStream = function (singleLink) {
|
|
581
|
-
|
|
582
|
-
|
|
569
|
+
var state = this.state;
|
|
570
|
+
if (state.selectedState) {
|
|
571
|
+
if (!state.selectedLinks.has(singleLink.index)) {
|
|
583
572
|
return NON_SELECTED_OPACITY;
|
|
584
573
|
}
|
|
585
|
-
else if (
|
|
586
|
-
this.state.selectedLinks.has(singleLink.index) &&
|
|
587
|
-
!this.state.selectedNode) {
|
|
574
|
+
else if (state.selectedLinks.has(singleLink.index) && !state.selectedNode) {
|
|
588
575
|
return SELECTED_STREAM_OPACITY;
|
|
589
576
|
}
|
|
590
577
|
}
|
|
591
578
|
return REST_STREAM_OPACITY;
|
|
592
579
|
};
|
|
593
580
|
SankeyChartBase.prototype._getOpacityStreamBorder = function (singleLink) {
|
|
594
|
-
|
|
581
|
+
var state = this.state;
|
|
582
|
+
if (state.selectedState && !state.selectedLinks.has(singleLink.index) && !state.selectedNode) {
|
|
595
583
|
return NON_SELECTED_STREAM_BORDER_OPACITY;
|
|
596
584
|
}
|
|
597
585
|
return NON_SELECTED_OPACITY;
|
|
@@ -613,7 +601,6 @@ var SankeyChartBase = /** @class */ (function (_super) {
|
|
|
613
601
|
});
|
|
614
602
|
};
|
|
615
603
|
/**
|
|
616
|
-
*
|
|
617
604
|
* @param text is the text which we are trying to truncate
|
|
618
605
|
* @param rectangleWidth is the width of the rectangle which will contain the text
|
|
619
606
|
* @param padding is the space we need to leave between the rect lines and other text
|
|
@@ -672,10 +659,9 @@ var SankeyChartBase = /** @class */ (function (_super) {
|
|
|
672
659
|
div.style('opacity', 0);
|
|
673
660
|
};
|
|
674
661
|
SankeyChartBase.prototype._isChartEmpty = function () {
|
|
675
|
-
|
|
676
|
-
|
|
677
|
-
|
|
678
|
-
this.props.data.SankeyChartData.links.length > 0);
|
|
662
|
+
var _a;
|
|
663
|
+
var sankeyChartData = (_a = this.props.data) === null || _a === void 0 ? void 0 : _a.SankeyChartData;
|
|
664
|
+
return !(sankeyChartData && sankeyChartData.nodes.length > 0 && sankeyChartData.links.length > 0);
|
|
679
665
|
};
|
|
680
666
|
return SankeyChartBase;
|
|
681
667
|
}(React.Component));
|