@fluentui/react-charts 0.0.0-nightly-20250814-0406.1 → 0.0.0-nightly-20250815-0407.1

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 (29) hide show
  1. package/CHANGELOG.md +15 -15
  2. package/dist/index.d.ts +15 -6
  3. package/lib/components/CommonComponents/CartesianChart.js +12 -16
  4. package/lib/components/CommonComponents/CartesianChart.js.map +1 -1
  5. package/lib/components/CommonComponents/CartesianChart.types.js.map +1 -1
  6. package/lib/components/DeclarativeChart/DeclarativeChart.js +3 -2
  7. package/lib/components/DeclarativeChart/DeclarativeChart.js.map +1 -1
  8. package/lib/components/DeclarativeChart/PlotlySchemaAdapter.js +13 -6
  9. package/lib/components/DeclarativeChart/PlotlySchemaAdapter.js.map +1 -1
  10. package/lib/components/VerticalStackedBarChart/VerticalStackedBarChart.js +126 -33
  11. package/lib/components/VerticalStackedBarChart/VerticalStackedBarChart.js.map +1 -1
  12. package/lib/components/VerticalStackedBarChart/VerticalStackedBarChart.types.js.map +1 -1
  13. package/lib/types/DataPoint.js.map +1 -1
  14. package/lib/utilities/utilities.js +10 -4
  15. package/lib/utilities/utilities.js.map +1 -1
  16. package/lib-commonjs/components/CommonComponents/CartesianChart.js +12 -15
  17. package/lib-commonjs/components/CommonComponents/CartesianChart.js.map +1 -1
  18. package/lib-commonjs/components/CommonComponents/CartesianChart.types.js.map +1 -1
  19. package/lib-commonjs/components/DeclarativeChart/DeclarativeChart.js +2 -1
  20. package/lib-commonjs/components/DeclarativeChart/DeclarativeChart.js.map +1 -1
  21. package/lib-commonjs/components/DeclarativeChart/PlotlySchemaAdapter.js +15 -6
  22. package/lib-commonjs/components/DeclarativeChart/PlotlySchemaAdapter.js.map +1 -1
  23. package/lib-commonjs/components/VerticalStackedBarChart/VerticalStackedBarChart.js +125 -32
  24. package/lib-commonjs/components/VerticalStackedBarChart/VerticalStackedBarChart.js.map +1 -1
  25. package/lib-commonjs/components/VerticalStackedBarChart/VerticalStackedBarChart.types.js.map +1 -1
  26. package/lib-commonjs/types/DataPoint.js.map +1 -1
  27. package/lib-commonjs/utilities/utilities.js +10 -4
  28. package/lib-commonjs/utilities/utilities.js.map +1 -1
  29. package/package.json +12 -12
