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