@fluentui/react-charts 9.3.7 → 9.3.8

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 (143) hide show
  1. package/CHANGELOG.md +27 -2
  2. package/dist/index.d.ts +55 -7
  3. package/lib/components/AreaChart/AreaChart.js +1 -28
  4. package/lib/components/AreaChart/AreaChart.js.map +1 -1
  5. package/lib/components/AreaChart/useAreaChartStyles.styles.js +1 -2
  6. package/lib/components/AreaChart/useAreaChartStyles.styles.js.map +1 -1
  7. package/lib/components/ChartTable/ChartTable.js +6 -1
  8. package/lib/components/ChartTable/ChartTable.js.map +1 -1
  9. package/lib/components/CommonComponents/Annotations/ChartAnnotationLayer.js +107 -67
  10. package/lib/components/CommonComponents/Annotations/ChartAnnotationLayer.js.map +1 -1
  11. package/lib/components/CommonComponents/Annotations/useChartAnnotationLayer.styles.js +7 -1
  12. package/lib/components/CommonComponents/Annotations/useChartAnnotationLayer.styles.js.map +1 -1
  13. package/lib/components/CommonComponents/Annotations/useChartAnnotationLayer.styles.raw.js +7 -1
  14. package/lib/components/CommonComponents/Annotations/useChartAnnotationLayer.styles.raw.js.map +1 -1
  15. package/lib/components/CommonComponents/CartesianChart.js +50 -32
  16. package/lib/components/CommonComponents/CartesianChart.js.map +1 -1
  17. package/lib/components/CommonComponents/CartesianChart.types.js.map +1 -1
  18. package/lib/components/CommonComponents/useCartesianChartStyles.styles.js +5 -5
  19. package/lib/components/CommonComponents/useCartesianChartStyles.styles.js.map +1 -1
  20. package/lib/components/CommonComponents/useCartesianChartStyles.styles.raw.js +4 -3
  21. package/lib/components/CommonComponents/useCartesianChartStyles.styles.raw.js.map +1 -1
  22. package/lib/components/DeclarativeChart/PlotlySchemaAdapter.js +261 -187
  23. package/lib/components/DeclarativeChart/PlotlySchemaAdapter.js.map +1 -1
  24. package/lib/components/DonutChart/DonutChart.js +6 -3
  25. package/lib/components/DonutChart/DonutChart.js.map +1 -1
  26. package/lib/components/FunnelChart/FunnelChart.js +6 -3
  27. package/lib/components/FunnelChart/FunnelChart.js.map +1 -1
  28. package/lib/components/GanttChart/GanttChart.js +1 -1
  29. package/lib/components/GanttChart/GanttChart.js.map +1 -1
  30. package/lib/components/GaugeChart/GaugeChart.js +6 -3
  31. package/lib/components/GaugeChart/GaugeChart.js.map +1 -1
  32. package/lib/components/GroupedVerticalBarChart/GroupedVerticalBarChart.js +17 -17
  33. package/lib/components/GroupedVerticalBarChart/GroupedVerticalBarChart.js.map +1 -1
  34. package/lib/components/GroupedVerticalBarChart/useGroupedVerticalBarChartStyles.styles.js +1 -2
  35. package/lib/components/GroupedVerticalBarChart/useGroupedVerticalBarChartStyles.styles.js.map +1 -1
  36. package/lib/components/HorizontalBarChartWithAxis/HorizontalBarChartWithAxis.js +2 -4
  37. package/lib/components/HorizontalBarChartWithAxis/HorizontalBarChartWithAxis.js.map +1 -1
  38. package/lib/components/Legends/Legends.js +3 -4
  39. package/lib/components/Legends/Legends.js.map +1 -1
  40. package/lib/components/LineChart/LineChart.js +66 -64
  41. package/lib/components/LineChart/LineChart.js.map +1 -1
  42. package/lib/components/LineChart/useLineChartStyles.styles.js +1 -2
  43. package/lib/components/LineChart/useLineChartStyles.styles.js.map +1 -1
  44. package/lib/components/SankeyChart/SankeyChart.js +1 -1
  45. package/lib/components/SankeyChart/SankeyChart.js.map +1 -1
  46. package/lib/components/SankeyChart/useSankeyChartStyles.styles.js +1 -2
  47. package/lib/components/SankeyChart/useSankeyChartStyles.styles.js.map +1 -1
  48. package/lib/components/ScatterChart/ScatterChart.js +18 -26
  49. package/lib/components/ScatterChart/ScatterChart.js.map +1 -1
  50. package/lib/components/ScatterChart/ScatterChart.types.js.map +1 -1
  51. package/lib/components/ScatterChart/useScatterChartStyles.styles.js +1 -2
  52. package/lib/components/ScatterChart/useScatterChartStyles.styles.js.map +1 -1
  53. package/lib/components/VerticalBarChart/VerticalBarChart.js +13 -78
  54. package/lib/components/VerticalBarChart/VerticalBarChart.js.map +1 -1
  55. package/lib/components/VerticalBarChart/useVerticalBarChartStyles.styles.js +1 -2
  56. package/lib/components/VerticalBarChart/useVerticalBarChartStyles.styles.js.map +1 -1
  57. package/lib/components/VerticalStackedBarChart/VerticalStackedBarChart.js +21 -32
  58. package/lib/components/VerticalStackedBarChart/VerticalStackedBarChart.js.map +1 -1
  59. package/lib/components/VerticalStackedBarChart/useVerticalStackedBarChartStyles.styles.js +1 -2
  60. package/lib/components/VerticalStackedBarChart/useVerticalStackedBarChartStyles.styles.js.map +1 -1
  61. package/lib/types/ChartAnnotation.js.map +1 -1
  62. package/lib/types/DataPoint.js.map +1 -1
  63. package/lib/utilities/Common.styles.js +0 -1
  64. package/lib/utilities/Common.styles.js.map +1 -1
  65. package/lib/utilities/Common.styles.raw.js +0 -1
  66. package/lib/utilities/Common.styles.raw.js.map +1 -1
  67. package/lib/utilities/image-export-utils.js +4 -4
  68. package/lib/utilities/image-export-utils.js.map +1 -1
  69. package/lib/utilities/utilities.js +220 -78
  70. package/lib/utilities/utilities.js.map +1 -1
  71. package/lib-commonjs/components/AreaChart/AreaChart.js +0 -26
  72. package/lib-commonjs/components/AreaChart/AreaChart.js.map +1 -1
  73. package/lib-commonjs/components/AreaChart/useAreaChartStyles.styles.js +0 -2
  74. package/lib-commonjs/components/AreaChart/useAreaChartStyles.styles.js.map +1 -1
  75. package/lib-commonjs/components/ChartTable/ChartTable.js +6 -1
  76. package/lib-commonjs/components/ChartTable/ChartTable.js.map +1 -1
  77. package/lib-commonjs/components/CommonComponents/Annotations/ChartAnnotationLayer.js +107 -67
  78. package/lib-commonjs/components/CommonComponents/Annotations/ChartAnnotationLayer.js.map +1 -1
  79. package/lib-commonjs/components/CommonComponents/Annotations/useChartAnnotationLayer.styles.js +7 -1
  80. package/lib-commonjs/components/CommonComponents/Annotations/useChartAnnotationLayer.styles.js.map +1 -1
  81. package/lib-commonjs/components/CommonComponents/Annotations/useChartAnnotationLayer.styles.raw.js +7 -1
  82. package/lib-commonjs/components/CommonComponents/Annotations/useChartAnnotationLayer.styles.raw.js.map +1 -1
  83. package/lib-commonjs/components/CommonComponents/CartesianChart.js +49 -31
  84. package/lib-commonjs/components/CommonComponents/CartesianChart.js.map +1 -1
  85. package/lib-commonjs/components/CommonComponents/CartesianChart.types.js.map +1 -1
  86. package/lib-commonjs/components/CommonComponents/useCartesianChartStyles.styles.js +3 -4
  87. package/lib-commonjs/components/CommonComponents/useCartesianChartStyles.styles.js.map +1 -1
  88. package/lib-commonjs/components/CommonComponents/useCartesianChartStyles.styles.raw.js +3 -2
  89. package/lib-commonjs/components/CommonComponents/useCartesianChartStyles.styles.raw.js.map +1 -1
  90. package/lib-commonjs/components/DeclarativeChart/PlotlySchemaAdapter.js +261 -186
  91. package/lib-commonjs/components/DeclarativeChart/PlotlySchemaAdapter.js.map +1 -1
  92. package/lib-commonjs/components/DonutChart/DonutChart.js +5 -2
  93. package/lib-commonjs/components/DonutChart/DonutChart.js.map +1 -1
  94. package/lib-commonjs/components/FunnelChart/FunnelChart.js +5 -2
  95. package/lib-commonjs/components/FunnelChart/FunnelChart.js.map +1 -1
  96. package/lib-commonjs/components/GanttChart/GanttChart.js +1 -1
  97. package/lib-commonjs/components/GanttChart/GanttChart.js.map +1 -1
  98. package/lib-commonjs/components/GaugeChart/GaugeChart.js +5 -2
  99. package/lib-commonjs/components/GaugeChart/GaugeChart.js.map +1 -1
  100. package/lib-commonjs/components/GroupedVerticalBarChart/GroupedVerticalBarChart.js +15 -15
  101. package/lib-commonjs/components/GroupedVerticalBarChart/GroupedVerticalBarChart.js.map +1 -1
  102. package/lib-commonjs/components/GroupedVerticalBarChart/useGroupedVerticalBarChartStyles.styles.js +0 -2
  103. package/lib-commonjs/components/GroupedVerticalBarChart/useGroupedVerticalBarChartStyles.styles.js.map +1 -1
  104. package/lib-commonjs/components/HorizontalBarChartWithAxis/HorizontalBarChartWithAxis.js +2 -4
  105. package/lib-commonjs/components/HorizontalBarChartWithAxis/HorizontalBarChartWithAxis.js.map +1 -1
  106. package/lib-commonjs/components/Legends/Legends.js +3 -4
  107. package/lib-commonjs/components/Legends/Legends.js.map +1 -1
  108. package/lib-commonjs/components/LineChart/LineChart.js +65 -63
  109. package/lib-commonjs/components/LineChart/LineChart.js.map +1 -1
  110. package/lib-commonjs/components/LineChart/useLineChartStyles.styles.js +0 -2
  111. package/lib-commonjs/components/LineChart/useLineChartStyles.styles.js.map +1 -1
  112. package/lib-commonjs/components/SankeyChart/SankeyChart.js +1 -1
  113. package/lib-commonjs/components/SankeyChart/SankeyChart.js.map +1 -1
  114. package/lib-commonjs/components/SankeyChart/useSankeyChartStyles.styles.js +0 -2
  115. package/lib-commonjs/components/SankeyChart/useSankeyChartStyles.styles.js.map +1 -1
  116. package/lib-commonjs/components/ScatterChart/ScatterChart.js +17 -25
  117. package/lib-commonjs/components/ScatterChart/ScatterChart.js.map +1 -1
  118. package/lib-commonjs/components/ScatterChart/ScatterChart.types.js.map +1 -1
  119. package/lib-commonjs/components/ScatterChart/useScatterChartStyles.styles.js +0 -2
  120. package/lib-commonjs/components/ScatterChart/useScatterChartStyles.styles.js.map +1 -1
  121. package/lib-commonjs/components/VerticalBarChart/VerticalBarChart.js +12 -77
  122. package/lib-commonjs/components/VerticalBarChart/VerticalBarChart.js.map +1 -1
  123. package/lib-commonjs/components/VerticalBarChart/useVerticalBarChartStyles.styles.js +0 -2
  124. package/lib-commonjs/components/VerticalBarChart/useVerticalBarChartStyles.styles.js.map +1 -1
  125. package/lib-commonjs/components/VerticalStackedBarChart/VerticalStackedBarChart.js +20 -31
  126. package/lib-commonjs/components/VerticalStackedBarChart/VerticalStackedBarChart.js.map +1 -1
  127. package/lib-commonjs/components/VerticalStackedBarChart/useVerticalStackedBarChartStyles.styles.js +0 -2
  128. package/lib-commonjs/components/VerticalStackedBarChart/useVerticalStackedBarChartStyles.styles.js.map +1 -1
  129. package/lib-commonjs/types/ChartAnnotation.js.map +1 -1
  130. package/lib-commonjs/types/DataPoint.js.map +1 -1
  131. package/lib-commonjs/utilities/Common.styles.js +0 -1
  132. package/lib-commonjs/utilities/Common.styles.js.map +1 -1
  133. package/lib-commonjs/utilities/Common.styles.raw.js +0 -1
  134. package/lib-commonjs/utilities/Common.styles.raw.js.map +1 -1
  135. package/lib-commonjs/utilities/image-export-utils.js +3 -3
  136. package/lib-commonjs/utilities/image-export-utils.js.map +1 -1
  137. package/lib-commonjs/utilities/utilities.js +232 -81
  138. package/lib-commonjs/utilities/utilities.js.map +1 -1
  139. package/package.json +9 -9
  140. package/lib/components/DeclarativeChart/imageExporter.js +0 -223
  141. package/lib/components/DeclarativeChart/imageExporter.js.map +0 -1
  142. package/lib-commonjs/components/DeclarativeChart/imageExporter.js +0 -233
  143. package/lib-commonjs/components/DeclarativeChart/imageExporter.js.map +0 -1