@@ -6,7 +6,7 @@ import { scaleLinear as d3ScaleLinear, scaleBand as d3ScaleBand, scaleUtc as d3S
6
6
  import { useId } from '@fluentui/react-utilities';
7
7
  import { tokens } from '@fluentui/react-theme';
8
8
  import { CartesianChart, ChartPopover, Legends } from '../../index';
9
- import { ChartTypes, getAccessibleDataObject, XAxisTypes, getTypeOfAxis, tooltipOfAxislabels, formatScientificLimitWidth, getBarWidth, getScalePadding, isScalePaddingDefined, calculateAppropriateBarWidth, formatDate, areArraysEqual, calculateLongestLabelWidth, useRtl, DataVizPalette, getColorFromToken, findVSBCNumericMinMaxOfY, createNumericYAxis, domainRangeOfDateForAreaLineVerticalBarChart, domainRangeOfVSBCNumeric, domainRangeOfXStringAxis, createStringYAxis, calcTotalWidth, calcBandwidth, calcRequiredWidth } from '../../utilities/index';
9
+ import { ChartTypes, getAccessibleDataObject, XAxisTypes, getTypeOfAxis, tooltipOfAxislabels, formatScientificLimitWidth, getBarWidth, getScalePadding, isScalePaddingDefined, calculateAppropriateBarWidth, formatDate, areArraysEqual, calculateLongestLabelWidth, useRtl, DataVizPalette, getColorFromToken, findVSBCNumericMinMaxOfY, YAxisType, createNumericYAxis, domainRangeOfDateForAreaLineVerticalBarChart, domainRangeOfVSBCNumeric, domainRangeOfXStringAxis, createStringYAxis, calcTotalWidth, calcBandwidth, calcRequiredWidth } from '../../utilities/index';
10
10
  import { toImage } from '../../utilities/image-export-utils';
11
11
  import { formatDateToLocaleString } from '@fluentui/chart-utilities';
12
12
  const barGapMultiplier = 0.2;
@@ -36,6 +36,8 @@ export const VerticalStackedBarChart = (props)=>{
36
36
  const cartesianChartRef = React.useRef(null);
37
37
  const Y_ORIGIN = 0;
38
38
  const _legendsRef = React.useRef(null);
39
+ let _yAxisType;
40
+ let _yAxisLabels = [];
39
41
  const [selectedLegends, setSelectedLegends] = React.useState(((_props_legendProps = props.legendProps) === null || _props_legendProps === void 0 ? void 0 : _props_legendProps.selectedLegends) || []);
40
42
  const [activeLegend, setActiveLegend] = React.useState(undefined);
41
43
  const [dataForHoverCard, setDataForHoverCard] = React.useState(0);
@@ -236,15 +238,22 @@ export const VerticalStackedBarChart = (props)=>{
236
238
  _lineObject = _getFormattedLineData(props.data);
237
239
  _xAxisInnerPadding = getScalePadding(props.xAxisInnerPadding, props.xAxisPadding, _xAxisType === XAxisTypes.StringAxis ? 2 / 3 : 1 / 2);
238
240
  _xAxisOuterPadding = getScalePadding(props.xAxisOuterPadding, props.xAxisPadding, 0);
241
+ _initYAxisParams();
239
242
  }
240
243
  function _createDataSetLayer() {
241
244
  const tempArr = [];
242
245
  const dataset = _points.map((singlePointData)=>{
246
+ tempArr.push(singlePointData.xAxisPoint);
247
+ if (_yAxisType === YAxisType.StringAxis) {
248
+ return {
249
+ x: singlePointData.xAxisPoint,
250
+ y: 0
251
+ };
252
+ }
243
253
  let total = 0;
244
254
  singlePointData.chartData.forEach((point)=>{
245
255
  total = total + point.data;
246
256
  });
247
- tempArr.push(singlePointData.xAxisPoint);
248
257
  return {
249
258
  x: singlePointData.xAxisPoint,
250
259
  y: total
@@ -275,7 +284,7 @@ export const VerticalStackedBarChart = (props)=>{
275
284
  }
276
285
  function _getGraphData(xScale, yScale, containerHeight, containerWidth, xElement) {
277
286
  const { xBarScale, yBarScale } = _getScales(containerHeight, containerWidth);
278
- return _bars = _createBar(xBarScale, yBarScale, containerHeight, xElement);
287
+ return _bars = _createBar(xBarScale, _yAxisType === YAxisType.StringAxis ? yScale : yBarScale, containerHeight, xElement);
279
288
  }
280
289
  function _getAxisData(yAxisData) {
281
290
  if (yAxisData && yAxisData.yAxisDomainValues.length) {
@@ -402,6 +411,7 @@ export const VerticalStackedBarChart = (props)=>{
402
411
  const y1 = useSecondaryYScale ? yScaleSecondary(lineObject[item][i - 1].y) : yScalePrimary(lineObject[item][i - 1].y);
403
412
  const x2 = xScale(lineObject[item][i].xItem.xAxisPoint);
404
413
  const y2 = useSecondaryYScale ? yScaleSecondary(lineObject[item][i].y) : yScalePrimary(lineObject[item][i].y);
414
+ const yScaleBandwidthTranslate = !useSecondaryYScale && _yAxisType === YAxisType.StringAxis ? yScalePrimary.bandwidth() / 2 : 0;
405
415
  if (lineBorderWidth > 0) {
406
416
  borderForLines.push(/*#__PURE__*/ React.createElement("line", {
407
417
  key: `${index}-${i}-BorderLine`,
@@ -414,7 +424,7 @@ export const VerticalStackedBarChart = (props)=>{
414
424
  fill: "transparent",
415
425
  strokeLinecap: "round",
416
426
  stroke: tokens.colorNeutralBackground1,
417
- transform: `translate(${xScaleBandwidthTranslate}, 0)`
427
+ transform: `translate(${xScaleBandwidthTranslate}, ${yScaleBandwidthTranslate})`
418
428
  }));
419
429
  }
420
430
  var _lineObject_item__lineOptions_strokeWidth, _lineObject_item__lineOptions_strokeLinecap;
@@ -429,7 +439,7 @@ export const VerticalStackedBarChart = (props)=>{
429
439
  strokeLinecap: (_lineObject_item__lineOptions_strokeLinecap = (_lineObject_item__lineOptions1 = lineObject[item][0].lineOptions) === null || _lineObject_item__lineOptions1 === void 0 ? void 0 : _lineObject_item__lineOptions1.strokeLinecap) !== null && _lineObject_item__lineOptions_strokeLinecap !== void 0 ? _lineObject_item__lineOptions_strokeLinecap : 'round',
430
440
  strokeDasharray: (_lineObject_item__lineOptions2 = lineObject[item][0].lineOptions) === null || _lineObject_item__lineOptions2 === void 0 ? void 0 : _lineObject_item__lineOptions2.strokeDasharray,
431
441
  stroke: lineObject[item][i].color,
432
- transform: `translate(${xScaleBandwidthTranslate}, 0)`,
442
+ transform: `translate(${xScaleBandwidthTranslate}, ${yScaleBandwidthTranslate})`,
433
443
  onMouseOver: (event)=>_lineHover(lineObject[item][i - 1], event),
434
444
  onMouseLeave: _handleMouseOut
435
445
  }));
@@ -441,6 +451,7 @@ export const VerticalStackedBarChart = (props)=>{
441
451
  refElement: null
442
452
  };
443
453
  const noBarsAndLinesActive = circlePoint.xItem.chartData.filter((dataPoint)=>_noLegendHighlighted() || _isLegendHighlighted(dataPoint.legend)).length === 0;
454
+ const yScaleBandwidthTranslate = !circlePoint.useSecondaryYScale && _yAxisType === YAxisType.StringAxis ? yScalePrimary.bandwidth() / 2 : 0;
444
455
  dots.push(/*#__PURE__*/ React.createElement("circle", {
445
456
  key: `${index}-${subIndex}-dot`,
446
457
  cx: xScale(circlePoint.xItem.xAxisPoint),
@@ -454,7 +465,7 @@ export const VerticalStackedBarChart = (props)=>{
454
465
  // Elements with visibility: hidden cannot receive focus, so use opacity: 0 instead to hide them.
455
466
  // For more information, see https://fuzzbomb.github.io/accessibility-demos/visually-hidden-focus-test.html
456
467
  opacity: _getCircleOpacityAndRadius(circlePoint.xItem.xAxisPoint, circlePoint.legend).opacity,
457
- transform: `translate(${xScaleBandwidthTranslate}, 0)`,
468
+ transform: `translate(${xScaleBandwidthTranslate}, ${yScaleBandwidthTranslate})`,
458
469
  ref: (e)=>circleRef.refElement = e,
459
470
  ...noBarsAndLinesActive ? {
460
471
  tabIndex: !props.hideTooltip ? 0 : undefined,
@@ -568,22 +579,29 @@ export const VerticalStackedBarChart = (props)=>{
568
579
  }
569
580
  function _getBarGapAndScale(bars, yBarScale, defaultTotalHeight) {
570
581
  const { barGapMax = 0 } = props;
571
- // When displaying gaps between the bars, the height of each bar is
572
- // adjusted so that the total of all bars is not changed by the gaps
573
- const totalData = bars.reduce((iter, value)=>iter + Math.abs(value.data), 0);
574
- const totalHeight = defaultTotalHeight !== null && defaultTotalHeight !== void 0 ? defaultTotalHeight : Math.abs(yBarScale(totalData) - yBarScale(Y_ORIGIN));
582
+ let totalData = 0;
583
+ let totalHeight;
575
584
  let sumOfPercent = 0;
576
- bars.forEach((point)=>{
577
- let value = Math.abs(point.data) / totalData * 100;
578
- if (value < 1 && value !== 0) {
579
- value = 1;
580
- }
581
- sumOfPercent += value;
582
- });
583
- const scalingRatio = sumOfPercent !== 0 ? sumOfPercent / 100 : 1;
585
+ let scalingRatio;
586
+ if (_yAxisType === YAxisType.StringAxis) {
587
+ totalHeight = defaultTotalHeight !== null && defaultTotalHeight !== void 0 ? defaultTotalHeight : bars.reduce((total, bar)=>total + yBarScale(bar.data), 0);
588
+ } else {
589
+ // When displaying gaps between the bars, the height of each bar is
590
+ // adjusted so that the total of all bars is not changed by the gaps
591
+ totalData = bars.reduce((iter, value)=>iter + Math.abs(value.data), 0);
592
+ totalHeight = defaultTotalHeight !== null && defaultTotalHeight !== void 0 ? defaultTotalHeight : Math.abs(yBarScale(totalData) - yBarScale(Y_ORIGIN));
593
+ bars.forEach((point)=>{
594
+ let value = Math.abs(point.data) / totalData * 100;
595
+ if (value < 1 && value !== 0) {
596
+ value = 1;
597
+ }
598
+ sumOfPercent += value;
599
+ });
600
+ scalingRatio = sumOfPercent !== 0 ? sumOfPercent / 100 : 1;
601
+ }
584
602
  const gaps = barGapMax && bars.length - 1;
585
603
  const gapHeight = gaps && Math.max(barGapMin, Math.min(barGapMax, totalHeight * barGapMultiplier / gaps));
586
- const heightValueScale = (totalHeight - gapHeight * gaps) / (totalData * scalingRatio);
604
+ const heightValueScale = _yAxisType === YAxisType.StringAxis ? 0 : (totalHeight - gapHeight * gaps) / (totalData * scalingRatio);
587
605
  return {
588
606
  gapHeight,
589
607
  heightValueScale,
@@ -733,7 +751,7 @@ export const VerticalStackedBarChart = (props)=>{
733
751
  const xPoint = xBarScale(_xAxisType === XAxisTypes.NumericAxis ? singleChartData.xAxisPoint : _xAxisType === XAxisTypes.DateAxis ? singleChartData.xAxisPoint : singleChartData.xAxisPoint);
734
752
  const xScaleBandwidthTranslate = _xAxisType !== XAxisTypes.StringAxis ? -_barWidth / 2 : (xBarScale.bandwidth() - _barWidth) / 2;
735
753
  let barTotalValue = 0;
736
- const barsToDisplay = singleChartData.chartData.filter((point)=>point.data !== 0);
754
+ const barsToDisplay = singleChartData.chartData.filter((point)=>point.data !== 0 && point.data !== '' && !(_yAxisType === YAxisType.StringAxis && typeof yBarScale(point.data) === 'undefined'));
737
755
  if (!barsToDisplay.length) {
738
756
  return undefined;
739
757
  }
@@ -741,7 +759,7 @@ export const VerticalStackedBarChart = (props)=>{
741
759
  if (heightValueScale < 0) {
742
760
  return undefined;
743
761
  }
744
- const yBaseline = containerHeight - _margins.bottom - yBarScale(Y_ORIGIN);
762
+ const yBaseline = containerHeight - _margins.bottom - (_yAxisType === YAxisType.StringAxis ? 0 : yBarScale(Y_ORIGIN));
745
763
  let yPositiveStart = yBaseline;
746
764
  let yNegativeStart = yBaseline;
747
765
  let yPoint = 0;
@@ -761,22 +779,29 @@ export const VerticalStackedBarChart = (props)=>{
761
779
  role: 'img',
762
780
  tabIndex: !props.hideTooltip && shouldHighlight ? 0 : undefined
763
781
  };
764
- let barHeight = Math.abs(heightValueScale * point.data);
765
- // FIXME: The current scaling logic may produce different min and gap heights for each bar stack.
766
- const minHeight = Math.max(heightValueScale * absStackTotal / 100.0, barMinimumHeight);
767
- if (barHeight < minHeight) {
768
- barHeight = minHeight;
769
- }
782
+ let barHeight;
770
783
  const gapOffset = index ? gapHeight : 0;
771
- if (point.data >= Y_ORIGIN) {
784
+ if (_yAxisType === YAxisType.StringAxis) {
785
+ barHeight = Math.max(containerHeight - _margins.bottom - (yBarScale(point.data) + yBarScale.bandwidth() / 2) - gapOffset, barMinimumHeight, 1);
772
786
  yPositiveStart -= barHeight + gapOffset;
773
787
  yPoint = yPositiveStart;
774
788
  } else {
775
- yPoint = yNegativeStart + gapOffset;
776
- yNegativeStart = yPoint + barHeight;
789
+ barHeight = Math.abs(heightValueScale * point.data);
790
+ // FIXME: The current scaling logic may produce different min and gap heights for each bar stack.
791
+ const minHeight = Math.max(heightValueScale * absStackTotal / 100.0, barMinimumHeight);
792
+ if (barHeight < minHeight) {
793
+ barHeight = minHeight;
794
+ }
795
+ if (point.data >= Y_ORIGIN) {
796
+ yPositiveStart -= barHeight + gapOffset;
797
+ yPoint = yPositiveStart;
798
+ } else {
799
+ yPoint = yNegativeStart + gapOffset;
800
+ yNegativeStart = yPoint + barHeight;
801
+ }
802
+ barTotalValue += point.data;
803
+ heightOfLastBar = index === barsToDisplay.length - 1 ? barHeight : 0;
777
804
  }
778
- barTotalValue += point.data;
779
- heightOfLastBar = index === barsToDisplay.length - 1 ? barHeight : 0;
780
805
  if (barCornerRadius && barHeight > barCornerRadius && index === barsToDisplay.length - 1) {
781
806
  return /*#__PURE__*/ React.createElement(React.Fragment, {
782
807
  key: index + indexNumber + `${shouldFocusWholeStack}`
@@ -839,7 +864,7 @@ export const VerticalStackedBarChart = (props)=>{
839
864
  };
840
865
  let showLabel = false;
841
866
  let barLabel = 0;
842
- if (!props.hideLabels) {
867
+ if (!props.hideLabels && _yAxisType !== YAxisType.StringAxis) {
843
868
  if (_noLegendHighlighted()) {
844
869
  showLabel = true;
845
870
  barLabel = barTotalValue;
@@ -909,6 +934,68 @@ export const VerticalStackedBarChart = (props)=>{
909
934
  endValue: d3Max(values)
910
935
  };
911
936
  }
937
+ function _initYAxisParams() {
938
+ if (_points[0].chartData.length > 0) {
939
+ _yAxisType = getTypeOfAxis(_points[0].chartData[0].data, false);
940
+ } else {
941
+ Object.keys(_lineObject).forEach((lineLegend)=>{
942
+ if (!_lineObject[lineLegend][0].useSecondaryYScale) {
943
+ _yAxisType = getTypeOfAxis(_lineObject[lineLegend][0].y, false);
944
+ }
945
+ });
946
+ }
947
+ if (_yAxisType === YAxisType.StringAxis) {
948
+ const legendToYValues = {};
949
+ _points.forEach((xPoint)=>{
950
+ xPoint.chartData.forEach((bar)=>{
951
+ if (!legendToYValues[bar.legend]) {
952
+ legendToYValues[bar.legend] = [
953
+ `${bar.data}`
954
+ ];
955
+ } else {
956
+ legendToYValues[bar.legend].push(`${bar.data}`);
957
+ }
958
+ });
959
+ });
960
+ const yAxisLabels = new Set();
961
+ Object.values(legendToYValues).forEach((yValues)=>{
962
+ yValues.forEach((yVal)=>{
963
+ yAxisLabels.add(yVal);
964
+ });
965
+ });
966
+ Object.values(_lineObject).forEach((linePoints)=>{
967
+ linePoints.forEach((linePoint)=>{
968
+ if (!linePoint.useSecondaryYScale) {
969
+ yAxisLabels.add(`${linePoint.y}`);
970
+ }
971
+ });
972
+ });
973
+ _yAxisLabels = Array.from(yAxisLabels);
974
+ }
975
+ }
976
+ function _getYDomainMargins(containerHeight) {
977
+ /**
978
+ * Specifies the extra top margin to apply above the highest y-axis tick label.
979
+ * Useful when stacked bars extend beyond the combined height of all y-axis labels (or categories).
980
+ */ let yAxisTickMarginTop = 0;
981
+ /** Total height available to render the bars */ const totalHeight = containerHeight - _margins.bottom - _margins.top;
982
+ if (_yAxisType === YAxisType.StringAxis) {
983
+ /** Maximum height of the stacked bars, expressed in multiples of the height of a y-axis label (or category) */ let maxBarHeightInLabels = 0;
984
+ _points.forEach((xPoint)=>{
985
+ /** Height of the stacked bar, expressed in multiples of the height of a y-axis label (or category) */ let barHeightInLabels = 0;
986
+ xPoint.chartData.forEach((bar)=>{
987
+ barHeightInLabels += _yAxisLabels.indexOf(`${bar.data}`) + 1;
988
+ });
989
+ maxBarHeightInLabels = Math.max(maxBarHeightInLabels, barHeightInLabels);
990
+ });
991
+ /** Height of a y-axis label (or category) */ const yAxisLabelHeight = maxBarHeightInLabels === 0 ? 0 : totalHeight / maxBarHeightInLabels;
992
+ yAxisTickMarginTop += yAxisLabelHeight * (maxBarHeightInLabels - _yAxisLabels.length);
993
+ }
994
+ return {
995
+ ..._margins,
996
+ top: _margins.top + yAxisTickMarginTop
997
+ };
998
+ }
912
999
  if (!_isChartEmpty()) {
913
1000
  _adjustProps();
914
1001
  const _isHavingLines = props.data.some((item)=>item.lineData && item.lineData.length > 0);
@@ -964,6 +1051,12 @@ export const VerticalStackedBarChart = (props)=>{
964
1051
  },
965
1052
  componentRef: cartesianChartRef,
966
1053
  showRoundOffXTickValues: !isScalePaddingDefined(props.xAxisInnerPadding, props.xAxisPadding),
1054
+ yAxisType: _yAxisType,
1055
+ stringDatasetForYAxisDomain: [
1056
+ '',
1057
+ ..._yAxisLabels
1058
+ ],
1059
+ getYDomainMargins: _getYDomainMargins,
967
1060
  /* eslint-disable react/jsx-no-bind */ children: (props)=>{
968
1061
  return /*#__PURE__*/ React.createElement(React.Fragment, null, /*#__PURE__*/ React.createElement("g", null, _bars), /*#__PURE__*/ React.createElement("g", null, _isHavingLines && _createLines(props.xScale, props.yScalePrimary, props.containerHeight, props.containerWidth, props.yScaleSecondary)));
969
1062
  }