@fluentui/react-charts 9.0.1 → 9.0.2

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 (79) hide show
  1. package/CHANGELOG.md +17 -2
  2. package/dist/index.d.ts +463 -36
  3. package/lib/GaugeChart.js +1 -0
  4. package/lib/GaugeChart.js.map +1 -0
  5. package/lib/GroupedVerticalBarChart.js +1 -0
  6. package/lib/GroupedVerticalBarChart.js.map +1 -0
  7. package/lib/ScatterChart.js +1 -0
  8. package/lib/ScatterChart.js.map +1 -0
  9. package/lib/components/GaugeChart/GaugeChart.js +589 -0
  10. package/lib/components/GaugeChart/GaugeChart.js.map +1 -0
  11. package/lib/components/GaugeChart/GaugeChart.types.js +4 -0
  12. package/lib/components/GaugeChart/GaugeChart.types.js.map +1 -0
  13. package/lib/components/GaugeChart/index.js +3 -0
  14. package/lib/components/GaugeChart/index.js.map +1 -0
  15. package/lib/components/GaugeChart/useGaugeChartStyles.styles.js +174 -0
  16. package/lib/components/GaugeChart/useGaugeChartStyles.styles.js.map +1 -0
  17. package/lib/components/GroupedVerticalBarChart/GroupedVerticalBarChart.js +492 -0
  18. package/lib/components/GroupedVerticalBarChart/GroupedVerticalBarChart.js.map +1 -0
  19. package/lib/components/GroupedVerticalBarChart/GroupedVerticalBarChart.types.js +4 -0
  20. package/lib/components/GroupedVerticalBarChart/GroupedVerticalBarChart.types.js.map +1 -0
  21. package/lib/components/GroupedVerticalBarChart/index.js +3 -0
  22. package/lib/components/GroupedVerticalBarChart/index.js.map +1 -0
  23. package/lib/components/GroupedVerticalBarChart/useGroupedVerticalBarChartStyles.styles.js +90 -0
  24. package/lib/components/GroupedVerticalBarChart/useGroupedVerticalBarChartStyles.styles.js.map +1 -0
  25. package/lib/components/Legends/Legends.types.js.map +1 -1
  26. package/lib/components/LineChart/LineChart.js.map +1 -1
  27. package/lib/components/ScatterChart/ScatterChart.js +478 -0
  28. package/lib/components/ScatterChart/ScatterChart.js.map +1 -0
  29. package/lib/components/ScatterChart/ScatterChart.types.js +4 -0
  30. package/lib/components/ScatterChart/ScatterChart.types.js.map +1 -0
  31. package/lib/components/ScatterChart/index.js +3 -0
  32. package/lib/components/ScatterChart/index.js.map +1 -0
  33. package/lib/components/ScatterChart/useScatterChartStyles.styles.js +65 -0
  34. package/lib/components/ScatterChart/useScatterChartStyles.styles.js.map +1 -0
  35. package/lib/components/Sparkline/Sparkline.js.map +1 -1
  36. package/lib/index.js +3 -0
  37. package/lib/index.js.map +1 -1
  38. package/lib/types/DataPoint.js.map +1 -1
  39. package/lib/utilities/utilities.js +123 -5
  40. package/lib/utilities/utilities.js.map +1 -1
  41. package/lib-commonjs/GaugeChart.js +6 -0
  42. package/lib-commonjs/GaugeChart.js.map +1 -0
  43. package/lib-commonjs/GroupedVerticalBarChart.js +6 -0
  44. package/lib-commonjs/GroupedVerticalBarChart.js.map +1 -0
  45. package/lib-commonjs/ScatterChart.js +6 -0
  46. package/lib-commonjs/ScatterChart.js.map +1 -0
  47. package/lib-commonjs/components/GaugeChart/GaugeChart.js +618 -0
  48. package/lib-commonjs/components/GaugeChart/GaugeChart.js.map +1 -0
  49. package/lib-commonjs/components/GaugeChart/GaugeChart.types.js +7 -0
  50. package/lib-commonjs/components/GaugeChart/GaugeChart.types.js.map +1 -0
  51. package/lib-commonjs/components/GaugeChart/index.js +8 -0
  52. package/lib-commonjs/components/GaugeChart/index.js.map +1 -0
  53. package/lib-commonjs/components/GaugeChart/useGaugeChartStyles.styles.js +252 -0
  54. package/lib-commonjs/components/GaugeChart/useGaugeChartStyles.styles.js.map +1 -0
  55. package/lib-commonjs/components/GroupedVerticalBarChart/GroupedVerticalBarChart.js +498 -0
  56. package/lib-commonjs/components/GroupedVerticalBarChart/GroupedVerticalBarChart.js.map +1 -0
  57. package/lib-commonjs/components/GroupedVerticalBarChart/GroupedVerticalBarChart.types.js +7 -0
  58. package/lib-commonjs/components/GroupedVerticalBarChart/GroupedVerticalBarChart.types.js.map +1 -0
  59. package/lib-commonjs/components/GroupedVerticalBarChart/index.js +8 -0
  60. package/lib-commonjs/components/GroupedVerticalBarChart/index.js.map +1 -0
  61. package/lib-commonjs/components/GroupedVerticalBarChart/useGroupedVerticalBarChartStyles.styles.js +139 -0
  62. package/lib-commonjs/components/GroupedVerticalBarChart/useGroupedVerticalBarChartStyles.styles.js.map +1 -0
  63. package/lib-commonjs/components/Legends/Legends.types.js.map +1 -1
  64. package/lib-commonjs/components/LineChart/LineChart.js.map +1 -1
  65. package/lib-commonjs/components/ScatterChart/ScatterChart.js +484 -0
  66. package/lib-commonjs/components/ScatterChart/ScatterChart.js.map +1 -0
  67. package/lib-commonjs/components/ScatterChart/ScatterChart.types.js +7 -0
  68. package/lib-commonjs/components/ScatterChart/ScatterChart.types.js.map +1 -0
  69. package/lib-commonjs/components/ScatterChart/index.js +8 -0
  70. package/lib-commonjs/components/ScatterChart/index.js.map +1 -0
  71. package/lib-commonjs/components/ScatterChart/useScatterChartStyles.styles.js +96 -0
  72. package/lib-commonjs/components/ScatterChart/useScatterChartStyles.styles.js.map +1 -0
  73. package/lib-commonjs/components/Sparkline/Sparkline.js.map +1 -1
  74. package/lib-commonjs/index.js +3 -0
  75. package/lib-commonjs/index.js.map +1 -1
  76. package/lib-commonjs/types/DataPoint.js.map +1 -1
  77. package/lib-commonjs/utilities/utilities.js +115 -5
  78. package/lib-commonjs/utilities/utilities.js.map +1 -1
  79. package/package.json +6 -6
