@fluentui/react-charting 5.14.42 → 5.15.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.
- package/CHANGELOG.json +55 -1
- package/CHANGELOG.md +24 -2
- package/dist/react-charting.js +1 -1
- package/dist/react-charting.min.js +1 -1
- package/lib/components/SankeyChart/SankeyChart.base.d.ts +79 -2
- package/lib/components/SankeyChart/SankeyChart.base.js +599 -32
- package/lib/components/SankeyChart/SankeyChart.base.js.map +1 -1
- package/lib/components/SankeyChart/SankeyChart.styles.js +39 -2
- package/lib/components/SankeyChart/SankeyChart.styles.js.map +1 -1
- package/lib/components/SankeyChart/SankeyChart.types.d.ts +20 -0
- package/lib/components/SankeyChart/SankeyChart.types.js.map +1 -1
- package/lib/types/IDataPoint.d.ts +5 -1
- package/lib/types/IDataPoint.js.map +1 -1
- package/lib/version.js +1 -1
- package/lib/version.js.map +1 -1
- package/lib-amd/components/SankeyChart/SankeyChart.base.d.ts +79 -2
- package/lib-amd/components/SankeyChart/SankeyChart.base.js +592 -31
- package/lib-amd/components/SankeyChart/SankeyChart.base.js.map +1 -1
- package/lib-amd/components/SankeyChart/SankeyChart.styles.js +38 -3
- package/lib-amd/components/SankeyChart/SankeyChart.styles.js.map +1 -1
- package/lib-amd/components/SankeyChart/SankeyChart.types.d.ts +20 -0
- package/lib-amd/components/SankeyChart/SankeyChart.types.js.map +1 -1
- package/lib-amd/types/IDataPoint.d.ts +5 -1
- package/lib-amd/types/IDataPoint.js.map +1 -1
- package/lib-amd/version.js +1 -1
- package/lib-amd/version.js.map +1 -1
- package/lib-commonjs/components/SankeyChart/SankeyChart.base.d.ts +79 -2
- package/lib-commonjs/components/SankeyChart/SankeyChart.base.js +597 -30
- package/lib-commonjs/components/SankeyChart/SankeyChart.base.js.map +1 -1
- package/lib-commonjs/components/SankeyChart/SankeyChart.styles.js +39 -2
- package/lib-commonjs/components/SankeyChart/SankeyChart.styles.js.map +1 -1
- package/lib-commonjs/components/SankeyChart/SankeyChart.types.d.ts +20 -0
- package/lib-commonjs/components/SankeyChart/SankeyChart.types.js.map +1 -1
- package/lib-commonjs/types/IDataPoint.d.ts +5 -1
- package/lib-commonjs/types/IDataPoint.js.map +1 -1
- package/lib-commonjs/version.js +1 -1
- package/lib-commonjs/version.js.map +1 -1
- package/package.json +8 -8
- package/src/components/SankeyChart/SankeyChart.types.ts +26 -0
|
@@ -1,16 +1,85 @@
|
|
|
1
|
-
define(["require", "exports", "tslib", "react", "@fluentui/react/lib/Utilities", "d3-sankey"], function (require, exports, tslib_1, React, Utilities_1, d3Sankey) {
|
|
1
|
+
define(["require", "exports", "tslib", "react", "@fluentui/react/lib/Utilities", "d3-sankey", "d3-shape", "d3-array", "../../index", "@fluentui/react/lib/Callout", "d3-selection", "@fluentui/react-focus"], function (require, exports, tslib_1, React, Utilities_1, d3Sankey, d3_shape_1, d3_array_1, index_1, Callout_1, d3_selection_1, react_focus_1) {
|
|
2
2
|
"use strict";
|
|
3
3
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
4
4
|
exports.SankeyChartBase = void 0;
|
|
5
5
|
var getClassNames = Utilities_1.classNamesFunction();
|
|
6
|
+
var PADDING_PERCENTAGE = 0.3;
|
|
7
|
+
var NON_SELECTED_NODE_AND_STREAM_COLOR = '#757575';
|
|
8
|
+
var DEFAULT_NODE_COLORS = [
|
|
9
|
+
{ fillColor: '#00758F', borderColor: '#002E39' },
|
|
10
|
+
{ fillColor: '#77004D', borderColor: '#43002C' },
|
|
11
|
+
{ fillColor: '#4F6BED', borderColor: '#3B52B4' },
|
|
12
|
+
{ fillColor: '#937600', borderColor: '#6D5700' },
|
|
13
|
+
{ fillColor: '#286EA8', borderColor: '#00457E' },
|
|
14
|
+
{ fillColor: '#A43FB1', borderColor: '#7C158A' },
|
|
15
|
+
{ fillColor: '#CC3595', borderColor: '#7F215D' },
|
|
16
|
+
{ fillColor: '#0E7878', borderColor: '#004E4E' },
|
|
17
|
+
{ fillColor: '#8764B8', borderColor: '#4B3867' },
|
|
18
|
+
{ fillColor: '#9C663F', borderColor: '#6D4123' },
|
|
19
|
+
];
|
|
20
|
+
var MIN_HEIGHT_FOR_DOUBLINE_TYPE = 36;
|
|
21
|
+
var MIN_HEIGHT_FOR_TYPE = 24;
|
|
22
|
+
var REST_STREAM_OPACITY = 1;
|
|
23
|
+
var NON_SELECTED_OPACITY = 1;
|
|
24
|
+
var SELECTED_STREAM_OPACITY = 0.3;
|
|
25
|
+
var NON_SELECTED_STREAM_BORDER_OPACITY = 0.5;
|
|
26
|
+
var DEFAULT_TEXT_COLOR = '#323130';
|
|
27
|
+
var NON_SELECTED_TEXT_COLOR = '#FFFFFF';
|
|
6
28
|
var SankeyChartBase = /** @class */ (function (_super) {
|
|
7
29
|
tslib_1.__extends(SankeyChartBase, _super);
|
|
8
30
|
function SankeyChartBase(props) {
|
|
9
31
|
var _this = _super.call(this, props) || this;
|
|
32
|
+
_this._isRtl = Utilities_1.getRTL();
|
|
33
|
+
// eslint-disable-next-line @typescript-eslint/no-explicit-any
|
|
34
|
+
_this._onCloseCallout = function () {
|
|
35
|
+
_this.setState({
|
|
36
|
+
isCalloutVisible: false,
|
|
37
|
+
refSelected: undefined,
|
|
38
|
+
descriptionMessage: '',
|
|
39
|
+
});
|
|
40
|
+
};
|
|
41
|
+
_this._onBlur = function () {
|
|
42
|
+
/**/
|
|
43
|
+
};
|
|
44
|
+
// eslint-disable-next-line @typescript-eslint/no-explicit-any
|
|
45
|
+
_this._fillNodeColors = function (singleNode) {
|
|
46
|
+
if (!_this.state.selectedState) {
|
|
47
|
+
return singleNode.color;
|
|
48
|
+
}
|
|
49
|
+
else if (_this.state.selectedState && _this.state.selectedNodes.has(singleNode.index) && _this.state.selectedNode) {
|
|
50
|
+
return _this.state.selectedNode.color;
|
|
51
|
+
}
|
|
52
|
+
else if (_this.state.selectedState && !_this.state.selectedNode) {
|
|
53
|
+
return singleNode.color;
|
|
54
|
+
}
|
|
55
|
+
};
|
|
56
|
+
// eslint-disable-next-line @typescript-eslint/no-explicit-any
|
|
57
|
+
_this._fillNodeBorder = function (singleNode) {
|
|
58
|
+
if (!_this.state.selectedState) {
|
|
59
|
+
return singleNode.borderColor;
|
|
60
|
+
}
|
|
61
|
+
else if (_this.state.selectedState && _this.state.selectedNodes.has(singleNode.index) && _this.state.selectedNode) {
|
|
62
|
+
return _this.state.selectedNode.borderColor;
|
|
63
|
+
}
|
|
64
|
+
else if (_this.state.selectedState && _this.state.selectedNodes.has(singleNode.index)) {
|
|
65
|
+
return singleNode.borderColor;
|
|
66
|
+
}
|
|
67
|
+
return singleNode.borderColor;
|
|
68
|
+
};
|
|
10
69
|
_this.state = {
|
|
11
|
-
containerHeight:
|
|
12
|
-
containerWidth:
|
|
70
|
+
containerHeight: 468,
|
|
71
|
+
containerWidth: 912,
|
|
72
|
+
selectedState: false,
|
|
73
|
+
selectedLinks: new Set(),
|
|
74
|
+
selectedNodes: new Set(),
|
|
75
|
+
shouldOverflow: false,
|
|
76
|
+
isCalloutVisible: false,
|
|
13
77
|
};
|
|
78
|
+
_this._calloutId = Utilities_1.getId('callout');
|
|
79
|
+
_this._linkId = Utilities_1.getId('link');
|
|
80
|
+
_this._margins = { top: 36, right: 48, bottom: 32, left: 48 };
|
|
81
|
+
_this._preRenderLayout();
|
|
82
|
+
_this._normalizeData = Utilities_1.memoizeFunction(function (data) { return _this._normalizeSankeyData(data); });
|
|
14
83
|
return _this;
|
|
15
84
|
}
|
|
16
85
|
SankeyChartBase.prototype.componentDidMount = function () {
|
|
@@ -34,58 +103,491 @@ define(["require", "exports", "tslib", "react", "@fluentui/react/lib/Utilities",
|
|
|
34
103
|
pathColor: pathColor,
|
|
35
104
|
className: className,
|
|
36
105
|
});
|
|
37
|
-
|
|
38
|
-
var
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
106
|
+
// We are using the this._margins.left and this._margins.top in sankey extent while constructing the layout
|
|
107
|
+
var _b = this._preRenderLayout(), height = _b.height, width = _b.width;
|
|
108
|
+
this._normalizeData(this.props.data.SankeyChartData);
|
|
109
|
+
var nodePadding = 8;
|
|
110
|
+
nodePadding = this._adjustPadding(this._sankey, height - 6, this._nodesInColumn);
|
|
111
|
+
this._sankey.nodePadding(nodePadding);
|
|
112
|
+
this._sankey(this.props.data.SankeyChartData);
|
|
113
|
+
this._populateNodeActualValue(this.props.data.SankeyChartData);
|
|
114
|
+
this._assignNodeColors();
|
|
115
|
+
var nodeData = this._createNodes(width);
|
|
116
|
+
var linkData = this._createLinks();
|
|
117
|
+
var calloutProps = {
|
|
118
|
+
isCalloutVisible: this.state.isCalloutVisible,
|
|
119
|
+
directionalHint: Callout_1.DirectionalHint.topAutoEdge,
|
|
120
|
+
id: "toolTip" + this._calloutId,
|
|
121
|
+
target: this.state.refSelected,
|
|
122
|
+
color: this.state.color,
|
|
123
|
+
XValue: this.state.xCalloutValue,
|
|
124
|
+
YValue: this.state.yCalloutValue ? this.state.yCalloutValue : this.state.dataForHoverCard,
|
|
125
|
+
descriptionMessage: this.state.descriptionMessage,
|
|
126
|
+
isBeakVisible: false,
|
|
127
|
+
gapSpace: 15,
|
|
128
|
+
onDismiss: this._onCloseCallout,
|
|
129
|
+
className: this._classNames.calloutContentRoot,
|
|
130
|
+
preventDismissOnLostFocus: true,
|
|
131
|
+
};
|
|
132
|
+
return (React.createElement("div", { className: this._classNames.root, role: 'presentation', ref: function (rootElem) { return (_this.chartContainer = rootElem); }, onMouseLeave: this._onCloseCallout },
|
|
133
|
+
React.createElement(react_focus_1.FocusZone, { direction: react_focus_1.FocusZoneDirection.bidirectional, isCircularNavigation: true, handleTabKey: react_focus_1.FocusZoneTabbableElements.all },
|
|
134
|
+
React.createElement("svg", { width: width, height: height, id: Utilities_1.getId('sankeyChart') },
|
|
135
|
+
React.createElement("g", { className: this._classNames.links, strokeOpacity: 1 }, linkData),
|
|
136
|
+
React.createElement("g", { className: this._classNames.nodes }, nodeData),
|
|
137
|
+
calloutProps.isCalloutVisible && (React.createElement(Callout_1.Callout, tslib_1.__assign({}, calloutProps),
|
|
138
|
+
React.createElement(index_1.ChartHoverCard, { XValue: calloutProps.XValue, YValue: calloutProps.YValue, color: calloutProps.color, descriptionMessage: calloutProps.descriptionMessage ? calloutProps.descriptionMessage : '' })))))));
|
|
139
|
+
};
|
|
140
|
+
SankeyChartBase.prototype._preRenderLayout = function () {
|
|
141
|
+
var width = this.state.containerWidth - this._margins.right;
|
|
142
|
+
var height = this.state.containerHeight - this._margins.bottom > 0 ? this.state.containerHeight - this._margins.bottom : 0;
|
|
143
|
+
this._sankey = d3Sankey
|
|
43
144
|
.sankey()
|
|
44
|
-
.nodeWidth(
|
|
45
|
-
.nodePadding(6)
|
|
145
|
+
.nodeWidth(124)
|
|
46
146
|
.extent([
|
|
47
|
-
[
|
|
147
|
+
[this._margins.left, this._margins.top],
|
|
48
148
|
[width - 1, height - 6],
|
|
49
|
-
])
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
|
|
149
|
+
])
|
|
150
|
+
.nodeAlign(this._isRtl ? d3Sankey.sankeyRight : d3Sankey.sankeyJustify);
|
|
151
|
+
return { height: height, width: width };
|
|
152
|
+
};
|
|
153
|
+
/**
|
|
154
|
+
* This is used for calculating the node non normalized value based on link non normalized value.
|
|
155
|
+
*
|
|
156
|
+
*/
|
|
157
|
+
SankeyChartBase.prototype._populateNodeActualValue = function (data) {
|
|
158
|
+
data.links.forEach(function (link) {
|
|
159
|
+
if (!link.unnormalizedValue) {
|
|
160
|
+
link.unnormalizedValue = link.value;
|
|
161
|
+
}
|
|
162
|
+
});
|
|
163
|
+
data.nodes.forEach(function (node) {
|
|
164
|
+
node.actualValue = Math.max(d3_array_1.sum(node.sourceLinks, function (link) { return link.unnormalizedValue; }), d3_array_1.sum(node.targetLinks, function (link) { return link.unnormalizedValue; }));
|
|
165
|
+
});
|
|
166
|
+
};
|
|
167
|
+
SankeyChartBase.prototype._normalizeSankeyData = function (data) {
|
|
168
|
+
this._nodesInColumn = this._populateNodeInColumns(data, this._sankey);
|
|
169
|
+
this._adjustOnePercentHeightNodes(this._nodesInColumn);
|
|
170
|
+
};
|
|
171
|
+
/**
|
|
172
|
+
*
|
|
173
|
+
* This is used to group nodes by column index.
|
|
174
|
+
*/
|
|
175
|
+
SankeyChartBase.prototype._populateNodeInColumns = function (graph, sankey) {
|
|
176
|
+
sankey(graph);
|
|
177
|
+
var nodesInColumn = {};
|
|
178
|
+
graph.nodes.forEach(function (node) {
|
|
179
|
+
var columnId = node.layer;
|
|
180
|
+
if (nodesInColumn[columnId]) {
|
|
181
|
+
nodesInColumn[columnId].push(node);
|
|
182
|
+
}
|
|
183
|
+
else {
|
|
184
|
+
nodesInColumn[columnId] = [node];
|
|
185
|
+
}
|
|
186
|
+
});
|
|
187
|
+
return nodesInColumn;
|
|
188
|
+
};
|
|
189
|
+
/**
|
|
190
|
+
* This is used to normalize the nodes value whose value is less than 1% of the total column value.
|
|
191
|
+
*
|
|
192
|
+
*/
|
|
193
|
+
SankeyChartBase.prototype._adjustOnePercentHeightNodes = function (nodesInColumn) {
|
|
194
|
+
var _this = this;
|
|
195
|
+
var totalColumnValue = Object.values(nodesInColumn).map(function (column) {
|
|
196
|
+
return d3_array_1.sum(column, function (node) { return node.value; });
|
|
197
|
+
});
|
|
198
|
+
totalColumnValue.forEach(function (columnValue, index) {
|
|
199
|
+
var totalPercentage = 0;
|
|
200
|
+
nodesInColumn[index].forEach(function (node) {
|
|
201
|
+
var nodePercentage = (node.value / columnValue) * 100;
|
|
202
|
+
node.actualValue = node.value;
|
|
203
|
+
//if the value is less than 1% then we are making it as 1% of total .
|
|
204
|
+
if (nodePercentage < 1) {
|
|
205
|
+
node.value = 0.01 * columnValue;
|
|
206
|
+
totalPercentage = totalPercentage + 1;
|
|
207
|
+
}
|
|
208
|
+
else {
|
|
209
|
+
totalPercentage = totalPercentage + nodePercentage;
|
|
210
|
+
}
|
|
211
|
+
});
|
|
212
|
+
//since we have adjusted the value to be 1% but we need to keep the sum of the percentage value under 100.
|
|
213
|
+
var scalingRatio = totalPercentage !== 0 ? totalPercentage / 100 : 1;
|
|
214
|
+
if (scalingRatio > 1) {
|
|
215
|
+
nodesInColumn[index].forEach(function (node) {
|
|
216
|
+
node.value = node.value / scalingRatio;
|
|
217
|
+
_this._changeColumnValue(node, node.actualValue, node.value);
|
|
218
|
+
});
|
|
219
|
+
}
|
|
220
|
+
});
|
|
221
|
+
};
|
|
222
|
+
/**
|
|
223
|
+
*
|
|
224
|
+
* This is used for normalizing each links value for reflecting the normalized node value.
|
|
225
|
+
*/
|
|
226
|
+
SankeyChartBase.prototype._changeColumnValue = function (node, originalValue, normalizedValue) {
|
|
227
|
+
node.sourceLinks.forEach(function (link) {
|
|
228
|
+
link.unnormalizedValue = link.value;
|
|
229
|
+
var linkRatio = link.value / originalValue;
|
|
230
|
+
link.value = normalizedValue * linkRatio;
|
|
231
|
+
});
|
|
232
|
+
node.targetLinks.forEach(function (link) {
|
|
233
|
+
link.unnormalizedValue = link.value;
|
|
234
|
+
var linkRatio = link.value / originalValue;
|
|
235
|
+
link.value = normalizedValue * linkRatio;
|
|
236
|
+
});
|
|
237
|
+
};
|
|
238
|
+
/**
|
|
239
|
+
*
|
|
240
|
+
* This is used to introduce dynamic padding for cases where the number of nodes in a column is huge
|
|
241
|
+
* so that we maintain a node to space ratio for such columns as if we fail to do so the
|
|
242
|
+
* chart is devoid of nodes and only shows links.
|
|
243
|
+
*/
|
|
244
|
+
// eslint-disable-next-line @typescript-eslint/no-explicit-any
|
|
245
|
+
SankeyChartBase.prototype._adjustPadding = function (sankey, height, nodesInColumn) {
|
|
246
|
+
var padding = this._sankey.nodePadding();
|
|
247
|
+
Object.values(nodesInColumn).forEach(function (column) {
|
|
248
|
+
var minPadding = PADDING_PERCENTAGE * height;
|
|
249
|
+
var toatlPaddingInColumn = height - d3_array_1.sum(column, function (node) { return node.y1 - node.y0; });
|
|
250
|
+
if (minPadding < toatlPaddingInColumn) {
|
|
251
|
+
//Here we are calculating the min of default and calculated padding, we will not increase the padding
|
|
252
|
+
//in any scenario.
|
|
253
|
+
padding = Math.min(padding, minPadding / (column.length - 1));
|
|
254
|
+
}
|
|
255
|
+
});
|
|
256
|
+
return padding;
|
|
57
257
|
};
|
|
58
258
|
SankeyChartBase.prototype._createLinks = function () {
|
|
259
|
+
var _this = this;
|
|
59
260
|
var links = [];
|
|
60
261
|
if (this.props.data.SankeyChartData) {
|
|
61
|
-
// eslint-disable-next-line @typescript-eslint/no-explicit-any
|
|
62
262
|
this.props.data.SankeyChartData.links.forEach(function (singleLink, index) {
|
|
63
|
-
var
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
|
|
263
|
+
var onMouseOut = function () {
|
|
264
|
+
_this._onStreamLeave(singleLink);
|
|
265
|
+
};
|
|
266
|
+
// eslint-disable-next-line @typescript-eslint/no-explicit-any
|
|
267
|
+
var data = function (d) {
|
|
268
|
+
return [
|
|
269
|
+
{ x: d.source.x1, y0: d.y0 + d.width / 2, y1: d.y0 - d.width / 2 },
|
|
270
|
+
{ x: d.target.x0, y0: d.y1 + d.width / 2, y1: d.y1 - d.width / 2 },
|
|
271
|
+
];
|
|
272
|
+
};
|
|
273
|
+
// eslint-disable-next-line @typescript-eslint/no-explicit-any
|
|
274
|
+
var dataPoints = data(singleLink);
|
|
275
|
+
var linkArea = d3_shape_1.area()
|
|
276
|
+
// eslint-disable-next-line @typescript-eslint/no-explicit-any
|
|
277
|
+
.x(function (p) { return p.x; })
|
|
278
|
+
// eslint-disable-next-line @typescript-eslint/no-explicit-any
|
|
279
|
+
.y0(function (p) { return p.y0; })
|
|
280
|
+
// eslint-disable-next-line @typescript-eslint/no-explicit-any
|
|
281
|
+
.y1(function (p) { return p.y1; })
|
|
282
|
+
.curve(d3_shape_1.curveBumpX);
|
|
283
|
+
var gradientUrl = "url(#gradient-" + _this._linkId + "-" + index + ")";
|
|
284
|
+
var link = (React.createElement("g", { key: _this._linkId + "-" + index },
|
|
285
|
+
React.createElement("defs", null,
|
|
286
|
+
React.createElement("linearGradient", { id: "gradient-" + _this._linkId + "-" + index, x1: "0%", y1: "0%", x2: "100%", y2: "0%" },
|
|
287
|
+
React.createElement("stop", { offset: "0", stopColor: singleLink.source.color }),
|
|
288
|
+
React.createElement("stop", { offset: "100%", stopColor: singleLink.target.color }))),
|
|
289
|
+
React.createElement("path", { d: linkArea(dataPoints), id: Utilities_1.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' +
|
|
290
|
+
singleLink.source.name +
|
|
291
|
+
'to' +
|
|
292
|
+
singleLink.target.name +
|
|
293
|
+
'with weight' +
|
|
294
|
+
singleLink.unnormalizedValue, role: "img" })));
|
|
68
295
|
links.push(link);
|
|
69
296
|
});
|
|
70
297
|
}
|
|
71
298
|
return links;
|
|
72
299
|
};
|
|
73
300
|
SankeyChartBase.prototype._createNodes = function (width) {
|
|
301
|
+
var _this = this;
|
|
74
302
|
var nodes = [];
|
|
75
303
|
if (this.props.data.SankeyChartData) {
|
|
76
304
|
// eslint-disable-next-line @typescript-eslint/no-explicit-any
|
|
77
305
|
this.props.data.SankeyChartData.nodes.forEach(function (singleNode, index) {
|
|
306
|
+
var onMouseOut = function () {
|
|
307
|
+
_this._onLeave(singleNode);
|
|
308
|
+
};
|
|
78
309
|
var height = singleNode.y1 - singleNode.y0 > 0 ? singleNode.y1 - singleNode.y0 : 0;
|
|
79
|
-
var
|
|
80
|
-
|
|
81
|
-
|
|
82
|
-
|
|
83
|
-
|
|
310
|
+
var padding = 8;
|
|
311
|
+
var textLengthForNodeWeight = 0;
|
|
312
|
+
// If the nodeWeight is in the same line as node description an extra padding
|
|
313
|
+
// of 6 px is required between node description and node weight.
|
|
314
|
+
if (height < MIN_HEIGHT_FOR_DOUBLINE_TYPE) {
|
|
315
|
+
padding = padding + 6;
|
|
316
|
+
var tspan = d3_selection_1.select('.nodeName').append('text').attr('class', 'tempText').append('tspan').text(null);
|
|
317
|
+
tspan.text(singleNode.actualValue);
|
|
318
|
+
if (tspan.node() !== null) {
|
|
319
|
+
textLengthForNodeWeight = tspan.node().getComputedTextLength();
|
|
320
|
+
padding = padding + textLengthForNodeWeight;
|
|
321
|
+
}
|
|
322
|
+
tspan.text(null);
|
|
323
|
+
d3_selection_1.selectAll('.tempText').remove();
|
|
324
|
+
}
|
|
325
|
+
// Since the total width of the node is 124 and we are giving margin of 8px from the left .
|
|
326
|
+
//So the actual value on which it will be truncated is 124-8=116.
|
|
327
|
+
var truncatedname = _this._truncateText(singleNode.name, 116, padding);
|
|
328
|
+
var isTruncated = truncatedname.slice(-3) === '...';
|
|
329
|
+
var id = Utilities_1.getId('tooltip');
|
|
330
|
+
var div = d3_selection_1.select('body')
|
|
331
|
+
.append('div')
|
|
332
|
+
.attr('id', id)
|
|
333
|
+
.attr('class', _this._classNames.toolTip)
|
|
334
|
+
.style('opacity', 0);
|
|
335
|
+
var nodeId = Utilities_1.getId('nodeBar');
|
|
336
|
+
var node = (React.createElement("g", { key: index, id: Utilities_1.getId('nodeGElement') },
|
|
337
|
+
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' + ("" + singleNode.name) + 'with weight' + ("" + singleNode.actualValue), role: "img" }),
|
|
338
|
+
singleNode.y1 - singleNode.y0 > MIN_HEIGHT_FOR_TYPE && (React.createElement("g", { className: _this._classNames.nodeTextContainer },
|
|
339
|
+
React.createElement("g", { className: "nodeName" },
|
|
340
|
+
React.createElement("text", { id: 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: !(!_this.state.selectedState ||
|
|
341
|
+
(_this.state.selectedState &&
|
|
342
|
+
_this.state.selectedNodes.has(singleNode.index) &&
|
|
343
|
+
_this.state.selectedNode) ||
|
|
344
|
+
(_this.state.selectedState && !_this.state.selectedNode))
|
|
345
|
+
? DEFAULT_TEXT_COLOR
|
|
346
|
+
: NON_SELECTED_TEXT_COLOR, fontSize: 10, onMouseOver: _this._showTooltip.bind(_this, singleNode.name, isTruncated, div), onMouseOut: _this._hideTooltip.bind(_this, div) }, truncatedname)),
|
|
347
|
+
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: !(!_this.state.selectedState ||
|
|
348
|
+
(_this.state.selectedState &&
|
|
349
|
+
_this.state.selectedNodes.has(singleNode.index) &&
|
|
350
|
+
_this.state.selectedNode) ||
|
|
351
|
+
(_this.state.selectedState && !_this.state.selectedNode))
|
|
352
|
+
? DEFAULT_TEXT_COLOR
|
|
353
|
+
: NON_SELECTED_TEXT_COLOR, fontSize: 14 }, singleNode.actualValue)))));
|
|
84
354
|
nodes.push(node);
|
|
85
355
|
});
|
|
86
356
|
return nodes;
|
|
87
357
|
}
|
|
88
358
|
};
|
|
359
|
+
// eslint-disable-next-line @typescript-eslint/no-explicit-any
|
|
360
|
+
SankeyChartBase.prototype._onLeave = function (singleNode) {
|
|
361
|
+
if (this.state.selectedState) {
|
|
362
|
+
this.setState({
|
|
363
|
+
selectedState: false,
|
|
364
|
+
selectedNodes: new Set(),
|
|
365
|
+
selectedLinks: new Set(),
|
|
366
|
+
selectedNode: undefined,
|
|
367
|
+
});
|
|
368
|
+
}
|
|
369
|
+
};
|
|
370
|
+
// eslint-disable-next-line @typescript-eslint/no-explicit-any
|
|
371
|
+
SankeyChartBase.prototype._onHover = function (singleNode, mouseEvent) {
|
|
372
|
+
mouseEvent.persist();
|
|
373
|
+
this._onCloseCallout();
|
|
374
|
+
if (!this.state.selectedState) {
|
|
375
|
+
var selectedLinks = this._getSelectedLinks(singleNode);
|
|
376
|
+
var selectedNodes = this._getSelectedNodes(selectedLinks);
|
|
377
|
+
selectedNodes.push(singleNode);
|
|
378
|
+
this.setState({
|
|
379
|
+
selectedState: true,
|
|
380
|
+
selectedNodes: new Set(Array.from(selectedNodes).map(function (node) { return node.index; })),
|
|
381
|
+
selectedLinks: new Set(Array.from(selectedLinks).map(function (link) { return link.index; })),
|
|
382
|
+
selectedNode: singleNode,
|
|
383
|
+
refSelected: mouseEvent,
|
|
384
|
+
isCalloutVisible: singleNode.y1 - singleNode.y0 < MIN_HEIGHT_FOR_TYPE,
|
|
385
|
+
color: singleNode.color,
|
|
386
|
+
xCalloutValue: singleNode.name,
|
|
387
|
+
// eslint-disable-next-line @typescript-eslint/no-explicit-any
|
|
388
|
+
yCalloutValue: singleNode.actualValue,
|
|
389
|
+
});
|
|
390
|
+
}
|
|
391
|
+
};
|
|
392
|
+
// eslint-disable-next-line @typescript-eslint/no-explicit-any
|
|
393
|
+
SankeyChartBase.prototype._onStreamHover = function (singleLink, mouseEvent) {
|
|
394
|
+
mouseEvent.persist();
|
|
395
|
+
this._onCloseCallout();
|
|
396
|
+
if (!this.state.selectedState) {
|
|
397
|
+
var _a = this._getSelectedLinksforStreamHover(singleLink), selectedLinks = _a.selectedLinks, selectedNodes = _a.selectedNodes;
|
|
398
|
+
this.setState({
|
|
399
|
+
selectedState: true,
|
|
400
|
+
selectedNodes: new Set(Array.from(selectedNodes).map(function (node) { return node.index; })),
|
|
401
|
+
selectedLinks: new Set(Array.from(selectedLinks).map(function (link) { return link.index; })),
|
|
402
|
+
refSelected: mouseEvent,
|
|
403
|
+
selectedLink: singleLink,
|
|
404
|
+
isCalloutVisible: true,
|
|
405
|
+
color: singleLink.source.color,
|
|
406
|
+
xCalloutValue: singleLink.target.name,
|
|
407
|
+
// eslint-disable-next-line @typescript-eslint/no-explicit-any
|
|
408
|
+
yCalloutValue: singleLink.source.actualValue,
|
|
409
|
+
descriptionMessage: 'from ' + singleLink.source.name,
|
|
410
|
+
});
|
|
411
|
+
}
|
|
412
|
+
};
|
|
413
|
+
SankeyChartBase.prototype._onStreamLeave = function (singleLink) {
|
|
414
|
+
if (this.state.selectedState) {
|
|
415
|
+
this.setState({
|
|
416
|
+
selectedState: false,
|
|
417
|
+
selectedNodes: new Set(),
|
|
418
|
+
selectedLinks: new Set(),
|
|
419
|
+
selectedLink: undefined,
|
|
420
|
+
});
|
|
421
|
+
}
|
|
422
|
+
};
|
|
423
|
+
SankeyChartBase.prototype._onFocusLink = function (singleLink, element) {
|
|
424
|
+
element.persist();
|
|
425
|
+
this._onCloseCallout();
|
|
426
|
+
this.setState({
|
|
427
|
+
refSelected: element.currentTarget,
|
|
428
|
+
selectedLink: singleLink,
|
|
429
|
+
isCalloutVisible: true,
|
|
430
|
+
color: singleLink.source.color,
|
|
431
|
+
xCalloutValue: singleLink.target.name,
|
|
432
|
+
// eslint-disable-next-line @typescript-eslint/no-explicit-any
|
|
433
|
+
yCalloutValue: singleLink.source.actualValue,
|
|
434
|
+
descriptionMessage: 'from ' + singleLink.source.name,
|
|
435
|
+
});
|
|
436
|
+
};
|
|
437
|
+
/**
|
|
438
|
+
* This is used to assign node fillcolors and borderColor cyclically when the user doesnt
|
|
439
|
+
* provide color to individual node.
|
|
440
|
+
*/
|
|
441
|
+
SankeyChartBase.prototype._assignNodeColors = function () {
|
|
442
|
+
var colors;
|
|
443
|
+
var borders;
|
|
444
|
+
if (this.props.colorsForNodes && this.props.borderColorsForNodes) {
|
|
445
|
+
colors = this.props.colorsForNodes;
|
|
446
|
+
borders = this.props.borderColorsForNodes;
|
|
447
|
+
}
|
|
448
|
+
else {
|
|
449
|
+
colors = DEFAULT_NODE_COLORS.map(function (color) { return color.fillColor; });
|
|
450
|
+
borders = DEFAULT_NODE_COLORS.map(function (color) { return color.borderColor; });
|
|
451
|
+
}
|
|
452
|
+
var currentIndex = 0;
|
|
453
|
+
this.props.data.SankeyChartData.nodes.forEach(function (node) {
|
|
454
|
+
if (!node.color && !node.borderColor) {
|
|
455
|
+
node.color = colors[currentIndex];
|
|
456
|
+
node.borderColor = borders[currentIndex];
|
|
457
|
+
}
|
|
458
|
+
else if (node.color && !node.borderColor) {
|
|
459
|
+
node.borderColor = '#757575';
|
|
460
|
+
}
|
|
461
|
+
else if (node.borderColor && !node.color) {
|
|
462
|
+
node.color = '#F5F5F5';
|
|
463
|
+
}
|
|
464
|
+
currentIndex = (currentIndex + 1) % colors.length;
|
|
465
|
+
});
|
|
466
|
+
};
|
|
467
|
+
// eslint-disable-next-line @typescript-eslint/no-explicit-any
|
|
468
|
+
SankeyChartBase.prototype._fillStreamColors = function (singleLink, gradientUrl) {
|
|
469
|
+
if (this.state.selectedState && this.state.selectedLinks.has(singleLink.index) && this.state.selectedNode) {
|
|
470
|
+
return this.state.selectedNode.color;
|
|
471
|
+
}
|
|
472
|
+
else if (this.state.selectedState && this.state.selectedLinks.has(singleLink.index)) {
|
|
473
|
+
return gradientUrl;
|
|
474
|
+
}
|
|
475
|
+
};
|
|
476
|
+
// eslint-disable-next-line @typescript-eslint/no-explicit-any
|
|
477
|
+
SankeyChartBase.prototype._fillStreamBorder = function (singleLink, gradientUrl) {
|
|
478
|
+
if (!this.state.selectedState) {
|
|
479
|
+
return NON_SELECTED_NODE_AND_STREAM_COLOR;
|
|
480
|
+
}
|
|
481
|
+
else if (this.state.selectedState && this.state.selectedLinks.has(singleLink.index) && this.state.selectedNode) {
|
|
482
|
+
return this.state.selectedNode.borderColor;
|
|
483
|
+
}
|
|
484
|
+
else if (this.state.selectedState && this.state.selectedLinks.has(singleLink.index)) {
|
|
485
|
+
return gradientUrl;
|
|
486
|
+
}
|
|
487
|
+
return NON_SELECTED_NODE_AND_STREAM_COLOR;
|
|
488
|
+
};
|
|
489
|
+
// eslint-disable-next-line @typescript-eslint/no-explicit-any
|
|
490
|
+
SankeyChartBase.prototype._getSelectedNodes = function (selectedLinks) {
|
|
491
|
+
// eslint-disable-next-line @typescript-eslint/no-explicit-any
|
|
492
|
+
var nodes = [];
|
|
493
|
+
selectedLinks.forEach(function (link) {
|
|
494
|
+
nodes.push(link.target);
|
|
495
|
+
if (nodes.indexOf(link.source) === -1) {
|
|
496
|
+
nodes.push(link.source);
|
|
497
|
+
}
|
|
498
|
+
});
|
|
499
|
+
return nodes;
|
|
500
|
+
};
|
|
501
|
+
// eslint-disable-next-line @typescript-eslint/no-explicit-any
|
|
502
|
+
SankeyChartBase.prototype._getSelectedLinks = function (singleNode) {
|
|
503
|
+
// eslint-disable-next-line @typescript-eslint/no-explicit-any, no-array-constructor
|
|
504
|
+
var q = new Array();
|
|
505
|
+
var finalLinks = new Set();
|
|
506
|
+
singleNode.sourceLinks.forEach(function (link) {
|
|
507
|
+
q.push(link);
|
|
508
|
+
finalLinks.add(link);
|
|
509
|
+
});
|
|
510
|
+
while (q.length > 0) {
|
|
511
|
+
var poppedLink = q.shift();
|
|
512
|
+
var node = poppedLink.target;
|
|
513
|
+
if (node && node.sourceLinks) {
|
|
514
|
+
node.sourceLinks.forEach(function (link) {
|
|
515
|
+
finalLinks.add(link);
|
|
516
|
+
q.push(link);
|
|
517
|
+
});
|
|
518
|
+
}
|
|
519
|
+
}
|
|
520
|
+
if (singleNode.targetLinks) {
|
|
521
|
+
singleNode.targetLinks.forEach(function (link) {
|
|
522
|
+
q.push(link);
|
|
523
|
+
finalLinks.add(link);
|
|
524
|
+
});
|
|
525
|
+
}
|
|
526
|
+
while (q.length > 0) {
|
|
527
|
+
var poppedLink = q.shift();
|
|
528
|
+
var node = poppedLink.source;
|
|
529
|
+
if (node && node.targetLinks) {
|
|
530
|
+
node.targetLinks.forEach(function (link) {
|
|
531
|
+
finalLinks.add(link);
|
|
532
|
+
q.push(link);
|
|
533
|
+
});
|
|
534
|
+
}
|
|
535
|
+
}
|
|
536
|
+
return finalLinks;
|
|
537
|
+
};
|
|
538
|
+
// eslint-disable-next-line @typescript-eslint/no-explicit-any
|
|
539
|
+
SankeyChartBase.prototype._getSelectedLinksforStreamHover = function (singleLink) {
|
|
540
|
+
// eslint-disable-next-line @typescript-eslint/no-explicit-any, no-array-constructor
|
|
541
|
+
var q = new Array();
|
|
542
|
+
var finalLinks = new Set();
|
|
543
|
+
var finalNodes = new Set();
|
|
544
|
+
q.push(singleLink.source);
|
|
545
|
+
finalLinks.add(singleLink);
|
|
546
|
+
while (q.length > 0) {
|
|
547
|
+
var poppedNode = q.shift();
|
|
548
|
+
finalNodes.add(poppedNode);
|
|
549
|
+
if (poppedNode.targetLinks && poppedNode.targetLinks.length > 0) {
|
|
550
|
+
poppedNode.targetLinks.forEach(function (link) {
|
|
551
|
+
q.push(link.source);
|
|
552
|
+
finalLinks.add(link);
|
|
553
|
+
});
|
|
554
|
+
}
|
|
555
|
+
}
|
|
556
|
+
q.push(singleLink.target);
|
|
557
|
+
while (q.length > 0) {
|
|
558
|
+
var poppedNode = q.shift();
|
|
559
|
+
finalNodes.add(poppedNode);
|
|
560
|
+
if (poppedNode.sourceLinks && poppedNode.sourceLinks.length > 0) {
|
|
561
|
+
poppedNode.sourceLinks.forEach(function (link) {
|
|
562
|
+
q.push(link.target);
|
|
563
|
+
finalLinks.add(link);
|
|
564
|
+
});
|
|
565
|
+
}
|
|
566
|
+
}
|
|
567
|
+
return {
|
|
568
|
+
selectedLinks: finalLinks,
|
|
569
|
+
selectedNodes: finalNodes,
|
|
570
|
+
};
|
|
571
|
+
};
|
|
572
|
+
SankeyChartBase.prototype._getOpacityStream = function (singleLink) {
|
|
573
|
+
if (this.state.selectedState) {
|
|
574
|
+
if (!this.state.selectedLinks.has(singleLink.index)) {
|
|
575
|
+
return NON_SELECTED_OPACITY;
|
|
576
|
+
}
|
|
577
|
+
else if (this.state.selectedState &&
|
|
578
|
+
this.state.selectedLinks.has(singleLink.index) &&
|
|
579
|
+
!this.state.selectedNode) {
|
|
580
|
+
return SELECTED_STREAM_OPACITY;
|
|
581
|
+
}
|
|
582
|
+
}
|
|
583
|
+
return REST_STREAM_OPACITY;
|
|
584
|
+
};
|
|
585
|
+
SankeyChartBase.prototype._getOpacityStreamBorder = function (singleLink) {
|
|
586
|
+
if (this.state.selectedState && !this.state.selectedLinks.has(singleLink.index) && !this.state.selectedNode) {
|
|
587
|
+
return NON_SELECTED_STREAM_BORDER_OPACITY;
|
|
588
|
+
}
|
|
589
|
+
return NON_SELECTED_OPACITY;
|
|
590
|
+
};
|
|
89
591
|
SankeyChartBase.prototype._fitParentContainer = function () {
|
|
90
592
|
var _this = this;
|
|
91
593
|
var _a = this.state, containerWidth = _a.containerWidth, containerHeight = _a.containerHeight;
|
|
@@ -102,6 +604,65 @@ define(["require", "exports", "tslib", "react", "@fluentui/react/lib/Utilities",
|
|
|
102
604
|
}
|
|
103
605
|
});
|
|
104
606
|
};
|
|
607
|
+
/**
|
|
608
|
+
*
|
|
609
|
+
* @param text is the text which we are trying to truncate
|
|
610
|
+
* @param rectangleWidth is the width of the rectangle which will contain the text
|
|
611
|
+
* @param padding is the space we need to leave between the rect lines and other text
|
|
612
|
+
* @param nodeWeight is the text if present needs to be accomodate in the same line as text.
|
|
613
|
+
* @returns the truncated text , if truncated given the above parameters.
|
|
614
|
+
*/
|
|
615
|
+
SankeyChartBase.prototype._truncateText = function (text, rectangleWidth, padding) {
|
|
616
|
+
var textLengthForNodeName = rectangleWidth - padding;
|
|
617
|
+
var elipsisLength = 0;
|
|
618
|
+
var tspan = d3_selection_1.select('.nodeName')
|
|
619
|
+
.append('text')
|
|
620
|
+
.attr('class', 'tempText')
|
|
621
|
+
.attr('font-size', '10')
|
|
622
|
+
.append('tspan')
|
|
623
|
+
.text(null);
|
|
624
|
+
tspan.text(text);
|
|
625
|
+
if (tspan.node() !== null && tspan.node().getComputedTextLength() <= textLengthForNodeName) {
|
|
626
|
+
return text;
|
|
627
|
+
}
|
|
628
|
+
tspan.text(null);
|
|
629
|
+
tspan.text('...');
|
|
630
|
+
if (tspan.node() !== null) {
|
|
631
|
+
elipsisLength = tspan.node().getComputedTextLength();
|
|
632
|
+
}
|
|
633
|
+
tspan.text(null);
|
|
634
|
+
var line = '';
|
|
635
|
+
for (var i = 0; i < text.length; i++) {
|
|
636
|
+
line += text[i];
|
|
637
|
+
tspan.text(line);
|
|
638
|
+
if (tspan.node() !== null) {
|
|
639
|
+
var w = tspan.node().getComputedTextLength();
|
|
640
|
+
if (w >= textLengthForNodeName - elipsisLength) {
|
|
641
|
+
line = line.slice(0, -1);
|
|
642
|
+
line += '...';
|
|
643
|
+
break;
|
|
644
|
+
}
|
|
645
|
+
}
|
|
646
|
+
}
|
|
647
|
+
tspan.text(null);
|
|
648
|
+
d3_selection_1.selectAll('.tempText').remove();
|
|
649
|
+
return line;
|
|
650
|
+
};
|
|
651
|
+
// eslint-disable-next-line @typescript-eslint/no-explicit-any
|
|
652
|
+
SankeyChartBase.prototype._showTooltip = function (text, checkTrcuncated, div, evt) {
|
|
653
|
+
if (checkTrcuncated) {
|
|
654
|
+
//Fixing tooltip position by attaching it to the element rather than page
|
|
655
|
+
div.style('opacity', 0.9);
|
|
656
|
+
div
|
|
657
|
+
.html(text)
|
|
658
|
+
.style('left', evt.pageX + 'px')
|
|
659
|
+
.style('top', evt.pageY - 28 + 'px');
|
|
660
|
+
}
|
|
661
|
+
};
|
|
662
|
+
// eslint-disable-next-line @typescript-eslint/no-explicit-any
|
|
663
|
+
SankeyChartBase.prototype._hideTooltip = function (div) {
|
|
664
|
+
div.style('opacity', 0);
|
|
665
|
+
};
|
|
105
666
|
return SankeyChartBase;
|
|
106
667
|
}(React.Component));
|
|
107
668
|
exports.SankeyChartBase = SankeyChartBase;
|