@fluentui/react-charts 0.0.0-nightly-20251215-0407.1 → 0.0.0-nightly-20251217-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 (103) hide show
  1. package/CHANGELOG.md +13 -13
  2. package/dist/index.d.ts +25 -1
  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/CommonComponents/CartesianChart.js +41 -31
  8. package/lib/components/CommonComponents/CartesianChart.js.map +1 -1
  9. package/lib/components/CommonComponents/CartesianChart.types.js.map +1 -1
  10. package/lib/components/CommonComponents/useCartesianChartStyles.styles.js +5 -5
  11. package/lib/components/CommonComponents/useCartesianChartStyles.styles.js.map +1 -1
  12. package/lib/components/CommonComponents/useCartesianChartStyles.styles.raw.js +4 -3
  13. package/lib/components/CommonComponents/useCartesianChartStyles.styles.raw.js.map +1 -1
  14. package/lib/components/DeclarativeChart/PlotlySchemaAdapter.js +177 -29
  15. package/lib/components/DeclarativeChart/PlotlySchemaAdapter.js.map +1 -1
  16. package/lib/components/GroupedVerticalBarChart/GroupedVerticalBarChart.js +17 -17
  17. package/lib/components/GroupedVerticalBarChart/GroupedVerticalBarChart.js.map +1 -1
  18. package/lib/components/GroupedVerticalBarChart/useGroupedVerticalBarChartStyles.styles.js +1 -2
  19. package/lib/components/GroupedVerticalBarChart/useGroupedVerticalBarChartStyles.styles.js.map +1 -1
  20. package/lib/components/Legends/Legends.js +3 -4
  21. package/lib/components/Legends/Legends.js.map +1 -1
  22. package/lib/components/LineChart/LineChart.js +1 -23
  23. package/lib/components/LineChart/LineChart.js.map +1 -1
  24. package/lib/components/LineChart/useLineChartStyles.styles.js +1 -2
  25. package/lib/components/LineChart/useLineChartStyles.styles.js.map +1 -1
  26. package/lib/components/SankeyChart/SankeyChart.js +1 -1
  27. package/lib/components/SankeyChart/SankeyChart.js.map +1 -1
  28. package/lib/components/SankeyChart/useSankeyChartStyles.styles.js +1 -2
  29. package/lib/components/SankeyChart/useSankeyChartStyles.styles.js.map +1 -1
  30. package/lib/components/ScatterChart/ScatterChart.js +1 -23
  31. package/lib/components/ScatterChart/ScatterChart.js.map +1 -1
  32. package/lib/components/ScatterChart/useScatterChartStyles.styles.js +1 -2
  33. package/lib/components/ScatterChart/useScatterChartStyles.styles.js.map +1 -1
  34. package/lib/components/VerticalBarChart/VerticalBarChart.js +8 -78
  35. package/lib/components/VerticalBarChart/VerticalBarChart.js.map +1 -1
  36. package/lib/components/VerticalBarChart/useVerticalBarChartStyles.styles.js +1 -2
  37. package/lib/components/VerticalBarChart/useVerticalBarChartStyles.styles.js.map +1 -1
  38. package/lib/components/VerticalStackedBarChart/VerticalStackedBarChart.js +14 -26
  39. package/lib/components/VerticalStackedBarChart/VerticalStackedBarChart.js.map +1 -1
  40. package/lib/components/VerticalStackedBarChart/useVerticalStackedBarChartStyles.styles.js +1 -2
  41. package/lib/components/VerticalStackedBarChart/useVerticalStackedBarChartStyles.styles.js.map +1 -1
  42. package/lib/types/DataPoint.js.map +1 -1
  43. package/lib/utilities/Common.styles.js +0 -1
  44. package/lib/utilities/Common.styles.js.map +1 -1
  45. package/lib/utilities/Common.styles.raw.js +0 -1
  46. package/lib/utilities/Common.styles.raw.js.map +1 -1
  47. package/lib/utilities/image-export-utils.js +4 -4
  48. package/lib/utilities/image-export-utils.js.map +1 -1
  49. package/lib/utilities/utilities.js +200 -67
  50. package/lib/utilities/utilities.js.map +1 -1
  51. package/lib-commonjs/components/AreaChart/AreaChart.js +0 -26
  52. package/lib-commonjs/components/AreaChart/AreaChart.js.map +1 -1
  53. package/lib-commonjs/components/AreaChart/useAreaChartStyles.styles.js +0 -2
  54. package/lib-commonjs/components/AreaChart/useAreaChartStyles.styles.js.map +1 -1
  55. package/lib-commonjs/components/CommonComponents/CartesianChart.js +40 -30
  56. package/lib-commonjs/components/CommonComponents/CartesianChart.js.map +1 -1
  57. package/lib-commonjs/components/CommonComponents/CartesianChart.types.js.map +1 -1
  58. package/lib-commonjs/components/CommonComponents/useCartesianChartStyles.styles.js +3 -4
  59. package/lib-commonjs/components/CommonComponents/useCartesianChartStyles.styles.js.map +1 -1
  60. package/lib-commonjs/components/CommonComponents/useCartesianChartStyles.styles.raw.js +3 -2
  61. package/lib-commonjs/components/CommonComponents/useCartesianChartStyles.styles.raw.js.map +1 -1
  62. package/lib-commonjs/components/DeclarativeChart/PlotlySchemaAdapter.js +177 -28
  63. package/lib-commonjs/components/DeclarativeChart/PlotlySchemaAdapter.js.map +1 -1
  64. package/lib-commonjs/components/GroupedVerticalBarChart/GroupedVerticalBarChart.js +15 -15
  65. package/lib-commonjs/components/GroupedVerticalBarChart/GroupedVerticalBarChart.js.map +1 -1
  66. package/lib-commonjs/components/GroupedVerticalBarChart/useGroupedVerticalBarChartStyles.styles.js +0 -2
  67. package/lib-commonjs/components/GroupedVerticalBarChart/useGroupedVerticalBarChartStyles.styles.js.map +1 -1
  68. package/lib-commonjs/components/Legends/Legends.js +3 -4
  69. package/lib-commonjs/components/Legends/Legends.js.map +1 -1
  70. package/lib-commonjs/components/LineChart/LineChart.js +0 -22
  71. package/lib-commonjs/components/LineChart/LineChart.js.map +1 -1
  72. package/lib-commonjs/components/LineChart/useLineChartStyles.styles.js +0 -2
  73. package/lib-commonjs/components/LineChart/useLineChartStyles.styles.js.map +1 -1
  74. package/lib-commonjs/components/SankeyChart/SankeyChart.js +1 -1
  75. package/lib-commonjs/components/SankeyChart/SankeyChart.js.map +1 -1
  76. package/lib-commonjs/components/SankeyChart/useSankeyChartStyles.styles.js +0 -2
  77. package/lib-commonjs/components/SankeyChart/useSankeyChartStyles.styles.js.map +1 -1
  78. package/lib-commonjs/components/ScatterChart/ScatterChart.js +0 -22
  79. package/lib-commonjs/components/ScatterChart/ScatterChart.js.map +1 -1
  80. package/lib-commonjs/components/ScatterChart/useScatterChartStyles.styles.js +0 -2
  81. package/lib-commonjs/components/ScatterChart/useScatterChartStyles.styles.js.map +1 -1
  82. package/lib-commonjs/components/VerticalBarChart/VerticalBarChart.js +7 -77
  83. package/lib-commonjs/components/VerticalBarChart/VerticalBarChart.js.map +1 -1
  84. package/lib-commonjs/components/VerticalBarChart/useVerticalBarChartStyles.styles.js +0 -2
  85. package/lib-commonjs/components/VerticalBarChart/useVerticalBarChartStyles.styles.js.map +1 -1
  86. package/lib-commonjs/components/VerticalStackedBarChart/VerticalStackedBarChart.js +13 -25
  87. package/lib-commonjs/components/VerticalStackedBarChart/VerticalStackedBarChart.js.map +1 -1
  88. package/lib-commonjs/components/VerticalStackedBarChart/useVerticalStackedBarChartStyles.styles.js +0 -2
  89. package/lib-commonjs/components/VerticalStackedBarChart/useVerticalStackedBarChartStyles.styles.js.map +1 -1
  90. package/lib-commonjs/types/DataPoint.js.map +1 -1
  91. package/lib-commonjs/utilities/Common.styles.js +0 -1
  92. package/lib-commonjs/utilities/Common.styles.js.map +1 -1
  93. package/lib-commonjs/utilities/Common.styles.raw.js +0 -1
  94. package/lib-commonjs/utilities/Common.styles.raw.js.map +1 -1
  95. package/lib-commonjs/utilities/image-export-utils.js +3 -3
  96. package/lib-commonjs/utilities/image-export-utils.js.map +1 -1
  97. package/lib-commonjs/utilities/utilities.js +212 -70
  98. package/lib-commonjs/utilities/utilities.js.map +1 -1
  99. package/package.json +12 -12
  100. package/lib/components/DeclarativeChart/imageExporter.js +0 -223
  101. package/lib/components/DeclarativeChart/imageExporter.js.map +0 -1
  102. package/lib-commonjs/components/DeclarativeChart/imageExporter.js +0 -233
  103. 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
@@ -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
@@ -1823,3 +1857,102 @@ export const findCalloutPoints = (calloutPointsByX, x)=>{
1823
1857
  values: calloutPointsByX[key]
1824
1858
  };
1825
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
+ };