@@ -0,0 +1,618 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", {
3
+ value: true
4
+ });
5
+ function _export(target, all) {
6
+ for(var name in all)Object.defineProperty(target, name, {
7
+ enumerable: true,
8
+ get: all[name]
9
+ });
10
+ }
11
+ _export(exports, {
12
+ ARC_PADDING: function() {
13
+ return ARC_PADDING;
14
+ },
15
+ BREAKPOINTS: function() {
16
+ return BREAKPOINTS;
17
+ },
18
+ GaugeChart: function() {
19
+ return GaugeChart;
20
+ },
21
+ calcNeedleRotation: function() {
22
+ return calcNeedleRotation;
23
+ },
24
+ getChartValueLabel: function() {
25
+ return getChartValueLabel;
26
+ },
27
+ getSegmentLabel: function() {
28
+ return getSegmentLabel;
29
+ }
30
+ });
31
+ const _interop_require_wildcard = require("@swc/helpers/_/_interop_require_wildcard");
32
+ const _react = /*#__PURE__*/ _interop_require_wildcard._(require("react"));
33
+ const _useGaugeChartStylesstyles = require("./useGaugeChartStyles.styles");
34
+ const _d3selection = require("d3-selection");
35
+ const _d3shape = require("d3-shape");
36
+ const _index = require("../../utilities/index");
37
+ const _localeutil = require("../../utilities/locale-util");
38
+ const _SVGTooltipText = require("../../utilities/SVGTooltipText");
39
+ const _index1 = require("../Legends/index");
40
+ const _reacttabster = require("@fluentui/react-tabster");
41
+ const _ChartPopover = require("../CommonComponents/ChartPopover");
42
+ const GAUGE_MARGIN = 16;
43
+ const LABEL_WIDTH = 36;
44
+ const LABEL_HEIGHT = 16;
45
+ const LABEL_OFFSET = 4;
46
+ const TITLE_OFFSET = 11;
47
+ const EXTRA_NEEDLE_LENGTH = 4;
48
+ const ARC_PADDING = 2;
49
+ const BREAKPOINTS = [
50
+ {
51
+ minRadius: 52,
52
+ arcWidth: 12,
53
+ fontSize: 20
54
+ },
55
+ {
56
+ minRadius: 70,
57
+ arcWidth: 16,
58
+ fontSize: 24
59
+ },
60
+ {
61
+ minRadius: 88,
62
+ arcWidth: 20,
63
+ fontSize: 32
64
+ },
65
+ {
66
+ minRadius: 106,
67
+ arcWidth: 24,
68
+ fontSize: 32
69
+ },
70
+ {
71
+ minRadius: 124,
72
+ arcWidth: 28,
73
+ fontSize: 40
74
+ },
75
+ {
76
+ minRadius: 142,
77
+ arcWidth: 32,
78
+ fontSize: 40
79
+ }
80
+ ];
81
+ const calcNeedleRotation = (chartValue, minValue, maxValue)=>{
82
+ let needleRotation = (chartValue - minValue) / (maxValue - minValue) * 180;
83
+ if (needleRotation < 0) {
84
+ needleRotation = 0;
85
+ } else if (needleRotation > 180) {
86
+ needleRotation = 180;
87
+ }
88
+ return needleRotation;
89
+ };
90
+ const getSegmentLabel = (segment, minValue, maxValue, variant, isAriaLabel = false)=>{
91
+ if (isAriaLabel) {
92
+ return minValue === 0 && variant === 'single-segment' ? `${segment.legend}, ${segment.size} out of ${maxValue} or ${(segment.size / maxValue * 100).toFixed()}%` : `${segment.legend}, ${segment.start} to ${segment.end}`;
93
+ }
94
+ return minValue === 0 && variant === 'single-segment' ? `${segment.size} (${(segment.size / maxValue * 100).toFixed()}%)` : `${segment.start} - ${segment.end}`;
95
+ };
96
+ const getChartValueLabel = (chartValue, minValue, maxValue, chartValueFormat, forCallout = false)=>{
97
+ if (forCallout) {
98
+ // When displaying the chart value as a percentage, use fractions in the callout, and vice versa.
99
+ // This helps clarify the actual value and avoid repetition.
100
+ return minValue !== 0 ? chartValue.toString() : chartValueFormat === 'fraction' ? `${(chartValue / maxValue * 100).toFixed()}%` : `${chartValue}/${maxValue}`;
101
+ }
102
+ return typeof chartValueFormat === 'function' ? chartValueFormat([
103
+ chartValue - minValue,
104
+ maxValue - minValue
105
+ ]) : minValue !== 0 ? chartValue.toString() : chartValueFormat === 'fraction' ? `${chartValue}/${maxValue}` : `${(chartValue / maxValue * 100).toFixed()}%`;
106
+ };
107
+ const GaugeChart = /*#__PURE__*/ _react.forwardRef((props, forwardedRef)=>{
108
+ var _props_legendProps;
109
+ const _getMargins = ()=>{
110
+ const { hideMinMax, chartTitle, sublabel } = props;
111
+ return {
112
+ left: (!hideMinMax ? LABEL_OFFSET + LABEL_WIDTH : 0) + GAUGE_MARGIN,
113
+ right: (!hideMinMax ? LABEL_OFFSET + LABEL_WIDTH : 0) + GAUGE_MARGIN,
114
+ top: (chartTitle ? TITLE_OFFSET + LABEL_HEIGHT : EXTRA_NEEDLE_LENGTH / 2) + GAUGE_MARGIN,
115
+ bottom: (sublabel ? LABEL_OFFSET + LABEL_HEIGHT : 0) + GAUGE_MARGIN
116
+ };
117
+ };
118
+ const _margins = _getMargins();
119
+ const _legendsHeight = !props.hideLegend ? 24 : 0;
120
+ const _rootElem = _react.useRef(null);
121
+ const _isRTL = (0, _index.useRtl)();
122
+ const [width, setWidth] = _react.useState(140 + _getMargins().left + _getMargins().right);
123
+ const [height, setHeight] = _react.useState(70 + _getMargins().top + _getMargins().bottom + _legendsHeight);
124
+ const [hoveredLegend, setHoveredLegend] = _react.useState('');
125
+ const [selectedLegends, setSelectedLegends] = _react.useState(((_props_legendProps = props.legendProps) === null || _props_legendProps === void 0 ? void 0 : _props_legendProps.selectedLegends) || []);
126
+ const [focusedElement, setFocusedElement] = _react.useState('');
127
+ // eslint-disable-next-line @typescript-eslint/no-explicit-any
128
+ const [clickPosition, setClickPosition] = _react.useState({
129
+ x: 0,
130
+ y: 0
131
+ });
132
+ const [isPopoverOpen, setPopoverOpen] = _react.useState(false);
133
+ const [hoverXValue, setHoverXValue] = _react.useState('');
134
+ const [hoverYValues, setHoverYValues] = _react.useState([]);
135
+ const prevPropsRef = _react.useRef(null);
136
+ const _width = props.width || width;
137
+ const _height = props.height || height;
138
+ const _outerRadius = Math.min((_width - (_margins.left + _margins.right)) / 2, _height - (_margins.top + _margins.bottom + _legendsHeight));
139
+ const { arcWidth, chartValueSize } = _getStylesBasedOnBreakpoint();
140
+ const _innerRadius = _outerRadius - arcWidth;
141
+ let _minValue;
142
+ let _maxValue;
143
+ let _segments;
144
+ let _calloutAnchor = '';
145
+ _react.useEffect(()=>{
146
+ if (prevPropsRef.current) {
147
+ var _prevProps_legendProps, _props_legendProps;
148
+ const prevProps = prevPropsRef.current;
149
+ if (!(0, _index.areArraysEqual)((_prevProps_legendProps = prevProps.legendProps) === null || _prevProps_legendProps === void 0 ? void 0 : _prevProps_legendProps.selectedLegends, (_props_legendProps = props.legendProps) === null || _props_legendProps === void 0 ? void 0 : _props_legendProps.selectedLegends)) {
150
+ var _props_legendProps1;
151
+ setSelectedLegends(((_props_legendProps1 = props.legendProps) === null || _props_legendProps1 === void 0 ? void 0 : _props_legendProps1.selectedLegends) || []);
152
+ }
153
+ if (prevProps.height !== props.height || prevProps.width !== props.width) {
154
+ setWidth(props.width);
155
+ setHeight(props.height);
156
+ }
157
+ }
158
+ prevPropsRef.current = props;
159
+ }, [
160
+ props
161
+ ]);
162
+ const classes = (0, _useGaugeChartStylesstyles.useGaugeChartStyles)(props);
163
+ function _getStylesBasedOnBreakpoint() {
164
+ for(let index = BREAKPOINTS.length - 1; index >= 0; index -= 1){
165
+ if (_outerRadius >= BREAKPOINTS[index].minRadius) {
166
+ return {
167
+ arcWidth: BREAKPOINTS[index].arcWidth,
168
+ chartValueSize: BREAKPOINTS[index].fontSize
169
+ };
170
+ }
171
+ }
172
+ return {
173
+ arcWidth: BREAKPOINTS[0].arcWidth,
174
+ chartValueSize: BREAKPOINTS[0].fontSize
175
+ };
176
+ }
177
+ function _processProps() {
178
+ const { minValue = 0, maxValue, segments, roundCorners } = props;
179
+ let total = minValue;
180
+ const processedSegments = segments.map((segment, index)=>{
181
+ const size = Math.max(segment.size, 0);
182
+ total += size;
183
+ return {
184
+ legend: segment.legend,
185
+ size,
186
+ color: typeof segment.color !== 'undefined' ? (0, _index.getColorFromToken)(segment.color, false) : (0, _index.getNextColor)(index, 0, false),
187
+ accessibilityData: segment.accessibilityData,
188
+ start: total - size,
189
+ end: total
190
+ };
191
+ });
192
+ if (typeof maxValue !== 'undefined' && total < maxValue) {
193
+ processedSegments.push({
194
+ legend: 'Unknown',
195
+ size: maxValue - total,
196
+ color: 'neutralLight',
197
+ start: total,
198
+ end: maxValue
199
+ });
200
+ total = maxValue;
201
+ }
202
+ const arcGenerator = (0, _d3shape.arc)().cornerRadius(roundCorners ? 3 : 0).padAngle(ARC_PADDING / _outerRadius).padRadius(_outerRadius);
203
+ const rtlSafeSegments = _isRTL ? Array.from(processedSegments).reverse() : processedSegments;
204
+ let prevAngle = -Math.PI / 2;
205
+ // eslint-disable-next-line @typescript-eslint/no-shadow
206
+ const arcs = rtlSafeSegments.map((segment, index)=>{
207
+ const endAngle = prevAngle + segment.size / (total - minValue) * Math.PI;
208
+ const d = arcGenerator({
209
+ innerRadius: _innerRadius,
210
+ outerRadius: _outerRadius,
211
+ startAngle: prevAngle,
212
+ endAngle
213
+ });
214
+ prevAngle = endAngle;
215
+ return {
216
+ d,
217
+ segmentIndex: _isRTL ? processedSegments.length - 1 - index : index,
218
+ startAngle: prevAngle - segment.size / (total - minValue) * Math.PI,
219
+ endAngle
220
+ };
221
+ });
222
+ _minValue = minValue;
223
+ _maxValue = total;
224
+ _segments = processedSegments;
225
+ return {
226
+ arcs
227
+ };
228
+ }
229
+ function _renderNeedle() {
230
+ const needleRotation = calcNeedleRotation(props.chartValue, _minValue, _maxValue);
231
+ const rtlSafeNeedleRotation = _isRTL ? 180 - needleRotation : needleRotation;
232
+ const strokeWidth = 2;
233
+ const halfStrokeWidth = strokeWidth / 2;
234
+ const needleLength = _outerRadius - _innerRadius + EXTRA_NEEDLE_LENGTH;
235
+ return /*#__PURE__*/ _react.createElement("g", {
236
+ transform: `rotate(${rtlSafeNeedleRotation}, 0, 0)`
237
+ }, /*#__PURE__*/ _react.createElement("path", {
238
+ d: `
239
+ M 0,${-halfStrokeWidth - 3}
240
+ L ${-needleLength},${-halfStrokeWidth - 1}
241
+ A ${halfStrokeWidth + 1},${halfStrokeWidth + 1},0,0,0,${-needleLength},${halfStrokeWidth + 1}
242
+ L 0,${halfStrokeWidth + 3}
243
+ A ${halfStrokeWidth + 3},${halfStrokeWidth + 3},0,0,0,0,${-halfStrokeWidth - 3}
244
+ `,
245
+ strokeWidth: strokeWidth,
246
+ className: classes.needle,
247
+ transform: `translate(${-_innerRadius + EXTRA_NEEDLE_LENGTH / 2})`,
248
+ "data-is-focusable": true,
249
+ onFocus: (e)=>_handleFocus(e, 'Needle'),
250
+ onBlur: _handleBlur,
251
+ onMouseEnter: (e)=>_handleMouseOver(e, 'Needle'),
252
+ onMouseMove: (e)=>_handleMouseOver(e, 'Needle'),
253
+ role: "img",
254
+ "aria-label": 'Current value: ' + getChartValueLabel(props.chartValue, _minValue, _maxValue, props.chartValueFormat)
255
+ }));
256
+ }
257
+ function _renderLegends() {
258
+ if (props.hideLegend) {
259
+ return null;
260
+ }
261
+ const legends = _segments.map((segment, index)=>{
262
+ const color = segment.color || (0, _index.getNextColor)(index, 0, false);
263
+ return {
264
+ title: segment.legend,
265
+ color,
266
+ hoverAction: ()=>{
267
+ setHoveredLegend(segment.legend);
268
+ },
269
+ onMouseOutAction: ()=>{
270
+ setHoveredLegend('');
271
+ }
272
+ };
273
+ });
274
+ return /*#__PURE__*/ _react.createElement("div", {
275
+ className: classes.legendsContainer,
276
+ style: {
277
+ width: props.width
278
+ }
279
+ }, /*#__PURE__*/ _react.createElement(_index1.Legends, {
280
+ legends: legends,
281
+ centerLegends: true,
282
+ ...props.legendProps,
283
+ // eslint-disable-next-line react/jsx-no-bind
284
+ onChange: _onLegendSelectionChange
285
+ }));
286
+ }
287
+ function _onLegendSelectionChange(selectedLegends, event, currentLegend) {
288
+ var _props_legendProps, _props_legendProps1;
289
+ if ((_props_legendProps = props.legendProps) === null || _props_legendProps === void 0 ? void 0 : _props_legendProps.canSelectMultipleLegends) {
290
+ setSelectedLegends(selectedLegends);
291
+ } else {
292
+ setSelectedLegends(selectedLegends.slice(-1));
293
+ }
294
+ if ((_props_legendProps1 = props.legendProps) === null || _props_legendProps1 === void 0 ? void 0 : _props_legendProps1.onChange) {
295
+ props.legendProps.onChange(selectedLegends, event, currentLegend);
296
+ }
297
+ }
298
+ /**
299
+ * This function checks if the given legend is highlighted or not.
300
+ * A legend can be highlighted in 2 ways:
301
+ * 1. selection: if the user clicks on it
302
+ * 2. hovering: if there is no selected legend and the user hovers over it
303
+ */ function _legendHighlighted(legend) {
304
+ return _getHighlightedLegend().includes(legend);
305
+ }
306
+ /**
307
+ * This function checks if none of the legends is selected or hovered.
308
+ */ function _noLegendHighlighted() {
309
+ return _getHighlightedLegend().length === 0;
310
+ }
311
+ function _getHighlightedLegend() {
312
+ return selectedLegends.length > 0 ? selectedLegends : hoveredLegend ? [
313
+ hoveredLegend
314
+ ] : [];
315
+ }
316
+ // eslint-disable-next-line @typescript-eslint/no-shadow
317
+ function _handleFocus(focusEvent, focusedElement) {
318
+ _showCallout(focusEvent, focusedElement, true);
319
+ }
320
+ function _handleBlur() {
321
+ _hideCallout(true);
322
+ }
323
+ function _handleMouseOver(mouseEvent, hoveredElement) {
324
+ _showCallout(mouseEvent, hoveredElement, false);
325
+ }
326
+ function _handleMouseOut() {
327
+ _hideCallout(false);
328
+ }
329
+ function _handleCalloutDismiss() {
330
+ _hideCallout(false);
331
+ }
332
+ // eslint-disable-next-line @typescript-eslint/no-explicit-any
333
+ function _showCallout(event, legend, isFocusEvent) {
334
+ if (_calloutAnchor === legend) {
335
+ return;
336
+ }
337
+ let clientX = 0;
338
+ let clientY = 0;
339
+ if ('clientX' in event) {
340
+ clientX = event.clientX;
341
+ clientY = event.clientY;
342
+ } else {
343
+ // eslint-disable-next-line @typescript-eslint/no-shadow
344
+ const target = event.currentTarget;
345
+ if (target && 'getBoundingClientRect' in target) {
346
+ const boundingRect = target.getBoundingClientRect();
347
+ clientX = boundingRect.left + boundingRect.width / 2;
348
+ clientY = boundingRect.top + boundingRect.height / 2;
349
+ }
350
+ }
351
+ _calloutAnchor = legend;
352
+ // eslint-disable-next-line @typescript-eslint/no-shadow
353
+ const hoverXValue = 'Current value is ' + getChartValueLabel(props.chartValue, _minValue, _maxValue, props.chartValueFormat, true);
354
+ // eslint-disable-next-line @typescript-eslint/no-shadow
355
+ const hoverYValues = _segments.map((segment)=>{
356
+ const yValue = {
357
+ legend: segment.legend,
358
+ y: getSegmentLabel(segment, _minValue, _maxValue, props.variant),
359
+ color: segment.color
360
+ };
361
+ return yValue;
362
+ });
363
+ _updatePosition(clientX, clientY);
364
+ setPopoverOpen([
365
+ 'Needle',
366
+ 'Chart value'
367
+ ].includes(legend) || _noLegendHighlighted() || _legendHighlighted(legend));
368
+ setHoverXValue(hoverXValue);
369
+ setHoverYValues(hoverYValues);
370
+ if (isFocusEvent) {
371
+ setFocusedElement(legend);
372
+ }
373
+ }
374
+ function _hideCallout(isBlurEvent) {
375
+ _calloutAnchor = '';
376
+ setPopoverOpen(false);
377
+ setHoverXValue('');
378
+ setHoverYValues([]);
379
+ if (isBlurEvent) {
380
+ setFocusedElement('');
381
+ }
382
+ }
383
+ function _wrapContent(content, id, maxWidth) {
384
+ const textElement = (0, _d3selection.select)(`#${id}`);
385
+ textElement.text(content);
386
+ if (!textElement.node()) {
387
+ return false;
388
+ }
389
+ let isOverflowing = false;
390
+ let textLength = textElement.node().getComputedTextLength();
391
+ while(textLength > maxWidth && content.length > 0){
392
+ content = content.slice(0, -1);
393
+ textElement.text(content + '...');
394
+ isOverflowing = true;
395
+ textLength = textElement.node().getComputedTextLength();
396
+ }
397
+ return isOverflowing;
398
+ }
399
+ // TO DO: Write a common functional component for Multi value callout and divide sub count method
400
+ // eslint-disable-next-line @typescript-eslint/no-explicit-any
401
+ function _multiValueCallout(calloutProps) {
402
+ const yValueHoverSubCountsExists = _yValueHoverSubCountsExists(calloutProps.YValueHover);
403
+ return /*#__PURE__*/ _react.createElement("div", {
404
+ className: classes.calloutContentRoot
405
+ }, /*#__PURE__*/ _react.createElement("div", {
406
+ className: classes.calloutDateTimeContainer,
407
+ style: yValueHoverSubCountsExists ? {
408
+ marginBottom: '11px'
409
+ } : {}
410
+ }, /*#__PURE__*/ _react.createElement("div", {
411
+ className: classes.calloutContentX,
412
+ ...(0, _index.getAccessibleDataObject)(calloutProps.xAxisCalloutAccessibilityData, 'text', false)
413
+ }, (0, _localeutil.convertToLocaleString)(calloutProps.hoverXValue, props.culture))), /*#__PURE__*/ _react.createElement("div", {
414
+ className: classes.calloutInfoContainer,
415
+ style: yValueHoverSubCountsExists ? {
416
+ display: 'flex'
417
+ } : {}
418
+ }, calloutProps.YValueHover && calloutProps.YValueHover.map((yValue, index, yValues)=>{
419
+ const isLast = index + 1 === yValues.length;
420
+ const { shouldDrawBorderBottom = false } = yValue;
421
+ return /*#__PURE__*/ _react.createElement("div", {
422
+ ...(0, _index.getAccessibleDataObject)(yValue.callOutAccessibilityData, 'text', false),
423
+ key: `callout-content-${index}`,
424
+ style: yValueHoverSubCountsExists ? {
425
+ display: 'inline-block',
426
+ ...shouldDrawBorderBottom && {
427
+ paddingBottom: '10px'
428
+ }
429
+ } : {
430
+ ...shouldDrawBorderBottom && {
431
+ paddingBottom: '10px'
432
+ }
433
+ }
434
+ }, _getCalloutContent(yValue, index, yValueHoverSubCountsExists, isLast));
435
+ }), !!calloutProps.descriptionMessage && /*#__PURE__*/ _react.createElement("div", {
436
+ className: classes.descriptionMessage
437
+ }, calloutProps.descriptionMessage)));
438
+ }
439
+ function _yValueHoverSubCountsExists(yValueHover) {
440
+ if (yValueHover) {
441
+ return yValueHover.some((yValue)=>yValue.yAxisCalloutData && typeof yValue.yAxisCalloutData !== 'string');
442
+ }
443
+ return false;
444
+ }
445
+ function _getCalloutContent(xValue, index, yValueHoverSubCountsExists, isLast) {
446
+ const marginStyle = isLast ? {} : {
447
+ marginRight: '16px'
448
+ };
449
+ const toDrawShape = xValue.index !== undefined && xValue.index !== -1;
450
+ const { culture } = props;
451
+ const yValue = (0, _localeutil.convertToLocaleString)(xValue.y, culture);
452
+ if (!xValue.yAxisCalloutData || typeof xValue.yAxisCalloutData === 'string') {
453
+ return /*#__PURE__*/ _react.createElement("div", {
454
+ style: yValueHoverSubCountsExists ? marginStyle : {}
455
+ }, yValueHoverSubCountsExists && /*#__PURE__*/ _react.createElement("div", {
456
+ className: "ms-fontWeight-semibold",
457
+ style: {
458
+ fontSize: '12pt'
459
+ }
460
+ }, xValue.legend, " (", yValue, ")"), /*#__PURE__*/ _react.createElement("div", {
461
+ id: `${index}_${xValue.y}`,
462
+ className: classes.calloutBlockContainer,
463
+ style: {
464
+ borderLeft: `4px solid ${xValue.color}`
465
+ }
466
+ }, toDrawShape && /*#__PURE__*/ _react.createElement(_index1.Shape, {
467
+ svgProps: {
468
+ className: classes.shapeStyles
469
+ },
470
+ pathProps: {
471
+ fill: xValue.color
472
+ },
473
+ shape: _index.Points[xValue.index % Object.keys(_index.pointTypes).length],
474
+ style: {
475
+ display: 'flex'
476
+ }
477
+ }), /*#__PURE__*/ _react.createElement("div", null, /*#__PURE__*/ _react.createElement("div", {
478
+ className: classes.calloutlegendText
479
+ }, " ", xValue.legend), /*#__PURE__*/ _react.createElement("div", {
480
+ className: classes.calloutContentY
481
+ }, (0, _localeutil.convertToLocaleString)(xValue.yAxisCalloutData ? xValue.yAxisCalloutData : xValue.y || xValue.data, culture)))));
482
+ } else {
483
+ const subcounts = xValue.yAxisCalloutData;
484
+ return /*#__PURE__*/ _react.createElement("div", {
485
+ style: marginStyle
486
+ }, /*#__PURE__*/ _react.createElement("div", {
487
+ className: "ms-fontWeight-semibold",
488
+ style: {
489
+ fontSize: '12pt'
490
+ }
491
+ }, xValue.legend, " (", yValue, ")"), Object.keys(subcounts).map((subcountName)=>{
492
+ return /*#__PURE__*/ _react.createElement("div", {
493
+ key: subcountName,
494
+ className: classes.calloutBlockContainer
495
+ }, /*#__PURE__*/ _react.createElement("div", {
496
+ className: classes.calloutlegendText
497
+ }, " ", (0, _localeutil.convertToLocaleString)(subcountName, culture)), /*#__PURE__*/ _react.createElement("div", {
498
+ className: classes.calloutContentY
499
+ }, (0, _localeutil.convertToLocaleString)(subcounts[subcountName], culture)));
500
+ }));
501
+ }
502
+ }
503
+ function _updatePosition(newX, newY) {
504
+ const threshold = 1; // Set a threshold for movement
505
+ const { x, y } = clickPosition;
506
+ // Calculate the distance moved
507
+ const distance = Math.sqrt(Math.pow(newX - x, 2) + Math.pow(newY - y, 2));
508
+ // Update the position only if the distance moved is greater than the threshold
509
+ if (distance > threshold) {
510
+ setClickPosition({
511
+ x: newX,
512
+ y: newY
513
+ });
514
+ setPopoverOpen(true);
515
+ }
516
+ }
517
+ function _getChartTitle() {
518
+ const { chartTitle } = props;
519
+ return (chartTitle ? `${chartTitle}. ` : '') + `Gauge chart with ${_segments.length} segments. `;
520
+ }
521
+ const { arcs } = _processProps();
522
+ const focusAttributes = (0, _reacttabster.useFocusableGroup)();
523
+ return /*#__PURE__*/ _react.createElement("div", {
524
+ className: classes.root,
525
+ ref: (el)=>_rootElem.current = el,
526
+ ...focusAttributes
527
+ }, /*#__PURE__*/ _react.createElement("svg", {
528
+ className: classes.chart,
529
+ style: {
530
+ width: props.width,
531
+ height: props.height - _legendsHeight
532
+ },
533
+ role: "region",
534
+ "aria-label": _getChartTitle(),
535
+ onMouseLeave: _handleMouseOut
536
+ }, /*#__PURE__*/ _react.createElement("g", {
537
+ transform: `translate(${width / 2}, ${height - (_margins.bottom + _legendsHeight)})`
538
+ }, props.chartTitle && /*#__PURE__*/ _react.createElement("text", {
539
+ x: 0,
540
+ y: -(_outerRadius + TITLE_OFFSET),
541
+ textAnchor: "middle",
542
+ className: classes.chartTitle,
543
+ "aria-hidden": true
544
+ }, props.chartTitle), !props.hideMinMax && /*#__PURE__*/ _react.createElement(_react.Fragment, null, /*#__PURE__*/ _react.createElement("text", {
545
+ x: (_isRTL ? 1 : -1) * (_outerRadius + LABEL_OFFSET),
546
+ y: 0,
547
+ textAnchor: "end",
548
+ className: classes.limits,
549
+ role: "img",
550
+ "aria-label": `Min value: ${_minValue}`
551
+ }, (0, _index.formatValueWithSIPrefix)(_minValue)), /*#__PURE__*/ _react.createElement("text", {
552
+ x: (_isRTL ? -1 : 1) * (_outerRadius + LABEL_OFFSET),
553
+ y: 0,
554
+ textAnchor: "start",
555
+ className: classes.limits,
556
+ role: "img",
557
+ "aria-label": `Max value: ${_maxValue}`
558
+ }, (0, _index.formatValueWithSIPrefix)(_maxValue))), arcs.map((arc, index)=>{
559
+ const segment = _segments[arc.segmentIndex];
560
+ return /*#__PURE__*/ _react.createElement(_react.Fragment, {
561
+ key: index
562
+ }, /*#__PURE__*/ _react.createElement("path", {
563
+ d: arc.d,
564
+ strokeWidth: focusedElement === segment.legend ? ARC_PADDING : 0,
565
+ className: classes.segment,
566
+ fill: segment.color,
567
+ opacity: _legendHighlighted(segment.legend) || _noLegendHighlighted() ? 1 : 0.1,
568
+ ...(0, _index.getAccessibleDataObject)({
569
+ ariaLabel: getSegmentLabel(segment, _minValue, _maxValue, props.variant, true),
570
+ ...segment.accessibilityData
571
+ }, 'img', true),
572
+ onFocus: (e)=>_handleFocus(e, segment.legend),
573
+ onBlur: _handleBlur,
574
+ onMouseEnter: (e)=>_handleMouseOver(e, segment.legend),
575
+ onMouseLeave: (e)=>_handleCalloutDismiss(),
576
+ onMouseMove: (e)=>_handleMouseOver(e, segment.legend),
577
+ "data-is-focusable": _legendHighlighted(segment.legend) || _noLegendHighlighted(),
578
+ tabIndex: segment.legend !== '' ? 0 : undefined
579
+ }));
580
+ }), _renderNeedle(), /*#__PURE__*/ _react.createElement("g", {
581
+ onMouseEnter: (e)=>_handleMouseOver(e, 'Chart value'),
582
+ onMouseMove: (e)=>_handleMouseOver(e, 'Chart value')
583
+ }, /*#__PURE__*/ _react.createElement(_SVGTooltipText.SVGTooltipText, {
584
+ content: getChartValueLabel(props.chartValue, _minValue, _maxValue, props.chartValueFormat),
585
+ textProps: {
586
+ x: 0,
587
+ y: 0,
588
+ textAnchor: 'middle',
589
+ className: classes.chartValue,
590
+ fontSize: chartValueSize,
591
+ 'aria-hidden': 'true'
592
+ },
593
+ maxWidth: _innerRadius * 2 - 24,
594
+ wrapContent: _wrapContent
595
+ })), props.sublabel && /*#__PURE__*/ _react.createElement(_SVGTooltipText.SVGTooltipText, {
596
+ content: props.sublabel,
597
+ textProps: {
598
+ x: 0,
599
+ y: 4,
600
+ textAnchor: 'middle',
601
+ dominantBaseline: 'hanging',
602
+ className: classes.sublabel
603
+ },
604
+ maxWidth: _innerRadius * 2,
605
+ wrapContent: _wrapContent
606
+ }))), _renderLegends(), !props.hideTooltip && isPopoverOpen && /*#__PURE__*/ _react.createElement(_ChartPopover.ChartPopover, {
607
+ ...props.calloutProps,
608
+ clickPosition: clickPosition,
609
+ isPopoverOpen: isPopoverOpen,
610
+ customCallout: {
611
+ customizedCallout: _multiValueCallout({
612
+ hoverXValue: hoverXValue,
613
+ YValueHover: hoverYValues
614
+ })
615
+ }
616
+ }));
617
+ });
618
+ GaugeChart.displayName = 'GaugeChart';