@@ -13,6 +13,8 @@ import { formatDateToLocaleString, formatToLocaleString, getMultiLevelDateTimeFo
13
13
  export const MIN_DOMAIN_MARGIN = 8;
14
14
  export const MIN_DONUT_RADIUS = 1;
15
15
  export const DEFAULT_DATE_STRING = '2000-01-01';
16
+ export const CARTESIAN_XAXIS_CLASSNAME = 'fui-cart__xAxis';
17
+ const CARTESIAN_XAXIS_TEXT_SELECTOR = `.${CARTESIAN_XAXIS_CLASSNAME} text`;
16
18
  export var ChartTypes = /*#__PURE__*/ function(ChartTypes) {
17
19
  ChartTypes[ChartTypes["AreaChart"] = 0] = "AreaChart";
18
20
  ChartTypes[ChartTypes["LineChart"] = 1] = "LineChart";
@@ -90,7 +92,7 @@ function yAxisTickFormatterInternal(value, limitWidth = false) {
90
92
  const xAxisValue = typeof domainValue === 'number' ? domainValue : domainValue.valueOf();
91
93
  return (defaultFormat === null || defaultFormat === void 0 ? void 0 : defaultFormat(xAxisValue)) === '' ? '' : formatToLocaleString(xAxisValue, culture);
92
94
  };
93
- if (hideTickOverlap && typeof xAxisCount === 'undefined') {
95
+ if (hideTickOverlap) {
94
96
  const longestLabelWidth = calcMaxLabelWidth(xAxisScale.ticks().map((v, i)=>tickFormat(v, i))) + 20;
95
97
  const [start, end] = xAxisScale.range();
96
98
  tickCount = Math.min(Math.max(1, Math.floor(Math.abs(end - start) / longestLabelWidth)), 10);
@@ -114,10 +116,12 @@ function yAxisTickFormatterInternal(value, limitWidth = false) {
114
116
  if (xAxisElement) {
115
117
  d3Select(xAxisElement).call(xAxis).selectAll('text').attr('aria-hidden', 'true').style('direction', 'ltr').style('unicode-bidi', 'isolate');
116
118
  }
117
- const tickValues = (customTickValues !== null && customTickValues !== void 0 ? customTickValues : xAxisScale.ticks(tickCount)).map(xAxis.tickFormat());
119
+ const tickValues = customTickValues !== null && customTickValues !== void 0 ? customTickValues : xAxisScale.ticks(tickCount);
120
+ const tickLabels = tickValues.map(xAxis.tickFormat());
118
121
  return {
119
122
  xScale: xAxisScale,
120
- tickValues
123
+ tickValues,
124
+ tickLabels
121
125
  };
122
126
  }
123
127
  /**
@@ -310,7 +314,7 @@ export function getDateFormatLevel(date, useUTC) {
310
314
  * @param {IXAxisParams} xAxisParams
311
315
  * @param {ITickParams} tickParams
312
316
  */ export function createDateXAxis(xAxisParams, tickParams, culture, options, timeFormatLocale, customDateTimeFormatter, useUTC, chartType) {
313
- const { domainNRangeValues, xAxisElement, tickPadding = 6, xAxistickSize = 6, xAxisCount, calcMaxLabelWidth, tickStep, tick0, tickText } = xAxisParams;
317
+ const { domainNRangeValues, xAxisElement, tickPadding = 6, xAxistickSize = 6, xAxisCount, hideTickOverlap, calcMaxLabelWidth, tickStep, tick0, tickText } = xAxisParams;
314
318
  const isUtcSet = useUTC === true || useUTC === 'utc';
315
319
  const xAxisScale = isUtcSet ? d3ScaleUtc() : d3ScaleTime();
316
320
  xAxisScale.domain([
@@ -354,10 +358,11 @@ export function getDateFormatLevel(date, useUTC) {
354
358
  }
355
359
  return formatDateToLocaleString(domainValue, culture, useUTC ? true : false, false, formatOptions);
356
360
  };
357
- const longestLabelWidth = calcMaxLabelWidth(xAxisScale.ticks().map(tickFormat)) + 40;
358
- const [start, end] = xAxisScale.range();
359
- const maxPossibleTickCount = Math.min(Math.max(1, Math.floor(Math.abs(end - start) / longestLabelWidth)), 10);
360
- tickCount = Math.min(maxPossibleTickCount, xAxisCount !== null && xAxisCount !== void 0 ? xAxisCount : tickCount);
361
+ if (hideTickOverlap) {
362
+ const longestLabelWidth = calcMaxLabelWidth(xAxisScale.ticks().map(tickFormat)) + 40;
363
+ const [start, end] = xAxisScale.range();
364
+ tickCount = Math.max(1, Math.floor(Math.abs(end - start) / longestLabelWidth));
365
+ }
361
366
  const xAxis = d3AxisBottom(xAxisScale).tickSize(xAxistickSize).tickPadding(tickPadding).ticks(tickCount).tickFormat(tickFormat);
362
367
  if ([
363
368
  8
@@ -376,10 +381,12 @@ export function getDateFormatLevel(date, useUTC) {
376
381
  if (xAxisElement) {
377
382
  d3Select(xAxisElement).call(xAxis).selectAll('text').attr('aria-hidden', 'true');
378
383
  }
379
- const tickValues = (customTickValues !== null && customTickValues !== void 0 ? customTickValues : xAxisScale.ticks(tickCount)).map(xAxis.tickFormat());
384
+ const tickValues = customTickValues !== null && customTickValues !== void 0 ? customTickValues : xAxisScale.ticks(tickCount);
385
+ const tickLabels = tickValues.map(xAxis.tickFormat());
380
386
  return {
381
387
  xScale: xAxisScale,
382
- tickValues
388
+ tickValues,
389
+ tickLabels
383
390
  };
384
391
  }
385
392
  /**
@@ -436,7 +443,8 @@ export function getDateFormatLevel(date, useUTC) {
436
443
  }
437
444
  return {
438
445
  xScale: xAxisScale,
439
- tickValues: tickValues.map(xAxis.tickFormat())
446
+ tickValues,
447
+ tickLabels: tickValues.map(xAxis.tickFormat())
440
448
  };
441
449
  }
442
450
  export function useRtl() {
@@ -774,14 +782,14 @@ export const DEFAULT_WRAP_WIDTH = 10;
774
782
  * @param {IWrapLabelProps} wrapLabelProps
775
783
  * @returns
776
784
  */ export function createWrapOfXLabels(wrapLabelProps) {
777
- const { node, xAxis, noOfCharsToTruncate, showXAxisLablesTooltip, width = DEFAULT_WRAP_WIDTH } = wrapLabelProps;
785
+ const { node, xAxis, noOfCharsToTruncate, showXAxisLablesTooltip, width = DEFAULT_WRAP_WIDTH, container } = wrapLabelProps;
778
786
  if (node === null) {
779
787
  return;
780
788
  }
781
789
  const axisNode = d3Select(node).call(xAxis);
782
790
  let removeVal = 0;
783
791
  let maxLines = 1;
784
- axisNode.selectAll('.tick text').each(function() {
792
+ axisNode.selectAll('.tick text').each(function(_, tickIndex) {
785
793
  const text = d3Select(this);
786
794
  const totalWord = text.text();
787
795
  const truncatedWord = `${text.text().slice(0, noOfCharsToTruncate)}...`;
@@ -793,33 +801,33 @@ export const DEFAULT_WRAP_WIDTH = 10;
793
801
  const lineHeight = 1.1; // ems
794
802
  const y = text.attr('y');
795
803
  const dy = parseFloat(text.attr('dy'));
796
- let tspan = text.text(null).append('tspan').attr('x', 0).attr('y', y).attr('id', 'BaseSpan').attr('dy', dy + 'em').attr('data-', totalWord);
797
- if (showXAxisLablesTooltip && totalWordLength > noOfCharsToTruncate) {
798
- tspan = text.append('tspan').attr('id', 'showDots').attr('x', 0).attr('y', y).attr('dy', dy + 'em').text(truncatedWord);
799
- } else if (showXAxisLablesTooltip && totalWordLength <= noOfCharsToTruncate) {
800
- tspan = text.append('tspan').attr('id', 'LessLength').attr('x', 0).attr('y', y).attr('dy', dy + 'em').text(totalWord);
804
+ let tspan = text.text(null).attr('data-full', totalWord).append('tspan').attr('x', 0).attr('y', y).attr('dy', dy + 'em');
805
+ if (showXAxisLablesTooltip) {
806
+ tspan.text(totalWordLength > noOfCharsToTruncate ? truncatedWord : totalWord);
801
807
  } else {
808
+ const maxWidth = Array.isArray(width) ? width[tickIndex] : width;
802
809
  while(word = words.pop()){
803
810
  line.push(word);
804
- tspan.text(line.join(' '));
805
- if (tspan.node().getComputedTextLength() > width && line.length > 1) {
811
+ const label = line.join(' ');
812
+ tspan.text(label);
813
+ const labelWidth = getTextSize(label, CARTESIAN_XAXIS_TEXT_SELECTOR, container).width;
814
+ if (labelWidth > maxWidth && line.length > 1) {
806
815
  line.pop();
807
816
  tspan.text(line.join(' '));
808
817
  line = [
809
818
  word
810
819
  ];
811
- tspan = text.append('tspan').attr('id', 'WordBreakId').attr('x', 0).attr('y', y).attr('dy', ++lineNumber * lineHeight + dy + 'em').text(word);
820
+ tspan = text.append('tspan').attr('x', 0).attr('y', y).attr('dy', ++lineNumber * lineHeight + dy + 'em').text(word);
812
821
  }
813
822
  }
814
823
  }
815
824
  maxLines = Math.max(maxLines, lineNumber + 1);
816
825
  });
817
826
  if (!showXAxisLablesTooltip) {
827
+ var _querySelector;
818
828
  let maxHeight = 12; // intial value to render corretly first time
819
- // eslint-disable-next-line @typescript-eslint/no-explicit-any
820
- const outerHTMLElement = document.getElementById('WordBreakId');
821
- const BoxCordinates = outerHTMLElement && outerHTMLElement.getBoundingClientRect();
822
- const boxHeight = BoxCordinates && BoxCordinates.height;
829
+ var _querySelector_getBoundingClientRect_height;
830
+ const boxHeight = (_querySelector_getBoundingClientRect_height = (_querySelector = (container !== null && container !== void 0 ? container : document).querySelector(`.${CARTESIAN_XAXIS_CLASSNAME} tspan`)) === null || _querySelector === void 0 ? void 0 : _querySelector.getBoundingClientRect().height) !== null && _querySelector_getBoundingClientRect_height !== void 0 ? _querySelector_getBoundingClientRect_height : 0;
823
831
  if (boxHeight > maxHeight) {
824
832
  maxHeight = boxHeight;
825
833
  }
@@ -835,24 +843,18 @@ yAxis, noOfCharsToTruncate, truncateLabel, isRtl) {
835
843
  if (node === null) {
836
844
  return;
837
845
  }
838
- let tickIndex = 0;
839
846
  const axisNode = d3Select(node).call(yAxis);
840
847
  axisNode.selectAll('.tick text').each(function() {
841
848
  const text = d3Select(this);
842
849
  const totalWord = text.text();
843
850
  const truncatedWord = isRtl ? `...${text.text().slice(0, noOfCharsToTruncate)}` : `${text.text().slice(0, noOfCharsToTruncate)}...`;
844
851
  const totalWordLength = text.text().length;
845
- const padding = 0; // ems
846
852
  const y = text.attr('y');
847
853
  const x = text.attr('x');
848
854
  const dy = parseFloat(text.attr('dy'));
849
- const dx = 0;
850
- const uid = tickIndex++;
851
- text.text(null).append('tspan').attr('x', x).attr('y', y).attr('id', `BaseSpan-${uid}`).attr('dy', dy + 'em').attr('data-', totalWord);
852
- if (truncateLabel && totalWordLength > noOfCharsToTruncate) {
853
- text.append('tspan').attr('id', `showDots-${uid}`).attr('x', x).attr('y', y).attr('dy', dy + 'em').attr('dx', padding + dx + 'em').text(truncatedWord);
854
- } else {
855
- text.append('tspan').attr('id', `LessLength-${uid}`).attr('x', x).attr('y', y).attr('dx', padding + dx + 'em').text(totalWord);
855
+ const tspan = text.text(null).attr('data-full', totalWord).append('tspan').attr('x', x).attr('y', y).attr('dy', dy + 'em');
856
+ if (truncateLabel) {
857
+ tspan.text(totalWordLength > noOfCharsToTruncate ? truncatedWord : totalWord);
856
858
  }
857
859
  });
858
860
  }
@@ -901,30 +903,30 @@ export const wrapContent = (content, id, maxWidth)=>{
901
903
  * On hover of the truncated word(at x axis labels tick), a tooltip will be appeared.
902
904
  */ // eslint-disable-next-line @typescript-eslint/no-explicit-any
903
905
  export function tooltipOfAxislabels(axistooltipProps) {
904
- const { tooltipCls, axis, id } = axistooltipProps;
906
+ const { tooltipCls, axis, id, container } = axistooltipProps;
905
907
  if (axis === null) {
906
908
  return null;
907
909
  }
908
- const div = d3Select('body').append('div').attr('id', id).attr('class', tooltipCls).style('opacity', 0);
909
- const aa = axis.selectAll('[id^="BaseSpan-"]')._groups[0];
910
- const baseSpanLength = aa && Object.keys(aa).length;
911
- const originalDataArray = [];
912
- for(let i = 0; i < baseSpanLength; i++){
913
- const originalData = aa[i].dataset && Object.values(aa[i].dataset)[0];
914
- originalDataArray.push(originalData);
915
- }
916
- const tickObject = axis.selectAll('.tick')._groups[0];
917
- const tickObjectLength = tickObject && Object.keys(tickObject).length;
918
- for(let i = 0; i < tickObjectLength; i++){
919
- const d1 = tickObject[i];
920
- d3Select(d1)// eslint-disable-next-line @typescript-eslint/no-explicit-any
910
+ const div = (container ? d3Select(container) : d3Select('body')).append('div').attr('id', id).attr('class', tooltipCls).style('opacity', 0);
911
+ axis.selectAll('.tick text').each(function() {
912
+ const tickSelection = d3Select(this);
913
+ const fullLabel = tickSelection.attr('data-full');
914
+ if (tickSelection.text() === fullLabel) {
915
+ return;
916
+ }
917
+ const tickEl = this;
918
+ tickSelection// eslint-disable-next-line @typescript-eslint/no-explicit-any
921
919
  .on('mouseover', (event, d)=>{
922
- div.style('opacity', 0.9);
923
- div.html(originalDataArray[i]).style('left', event.pageX + 'px').style('top', event.pageY - 28 + 'px');
920
+ const containerBounds = container === null || container === void 0 ? void 0 : container.getBoundingClientRect();
921
+ const tickBounds = tickEl.getBoundingClientRect();
922
+ const tooltipBottom = containerBounds ? containerBounds.bottom - (tickBounds.top - 4) : tickBounds.top - 4;
923
+ var _containerBounds_left;
924
+ const tooltipLeft = (tickBounds.left + tickBounds.right) / 2 - ((_containerBounds_left = containerBounds === null || containerBounds === void 0 ? void 0 : containerBounds.left) !== null && _containerBounds_left !== void 0 ? _containerBounds_left : 0);
925
+ div.text(fullLabel).style('bottom', `${tooltipBottom}px`).style('left', `${tooltipLeft}px`).style('transform', 'translateX(-50%)').style('opacity', 0.9);
924
926
  }).on('mouseout', (d)=>{
925
927
  div.style('opacity', 0);
926
928
  });
927
- }
929
+ });
928
930
  }
929
931
  /**
930
932
  * Find the axis type of line chart and area chart from given data
@@ -950,11 +952,11 @@ export function tooltipOfAxislabels(axistooltipProps) {
950
952
  * @param {number} width
951
953
  * @param {boolean} isRTL
952
954
  * @returns {IDomainNRange}
953
- */ export function domainRangeOfNumericForAreaLineScatterCharts(points, margins, width, isRTL, scaleType, hasMarkersMode) {
955
+ */ export function domainRangeOfNumericForAreaLineScatterCharts(points, margins, width, isRTL, scaleType, hasMarkersMode, xMinVal, xMaxVal) {
954
956
  const isScatterPolar = isScatterPolarSeries(points);
955
957
  let [xMin, xMax] = getScatterXDomainExtent(points, scaleType);
956
958
  if (hasMarkersMode) {
957
- const xPadding = getDomainPaddingForMarkers(xMin, xMax, scaleType);
959
+ const xPadding = getDomainPaddingForMarkers(xMin, xMax, scaleType, xMinVal, xMaxVal);
958
960
  xMin = xMin - xPadding.start;
959
961
  xMax = xMax + xPadding.end;
960
962
  }
@@ -1466,8 +1468,8 @@ export function areArraysEqual(arr1, arr2) {
1466
1468
  return true;
1467
1469
  }
1468
1470
  const cssVarRegExp = /var\((--[a-zA-Z0-9\-]+)\)/g;
1469
- export function resolveCSSVariables(chartContainer, styleRules) {
1470
- const containerStyles = getComputedStyle(chartContainer);
1471
+ export function resolveCSSVariables(container, styleRules) {
1472
+ const containerStyles = getComputedStyle(container);
1471
1473
  return styleRules.replace(cssVarRegExp, (match, group1)=>{
1472
1474
  return containerStyles.getPropertyValue(group1);
1473
1475
  });
@@ -1570,11 +1572,6 @@ export function copyStyle(properties, fromEl, toEl) {
1570
1572
  });
1571
1573
  }
1572
1574
  }
1573
- let measurementSpanCounter = 0;
1574
- function getUniqueMeasurementSpanId() {
1575
- measurementSpanCounter++;
1576
- return `measurement_span_${measurementSpanCounter}`;
1577
- }
1578
1575
  const MEASUREMENT_SPAN_STYLE = {
1579
1576
  position: 'absolute',
1580
1577
  visibility: 'hidden',
@@ -1585,23 +1582,60 @@ const MEASUREMENT_SPAN_STYLE = {
1585
1582
  border: 'none',
1586
1583
  whiteSpace: 'pre'
1587
1584
  };
1588
- export const createMeasurementSpan = (text, className, parentElement)=>{
1589
- const MEASUREMENT_SPAN_ID = getUniqueMeasurementSpanId();
1585
+ const MEASUREMENT_SPAN_ID = 'fui_measurement_span';
1586
+ const TEXT_STYLE_PROPERTIES = [
1587
+ 'font-size',
1588
+ 'font-family',
1589
+ 'font-weight',
1590
+ 'font-style',
1591
+ 'letter-spacing',
1592
+ 'text-transform'
1593
+ ];
1594
+ export const measureTextWithDOM = (text, cssSelector, container)=>{
1590
1595
  let measurementSpan = document.getElementById(MEASUREMENT_SPAN_ID);
1591
1596
  if (!measurementSpan) {
1592
1597
  measurementSpan = document.createElement('span');
1593
1598
  measurementSpan.setAttribute('id', MEASUREMENT_SPAN_ID);
1594
1599
  measurementSpan.setAttribute('aria-hidden', 'true');
1595
- if (parentElement) {
1596
- parentElement.appendChild(measurementSpan);
1597
- } else {
1598
- document.body.appendChild(measurementSpan);
1599
- }
1600
+ (container !== null && container !== void 0 ? container : document.body).appendChild(measurementSpan);
1600
1601
  }
1601
- measurementSpan.setAttribute('class', className);
1602
1602
  Object.assign(measurementSpan.style, MEASUREMENT_SPAN_STYLE);
1603
+ const refEl = (container !== null && container !== void 0 ? container : document).querySelector(cssSelector);
1604
+ if (refEl) {
1605
+ copyStyle(TEXT_STYLE_PROPERTIES, refEl, measurementSpan);
1606
+ }
1603
1607
  measurementSpan.textContent = `${text}`;
1604
- return measurementSpan;
1608
+ const rect = measurementSpan.getBoundingClientRect();
1609
+ return {
1610
+ node: measurementSpan,
1611
+ width: rect.width,
1612
+ height: rect.height
1613
+ };
1614
+ };
1615
+ const CACHE_SIZE = 2000;
1616
+ const textSizeCache = new Map();
1617
+ export const getTextSize = (text, cssSelector, container)=>{
1618
+ const cacheKey = `${text}|${cssSelector}`;
1619
+ const cachedResult = textSizeCache.get(cacheKey);
1620
+ if (cachedResult) {
1621
+ return cachedResult;
1622
+ }
1623
+ const { width, height } = measureTextWithDOM(text, cssSelector, container);
1624
+ // TODO: Improve cache eviction strategy if needed (e.g., LRU)
1625
+ if (textSizeCache.size >= CACHE_SIZE) {
1626
+ const firstKey = textSizeCache.keys().next().value;
1627
+ if (!isInvalidValue(firstKey)) {
1628
+ textSizeCache.delete(firstKey);
1629
+ }
1630
+ }
1631
+ textSizeCache.set(cacheKey, {
1632
+ width,
1633
+ height
1634
+ });
1635
+ return {
1636
+ width,
1637
+ height
1638
+ };
1605
1639
  };
1606
1640
  /**
1607
1641
  * Utility function to check if an array of points is scatterpolar
@@ -1633,17 +1667,26 @@ const createNumericScale = (scaleType)=>{
1633
1667
  return d3ScaleLinear();
1634
1668
  }
1635
1669
  };
1636
- export const getDomainPaddingForMarkers = (minVal, maxVal, scaleType)=>{
1670
+ export const getDomainPaddingForMarkers = (minVal, maxVal, scaleType, userMinVal, userMaxVal)=>{
1637
1671
  if (scaleType === 'log') {
1638
1672
  return {
1639
1673
  start: minVal * 0.5,
1640
1674
  end: maxVal
1641
1675
  };
1642
1676
  }
1643
- const defaultPadding = (maxVal - minVal) * 0.1;
1677
+ /* if user explicitly sets userMinVal or userMaxVal, we will check that to avoid excessive padding on either side.
1678
+ If the difference between minVal and userMinVal is more than 10% of the data range, we set padding to 0 on that side.
1679
+ this is to avoid cases where userMinVal is significantly smaller than minVal or userMaxVal is significantly larger than
1680
+ maxVal, which would lead to excessive padding. In other cases, we apply the default 10% padding on both sides.
1681
+ */ const rangePadding = (maxVal - minVal) * 0.1;
1682
+ // If explicit bounds are set and they're far from the data range, don't add extra padding
1683
+ const paddingAlreadySatisfiedAtMin = userMinVal !== undefined && rangePadding > Math.abs(minVal - Math.min(minVal, userMinVal));
1684
+ const paddingAlreadySatisfiedAtMax = userMaxVal !== undefined && rangePadding > Math.abs(maxVal - Math.max(maxVal, userMaxVal));
1685
+ const startPadding = paddingAlreadySatisfiedAtMin ? 0 : rangePadding;
1686
+ const endPadding = paddingAlreadySatisfiedAtMax ? 0 : rangePadding;
1644
1687
  return {
1645
- start: defaultPadding,
1646
- end: defaultPadding
1688
+ start: startPadding,
1689
+ end: endPadding
1647
1690
  };
1648
1691
  };
1649
1692
  /**
@@ -1672,7 +1715,7 @@ export const getScatterXDomainExtent = (points, scaleType)=>{
1672
1715
  xMax
1673
1716
  ];
1674
1717
  };
1675
- export const getRangeForScatterMarkerSize = ({ data, xScale, yScalePrimary, yScaleSecondary, useSecondaryYScale, xScaleType, yScaleType: primaryYScaleType, secondaryYScaleType })=>{
1718
+ export const getRangeForScatterMarkerSize = ({ data, xScale, yScalePrimary, yScaleSecondary, useSecondaryYScale, xScaleType, yScaleType: primaryYScaleType, secondaryYScaleType, xMinValue, xMaxValue, yMinValue, yMaxValue })=>{
1676
1719
  // Note: This function is executed after the scale is created, so the actual padding can be
1677
1720
  // obtained by calculating the difference between the respective minimums or maximums of the
1678
1721
  // scale domain and the data. However, doing so often causes the marker size to scale up
@@ -1683,13 +1726,13 @@ export const getRangeForScatterMarkerSize = ({ data, xScale, yScalePrimary, ySca
1683
1726
  // it the other way around (i.e., adjusting the scale domain first with padding and then scaling
1684
1727
  // the markers to fit inside the plot area).
1685
1728
  const [xMin, xMax] = getScatterXDomainExtent(data, xScaleType);
1686
- const xPadding = getDomainPaddingForMarkers(+xMin, +xMax, xScaleType);
1729
+ const xPadding = getDomainPaddingForMarkers(+xMin, +xMax, xScaleType, xMinValue, xMaxValue);
1687
1730
  const scaleXMin = xMin instanceof Date ? new Date(+xMin - xPadding.start) : xMin - xPadding.start;
1688
1731
  const scaleXMax = xMax instanceof Date ? new Date(+xMax + xPadding.end) : xMax + xPadding.end;
1689
1732
  const extraXPixels = Math.min(Math.abs(xScale(xMin) - xScale(scaleXMin)), Math.abs(xScale(scaleXMax) - xScale(xMax)));
1690
1733
  const yScaleType = useSecondaryYScale ? secondaryYScaleType : primaryYScaleType;
1691
1734
  const { startValue: yMin, endValue: yMax } = findNumericMinMaxOfY(data, undefined, useSecondaryYScale, yScaleType);
1692
- const yPadding = getDomainPaddingForMarkers(yMin, yMax, yScaleType);
1735
+ const yPadding = getDomainPaddingForMarkers(yMin, yMax, yScaleType, yMinValue, yMaxValue);
1693
1736
  const scaleYMin = yMin - yPadding.start;
1694
1737
  const scaleYMax = yMax + yPadding.end;
1695
1738
  const yScale = useSecondaryYScale ? yScaleSecondary : yScalePrimary;
@@ -1741,7 +1784,7 @@ const generateNumericTicks = (scaleType, tickStep, tick0, scaleDomain)=>{
1741
1784
  const refTick = typeof tick0 === 'number' ? tick0 : 0;
1742
1785
  if (scaleType === 'log') {
1743
1786
  if (typeof tickStep === 'number' && tickStep > 0) {
1744
- return generateLinearTicks(refTick, tickStep, scaleDomain.map((d)=>Math.log10(d))).map((t)=>Math.pow(10, t));
1787
+ return generateLinearTicks(refTick, tickStep, scaleDomain.map((d)=>Math.log10(d))).map((t)=>10 ** t);
1745
1788
  }
1746
1789
  if (typeof tickStep === 'string') {
1747
1790
  const prefix = tickStep[0];
@@ -1798,7 +1841,7 @@ const generateDateTicks = (tickStep, tick0, scaleDomain, useUTC)=>{
1798
1841
  * @param value - The value that is being rounded.
1799
1842
  * @param precision - The number of decimal places to round the number to
1800
1843
  */ export function precisionRound(value, precision, base = 10) {
1801
- const exp = Math.pow(base, precision);
1844
+ const exp = base ** precision;
1802
1845
  return Math.round(value * exp) / exp;
1803
1846
  }
1804
1847
  export const findCalloutPoints = (calloutPointsByX, x)=>{
@@ -1814,3 +1857,102 @@ export const findCalloutPoints = (calloutPointsByX, x)=>{
1814
1857
  values: calloutPointsByX[key]
1815
1858
  };
1816
1859
  };
1860
+ export const autoLayoutXAxisLabels = (tickValues, tickLabels, scale, axisNode, containerWidth, container)=>{
1861
+ let requiresWrap = false;
1862
+ let requiresTruncate = false;
1863
+ const maxWidths = [];
1864
+ const [rangeStart, rangeEnd] = scale.range();
1865
+ const isRTL = rangeEnd - rangeStart < 0;
1866
+ const start = isRTL ? containerWidth : 0;
1867
+ const end = isRTL ? 0 : containerWidth;
1868
+ const getTickPosition = (index)=>{
1869
+ var _scale;
1870
+ // eslint-disable-next-line @typescript-eslint/no-explicit-any
1871
+ return ((_scale = scale(tickValues[index])) !== null && _scale !== void 0 ? _scale : 0) + ('bandwidth' in scale ? scale.bandwidth() / 2 : 0);
1872
+ };
1873
+ const getLabelWidth = (text)=>{
1874
+ return getTextSize(text, CARTESIAN_XAXIS_TEXT_SELECTOR, container).width;
1875
+ };
1876
+ for(let i = 0; i < tickValues.length; i++){
1877
+ const position = getTickPosition(i);
1878
+ const leftSpace = Math.abs(i > 0 ? (position - getTickPosition(i - 1)) / 2 : position - start);
1879
+ const rightSpace = Math.abs(i + 1 < tickValues.length ? (getTickPosition(i + 1) - position) / 2 : end - position);
1880
+ const maxAvailableWidth = Math.min(leftSpace, rightSpace) * 2 - 8; // 4px padding on both sides
1881
+ const label = tickLabels[i];
1882
+ const labelWidth = getLabelWidth(label);
1883
+ maxWidths.push(maxAvailableWidth);
1884
+ if (labelWidth > maxAvailableWidth) {
1885
+ const longestWordWidth = Math.max(...label.split(/\s+/).map((word)=>getLabelWidth(word)));
1886
+ if (longestWordWidth <= maxAvailableWidth) {
1887
+ requiresWrap = true;
1888
+ } else {
1889
+ requiresTruncate = true;
1890
+ }
1891
+ }
1892
+ }
1893
+ if (requiresTruncate) {
1894
+ return truncateAndStaggerXAxisLabels(tickValues, tickLabels, scale, axisNode, containerWidth, container);
1895
+ }
1896
+ if (requiresWrap) {
1897
+ var _createWrapOfXLabels;
1898
+ return (_createWrapOfXLabels = createWrapOfXLabels({
1899
+ node: axisNode,
1900
+ // eslint-disable-next-line @typescript-eslint/no-explicit-any
1901
+ xAxis: scale,
1902
+ noOfCharsToTruncate: 100,
1903
+ showXAxisLablesTooltip: false,
1904
+ width: maxWidths,
1905
+ container
1906
+ })) !== null && _createWrapOfXLabels !== void 0 ? _createWrapOfXLabels : 0;
1907
+ }
1908
+ return 0;
1909
+ };
1910
+ const truncateAndStaggerXAxisLabels = (tickValues, tickLabels, scale, axisNode, containerWidth, container)=>{
1911
+ if (!axisNode) {
1912
+ return 0;
1913
+ }
1914
+ let maxHeight = 12;
1915
+ const [rangeStart, rangeEnd] = scale.range();
1916
+ const isRTL = rangeEnd - rangeStart < 0;
1917
+ const start = isRTL ? containerWidth : 0;
1918
+ const end = isRTL ? 0 : containerWidth;
1919
+ const getTickPosition = (index)=>{
1920
+ var _scale;
1921
+ // eslint-disable-next-line @typescript-eslint/no-explicit-any
1922
+ return ((_scale = scale(tickValues[index])) !== null && _scale !== void 0 ? _scale : 0) + ('bandwidth' in scale ? scale.bandwidth() / 2 : 0);
1923
+ };
1924
+ const getLabelSize = (text)=>{
1925
+ return getTextSize(text, CARTESIAN_XAXIS_TEXT_SELECTOR, container);
1926
+ };
1927
+ d3Select(axisNode).selectAll('.tick text').each(function(_, i) {
1928
+ const position = getTickPosition(i);
1929
+ const leftSpace = Math.abs(i > 0 ? position - getTickPosition(i - 1) : position - start);
1930
+ const rightSpace = Math.abs(i + 1 < tickValues.length ? getTickPosition(i + 1) - position : end - position);
1931
+ const maxAvailableWidth = Math.min(leftSpace, rightSpace) * 2 - 8; // 4px padding on both sides
1932
+ const label = tickLabels[i];
1933
+ const textNode = d3Select(this).text(null).attr('data-full', label);
1934
+ const lineHeight = 1.1; // ems
1935
+ const y = textNode.attr('y');
1936
+ const dy = parseFloat(textNode.attr('dy'));
1937
+ textNode.append('tspan').attr('x', 0).attr('y', y).attr('dy', (i % 2 === 1 ? lineHeight : 0) + dy + 'em').text(truncateTextToFitWidth(label, maxAvailableWidth, (s)=>getLabelSize(s).width));
1938
+ maxHeight = Math.max(maxHeight, getLabelSize(label).height);
1939
+ });
1940
+ return tickValues.length > 1 ? maxHeight : 0;
1941
+ };
1942
+ const truncateTextToFitWidth = (text, maxWidth, measure)=>{
1943
+ if (measure(text) <= maxWidth) {
1944
+ return text;
1945
+ }
1946
+ let lo = 1;
1947
+ let hi = text.length;
1948
+ while(lo < hi){
1949
+ const mid = Math.floor((lo + hi + 1) / 2);
1950
+ const candidate = text.slice(0, mid) + '...';
1951
+ if (measure(candidate) <= maxWidth) {
1952
+ lo = mid;
1953
+ } else {
1954
+ hi = mid - 1;
1955
+ }
1956
+ }
1957
+ return text.slice(0, lo) + '...';
1958
+ };