axidio-styleguide-library1-v2 0.2.24 → 0.2.25

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.
@@ -6640,15 +6640,18 @@ class HorizontalBarsWithScrollZoomComponent extends ComponentUniqueId {
6640
6640
  this.isTransparentBackground = false;
6641
6641
  this.isCC = false;
6642
6642
  this.isZoomedOut = true;
6643
- this.TICK_LENGTHS = {
6644
- short: 4,
6645
- long: 16,
6646
- shortBg: 5,
6647
- longBg: 30,
6648
- };
6649
- this.SPACING = {
6650
- rightSvgWidth: 60,
6651
- leftAndRight: 50,
6643
+ this.CONSTANTS = {
6644
+ RIGHT_SVG_WIDTH: 60,
6645
+ LEFT_RIGHT_SPACES: 50,
6646
+ SHORT_TICK_LENGTH: 4,
6647
+ LONG_TICK_LENGTH: 16,
6648
+ SHORT_TICK_LENGTH_BG: 5,
6649
+ LONG_TICK_LENGTH_BG: 30,
6650
+ MIN_MOBILE_BAR_WIDTH: 32,
6651
+ DESKTOP_MIN_BAR_WIDTH: 40,
6652
+ MOBILE_BAR_PADDING: 12,
6653
+ ZOOM_THRESHOLD: 30,
6654
+ ZOOM_IN_THRESHOLD: 8,
6652
6655
  };
6653
6656
  this.defaultConfiguration = {
6654
6657
  margin: { top: 20, right: 20, bottom: 20, left: 40 },
@@ -6665,24 +6668,54 @@ class HorizontalBarsWithScrollZoomComponent extends ComponentUniqueId {
6665
6668
  forComparison: true,
6666
6669
  headerMenuOptions: HeaderConfigHelper.headerConfig.headerMenuOptions,
6667
6670
  yAxisGrid: false,
6671
+ // Optional configs with undefined defaults
6672
+ isHeaderVisible: undefined,
6673
+ isTransparentBackground: undefined,
6674
+ isTopCaptionVisible: undefined,
6675
+ isMultiChartGridLine: undefined,
6676
+ isFullScreen: undefined,
6677
+ customYscale: undefined,
6678
+ isXaxisLabelHidden: undefined,
6679
+ isYaxisLabelHidden: undefined,
6680
+ isYaxisHidden: undefined,
6681
+ isYaxisDashed: undefined,
6682
+ isXaxisColor: undefined,
6683
+ textFormatter: undefined,
6684
+ showTotalOnTop: undefined,
6685
+ backendFormatterHasPriority: undefined,
6686
+ showAngledLabels: undefined,
6687
+ isNoAlternateXaxisText: undefined,
6688
+ isXgridBetweenLabels: undefined,
6689
+ showXaxisTop: undefined,
6690
+ xAxisGrid: undefined,
6691
+ xLabelsOnSameLine: undefined,
6692
+ hideXaxisTick: undefined,
6693
+ isDrilldownChart: undefined,
6694
+ isTargetLine: undefined,
6695
+ displayTitleOnTop: undefined,
6696
+ isToggleVisible: undefined,
6697
+ isTitleHidden: undefined,
6668
6698
  };
6669
6699
  }
6670
6700
  ngOnInit() { }
6671
- ngOnChanges(changes) {
6672
- this.redrawChart();
6701
+ ngOnChanges() {
6702
+ this.removeExistingChart();
6703
+ this.initializeStackedChart();
6673
6704
  }
6674
6705
  onResized(event) {
6675
- setTimeout(() => this.redrawChart(), 10);
6706
+ setTimeout(() => {
6707
+ this.removeExistingChart();
6708
+ this.initializeStackedChart();
6709
+ }, 10);
6676
6710
  }
6677
6711
  isZoomOutSelected(isZoomOut) {
6678
6712
  this.isZoomedOut = isZoomOut;
6679
- this.redrawChart();
6713
+ this.ngOnChanges();
6680
6714
  }
6681
- redrawChart() {
6715
+ removeExistingChart() {
6682
6716
  d3.select('#' + this.uniqueId).remove();
6683
- this.initializeStackedChart();
6684
6717
  }
6685
- getDeviceBreakpoints() {
6718
+ getDeviceConfig() {
6686
6719
  const width = window.innerWidth;
6687
6720
  return {
6688
6721
  isMobile: width < 576,
@@ -6690,7 +6723,7 @@ class HorizontalBarsWithScrollZoomComponent extends ComponentUniqueId {
6690
6723
  isDesktop: width >= 992,
6691
6724
  };
6692
6725
  }
6693
- applyResponsiveConfig(device) {
6726
+ configureResponsiveSettings(device) {
6694
6727
  if (device.isMobile) {
6695
6728
  this.chartConfiguration.margin = { top: 20, right: 10, bottom: 40, left: 30 };
6696
6729
  this.chartConfiguration.numberOfYTicks = 4;
@@ -6708,9 +6741,9 @@ class HorizontalBarsWithScrollZoomComponent extends ComponentUniqueId {
6708
6741
  }
6709
6742
  }
6710
6743
  mergeConfigurations() {
6711
- Object.keys(this.defaultConfiguration).forEach((key) => {
6744
+ for (const key in this.defaultConfiguration) {
6712
6745
  this.chartConfiguration[key] = ChartHelper.getValueByConfigurationType(key, this.defaultConfiguration, this.customChartConfiguration);
6713
- });
6746
+ }
6714
6747
  }
6715
6748
  prepareMetaData(metaData) {
6716
6749
  if (!metaData.unit)
@@ -6725,183 +6758,70 @@ class HorizontalBarsWithScrollZoomComponent extends ComponentUniqueId {
6725
6758
  }
6726
6759
  return metaData;
6727
6760
  }
6728
- parseTargetValue(targetLineData) {
6729
- if (!targetLineData?.target)
6730
- return null;
6731
- const parsedNum = parseFloat(String(targetLineData.target));
6732
- if (isNaN(parsedNum))
6733
- return null;
6734
- return Number.isInteger(parsedNum)
6735
- ? parseInt(String(targetLineData.target))
6736
- : parsedNum;
6737
- }
6738
- calculateDimensions(containerWidth, containerHeight, margin, device) {
6761
+ calculateDimensions(chartContainer, verticalContainer, margin, device, dataLength) {
6762
+ const containerWidth = chartContainer.node().getBoundingClientRect().width;
6763
+ const containerHeight = verticalContainer.node().getBoundingClientRect().height;
6739
6764
  let width = containerWidth - margin.left - margin.right;
6740
6765
  let height = containerHeight * (this.chartConfiguration.svgHeight / 100) - margin.top - margin.bottom;
6741
- // Adjust width for zoom levels
6742
- const dataLength = this.chartData.data.length;
6743
- if (dataLength > 30 && this.isZoomedOut) {
6766
+ // Handle zoom out scenario
6767
+ if (dataLength > this.CONSTANTS.ZOOM_THRESHOLD && this.isZoomedOut) {
6744
6768
  const minWidth = dataLength * (device.isMobile ? 15 : 25);
6745
6769
  width = Math.max(width, minWidth);
6746
6770
  }
6747
- if (dataLength > 8 && !this.isZoomedOut) {
6771
+ // Handle zoom in scenario
6772
+ if (dataLength > this.CONSTANTS.ZOOM_IN_THRESHOLD && !this.isZoomedOut) {
6748
6773
  width = dataLength * (device.isMobile ? 60 : 130);
6749
6774
  }
6750
- // Apply special height configurations
6751
- if (this.chartConfiguration.isFullScreen && this.chartConfiguration.svgHeight !== 80) {
6752
- height = this.chartConfiguration.svgHeight;
6753
- }
6754
- else if (this.chartConfiguration.isFullScreen) {
6755
- height = containerHeight;
6775
+ // Handle full screen
6776
+ if (this.chartConfiguration.isFullScreen) {
6777
+ height = this.chartConfiguration.svgHeight !== 80
6778
+ ? this.chartConfiguration.svgHeight
6779
+ : containerHeight;
6756
6780
  }
6781
+ // Handle drilldown
6757
6782
  if (this.chartConfiguration.isDrilldownChart) {
6758
6783
  height = containerHeight - margin.top - margin.bottom - (device.isMobile ? 60 : 130);
6759
6784
  }
6760
- return { width, height };
6761
- }
6762
- calculateBarDimensions(width, dataLength, device) {
6785
+ // Calculate bar dimensions
6763
6786
  let barWidth;
6764
6787
  let barPadding;
6765
6788
  let requiredSvgWidth;
6766
6789
  if (device.isMobile) {
6767
- const minBarWidth = 32;
6768
- barWidth = minBarWidth;
6769
- barPadding = 12;
6770
- requiredSvgWidth = Math.max(width - this.SPACING.rightSvgWidth, (barWidth + barPadding) * dataLength + this.SPACING.leftAndRight * 2 +
6771
- this.SPACING.rightSvgWidth - barPadding);
6790
+ barWidth = this.CONSTANTS.MIN_MOBILE_BAR_WIDTH;
6791
+ barPadding = this.CONSTANTS.MOBILE_BAR_PADDING;
6792
+ requiredSvgWidth = Math.max(width - this.CONSTANTS.RIGHT_SVG_WIDTH, (barWidth + barPadding) * dataLength + this.CONSTANTS.LEFT_RIGHT_SPACES * 2 +
6793
+ this.CONSTANTS.RIGHT_SVG_WIDTH - barPadding);
6772
6794
  }
6773
6795
  else {
6774
- barWidth = Math.max(40, (width - this.SPACING.rightSvgWidth - this.SPACING.leftAndRight * 2) / dataLength);
6796
+ barWidth = Math.max(this.CONSTANTS.DESKTOP_MIN_BAR_WIDTH, (width - this.CONSTANTS.RIGHT_SVG_WIDTH - this.CONSTANTS.LEFT_RIGHT_SPACES * 2) / dataLength);
6775
6797
  barPadding = 0;
6776
- requiredSvgWidth = width - this.SPACING.rightSvgWidth;
6777
- }
6778
- return { barWidth, barPadding, requiredSvgWidth };
6779
- }
6780
- createScales(data, height, width, device) {
6781
- const xScale = d3
6782
- .scaleBand()
6783
- .rangeRound([
6784
- this.SPACING.leftAndRight,
6785
- width - this.SPACING.rightSvgWidth - this.SPACING.leftAndRight
6786
- ])
6787
- .domain(data.map(d => d.name).reverse())
6788
- .padding(device.isMobile ? 0.2 : 0.5);
6789
- const yScale = d3.scaleLinear().rangeRound([height, 0]);
6790
- return { xScale, yScale };
6791
- }
6792
- calculateYScaleDomain(layers, targetValue) {
6793
- let maxValue = d3.max(layers, (d) => d3.max(d, (d) => d[1])) || 0;
6794
- if (maxValue === 0) {
6795
- maxValue = targetValue ? targetValue + 20 : 100;
6796
- }
6797
- if (this.chartConfiguration.customYscale) {
6798
- maxValue *= this.chartConfiguration.customYscale;
6799
- }
6800
- if (targetValue && maxValue < targetValue) {
6801
- maxValue = maxValue < 10 && targetValue < 10
6802
- ? targetValue + 3
6803
- : targetValue + 20;
6804
- }
6805
- return maxValue;
6806
- }
6807
- shouldShowTargetLineColor(d, targetValue) {
6808
- return !!(!isNaN(d[0]) &&
6809
- !isNaN(d[1]) &&
6810
- this.chartData.targetLineData &&
6811
- targetValue &&
6812
- parseFloat(d[1]) - parseFloat(d[0]) >= targetValue);
6813
- }
6814
- getBarFillColor(d, key, metaData, targetValue) {
6815
- if (this.shouldShowTargetLineColor(d, targetValue)) {
6816
- return this.chartData.targetLineData?.barAboveTargetColor || metaData.colors[key];
6798
+ requiredSvgWidth = width - this.CONSTANTS.RIGHT_SVG_WIDTH;
6817
6799
  }
6818
- return metaData.colors[key];
6819
- }
6820
- isAcronym(label) {
6821
- const alphaOnly = label.replace(/[^A-Za-z]/g, '');
6822
- return (label.length <= 4 && /^[A-Z]+$/.test(label)) ||
6823
- (label === label.toUpperCase() && /[A-Z]/.test(label));
6824
- }
6825
- formatAxisLabel(text) {
6826
- const isAcr = this.isAcronym(text);
6827
6800
  return {
6828
- formatted: isAcr ? text.toUpperCase() : text.toLowerCase(),
6829
- isAcronym: isAcr
6801
+ width,
6802
+ height,
6803
+ containerWidth,
6804
+ containerHeight,
6805
+ barWidth,
6806
+ barPadding,
6807
+ requiredSvgWidth,
6830
6808
  };
6831
6809
  }
6832
- initializeStackedChart() {
6833
- const device = this.getDeviceBreakpoints();
6834
- this.applyResponsiveConfig(device);
6835
- this.mergeConfigurations();
6836
- const { data, metaData, lineData } = this.chartData;
6837
- const preparedMetaData = this.prepareMetaData(metaData);
6838
- const targetValue = this.parseTargetValue(this.chartData.targetLineData);
6839
- const chartContainer = d3.select(this.containerElt.nativeElement);
6840
- const verticalstackedcontainer = d3.select(this.verticalstackedcontainerElt.nativeElement);
6841
- const margin = this.chartConfiguration.margin;
6842
- const containerWidth = chartContainer.node().getBoundingClientRect().width;
6843
- const containerHeight = verticalstackedcontainer.node().getBoundingClientRect().height;
6844
- const { width, height } = this.calculateDimensions(containerWidth, containerHeight, margin, device);
6845
- // Apply visibility configurations
6846
- if (this.chartConfiguration.isHeaderVisible !== undefined) {
6847
- this.isHeaderVisible = this.chartConfiguration.isHeaderVisible;
6848
- }
6849
- if (this.chartConfiguration.isTopCaptionVisible !== undefined) {
6850
- this.isTopCaptionVisible = this.chartConfiguration.isTopCaptionVisible;
6851
- }
6852
- if (this.chartConfiguration.isTransparentBackground !== undefined) {
6853
- this.isTransparentBackground = this.chartConfiguration.isTransparentBackground;
6854
- }
6855
- // Create formatters
6856
- const formatFromBackend = this.chartConfiguration.textFormatter
6857
- ? ChartHelper.dataValueFormatter(this.chartConfiguration.textFormatter)
6858
- : null;
6859
- const formatForHugeNumbers = ChartHelper.dataValueFormatter('.2s');
6860
- // Create SVG containers
6861
- const { barWidth, barPadding, requiredSvgWidth } = this.calculateBarDimensions(width, data.length, device);
6862
- const outerContainer = this.createOuterContainer(chartContainer, height, margin);
6863
- const { svgYAxisLeft, svgYAxisRight } = this.createAxisContainers(outerContainer, height, margin);
6864
- const { innerContainer, svg } = this.createInnerContainer(outerContainer, requiredSvgWidth, height, margin, device);
6865
- // Create scales
6866
- const { xScale, yScale } = this.createScales(data, height, width, device);
6867
- // Stack data
6868
- const stack = d3
6869
- .stack()
6870
- .keys(preparedMetaData.keyList)
6871
- .offset(d3.stackOffsetNone);
6872
- const layers = stack(data);
6873
- // Set Y scale domain
6874
- const maxValue = this.calculateYScaleDomain(layers, targetValue || undefined);
6875
- yScale.domain([0, maxValue]).nice();
6876
- // Render chart elements
6877
- this.renderGrids(svg, xScale, yScale, height, width);
6878
- this.renderBars(svg, layers, xScale, yScale, preparedMetaData, device, barWidth, barPadding, targetValue, formatFromBackend, formatForHugeNumbers);
6879
- this.renderAxes(svg, svgYAxisLeft, svgYAxisRight, xScale, yScale, data, height, width, device);
6880
- this.renderLabels(svg, svgYAxisLeft, preparedMetaData, height, width, margin);
6881
- if (this.chartData.targetLineData && targetValue) {
6882
- this.renderTargetLine(svg, svgYAxisRight, yScale, width, targetValue, preparedMetaData);
6883
- }
6884
- if (lineData) {
6885
- this.renderLineChart(svg, lineData, xScale, height, preparedMetaData.colors);
6886
- }
6887
- }
6888
- createOuterContainer(chartContainer, height, margin) {
6889
- return chartContainer
6810
+ createSvgContainers(chartContainer, dimensions, margin) {
6811
+ const outerContainer = chartContainer
6890
6812
  .append('div')
6891
6813
  .attr('id', this.uniqueId)
6892
6814
  .attr('class', 'outer-container')
6893
6815
  .style('width', '100%')
6894
- .style('height', height)
6816
+ .style('height', dimensions.height)
6895
6817
  .style('overflow-x', 'hidden')
6896
6818
  .style('padding-left', `${margin.left}px`)
6897
6819
  .style('margin-left', '10px')
6898
- .style('padding-right', `${this.SPACING.rightSvgWidth}px`);
6899
- }
6900
- createAxisContainers(outerContainer, height, margin) {
6820
+ .style('padding-right', `${this.CONSTANTS.RIGHT_SVG_WIDTH}px`);
6901
6821
  const svgYAxisLeft = outerContainer
6902
6822
  .append('svg')
6903
6823
  .attr('width', '80')
6904
- .attr('height', height + margin.top + margin.bottom)
6824
+ .attr('height', dimensions.height + margin.top + margin.bottom)
6905
6825
  .style('position', 'absolute')
6906
6826
  .style('left', '0')
6907
6827
  .style('z-index', 1)
@@ -6909,65 +6829,85 @@ class HorizontalBarsWithScrollZoomComponent extends ComponentUniqueId {
6909
6829
  .attr('transform', `translate(${margin.left + 10},${margin.top})`);
6910
6830
  const svgYAxisRight = outerContainer
6911
6831
  .append('svg')
6912
- .attr('width', this.SPACING.rightSvgWidth)
6913
- .attr('height', height + margin.top + margin.bottom)
6832
+ .attr('width', this.CONSTANTS.RIGHT_SVG_WIDTH)
6833
+ .attr('height', dimensions.height + margin.top + margin.bottom)
6914
6834
  .style('position', 'absolute')
6915
6835
  .style('right', '2px')
6916
6836
  .style('z-index', 1)
6917
6837
  .append('g')
6918
6838
  .attr('transform', `translate(0,${margin.top})`);
6919
- return { svgYAxisLeft, svgYAxisRight };
6920
- }
6921
- createInnerContainer(outerContainer, requiredSvgWidth, height, margin, device) {
6922
6839
  const innerContainer = outerContainer
6923
6840
  .append('div')
6924
6841
  .attr('class', 'inner-container')
6925
6842
  .style('width', '100%')
6926
- .style('overflow-x', device.isMobile ? 'auto' : 'auto');
6843
+ .style('overflow-x', 'auto');
6927
6844
  const svg = innerContainer
6928
6845
  .append('svg')
6929
- .attr('width', requiredSvgWidth)
6930
- .attr('height', height + margin.top + margin.bottom + 30)
6846
+ .attr('width', dimensions.requiredSvgWidth)
6847
+ .attr('height', dimensions.height + margin.top + margin.bottom + 30)
6931
6848
  .append('g')
6932
6849
  .attr('transform', `translate(0,${margin.top})`);
6933
- return { innerContainer, svg };
6850
+ return { svg, svgYAxisLeft, svgYAxisRight, innerContainer };
6934
6851
  }
6935
- renderGrids(svg, xScale, yScale, height, width) {
6936
- if (this.chartConfiguration.isXgridBetweenLabels) {
6937
- svg
6938
- .append('g')
6939
- .attr('class', 'grid')
6940
- .attr('transform', `translate(${xScale.bandwidth() / 2},${height})`)
6941
- .call(d3.axisBottom(xScale).tickSize(-height).tickFormat(''))
6942
- .style('stroke-dasharray', '5 5')
6943
- .style('color', '#999999')
6944
- .call((g) => g.select('.domain').remove());
6852
+ createScales(data, layers, lineData, dimensions, device) {
6853
+ const { width, height, barWidth, barPadding } = dimensions;
6854
+ const xScale = d3
6855
+ .scaleBand()
6856
+ .rangeRound([
6857
+ this.CONSTANTS.LEFT_RIGHT_SPACES,
6858
+ width - this.CONSTANTS.RIGHT_SVG_WIDTH - this.CONSTANTS.LEFT_RIGHT_SPACES
6859
+ ])
6860
+ .domain(data.map(d => d.name).reverse())
6861
+ .padding(device.isMobile ? 0.2 : 0.5);
6862
+ const xScaleFromOrigin = d3
6863
+ .scaleBand()
6864
+ .rangeRound([width - this.CONSTANTS.RIGHT_SVG_WIDTH, 0])
6865
+ .domain(data.map(d => d.name).reverse());
6866
+ const yScale = d3.scaleLinear().rangeRound([height, 0]);
6867
+ let maxValue = d3.max(layers, (d) => d3.max(d, (d) => d[1]));
6868
+ if (maxValue === 0) {
6869
+ maxValue = this.chartData.targetLineData
6870
+ ? Number(this.chartData.targetLineData.target) + 20
6871
+ : 100;
6945
6872
  }
6946
- if (this.chartConfiguration.yAxisGrid) {
6947
- svg
6948
- .append('g')
6949
- .attr('class', 'grid')
6950
- .call(d3
6951
- .axisLeft(yScale)
6952
- .ticks(this.chartConfiguration.numberOfYTicks)
6953
- .tickSize(-width)
6954
- .tickFormat(''))
6955
- .style('color', 'var(--chart-grid-color)')
6956
- .style('opacity', '1');
6873
+ if (this.chartConfiguration.customYscale) {
6874
+ maxValue *= this.chartConfiguration.customYscale;
6957
6875
  }
6958
- if (this.chartConfiguration.xAxisGrid) {
6959
- this.chartConfiguration.xAxisGrid.forEach((gridPos, index) => {
6960
- svg
6961
- .append('g')
6962
- .attr('class', `x${index + 2} axis${index + 2}`)
6963
- .style('color', 'var(--chart-grid-color)')
6964
- .attr('transform', `translate(0,${height * gridPos})`)
6965
- .call(d3.axisBottom(xScale).tickSize(0).ticks(5).tickFormat(''))
6966
- .style('fill', 'var(--chart-text-color)');
6967
- });
6876
+ if (this.chartData.targetLineData && maxValue < Number(this.chartData.targetLineData.target)) {
6877
+ const target = Number(this.chartData.targetLineData.target);
6878
+ maxValue = maxValue < 10 && target < 10 ? target + 3 : target + 20;
6879
+ }
6880
+ yScale.domain([0, maxValue]).nice();
6881
+ let lineYscale = null;
6882
+ if (lineData) {
6883
+ lineYscale = d3
6884
+ .scaleLinear()
6885
+ .domain([0, d3.max(lineData, d => +d.value)])
6886
+ .range([height, 0]);
6887
+ }
6888
+ return { xScale, xScaleFromOrigin, yScale, lineYscale };
6889
+ }
6890
+ createAxes(scales) {
6891
+ const xAxis = d3
6892
+ .axisBottom(scales.xScale)
6893
+ .tickSize(0)
6894
+ .tickFormat(this.chartConfiguration.xAxisLabelFomatter);
6895
+ const yAxis = d3
6896
+ .axisLeft(scales.yScale)
6897
+ .ticks(this.chartConfiguration.numberOfYTicks)
6898
+ .tickSize(0)
6899
+ .tickFormat(this.chartConfiguration.yAxisLabelFomatter);
6900
+ let yLineAxis = null;
6901
+ if (scales.lineYscale) {
6902
+ yLineAxis = d3
6903
+ .axisRight(scales.lineYscale)
6904
+ .ticks(this.chartConfiguration.numberOfYTicks)
6905
+ .tickSize(0)
6906
+ .tickFormat(this.chartConfiguration.yLineAxisLabelFomatter);
6968
6907
  }
6908
+ return { xAxis, yAxis, yLineAxis };
6969
6909
  }
6970
- renderBars(svg, layers, xScale, yScale, metaData, device, barWidth, barPadding, targetValue, formatFromBackend, formatForHugeNumbers) {
6910
+ renderBars(svg, layers, scales, metaData, dimensions, device) {
6971
6911
  const layer = svg
6972
6912
  .selectAll('.layer')
6973
6913
  .data(layers)
@@ -6975,7 +6915,17 @@ class HorizontalBarsWithScrollZoomComponent extends ComponentUniqueId {
6975
6915
  .append('g')
6976
6916
  .attr('class', 'layer')
6977
6917
  .style('fill', (d) => metaData.colors[d.key]);
6978
- const rect = layer.selectAll('rect').data((d) => d).enter();
6918
+ const rect = layer
6919
+ .selectAll('rect')
6920
+ .data((d) => d)
6921
+ .enter();
6922
+ this.appendRectangles(rect, scales, metaData, dimensions, device);
6923
+ this.addInteractions(rect, svg, metaData, scales);
6924
+ return rect;
6925
+ }
6926
+ appendRectangles(rect, scales, metaData, dimensions, device) {
6927
+ const { barWidth, barPadding } = dimensions;
6928
+ const { xScale, yScale } = scales;
6979
6929
  rect
6980
6930
  .append('rect')
6981
6931
  .on('click', (d) => {
@@ -6994,9 +6944,9 @@ class HorizontalBarsWithScrollZoomComponent extends ComponentUniqueId {
6994
6944
  })
6995
6945
  .attr('x', (d, i) => {
6996
6946
  if (device.isMobile) {
6997
- return this.SPACING.leftAndRight + i * (barWidth + barPadding);
6947
+ return this.CONSTANTS.LEFT_RIGHT_SPACES + i * (barWidth + barPadding);
6998
6948
  }
6999
- if (this.chartConfiguration.isMultiChartGridLine === undefined) {
6949
+ if (!this.chartConfiguration.isMultiChartGridLine) {
7000
6950
  return xScale(d.data.name);
7001
6951
  }
7002
6952
  if (this.chartConfiguration.isDrilldownChart && this.chartData.data.length <= 3) {
@@ -7014,99 +6964,307 @@ class HorizontalBarsWithScrollZoomComponent extends ComponentUniqueId {
7014
6964
  .attr('width', (d) => {
7015
6965
  if (device.isMobile)
7016
6966
  return barWidth;
7017
- if (this.chartConfiguration.isMultiChartGridLine === undefined) {
6967
+ if (!this.chartConfiguration.isMultiChartGridLine)
7018
6968
  return xScale.bandwidth();
6969
+ if (this.chartConfiguration.isDrilldownChart && this.chartData.data.length <= 3) {
6970
+ return 70;
7019
6971
  }
7020
- return this.chartConfiguration.isDrilldownChart && this.chartData.data.length <= 3
7021
- ? 70
7022
- : xScale.bandwidth() * 0.8;
6972
+ return xScale.bandwidth() * 0.8;
7023
6973
  })
7024
6974
  .style('cursor', (d) => {
7025
- if (!metaData.hasDrillDown)
7026
- return 'default';
7027
- if (metaData.barWithoutClick?.includes(d.data.name.toLowerCase())) {
7028
- return 'default';
6975
+ if (metaData.hasDrillDown) {
6976
+ if (metaData.barWithoutClick?.includes(d.data.name.toLowerCase())) {
6977
+ return 'default';
6978
+ }
6979
+ return 'pointer';
7029
6980
  }
7030
- return 'pointer';
6981
+ return 'default';
7031
6982
  })
7032
- .style('fill', (d) => this.getBarFillColor(d, d.key, metaData, targetValue || undefined));
7033
- // Add tooltips and labels
7034
- if (!this.isCC && !this.chartConfiguration.isMultiChartGridLine) {
7035
- rect.append('svg:title').text((d) => d[1] - d[0]);
6983
+ .style('fill', (d) => this.getBarColor(d, metaData));
6984
+ }
6985
+ getBarColor(d, metaData) {
6986
+ if (!isNaN(d[0]) &&
6987
+ !isNaN(d[1]) &&
6988
+ this.chartData.targetLineData &&
6989
+ parseFloat(d[1]) - parseFloat(d[0]) >= parseFloat(String(this.chartData.targetLineData.target))) {
6990
+ return this.chartData.targetLineData.barAboveTargetColor || metaData.colors[d.key];
7036
6991
  }
7037
- this.addBarLabels(rect, xScale, yScale, metaData, formatFromBackend, formatForHugeNumbers);
6992
+ return metaData.colors[d.key];
7038
6993
  }
7039
- addBarLabels(rect, xScale, yScale, metaData, formatFromBackend, formatForHugeNumbers) {
7040
- if (this.chartConfiguration.showTotalOnTop) {
7041
- rect
7042
- .append('text')
7043
- .attr('x', (d) => xScale(d.data.name) + xScale.bandwidth() / 2)
7044
- .attr('class', 'lib-verticalstack-labels-ontop-weklycharts')
7045
- .attr('y', (d) => yScale(d[1]) - 3)
7046
- .text((d) => {
7047
- if (!isNaN(d[1] - d[0]) && d[1] - d[0] !== 0) {
7048
- const value = d[1] - d[0];
7049
- const formatter = value <= 999 ? formatFromBackend : formatForHugeNumbers;
7050
- return metaData.unit ? metaData.unit + formatter(value) : formatter(value);
7051
- }
7052
- });
6994
+ addInteractions(rect, svg, metaData, scales) {
6995
+ rect
6996
+ .selectAll('rect')
6997
+ .on('mouseenter', (d) => this.handleMouseOver(d, svg, metaData, scales))
6998
+ .on('mouseout', (d) => this.handleMouseOut(svg, metaData));
6999
+ }
7000
+ handleMouseOver(d, svg, metaData, scales) {
7001
+ if (!this.chartConfiguration.displayTitleOnTop)
7002
+ return;
7003
+ svg.selectAll('rect')
7004
+ .filter((data) => data === d)
7005
+ .style('fill', (d) => this.getHoverColor(d, metaData));
7006
+ this.displayTooltip(d, svg, metaData, scales);
7007
+ }
7008
+ getHoverColor(d, metaData) {
7009
+ if (!isNaN(d[0]) &&
7010
+ !isNaN(d[1]) &&
7011
+ this.chartData.targetLineData &&
7012
+ parseFloat(d[1]) - parseFloat(d[0]) >= parseFloat(String(this.chartData.targetLineData.target))) {
7013
+ return this.chartData.targetLineData.barAboveTargetHoverColor ||
7014
+ this.chartData.targetLineData.barAboveTargetColor ||
7015
+ metaData.colors[d.key];
7053
7016
  }
7017
+ return metaData.hoverColor || metaData.colors[d.key];
7054
7018
  }
7055
- renderAxes(svg, svgYAxisLeft, svgYAxisRight, xScale, yScale, data, height, width, device) {
7056
- const xAxis = d3
7057
- .axisBottom(xScale)
7058
- .tickSize(0)
7059
- .tickFormat(this.chartConfiguration.xAxisLabelFomatter);
7060
- const yAxis = d3
7061
- .axisLeft(yScale)
7062
- .ticks(this.chartConfiguration.numberOfYTicks)
7063
- .tickSize(0)
7064
- .tickFormat(this.chartConfiguration.yAxisLabelFomatter);
7065
- // Render based on chart type
7066
- if (this.chartConfiguration.isMultiChartGridLine === undefined) {
7067
- this.renderStandardAxes(svg, xAxis, yAxis, data, height, device);
7019
+ displayTooltip(d, svg, metaData, scales) {
7020
+ const { xScale, yScale } = scales;
7021
+ const value = d[1] - d[0];
7022
+ if (isNaN(value))
7023
+ return;
7024
+ const width = /week/i.test(d.data.name) && /\d{4}-\d{2}-\d{2}/.test(d.data.name)
7025
+ ? '250px'
7026
+ : xScale.bandwidth() + this.CONSTANTS.LEFT_RIGHT_SPACES * 2 > 180
7027
+ ? '180px'
7028
+ : xScale.bandwidth() + this.CONSTANTS.LEFT_RIGHT_SPACES * 2;
7029
+ svg
7030
+ .append('foreignObject')
7031
+ .attr('x', this.calculateTooltipX(d, xScale, width))
7032
+ .attr('class', 'lib-verticalstack-title-ontop')
7033
+ .attr('y', yScale(d[1]) - 51)
7034
+ .attr('width', width)
7035
+ .attr('height', 40)
7036
+ .append('xhtml:div')
7037
+ .attr('class', 'title')
7038
+ .style('z-index', 99)
7039
+ .html(this.generateTooltipHtml(d, metaData, value));
7040
+ }
7041
+ calculateTooltipX(d, xScale, width) {
7042
+ const bandwidth = xScale.bandwidth();
7043
+ const numericWidth = typeof width === 'string' ? parseInt(width) : width;
7044
+ if (bandwidth + this.CONSTANTS.LEFT_RIGHT_SPACES * 2 > 180) {
7045
+ return xScale(d.data.name) - this.CONSTANTS.LEFT_RIGHT_SPACES +
7046
+ (bandwidth + this.CONSTANTS.LEFT_RIGHT_SPACES * 2 - 180) / 2;
7047
+ }
7048
+ return xScale(d.data.name) - this.CONSTANTS.LEFT_RIGHT_SPACES;
7049
+ }
7050
+ generateTooltipHtml(d, metaData, value) {
7051
+ if (value === 0)
7052
+ return '<span class="title-top-text">0</span>';
7053
+ const dataType = metaData.dataType || '';
7054
+ const name = d.data.name ? `<span class="title-bar-name">${d.data.name}</span>` : '';
7055
+ const valueText = metaData.unit
7056
+ ? `${metaData.unit}${value} ${dataType}`
7057
+ : `${value} ${dataType}`;
7058
+ return `${name}<span class="title-top-text">${valueText}</span>`;
7059
+ }
7060
+ handleMouseOut(svg, metaData) {
7061
+ if (!this.chartConfiguration.displayTitleOnTop)
7062
+ return;
7063
+ svg.selectAll('rect')
7064
+ .style('fill', (d) => this.getBarColor(d, metaData));
7065
+ svg.selectAll('.lib-verticalstack-title-ontop').remove();
7066
+ }
7067
+ renderAxisLabels(svg, svgYAxisLeft, metaData, dimensions, margin) {
7068
+ if (metaData.yLabel) {
7069
+ this.addYAxisLabel(svgYAxisLeft, metaData.yLabel, dimensions.height, margin);
7070
+ }
7071
+ if (metaData.xLabel) {
7072
+ this.addXAxisLabel(svg, metaData.xLabel, dimensions.width, dimensions.height, margin);
7073
+ }
7074
+ }
7075
+ addYAxisLabel(svgYAxisLeft, label, height, margin) {
7076
+ const isria = this.customChartConfiguration?.isRia;
7077
+ const isAcronym = this.isAcronymLabel(label);
7078
+ const yPosition = isria ? -margin.left / 2 - 30 : -margin.left / 2 - 40;
7079
+ svgYAxisLeft.selectAll('.lib-axis-group-label, .lib-ylabel-drilldowncharts, .lib-ylabel-weeklyCharts').remove();
7080
+ svgYAxisLeft
7081
+ .append('text')
7082
+ .attr('class', this.getYAxisLabelClass())
7083
+ .attr('style', this.chartConfiguration.yAxisCustomlabelStyles)
7084
+ .attr('transform', 'rotate(-90)')
7085
+ .attr('y', yPosition)
7086
+ .attr('x', -height / 2)
7087
+ .attr('dy', '1em')
7088
+ .style('text-anchor', 'middle')
7089
+ .style('fill', 'var(--chart-text-color)')
7090
+ .text(isAcronym ? label.toUpperCase() : label.toLowerCase())
7091
+ .style('text-transform', isAcronym ? 'none' : 'capitalize');
7092
+ }
7093
+ addXAxisLabel(svg, label, width, height, margin) {
7094
+ const isria = this.customChartConfiguration?.isRia;
7095
+ const isAcronym = this.isAcronymLabel(label);
7096
+ const xPosition = isria
7097
+ ? height + margin.top + margin.bottom
7098
+ : height + margin.top + margin.bottom + 10;
7099
+ svg
7100
+ .append('text')
7101
+ .attr('class', this.getXAxisLabelClass())
7102
+ .attr('style', this.chartConfiguration.xAxisCustomlabelStyles)
7103
+ .attr('transform', `translate(${width / 2},${xPosition})`)
7104
+ .style('text-anchor', 'middle')
7105
+ .style('fill', 'var(--chart-text-color)')
7106
+ .text(isAcronym ? label.toUpperCase() : label.toLowerCase())
7107
+ .style('text-transform', isAcronym ? 'none' : 'capitalize');
7108
+ }
7109
+ isAcronymLabel(label) {
7110
+ const cleanLabel = label.replace(/[^A-Za-z]/g, '');
7111
+ return (label.length <= 4 && /^[A-Z]+$/.test(label)) ||
7112
+ (label === label.toUpperCase() && /[A-Z]/.test(label));
7113
+ }
7114
+ getYAxisLabelClass() {
7115
+ let baseClass = 'lib-axis-group-label font-size-1';
7116
+ if (this.chartConfiguration.isDrilldownChart) {
7117
+ return `${baseClass} lib-ylabel-drilldowncharts`;
7118
+ }
7119
+ if (this.chartConfiguration.isMultiChartGridLine !== undefined) {
7120
+ return `${baseClass} lib-ylabel-weeklyCharts`;
7121
+ }
7122
+ return `${baseClass} lib-axis-waterfall-label`;
7123
+ }
7124
+ getXAxisLabelClass() {
7125
+ let baseClass = 'lib-axis-group-label font-size-1';
7126
+ if (this.chartConfiguration.isDrilldownChart) {
7127
+ return `${baseClass} lib-xlabel-drilldowncharts`;
7128
+ }
7129
+ if (this.chartConfiguration.isMultiChartGridLine !== undefined) {
7130
+ return `${baseClass} lib-xlabel-weeklyCharts`;
7131
+ }
7132
+ return `${baseClass} lib-axis-waterfall-label`;
7133
+ }
7134
+ applyConfigurationFlags() {
7135
+ if (this.chartConfiguration.isHeaderVisible !== undefined) {
7136
+ this.isHeaderVisible = this.chartConfiguration.isHeaderVisible;
7137
+ }
7138
+ if (this.chartConfiguration.isTopCaptionVisible !== undefined) {
7139
+ this.isTopCaptionVisible = this.chartConfiguration.isTopCaptionVisible;
7140
+ }
7141
+ if (this.chartConfiguration.isTransparentBackground !== undefined) {
7142
+ this.isTransparentBackground = this.chartConfiguration.isTransparentBackground;
7143
+ }
7144
+ }
7145
+ initializeStackedChart() {
7146
+ const device = this.getDeviceConfig();
7147
+ this.configureResponsiveSettings(device);
7148
+ this.mergeConfigurations();
7149
+ this.applyConfigurationFlags();
7150
+ const data = this.chartData.data;
7151
+ const metaData = this.prepareMetaData(this.chartData.metaData);
7152
+ const lineData = this.chartData.lineData;
7153
+ const colors = metaData.colors;
7154
+ const keyList = metaData.keyList;
7155
+ const chartContainer = d3.select(this.containerElt.nativeElement);
7156
+ const verticalstackedcontainer = d3.select(this.verticalstackedcontainerElt.nativeElement);
7157
+ const margin = this.chartConfiguration.margin;
7158
+ const dimensions = this.calculateDimensions(chartContainer, verticalstackedcontainer, margin, device, data.length);
7159
+ const { svg, svgYAxisLeft, svgYAxisRight } = this.createSvgContainers(chartContainer, dimensions, margin);
7160
+ // Create stack and layers
7161
+ const stack = d3.stack().keys(keyList).offset(d3.stackOffsetNone);
7162
+ const layers = stack(data);
7163
+ data.sort((a, b) => b.total - a.total);
7164
+ const scales = this.createScales(data, layers, lineData, dimensions, device);
7165
+ const axes = this.createAxes(scales);
7166
+ // Render chart elements
7167
+ this.renderGrids(svg, scales, dimensions);
7168
+ const rect = this.renderBars(svg, layers, scales, metaData, dimensions, device);
7169
+ this.renderAxes(svg, svgYAxisLeft, svgYAxisRight, axes, scales, dimensions, device, data);
7170
+ this.renderAxisLabels(svg, svgYAxisLeft, metaData, dimensions, margin);
7171
+ this.renderTargetLine(svg, svgYAxisRight, scales, dimensions, metaData);
7172
+ this.renderDataLabels(rect, scales, metaData, dimensions);
7173
+ this.renderLineChart(svg, lineData, scales, colors, metaData);
7174
+ }
7175
+ renderGrids(svg, scales, dimensions) {
7176
+ if (this.chartConfiguration.isXgridBetweenLabels) {
7177
+ svg
7178
+ .append('g')
7179
+ .attr('class', 'grid')
7180
+ .attr('transform', `translate(${scales.xScale.bandwidth() / 2},${dimensions.height})`)
7181
+ .call(d3.axisBottom(scales.xScale).tickSize(-dimensions.height).tickFormat(''))
7182
+ .style('stroke-dasharray', '5 5')
7183
+ .style('color', '#999999')
7184
+ .call((g) => g.select('.domain').remove());
7185
+ }
7186
+ if (this.chartConfiguration.yAxisGrid) {
7187
+ svg
7188
+ .append('g')
7189
+ .attr('class', 'grid')
7190
+ .call(d3
7191
+ .axisLeft(scales.yScale)
7192
+ .ticks(this.chartConfiguration.numberOfYTicks)
7193
+ .tickSize(-dimensions.width)
7194
+ .tickFormat(''))
7195
+ .style('color', 'var(--chart-grid-color)')
7196
+ .style('opacity', '1');
7197
+ }
7198
+ if (this.chartConfiguration.xAxisGrid) {
7199
+ for (let j = 0; j < this.chartConfiguration.xAxisGrid.length; j++) {
7200
+ svg
7201
+ .append('g')
7202
+ .attr('class', `x${j + 2} axis${j + 2}`)
7203
+ .style('color', 'var(--chart-grid-color)')
7204
+ .attr('transform', `translate(0,${dimensions.height * this.chartConfiguration.xAxisGrid[j]})`)
7205
+ .call(d3.axisBottom(scales.xScale).tickSize(0).ticks(5).tickFormat(''))
7206
+ .style('fill', 'var(--chart-text-color)');
7207
+ }
7208
+ }
7209
+ }
7210
+ renderAxes(svg, svgYAxisLeft, svgYAxisRight, axes, scales, dimensions, device, data) {
7211
+ if (this.chartConfiguration.showXaxisTop) {
7212
+ svg
7213
+ .append('g')
7214
+ .attr('class', 'lib-line-axis-text lib-line-x-axis-text x-axis')
7215
+ .attr('style', this.chartConfiguration.xAxisCustomTextStyles)
7216
+ .call(d3.axisBottom(scales.xScale).tickSize(0));
7217
+ svg.selectAll('.x-axis > g > text').attr('class', 'lib-display-hidden');
7218
+ }
7219
+ if (!this.chartConfiguration.isMultiChartGridLine) {
7220
+ this.renderStandardAxes(svg, axes, scales, dimensions, device, data);
7068
7221
  }
7069
7222
  else if (this.chartConfiguration.isDrilldownChart) {
7070
- this.renderDrilldownAxes(svg, svgYAxisLeft, svgYAxisRight, xAxis, yAxis, height);
7223
+ this.renderDrilldownAxes(svg, svgYAxisLeft, svgYAxisRight, axes, scales, dimensions);
7071
7224
  }
7072
7225
  else {
7073
- this.renderMultiChartAxes(svg, xAxis, yAxis, height);
7226
+ this.renderMultiChartAxes(svg, axes, scales, dimensions);
7074
7227
  }
7075
- this.styleAxisDomains(svg, svgYAxisLeft, svgYAxisRight);
7228
+ this.applyAxisStyling(svg, svgYAxisLeft, svgYAxisRight);
7229
+ this.applyAxisConfigurations(svg, scales, dimensions, data);
7076
7230
  }
7077
- renderStandardAxes(svg, xAxis, yAxis, data, height, device) {
7231
+ renderStandardAxes(svg, axes, scales, dimensions, device, data) {
7078
7232
  if (device.isMobile) {
7079
- this.renderMobileXAxis(svg, data, height, device);
7233
+ this.renderMobileXAxis(svg, data, dimensions);
7080
7234
  }
7081
7235
  else {
7082
7236
  svg
7083
7237
  .append('g')
7084
- .attr('transform', `translate(0,${height})`)
7238
+ .attr('transform', `translate(0,${dimensions.height})`)
7085
7239
  .attr('class', 'lib-stacked-x-axis-text')
7086
- .call(xAxis)
7240
+ .call(axes.xAxis)
7087
7241
  .selectAll('text')
7088
7242
  .style('fill', 'var(--chart-text-color)')
7089
7243
  .style('font-size', '12px')
7090
- .attr('text-anchor', 'middle');
7244
+ .attr('text-anchor', 'middle')
7245
+ .attr('dx', '0')
7246
+ .attr('dy', '0.71em')
7247
+ .attr('transform', null);
7091
7248
  }
7092
7249
  svg
7093
7250
  .append('g')
7094
7251
  .attr('class', 'lib-stacked-y-axis-text')
7095
- .call(yAxis)
7252
+ .attr('style', this.chartConfiguration.yAxisCustomTextStyles)
7253
+ .call(axes.yAxis)
7096
7254
  .selectAll('text')
7097
7255
  .style('fill', 'var(--chart-text-color)');
7098
7256
  }
7099
- renderMobileXAxis(svg, data, height, device) {
7100
- const barWidth = 32;
7101
- const barPadding = 12;
7257
+ renderMobileXAxis(svg, data, dimensions) {
7102
7258
  svg.selectAll('.custom-x-label').remove();
7103
7259
  data.forEach((d, i) => {
7104
- const xVal = this.SPACING.leftAndRight + i * (barWidth + barPadding) + barWidth / 2;
7260
+ const xVal = this.CONSTANTS.LEFT_RIGHT_SPACES +
7261
+ i * (dimensions.barWidth + dimensions.barPadding) +
7262
+ dimensions.barWidth / 2;
7105
7263
  svg
7106
7264
  .append('text')
7107
7265
  .attr('class', 'custom-x-label')
7108
7266
  .attr('x', 0)
7109
- .attr('y', height + 18)
7267
+ .attr('y', dimensions.height + 18)
7110
7268
  .attr('text-anchor', 'middle')
7111
7269
  .attr('transform', `translate(${xVal + 20},0)`)
7112
7270
  .style('font-size', '10px')
@@ -7115,204 +7273,350 @@ class HorizontalBarsWithScrollZoomComponent extends ComponentUniqueId {
7115
7273
  .text(d.name.substring(0, 3));
7116
7274
  });
7117
7275
  }
7118
- renderDrilldownAxes(svg, svgYAxisLeft, svgYAxisRight, xAxis, yAxis, height) {
7276
+ renderDrilldownAxes(svg, svgYAxisLeft, svgYAxisRight, axes, scales, dimensions) {
7119
7277
  svg
7120
7278
  .append('g')
7121
- .attr('transform', `translate(0,${height})`)
7279
+ .attr('transform', `translate(0,${dimensions.height})`)
7122
7280
  .attr('class', 'lib-stacked-x-axis-text multichart1')
7123
- .call(xAxis)
7281
+ .call(axes.xAxis)
7124
7282
  .style('display', 'none');
7125
7283
  svgYAxisLeft
7126
7284
  .append('g')
7127
7285
  .attr('class', 'lib-yaxis-labels-texts-drilldown yaxis-dashed')
7128
- .call(yAxis)
7286
+ .attr('style', this.chartConfiguration.yAxisCustomTextStyles)
7287
+ .call(axes.yAxis)
7129
7288
  .selectAll('text')
7130
7289
  .style('fill', 'var(--chart-text-color)');
7131
7290
  svgYAxisRight
7132
7291
  .append('g')
7133
7292
  .attr('class', 'lib-yaxis-labels-texts-drilldown yaxis-dashed')
7134
- .call(yAxis)
7293
+ .attr('style', this.chartConfiguration.yAxisCustomTextStyles)
7294
+ .call(axes.yAxis)
7135
7295
  .style('display', 'none');
7136
7296
  }
7137
- renderMultiChartAxes(svg, xAxis, yAxis, height) {
7297
+ renderMultiChartAxes(svg, axes, scales, dimensions) {
7138
7298
  svg
7139
7299
  .append('g')
7140
- .attr('transform', `translate(0,${height})`)
7300
+ .attr('transform', `translate(0,${dimensions.height})`)
7141
7301
  .attr('class', 'lib-stacked-x-axis-text multichart')
7142
- .call(xAxis)
7302
+ .call(axes.xAxis)
7143
7303
  .selectAll('text')
7144
7304
  .style('fill', 'var(--chart-text-color)');
7145
7305
  svg
7146
7306
  .append('g')
7147
7307
  .attr('class', 'lib-stacked-y-axis-text yaxis-dashed')
7148
- .call(yAxis)
7308
+ .attr('style', this.chartConfiguration.yAxisCustomTextStyles)
7309
+ .call(axes.yAxis)
7149
7310
  .selectAll('text')
7150
7311
  .style('fill', 'var(--chart-text-color)');
7151
7312
  }
7152
- styleAxisDomains(svg, svgYAxisLeft, svgYAxisRight) {
7153
- const axisStyle = {
7154
- stroke: 'var(--chart-axis-color)',
7155
- 'stroke-width': '1px'
7313
+ applyAxisStyling(svg, svgYAxisLeft, svgYAxisRight) {
7314
+ const styleAxisDomain = (container) => {
7315
+ container.selectAll('.domain')
7316
+ .style('stroke', 'var(--chart-axis-color)')
7317
+ .style('stroke-width', '1px');
7156
7318
  };
7157
- [svg, svgYAxisLeft, svgYAxisRight].forEach(element => {
7158
- element.selectAll('.domain')
7159
- .style('stroke', axisStyle.stroke)
7160
- .style('stroke-width', axisStyle['stroke-width']);
7161
- });
7162
- }
7163
- renderLabels(svg, svgYAxisLeft, metaData, height, width, margin) {
7164
- if (metaData.yLabel) {
7165
- this.renderYAxisLabel(svgYAxisLeft, metaData.yLabel, height, margin);
7319
+ styleAxisDomain(svg);
7320
+ styleAxisDomain(svgYAxisLeft);
7321
+ styleAxisDomain(svgYAxisRight);
7322
+ if (this.chartConfiguration.isYaxisDashed) {
7323
+ d3.selectAll('.yaxis-dashed')
7324
+ .style('stroke-dasharray', '5 5')
7325
+ .style('color', 'var(--chart-grid-color)');
7166
7326
  }
7167
- if (metaData.xLabel) {
7168
- this.renderXAxisLabel(svg, metaData.xLabel, height, width, margin);
7327
+ if (this.chartConfiguration.isXaxisColor) {
7328
+ d3.selectAll('.multichart').style('color', this.chartConfiguration.isXaxisColor || 'var(--chart-text-color)');
7169
7329
  }
7170
7330
  }
7171
- renderYAxisLabel(svgYAxisLeft, yLabel, height, margin) {
7172
- svgYAxisLeft.selectAll('.lib-axis-group-label, .lib-ylabel-drilldowncharts, .lib-ylabel-weeklyCharts').remove();
7173
- const { formatted, isAcronym } = this.formatAxisLabel(yLabel);
7174
- const isRia = this.customChartConfiguration?.isRia;
7175
- const yPosition = isRia ? -margin.left / 2 - 30 : -margin.left / 2 - 40;
7176
- let labelClass = 'lib-axis-group-label font-size-1';
7177
- if (this.chartConfiguration.isDrilldownChart) {
7178
- labelClass += ' lib-ylabel-drilldowncharts';
7331
+ applyAxisConfigurations(svg, scales, dimensions, data) {
7332
+ if (this.chartConfiguration.isMultiChartGridLine !== undefined) {
7333
+ d3.selectAll('.multichart > g > text').attr('class', 'lib-display-hidden');
7179
7334
  }
7180
- else if (this.chartConfiguration.isMultiChartGridLine !== undefined) {
7181
- labelClass += ' lib-ylabel-weeklyCharts';
7335
+ if (this.chartConfiguration.isXaxisLabelHidden) {
7336
+ d3.selectAll('.multichart > g > text').attr('class', 'lib-display-hidden');
7182
7337
  }
7183
- else {
7184
- labelClass += ' lib-axis-waterfall-label';
7338
+ else if (this.chartConfiguration.isXaxisLabelHidden !== undefined) {
7339
+ this.renderCustomXAxis(svg, scales, dimensions, data);
7185
7340
  }
7186
- svgYAxisLeft
7341
+ if (this.chartConfiguration.isYaxisLabelHidden) {
7342
+ svg.selectAll('.yaxis-dashed > g > text').attr('class', 'lib-display-hidden');
7343
+ }
7344
+ if (this.chartConfiguration.isYaxisHidden) {
7345
+ d3.selectAll('.yaxis-dashed').attr('class', 'lib-display-hidden');
7346
+ }
7347
+ if (this.isZoomedOut && data.length > 9) {
7348
+ svg
7349
+ .selectAll('.lib-xaxis-labels-texts-drilldown')
7350
+ .attr('transform', 'rotate(-90)')
7351
+ .attr('text-anchor', 'end')
7352
+ .attr('x', '-5')
7353
+ .attr('dy', null);
7354
+ }
7355
+ }
7356
+ renderCustomXAxis(svg, scales, dimensions, data) {
7357
+ const device = this.getDeviceConfig();
7358
+ svg
7359
+ .append('g')
7360
+ .attr('class', 'x1 axis1')
7361
+ .attr('transform', `translate(0,${dimensions.height})`)
7362
+ .style('color', '#000')
7363
+ .call(d3.axisBottom(scales.xScale).tickSize(0))
7364
+ .call((g) => g.select('.domain').attr('fill', 'none'));
7365
+ this.styleCustomXAxisTicks(svg, data, device);
7366
+ if (this.chartConfiguration.xLabelsOnSameLine) {
7367
+ this.applyXLabelsOnSameLine(svg, device);
7368
+ }
7369
+ }
7370
+ styleCustomXAxisTicks(svg, data, device) {
7371
+ let alternateText = false;
7372
+ svg.selectAll('.x1.axis1 .tick line').attr('y2', () => {
7373
+ if (this.chartConfiguration.hideXaxisTick)
7374
+ return 0;
7375
+ if (alternateText && !this.chartConfiguration.isNoAlternateXaxisText) {
7376
+ alternateText = false;
7377
+ return this.CONSTANTS.LONG_TICK_LENGTH_BG - 7;
7378
+ }
7379
+ alternateText = true;
7380
+ return this.CONSTANTS.SHORT_TICK_LENGTH_BG - 4;
7381
+ });
7382
+ alternateText = false;
7383
+ svg
7384
+ .selectAll('g.x1.axis1 g.tick text')
7385
+ .attr('class', () => {
7386
+ if (this.chartConfiguration.isDrilldownChart) {
7387
+ return data.length > 8
7388
+ ? 'lib-xaxis-labels-texts-drilldown-alt'
7389
+ : 'lib-xaxis-labels-texts-drilldown';
7390
+ }
7391
+ return 'lib-xaxis-labels-texts-weeklycharts';
7392
+ })
7393
+ .attr('y', () => {
7394
+ if (alternateText) {
7395
+ alternateText = false;
7396
+ return this.CONSTANTS.LONG_TICK_LENGTH_BG;
7397
+ }
7398
+ alternateText = true;
7399
+ return this.CONSTANTS.SHORT_TICK_LENGTH_BG;
7400
+ });
7401
+ }
7402
+ applyXLabelsOnSameLine(svg, device) {
7403
+ svg
7404
+ .selectAll('g.x1.axis1 g.tick text')
7405
+ .attr('class', 'lib-xaxis-labels-texts-drilldown')
7406
+ .attr('y', this.CONSTANTS.SHORT_TICK_LENGTH_BG)
7407
+ .text((d) => {
7408
+ if (device.isMobile) {
7409
+ return d.split(' ')[0].substring(0, 3);
7410
+ }
7411
+ const trimmed = d.trim();
7412
+ const spaceIndex = trimmed.indexOf(' ');
7413
+ return spaceIndex > -1
7414
+ ? trimmed.substring(0, spaceIndex).toLowerCase()
7415
+ : trimmed.toLowerCase();
7416
+ })
7417
+ .attr('transform', function (d, i) {
7418
+ if (device.isMobile) {
7419
+ const parent = this.parentNode?.parentNode;
7420
+ const totalBars = parent ? d3.select(parent).selectAll('g.tick').size() : 0;
7421
+ return totalBars === 2 ? 'translate(0,0)' : `translate(${i * 30},0)`;
7422
+ }
7423
+ return null;
7424
+ });
7425
+ svg
7426
+ .selectAll('g.x1.axis1 g.tick')
7187
7427
  .append('text')
7188
- .attr('class', labelClass)
7189
- .attr('style', this.chartConfiguration.yAxisCustomlabelStyles)
7190
- .attr('transform', 'rotate(-90)')
7191
- .attr('y', yPosition)
7192
- .attr('x', -height / 2)
7193
- .attr('dy', '1em')
7194
- .style('text-anchor', 'middle')
7195
- .style('fill', 'var(--chart-text-color)')
7196
- .text(formatted)
7197
- .style('text-transform', isAcronym ? 'none' : 'capitalize');
7428
+ .attr('class', 'lib-xaxis-labels-texts-drilldown')
7429
+ .attr('y', this.CONSTANTS.LONG_TICK_LENGTH_BG)
7430
+ .attr('fill', 'currentColor')
7431
+ .text((d) => {
7432
+ if (device.isMobile)
7433
+ return '';
7434
+ const trimmed = d.trim();
7435
+ const spaceIndex = trimmed.indexOf(' ');
7436
+ return spaceIndex > -1
7437
+ ? trimmed.substring(spaceIndex).toLowerCase()
7438
+ : '';
7439
+ })
7440
+ .attr('transform', (d, i) => {
7441
+ return device.isMobile && i === 0 ? 'translate(20,0)' : null;
7442
+ });
7198
7443
  }
7199
- renderXAxisLabel(svg, xLabel, height, width, margin) {
7200
- const { formatted, isAcronym } = this.formatAxisLabel(xLabel);
7201
- const isRia = this.customChartConfiguration?.isRia;
7202
- const xPosition = isRia
7203
- ? height + margin.top + margin.bottom
7204
- : height + margin.top + margin.bottom + 10;
7205
- let labelClass = 'lib-axis-group-label font-size-1';
7206
- if (this.chartConfiguration.isDrilldownChart) {
7207
- labelClass += ' lib-xlabel-drilldowncharts';
7444
+ renderDataLabels(rect, scales, metaData, dimensions) {
7445
+ if (!this.isCC && !this.chartConfiguration.isMultiChartGridLine) {
7446
+ rect.append('svg:title').text((d) => d[1] - d[0]);
7208
7447
  }
7209
- else if (this.chartConfiguration.isMultiChartGridLine !== undefined) {
7210
- labelClass += ' lib-xlabel-weeklyCharts';
7448
+ if (this.chartConfiguration.showTotalOnTop) {
7449
+ this.renderTopLabels(rect, scales, metaData);
7211
7450
  }
7212
- else {
7213
- labelClass += ' lib-axis-waterfall-label';
7451
+ if (this.chartConfiguration.showAngledLabels) {
7452
+ this.renderAngledLabels(rect, scales, metaData);
7214
7453
  }
7215
- svg
7454
+ }
7455
+ renderTopLabels(rect, scales, metaData) {
7456
+ const formatFromBackend = this.chartConfiguration.textFormatter
7457
+ ? ChartHelper.dataValueFormatter(this.chartConfiguration.textFormatter)
7458
+ : (d) => d;
7459
+ const formatForHugeNumbers = ChartHelper.dataValueFormatter('.2s');
7460
+ rect
7216
7461
  .append('text')
7217
- .attr('class', labelClass)
7218
- .attr('style', this.chartConfiguration.xAxisCustomlabelStyles)
7219
- .attr('transform', `translate(${width / 2},${xPosition})`)
7220
- .style('text-anchor', 'middle')
7221
- .style('fill', 'var(--chart-text-color)')
7222
- .text(formatted)
7223
- .style('text-transform', isAcronym ? 'none' : 'capitalize');
7462
+ .attr('x', (d) => scales.xScale(d.data.name) + scales.xScale.bandwidth() / 2)
7463
+ .attr('class', 'lib-verticalstack-labels-ontop-weklycharts')
7464
+ .attr('y', (d) => scales.yScale(d[1]) - 3)
7465
+ .text((d) => {
7466
+ const value = d[1] - d[0];
7467
+ if (isNaN(value) || value === 0)
7468
+ return;
7469
+ const formattedValue = value <= 999
7470
+ ? formatFromBackend(value)
7471
+ : formatForHugeNumbers(value);
7472
+ return metaData.unit ? metaData.unit + formattedValue : formattedValue;
7473
+ });
7224
7474
  }
7225
- renderTargetLine(svg, svgYAxisRight, yScale, width, targetValue, metaData) {
7226
- const yZero = yScale(targetValue);
7227
- // Draw target line
7475
+ renderAngledLabels(rect, scales, metaData) {
7476
+ const formatFromBackend = this.chartConfiguration.textFormatter
7477
+ ? ChartHelper.dataValueFormatter(this.chartConfiguration.textFormatter)
7478
+ : (d) => d;
7479
+ const formatForHugeNumbers = ChartHelper.dataValueFormatter('.2s');
7480
+ const tempObjectHolder = {};
7481
+ rect
7482
+ .append('text')
7483
+ .attr('x', 0)
7484
+ .attr('y', 0)
7485
+ .attr('fill', (d) => metaData.colors[d.key])
7486
+ .attr('class', 'lib-data-labels-angled-weeklycharts')
7487
+ .text((d) => {
7488
+ const value = d[1] - d[0];
7489
+ if (isNaN(value) || value <= 0)
7490
+ return;
7491
+ const formattedValue = value <= 999
7492
+ ? formatFromBackend(value)
7493
+ : formatForHugeNumbers(value);
7494
+ return metaData.unit ? metaData.unit + formattedValue : formattedValue;
7495
+ })
7496
+ .attr('transform', (d) => {
7497
+ const value = d[1] - d[0];
7498
+ if (isNaN(value) || value <= 0)
7499
+ return 'rotate(0)';
7500
+ let total = 0;
7501
+ let incrementer = 1;
7502
+ metaData.keyList.forEach(key => {
7503
+ if (d.data[key]) {
7504
+ total += d.data[key];
7505
+ }
7506
+ else {
7507
+ incrementer = 2;
7508
+ }
7509
+ });
7510
+ tempObjectHolder[d.data.name] = (tempObjectHolder[d.data.name] || 0) + incrementer;
7511
+ const position = tempObjectHolder[d.data.name];
7512
+ const xPos = scales.xScale(d.data.name);
7513
+ const bandwidth = scales.xScale.bandwidth();
7514
+ const yPos = scales.yScale(total) - 3;
7515
+ switch (position) {
7516
+ case 1:
7517
+ return `translate(${xPos + bandwidth / 3},${yPos}) rotate(270)`;
7518
+ case 2:
7519
+ return `translate(${xPos + bandwidth / 2 + 2},${yPos}) rotate(270)`;
7520
+ default:
7521
+ return `translate(${xPos + (bandwidth * 3) / 4},${yPos}) rotate(270)`;
7522
+ }
7523
+ });
7524
+ }
7525
+ renderTargetLine(svg, svgYAxisRight, scales, dimensions, metaData) {
7526
+ if (!this.chartData.targetLineData)
7527
+ return;
7528
+ const parsedTarget = this.parseTargetValue(this.chartData.targetLineData.target);
7529
+ const yZero = scales.yScale(parsedTarget);
7228
7530
  svg
7229
7531
  .append('line')
7230
7532
  .attr('x1', 0)
7231
- .attr('x2', width)
7533
+ .attr('x2', dimensions.width)
7232
7534
  .attr('y1', yZero)
7233
7535
  .attr('y2', yZero)
7234
7536
  .style('stroke-dasharray', '5 5')
7235
7537
  .style('stroke', this.chartData.targetLineData.color);
7236
- // Add target label
7237
- const targetLineName = this.chartData.targetLineData?.targetName || 'target';
7538
+ this.renderTargetLabel(svgYAxisRight, yZero, metaData);
7539
+ }
7540
+ parseTargetValue(target) {
7541
+ const parsed = parseFloat(String(target));
7542
+ if (isNaN(parsed))
7543
+ return 0;
7544
+ return Number.isInteger(parsed) ? parseInt(String(target)) : parsed;
7545
+ }
7546
+ renderTargetLabel(svgYAxisRight, yZero, metaData) {
7238
7547
  const dataType = metaData.dataType || '';
7548
+ const targetName = this.chartData.targetLineData.targetName || 'target';
7239
7549
  svgYAxisRight
7240
7550
  .append('foreignObject')
7241
7551
  .attr('transform', `translate(0,${yZero - 13})`)
7242
- .attr('width', this.SPACING.rightSvgWidth)
7552
+ .attr('width', this.CONSTANTS.RIGHT_SVG_WIDTH)
7243
7553
  .attr('height', 50)
7244
7554
  .append('xhtml:div')
7245
7555
  .attr('class', 'target-display')
7246
7556
  .style('color', 'var(--chart-text-color)')
7247
- .html(`
7248
- <div>${targetLineName}</div>
7249
- <div>${targetValue}${dataType}</div>
7250
- `);
7557
+ .html(`<div>${targetName}</div><div>${this.chartData.targetLineData.target}${dataType}</div>`);
7251
7558
  }
7252
- renderLineChart(svg, lineData, xScale, height, colors) {
7253
- const lineYscale = d3
7254
- .scaleLinear()
7255
- .domain([0, d3.max(lineData, (d) => +d.value) || 0])
7256
- .range([height, 0]);
7559
+ renderLineChart(svg, lineData, scales, colors, metaData) {
7560
+ if (!lineData || !colors)
7561
+ return;
7257
7562
  const dataGroup = d3
7258
7563
  .nest()
7259
7564
  .key((d) => d.category)
7260
7565
  .entries(lineData);
7261
7566
  const lineGen = d3
7262
7567
  .line()
7263
- .x((d) => xScale(d.name) + xScale.bandwidth() / 2)
7264
- .y((d) => lineYscale(d.value));
7568
+ .x((d) => scales.xScale(d.name) + scales.xScale.bandwidth() / 2)
7569
+ .y((d) => scales.lineYscale(d.value));
7265
7570
  dataGroup.forEach((group) => {
7266
- // Draw line
7267
7571
  svg
7268
7572
  .append('path')
7269
7573
  .datum(group.values)
7270
7574
  .attr('fill', 'none')
7271
7575
  .attr('stroke', (d) => {
7272
- if (d[0] && 'category' in d[0]) {
7273
- return colors[d[0].category];
7274
- }
7275
- return this.chartConfiguration.lineGraphColor;
7576
+ return d[0]?.category
7577
+ ? colors[d[0].category]
7578
+ : this.chartConfiguration.lineGraphColor;
7276
7579
  })
7277
7580
  .attr('stroke-width', 2.5)
7278
- .attr('d', lineGen(group.values));
7279
- // Draw dots
7280
- const dot = svg
7281
- .selectAll('myCircles')
7282
- .data(group.values)
7283
- .enter()
7284
- .append('g')
7285
- .on('click', (d) => this.handleClick(d));
7286
- dot
7287
- .append('circle')
7288
- .attr('fill', (d) => {
7289
- if ('category' in d) {
7290
- return colors[d.category];
7291
- }
7292
- return this.chartConfiguration.lineGraphColor;
7293
- })
7294
- .attr('stroke', 'none')
7295
- .attr('cx', (d) => xScale(d.name) + xScale.bandwidth() / 2)
7296
- .attr('cy', (d) => lineYscale(d.value))
7297
- .attr('r', 3)
7298
- .style('cursor', 'pointer');
7299
- // Add labels if configured
7300
- if (this.chartConfiguration.lineGraphColor) {
7301
- dot
7302
- .append('text')
7303
- .attr('class', 'dots')
7304
- .attr('fill', this.chartConfiguration.lineGraphColor)
7305
- .attr('style', 'font-size: 0.85em; font-weight: bold')
7306
- .attr('x', (d) => xScale(d.name) + xScale.bandwidth() / 2)
7307
- .attr('y', (d) => lineYscale(d.value))
7308
- .attr('dy', '-1em')
7309
- .text((d) => this.chartConfiguration.labelFormatter(d.value));
7310
- }
7581
+ .attr('d', lineGen);
7582
+ this.renderLineDots(svg, group.values, scales, colors);
7311
7583
  });
7312
7584
  }
7313
- handleClick(data) {
7314
- if (this.chartData?.metaData?.hasDrillDown || data?.toggleFrom) {
7315
- this.clickEvent.emit(data);
7585
+ renderLineDots(svg, values, scales, colors) {
7586
+ const dot = svg
7587
+ .selectAll('.line-dots')
7588
+ .data(values)
7589
+ .enter()
7590
+ .append('g')
7591
+ .on('click', (d) => this.handleClick(d));
7592
+ dot
7593
+ .append('circle')
7594
+ .attr('fill', (d) => {
7595
+ return d.category
7596
+ ? colors[d.category]
7597
+ : this.chartConfiguration.lineGraphColor;
7598
+ })
7599
+ .attr('stroke', 'none')
7600
+ .attr('cx', (d) => scales.xScale(d.name) + scales.xScale.bandwidth() / 2)
7601
+ .attr('cy', (d) => scales.lineYscale(d.value))
7602
+ .attr('r', 3)
7603
+ .style('cursor', 'pointer');
7604
+ if (this.chartConfiguration.lineGraphColor) {
7605
+ dot
7606
+ .append('text')
7607
+ .attr('class', 'dots')
7608
+ .attr('fill', this.chartConfiguration.lineGraphColor)
7609
+ .style('font-size', '.85em')
7610
+ .style('font-weight', 'bold')
7611
+ .attr('x', (d) => scales.xScale(d.name) + scales.xScale.bandwidth() / 2)
7612
+ .attr('y', (d) => scales.lineYscale(d.value))
7613
+ .attr('dy', '-1em')
7614
+ .text((d) => this.chartConfiguration.labelFormatter(d.value));
7615
+ }
7616
+ }
7617
+ handleClick(d) {
7618
+ if (this.chartData?.metaData?.hasDrillDown || d?.toggleFrom) {
7619
+ this.clickEvent.emit(d);
7316
7620
  }
7317
7621
  }
7318
7622
  handleHeaderMenuClick(id) {
@@ -7455,6 +7759,9 @@ class HorizontalGroupedBarWithScrollZoomComponent extends ComponentUniqueId {
7455
7759
  var alternate_text = false;
7456
7760
  var short_tick_length = 4;
7457
7761
  var long_tick_length = 16;
7762
+ /**
7763
+ * longer tick length needed for weekly charts
7764
+ */
7458
7765
  var short_tick_length_bg = 5;
7459
7766
  var long_tick_length_bg = 30;
7460
7767
  var leftAndRightSpaces = 50;
@@ -7466,6 +7773,9 @@ class HorizontalGroupedBarWithScrollZoomComponent extends ComponentUniqueId {
7466
7773
  data = this.chartData.data;
7467
7774
  metaData = this.chartData.metaData;
7468
7775
  lineData = this.chartData.lineData;
7776
+ // if (lineData || this.chartData.targetLineData) {
7777
+ // rightSvgWidth = 60;
7778
+ // }
7469
7779
  if (!metaData.colorAboveTarget) {
7470
7780
  metaData['colorAboveTarget'] = metaData.colors;
7471
7781
  }
@@ -7502,10 +7812,16 @@ class HorizontalGroupedBarWithScrollZoomComponent extends ComponentUniqueId {
7502
7812
  else
7503
7813
  width = this.chartData.data.length * 160;
7504
7814
  }
7815
+ // if (this.chartData.data.length > 8) {
7816
+ // width = this.chartData.data.length * 140;
7817
+ // }
7505
7818
  var height = parseInt(verticalstackedcontainer.style('height')) *
7506
7819
  (self.chartConfiguration.svgHeight / 100) -
7507
7820
  margin.top -
7508
7821
  margin.bottom;
7822
+ /**
7823
+ * entire height used in weekly charts as x axis needed to be displayed at the bottom of the chart
7824
+ */
7509
7825
  if (this.chartConfiguration.isFullScreen != undefined &&
7510
7826
  this.chartConfiguration.isFullScreen) {
7511
7827
  height =
@@ -7527,15 +7843,30 @@ class HorizontalGroupedBarWithScrollZoomComponent extends ComponentUniqueId {
7527
7843
  margin.bottom -
7528
7844
  100;
7529
7845
  }
7846
+ /**
7847
+ * for hiding header
7848
+ * used by weekly charts
7849
+ */
7530
7850
  if (this.chartConfiguration.isHeaderVisible != undefined)
7531
7851
  this.isHeaderVisible = this.chartConfiguration.isHeaderVisible;
7852
+ /**
7853
+ * for hiding legends
7854
+ * used by weekly charts
7855
+ */
7532
7856
  if (this.chartConfiguration.legendVisible != undefined) {
7533
7857
  this.legendVisible = this.chartConfiguration.legendVisible;
7534
7858
  }
7859
+ /**
7860
+ * for removing background color so that it can take parents color
7861
+ *
7862
+ */
7535
7863
  if (this.chartConfiguration.isTransparentBackground != undefined) {
7536
7864
  this.isTransparentBackground =
7537
7865
  this.chartConfiguration.isTransparentBackground;
7538
7866
  }
7867
+ /**
7868
+ * format data values based on configuration received
7869
+ */
7539
7870
  if (this.chartConfiguration.textFormatter != undefined) {
7540
7871
  formatFromBackend = ChartHelper.dataValueFormatter(this.chartConfiguration.textFormatter);
7541
7872
  formatForHugeNumbers = ChartHelper.dataValueFormatter('.2s');
@@ -7548,6 +7879,7 @@ class HorizontalGroupedBarWithScrollZoomComponent extends ComponentUniqueId {
7548
7879
  .style('height', height)
7549
7880
  .style('overflow-x', 'hidden')
7550
7881
  .style('padding-left', `${margin.left}px`)
7882
+ // .call(ChartHelper.responsivefy)
7551
7883
  .style('padding-right', `${rightSvgWidth}px`)
7552
7884
  .style('margin-left', '15px');
7553
7885
  var svgYAxisLeft = outerContainer
@@ -7575,8 +7907,10 @@ class HorizontalGroupedBarWithScrollZoomComponent extends ComponentUniqueId {
7575
7907
  .style('overflow-x', 'auto');
7576
7908
  var svg = innerContainer
7577
7909
  .append('svg')
7910
+ // .attr('id', self.uniqueId)
7578
7911
  .attr('width', width - rightSvgWidth)
7579
7912
  .attr('height', height + margin.top + margin.bottom + 60)
7913
+ // .call(ChartHelper.responsivefy)
7580
7914
  .append('g')
7581
7915
  .attr('transform', 'translate(' + 0 + ',' + margin.top + ')');
7582
7916
  var subgroups = keyList;
@@ -7585,6 +7919,9 @@ class HorizontalGroupedBarWithScrollZoomComponent extends ComponentUniqueId {
7585
7919
  return d.name;
7586
7920
  })
7587
7921
  .keys();
7922
+ /**
7923
+ * x axis range made similar to line chart or vertical stack so that all the charts will get aligned with each other.
7924
+ */
7588
7925
  if (this.chartConfiguration.isMultiChartGridLine != undefined) {
7589
7926
  x = d3
7590
7927
  .scaleBand()
@@ -7602,11 +7939,27 @@ class HorizontalGroupedBarWithScrollZoomComponent extends ComponentUniqueId {
7602
7939
  .range([leftAndRightSpaces, width - rightSvgWidth - leftAndRightSpaces])
7603
7940
  .padding([0.3]);
7604
7941
  }
7942
+ // x.bandwidth(96);
7605
7943
  var xScaleFromOrigin = d3
7606
7944
  .scaleBand()
7607
7945
  .domain(groups)
7608
7946
  .range([0, width - rightSvgWidth]);
7947
+ // .padding([0.2]);
7948
+ /**
7949
+ * draw second x axis on top
7950
+ */
7951
+ // if (self.chartConfiguration.showXaxisTop) {
7952
+ // svg
7953
+ // .append('g')
7954
+ // .attr('class', 'lib-line-axis-text lib-line-x-axis-text x-axis')
7955
+ // .attr('style', self.chartConfiguration.xAxisCustomTextStyles)
7956
+ // .call(d3.axisBottom(x).tickSize(0));
7957
+ // }
7958
+ // d3.svg.axis().scale(x).orient('bottom').ticks(1).innerTickSize(-height);
7609
7959
  if (this.chartConfiguration.isMultiChartGridLine == undefined) {
7960
+ /**
7961
+ * normal ticks for all dashboard charts
7962
+ */
7610
7963
  svg
7611
7964
  .append('g')
7612
7965
  .attr('class', 'x1 axis1')
@@ -7614,12 +7967,13 @@ class HorizontalGroupedBarWithScrollZoomComponent extends ComponentUniqueId {
7614
7967
  .call(d3.axisBottom(x))
7615
7968
  .call((g) => g.select('.domain').remove());
7616
7969
  svg.selectAll('g.x1.axis1 g.tick line').remove();
7970
+ // Only move x-axis labels further down for grouped charts if there is no xLabel
7617
7971
  if (subgroups.length > 1 && !metaData.xLabel) {
7618
7972
  svg
7619
7973
  .selectAll('g.x1.axis1 g.tick text')
7620
7974
  .attr('class', 'lib-xaxis-labels-texts-drilldown')
7621
7975
  .style('fill', 'var(--chart-text-color)')
7622
- .attr('y', 32);
7976
+ .attr('y', 32); // Increase distance from bars (default is ~9)
7623
7977
  }
7624
7978
  else {
7625
7979
  svg
@@ -7627,14 +7981,32 @@ class HorizontalGroupedBarWithScrollZoomComponent extends ComponentUniqueId {
7627
7981
  .attr('class', 'lib-xaxis-labels-texts-drilldown')
7628
7982
  .style('fill', 'var(--chart-text-color)');
7629
7983
  }
7984
+ // .attr('y', function () {
7985
+ // if (alternate_text) {
7986
+ // alternate_text = false;
7987
+ // return long_tick_length + 1;
7988
+ // } else {
7989
+ // alternate_text = true;
7990
+ // return short_tick_length + 1;
7991
+ // }
7992
+ // });
7630
7993
  }
7631
7994
  else {
7995
+ /**
7996
+ * bigger ticks for weekly charts and more space from x axis to labels
7997
+ */
7998
+ /**
7999
+ * draw x axis
8000
+ */
7632
8001
  svg
7633
8002
  .append('g')
7634
8003
  .attr('class', 'x1 axis1')
7635
8004
  .attr('transform', 'translate(0,' + height + ')')
7636
8005
  .call(d3.axisBottom(x).tickSize(0))
7637
8006
  .call((g) => g.select('.domain').attr('fill', 'none'));
8007
+ /**
8008
+ * tick line size in alternate fashion
8009
+ */
7638
8010
  svg.selectAll('g.x1.axis1 g.tick line').attr('y2', function () {
7639
8011
  if (alternate_text &&
7640
8012
  self.chartConfiguration.isNoAlternateXaxisText == undefined) {
@@ -7646,11 +8018,19 @@ class HorizontalGroupedBarWithScrollZoomComponent extends ComponentUniqueId {
7646
8018
  return short_tick_length_bg - 4;
7647
8019
  }
7648
8020
  });
8021
+ /**
8022
+ * reset the flag so that values can be shown in same alternate fashion
8023
+ */
7649
8024
  alternate_text = false;
8025
+ /**
8026
+ * print x-axis label texts
8027
+ * used by weekly charts
8028
+ */
7650
8029
  svg
7651
8030
  .selectAll('g.x1.axis1 g.tick text')
7652
8031
  .attr('class', 'lib-xaxis-labels-texts-weeklycharts')
7653
8032
  .attr('y', function () {
8033
+ // Minimize gap in maximized (fullscreen) view for weekly charts
7654
8034
  if (self.chartConfiguration.isFullScreen) {
7655
8035
  return short_tick_length_bg;
7656
8036
  }
@@ -7671,6 +8051,7 @@ class HorizontalGroupedBarWithScrollZoomComponent extends ComponentUniqueId {
7671
8051
  .style('font-size', this.isHeaderVisible ? '18px' : '14px')
7672
8052
  .attr('text-anchor', 'middle')
7673
8053
  .attr('y', function (d) {
8054
+ // For grouped bar charts with many bars and xLabel present, only add 5 if the label is a date
7674
8055
  if (subgroups.length > 1 && data.length > 8 && metaData.xLabel) {
7675
8056
  const isDateLabel = /\d{2,4}[-\/]/.test(d);
7676
8057
  if (self.chartConfiguration.isFullScreen) {
@@ -7678,13 +8059,16 @@ class HorizontalGroupedBarWithScrollZoomComponent extends ComponentUniqueId {
7678
8059
  }
7679
8060
  return isDateLabel ? short_tick_length_bg + 14 : short_tick_length_bg;
7680
8061
  }
8062
+ // For grouped bar charts with many bars and NO xLabel, add space as before, but reduce in fullscreen
7681
8063
  if (subgroups.length > 1 && data.length > 8 && !metaData.xLabel) {
7682
8064
  const chartHasExtraBottom = (self.chartConfiguration.margin && self.chartConfiguration.margin.bottom >= 40);
7683
8065
  if (self.chartConfiguration.isFullScreen) {
8066
+ // Reduce extra gap in maximized view
7684
8067
  return short_tick_length_bg + 2;
7685
8068
  }
7686
8069
  return chartHasExtraBottom ? short_tick_length_bg : short_tick_length_bg + 10;
7687
8070
  }
8071
+ // Default/fallback logic for other cases
7688
8072
  let baseY = self.isHeaderVisible ? short_tick_length_bg + 25 : short_tick_length_bg;
7689
8073
  if (subgroups.length > 1 &&
7690
8074
  !metaData.xLabel &&
@@ -7694,6 +8078,7 @@ class HorizontalGroupedBarWithScrollZoomComponent extends ComponentUniqueId {
7694
8078
  if (/\d{2,4}[-\/]\d{2,4}/.test(d) && d.indexOf(' ') > -1) {
7695
8079
  baseY += 4;
7696
8080
  }
8081
+ // In maximized view, reduce baseY slightly for grouped bars
7697
8082
  if (self.chartConfiguration.isFullScreen && subgroups.length > 1) {
7698
8083
  baseY = Math.max(short_tick_length_bg, baseY - 10);
7699
8084
  }
@@ -7701,9 +8086,9 @@ class HorizontalGroupedBarWithScrollZoomComponent extends ComponentUniqueId {
7701
8086
  })
7702
8087
  .attr('x', function (d) {
7703
8088
  if (self.chartData.data.length > 8 && !self.isZoomedOut) {
7704
- return 1;
8089
+ return 1; // Move first line text slightly to the left in zoom-in view for better alignment
7705
8090
  }
7706
- return 0;
8091
+ return 0; // Default position
7707
8092
  })
7708
8093
  .text(function (d) {
7709
8094
  var isValueToBeIgnored = false;
@@ -7721,10 +8106,13 @@ class HorizontalGroupedBarWithScrollZoomComponent extends ComponentUniqueId {
7721
8106
  if (isValueToBeIgnored) {
7722
8107
  return '';
7723
8108
  }
8109
+ // Always add space before and after hyphen for date range labels, even when header is visible and label is single line
8110
+ // Apply for grouped bar charts and single bar charts, header visible, single line
7724
8111
  const dateRangeRegex = /(\d{2,4}[-\/]\d{2}[-\/]\d{2,4})\s*-\s*(\d{2,4}[-\/]\d{2}[-\/]\d{2,4})/;
7725
8112
  if (dateRangeRegex.test(d.trim())) {
7726
8113
  return d.trim().replace(dateRangeRegex, (m, d1, d2) => `${d1} - ${d2}`);
7727
8114
  }
8115
+ // Split date and week labels into two lines in grouped bar zoom-in view (and minimized view)
7728
8116
  const isDateLabel = /\d{2,4}[-\/]/.test(d);
7729
8117
  const isWeekLabel = /week|wk|w\d+/i.test(d);
7730
8118
  if (subgroups.length > 1 && !self.isZoomedOut && data.length > 8 && d.indexOf(' ') > -1 && (isDateLabel || isWeekLabel)) {
@@ -7732,6 +8120,7 @@ class HorizontalGroupedBarWithScrollZoomComponent extends ComponentUniqueId {
7732
8120
  var second = d.substring(d.indexOf(' ') + 1).trim();
7733
8121
  return first + '\n' + second;
7734
8122
  }
8123
+ // Also keep previous logic for minimized view
7735
8124
  if (isDateLabel) {
7736
8125
  if (!self.isHeaderVisible && data.length > 8 && d.indexOf(' ') > -1) {
7737
8126
  var first = d.substring(0, d.indexOf(' '));
@@ -7746,7 +8135,9 @@ class HorizontalGroupedBarWithScrollZoomComponent extends ComponentUniqueId {
7746
8135
  return d.trim().substring(0, d.indexOf(' ')).toLowerCase();
7747
8136
  }
7748
8137
  return d.toLowerCase();
8138
+ // If label looks like a date (contains digits and - or /)
7749
8139
  const isDateLabel2 = /\d{2,4}[-\/]/.test(d);
8140
+ // Only split date/week labels if there are many grouped bars and header is not visible
7750
8141
  if (isDateLabel) {
7751
8142
  if (!self.isHeaderVisible && data.length > 8 && d.indexOf(' ') > -1) {
7752
8143
  var first = d.substring(0, d.indexOf(' '));
@@ -7762,7 +8153,9 @@ class HorizontalGroupedBarWithScrollZoomComponent extends ComponentUniqueId {
7762
8153
  }
7763
8154
  return d.toLowerCase();
7764
8155
  });
8156
+ // Now apply writing-mode: sideways-lr for grouped charts with date labels in zoomed-out view and many bars
7765
8157
  xAxisLabels.each(function (d) {
8158
+ // Only apply writing-mode for exact date labels, not those containing 'week' or similar
7766
8159
  const isDateLabel = /^(\d{2,4}[-\/])?\d{2,4}[-\/]\d{2,4}$/.test(d.trim());
7767
8160
  const isWeekLabel = /week|wk|w\d+/i.test(d);
7768
8161
  if (subgroups.length > 1 && self.isZoomedOut && data.length > 8 && isDateLabel && !isWeekLabel) {
@@ -7773,7 +8166,7 @@ class HorizontalGroupedBarWithScrollZoomComponent extends ComponentUniqueId {
7773
8166
  svg
7774
8167
  .selectAll('g.x1.axis1 g.tick')
7775
8168
  .filter(function (d) {
7776
- return !/\d{2,4}[-\/]/.test(d);
8169
+ return !/\d{2,4}[-\/]/.test(d); // Only process non-date labels
7777
8170
  })
7778
8171
  .append('text')
7779
8172
  .attr('class', 'lib-xaxis-labels-texts-drilldown')
@@ -7781,9 +8174,9 @@ class HorizontalGroupedBarWithScrollZoomComponent extends ComponentUniqueId {
7781
8174
  .attr('fill', 'var(--chart-text-color)')
7782
8175
  .attr('x', function (d) {
7783
8176
  if (self.chartData.data.length > 8 && !self.isZoomedOut) {
7784
- return 1;
8177
+ return 1; // Move text slightly to the left
7785
8178
  }
7786
- return 0;
8179
+ return 0; // Default position
7787
8180
  })
7788
8181
  .text(function (d) {
7789
8182
  if (d.trim().indexOf(' ') > -1) {
@@ -7810,6 +8203,7 @@ class HorizontalGroupedBarWithScrollZoomComponent extends ComponentUniqueId {
7810
8203
  .selectAll('g.x1.axis1 g.tick text')
7811
8204
  .classed('mobile-xaxis-override', true);
7812
8205
  }
8206
+ /**y scale for left y axis */
7813
8207
  var y = d3.scaleLinear().rangeRound([height, 0]);
7814
8208
  var maxValue = d3.max(data, (d) => d3.max(keyList, (key) => +d[key]));
7815
8209
  if (maxValue == 0) {
@@ -7820,7 +8214,27 @@ class HorizontalGroupedBarWithScrollZoomComponent extends ComponentUniqueId {
7820
8214
  maxValue = 100;
7821
8215
  }
7822
8216
  }
8217
+ if (self.chartConfiguration.yAxisGrid) {
8218
+ // svg
8219
+ // .append('g')
8220
+ // .attr('class', 'grid')
8221
+ // .call(
8222
+ // d3
8223
+ // .axisLeft(y)
8224
+ // .ticks(self.chartConfiguration.numberOfYTicks)
8225
+ // .tickSize(-width)
8226
+ // .tickFormat('')
8227
+ // )
8228
+ // // .style('stroke-dasharray', '5 5')
8229
+ // .style('color', '#B9B9B9')
8230
+ // .style('opacity', '0.5')
8231
+ // .call((g) => g.select('.domain').remove());
8232
+ }
7823
8233
  if (this.chartConfiguration.customYscale) {
8234
+ /**
8235
+ * increase y-scale so that values wont cross or exceed out of range
8236
+ * used in weekly charts
8237
+ */
7824
8238
  maxValue = maxValue * this.chartConfiguration.customYscale;
7825
8239
  }
7826
8240
  if (this.chartData.targetLineData &&
@@ -7858,6 +8272,10 @@ class HorizontalGroupedBarWithScrollZoomComponent extends ComponentUniqueId {
7858
8272
  .tickSize(0)
7859
8273
  .tickFormat(self.chartConfiguration.yLineAxisLabelFomatter);
7860
8274
  }
8275
+ /**
8276
+ * show x-axis grid between labels
8277
+ * used by weekly charts
8278
+ */
7861
8279
  if (self.chartConfiguration.isXgridBetweenLabels) {
7862
8280
  svg
7863
8281
  .append('g')
@@ -7865,7 +8283,7 @@ class HorizontalGroupedBarWithScrollZoomComponent extends ComponentUniqueId {
7865
8283
  .attr('transform', 'translate(' + x.bandwidth() / 2 + ',' + height + ')')
7866
8284
  .call(d3.axisBottom(x).tickSize(-height).tickFormat(''))
7867
8285
  .style('stroke-dasharray', '5 5')
7868
- .style('color', 'var(--chart-grid-color, #999999)')
8286
+ .style('color', 'var(--chart-grid-color, #999999)') // Use CSS variable
7869
8287
  .call((g) => g.select('.domain').remove());
7870
8288
  }
7871
8289
  if (this.chartConfiguration.yAxisGrid) {
@@ -7880,7 +8298,7 @@ class HorizontalGroupedBarWithScrollZoomComponent extends ComponentUniqueId {
7880
8298
  .call((g) => {
7881
8299
  g.select('.domain')
7882
8300
  .remove()
7883
- .style('stroke', 'var(--chart-domain-color, #000000)');
8301
+ .style('stroke', 'var(--chart-domain-color, #000000)'); // Add CSS variable for domain
7884
8302
  });
7885
8303
  }
7886
8304
  else {
@@ -7891,27 +8309,36 @@ class HorizontalGroupedBarWithScrollZoomComponent extends ComponentUniqueId {
7891
8309
  .style('opacity', '0.5')
7892
8310
  .call((g) => {
7893
8311
  g.select('.domain')
7894
- .style('stroke', 'var(--chart-domain-color, #000000)')
7895
- .style('stroke-width', '1px');
8312
+ .style('stroke', 'var(--chart-domain-color, #000000)') // Add CSS variable for domain
8313
+ .style('stroke-width', '1px'); // Ensure visibility
7896
8314
  });
7897
8315
  }
7898
8316
  var xSubgroup = d3.scaleBand().domain(subgroups);
7899
8317
  if (subgroups.length > 1 && !this.isZoomedOut) {
8318
+ // For grouped bar charts in zoom-in view, use full x.bandwidth() for subgroups
7900
8319
  xSubgroup.range([0, x.bandwidth()]);
7901
8320
  }
7902
8321
  else if (subgroups.length === 1 && !this.isZoomedOut) {
8322
+ // For single-bar (non-grouped) charts in zoom-in view, set bar width to 100 (increased from 80)
7903
8323
  xSubgroup.range([0, 100]);
7904
8324
  }
7905
8325
  else if (this.chartConfiguration.isMultiChartGridLine == undefined) {
7906
8326
  xSubgroup.range([0, x.bandwidth()]);
7907
8327
  }
7908
8328
  else {
8329
+ // used to make grouped bars with lesser width as we are not using padding for width
7909
8330
  xSubgroup.range([0, x.bandwidth()]);
7910
8331
  }
8332
+ // if (this.chartConfiguration.isDrilldownChart) {
8333
+ // }
7911
8334
  var color = d3
7912
8335
  .scaleOrdinal()
7913
8336
  .domain(subgroups)
7914
8337
  .range(Object.values(metaData.colors));
8338
+ // var colorAboveTarget = d3
8339
+ // .scaleOrdinal()
8340
+ // .domain(subgroups)
8341
+ // .range(Object.values(metaData.colorAboveTarget));
7915
8342
  var state = svg
7916
8343
  .append('g')
7917
8344
  .selectAll('.state')
@@ -7926,8 +8353,10 @@ class HorizontalGroupedBarWithScrollZoomComponent extends ComponentUniqueId {
7926
8353
  .data(function (d) {
7927
8354
  let newList = [];
7928
8355
  subgroups.map(function (key) {
8356
+ // if (key !== "group") {
7929
8357
  let obj = { key: key, value: d[key], name: d.name };
7930
8358
  newList.push(obj);
8359
+ // }
7931
8360
  });
7932
8361
  return newList;
7933
8362
  })
@@ -7940,6 +8369,7 @@ class HorizontalGroupedBarWithScrollZoomComponent extends ComponentUniqueId {
7940
8369
  !metaData.barWithoutClick.length ||
7941
8370
  (!metaData.barWithoutClick.includes(d?.name) &&
7942
8371
  !metaData.barWithoutClick.includes(d?.key)))
8372
+ // self.handleClick(d.data.name);
7943
8373
  self.handleClick(d);
7944
8374
  }
7945
8375
  })
@@ -7950,6 +8380,7 @@ class HorizontalGroupedBarWithScrollZoomComponent extends ComponentUniqueId {
7950
8380
  let keys = Object.keys(indiv).filter((temp, i) => i != 0);
7951
8381
  tempScale = d3.scaleBand().domain(keys).range([0, x.bandwidth()]);
7952
8382
  if (x.bandwidth() > 100) {
8383
+ // Increase bar width a bit in zoom-in view
7953
8384
  let reducedBarWidth = 60;
7954
8385
  if (!self.isZoomedOut) {
7955
8386
  reducedBarWidth = 30;
@@ -7991,19 +8422,23 @@ class HorizontalGroupedBarWithScrollZoomComponent extends ComponentUniqueId {
7991
8422
  return y(0);
7992
8423
  })
7993
8424
  .attr('width', function (d) {
8425
+ // For grouped bar charts in zoom-in view, set bar width to 50 for maximum thickness
7994
8426
  if (subgroups.length > 1 && !self.isZoomedOut) {
7995
8427
  return 50;
7996
8428
  }
8429
+ // For single-bar (non-grouped) charts in zoom-in view, set bar width to 80
7997
8430
  if (subgroups.length === 1 && !self.isZoomedOut) {
7998
8431
  return 80;
7999
8432
  }
8000
8433
  let tempScale = d3.scaleBand().domain([]).range([0, 0]);
8434
+ // Default logic for other chart types
8001
8435
  if (self.chartConfiguration.isDrilldownChart) {
8002
8436
  data.map((indiv) => {
8003
8437
  if (indiv.name == d.name) {
8004
8438
  let keys = Object.keys(indiv).filter((temp, i) => i != 0);
8005
8439
  tempScale = d3.scaleBand().domain(keys).range([0, x.bandwidth()]);
8006
8440
  if (x.bandwidth() > 100) {
8441
+ // Increase bar width a bit in zoom-in view
8007
8442
  let reducedBarWidth = 60;
8008
8443
  if (!self.isZoomedOut) {
8009
8444
  reducedBarWidth = 100;
@@ -8071,6 +8506,9 @@ class HorizontalGroupedBarWithScrollZoomComponent extends ComponentUniqueId {
8071
8506
  }
8072
8507
  return self.chartData.metaData.colors[d.key];
8073
8508
  });
8509
+ /**
8510
+ * display angled texts on the bars
8511
+ */
8074
8512
  if (this.chartConfiguration.textsOnBar != undefined && !this.isZoomedOut) {
8075
8513
  state
8076
8514
  .selectAll('text')
@@ -8105,7 +8543,7 @@ class HorizontalGroupedBarWithScrollZoomComponent extends ComponentUniqueId {
8105
8543
  .style('font-weight', 'bold')
8106
8544
  .style('font-size', function (d) {
8107
8545
  if (self.isZoomedOut) {
8108
- return '9px';
8546
+ return '9px'; // 👈 Zoomed out mode
8109
8547
  }
8110
8548
  if (self.chartConfiguration.isDrilldownChart) {
8111
8549
  if (window.innerWidth > 1900) {
@@ -8135,12 +8573,14 @@ class HorizontalGroupedBarWithScrollZoomComponent extends ComponentUniqueId {
8135
8573
  0 + (x.bandwidth() - 200) / 2,
8136
8574
  x.bandwidth() - (x.bandwidth() - 200) / 2,
8137
8575
  ]);
8576
+ // .padding(0.05);
8138
8577
  }
8139
8578
  else
8140
8579
  tempScale.range([
8141
8580
  0 + (x.bandwidth() - 300) / 2,
8142
8581
  x.bandwidth() - (x.bandwidth() - 300) / 2,
8143
8582
  ]);
8583
+ // .padding(0.05);
8144
8584
  }
8145
8585
  else
8146
8586
  tempScale.range([
@@ -8150,9 +8590,16 @@ class HorizontalGroupedBarWithScrollZoomComponent extends ComponentUniqueId {
8150
8590
  }
8151
8591
  }
8152
8592
  });
8593
+ /**
8594
+ * if set, then all texts ll be horizontal
8595
+ */
8153
8596
  if (self.chartConfiguration.textAlwaysHorizontal) {
8154
8597
  return ('translate(' + xSubgroup(d.key) + ',' + (y(d.value) - 3) + ')');
8155
8598
  }
8599
+ /**
8600
+ * rotate texts having more than one digits
8601
+ */
8602
+ // if (d.value > 9)
8156
8603
  if (!isNaN(tempScale(d.key)))
8157
8604
  return ('translate(' +
8158
8605
  (tempScale(d.key) + tempScale.bandwidth() * 0.55) +
@@ -8160,6 +8607,14 @@ class HorizontalGroupedBarWithScrollZoomComponent extends ComponentUniqueId {
8160
8607
  (y(0) - 10) +
8161
8608
  ') rotate(270)');
8162
8609
  return 'translate(0,0)';
8610
+ // else
8611
+ // return (
8612
+ // 'translate(' +
8613
+ // (tempScale(d.key) + tempScale.bandwidth() / 2) +
8614
+ // ',' +
8615
+ // y(0) +
8616
+ // ')'
8617
+ // );
8163
8618
  })
8164
8619
  .on('click', function (d) {
8165
8620
  if (!metaData.barWithoutClick ||
@@ -8189,6 +8644,7 @@ class HorizontalGroupedBarWithScrollZoomComponent extends ComponentUniqueId {
8189
8644
  svg
8190
8645
  .append('foreignObject')
8191
8646
  .attr('x', function () {
8647
+ // ...existing code for tempScale calculation...
8192
8648
  var elementsCounter;
8193
8649
  data.map((indiv) => {
8194
8650
  if (indiv.name == d.name) {
@@ -8297,7 +8753,7 @@ class HorizontalGroupedBarWithScrollZoomComponent extends ComponentUniqueId {
8297
8753
  .append('g')
8298
8754
  .attr('class', 'x2 axis2')
8299
8755
  .attr('transform', 'translate(0,' + height + ')')
8300
- .style('color', 'var(--chart-axis-color, #000)')
8756
+ .style('color', 'var(--chart-axis-color, #000)') // Use CSS variable instead of hardcoded #000
8301
8757
  .call(d3.axisBottom(xScaleFromOrigin).tickSize(0))
8302
8758
  .call((g) => g.select('.domain').attr('fill', 'none'));
8303
8759
  svg.selectAll('g.x2.axis2 g.tick text').style('display', 'none');
@@ -8325,6 +8781,7 @@ class HorizontalGroupedBarWithScrollZoomComponent extends ComponentUniqueId {
8325
8781
  return formatted >= 1000 ? formatted / 1000 + 'k' : formatted;
8326
8782
  }))
8327
8783
  .call((g) => {
8784
+ // Style the domain line for theme support
8328
8785
  g.select('.domain')
8329
8786
  .style('stroke', 'var(--chart-domain-color, #000000)')
8330
8787
  .style('stroke-width', '1px');
@@ -8338,23 +8795,40 @@ class HorizontalGroupedBarWithScrollZoomComponent extends ComponentUniqueId {
8338
8795
  .attr('transform', 'translate(0,0)')
8339
8796
  .call(y)
8340
8797
  .style('display', 'none');
8798
+ /**
8799
+ * hide x axis labels
8800
+ * config is there for future use
8801
+ * used by weekly charts
8802
+ */
8341
8803
  if (this.chartConfiguration.isXaxisLabelHidden != undefined &&
8342
8804
  this.chartConfiguration.isXaxisLabelHidden) {
8343
8805
  d3.selectAll('g.lib-line-x-axis-text > g > text').attr('class', 'lib-display-hidden');
8344
8806
  }
8807
+ /**
8808
+ * hide y axis labels
8809
+ * used by weekly charts
8810
+ */
8345
8811
  if (this.chartConfiguration.isYaxisLabelHidden != undefined &&
8346
8812
  this.chartConfiguration.isYaxisLabelHidden) {
8347
8813
  d3.selectAll('.yaxis-dashed > g > text').attr('class', 'lib-display-hidden');
8348
8814
  }
8815
+ /**
8816
+ * hide y axis labels
8817
+ * config is there for future use
8818
+ */
8349
8819
  if (this.chartConfiguration.isYaxisHidden != undefined &&
8350
8820
  this.chartConfiguration.isYaxisHidden) {
8351
8821
  d3.selectAll('.yaxis-dashed').attr('class', 'lib-display-hidden');
8352
8822
  }
8823
+ /**
8824
+ * dashed y axis
8825
+ * used by weekly charts
8826
+ */
8353
8827
  if (this.chartConfiguration.isYaxisDashed != undefined &&
8354
8828
  this.chartConfiguration.isYaxisDashed) {
8355
8829
  d3.selectAll('.yaxis-dashed')
8356
8830
  .style('stroke-dasharray', '5 5')
8357
- .style('color', 'var(--chart-axis-color, #999999)');
8831
+ .style('color', 'var(--chart-axis-color, #999999)'); // Use CSS variable
8358
8832
  }
8359
8833
  if (lineData != null) {
8360
8834
  if (lineData && self.chartConfiguration.showLineChartAxis) {
@@ -8366,12 +8840,28 @@ class HorizontalGroupedBarWithScrollZoomComponent extends ComponentUniqueId {
8366
8840
  .call(yLineAxis);
8367
8841
  }
8368
8842
  }
8843
+ /**
8844
+ * used to display y label
8845
+ */
8846
+ // if (this.isZoomedOut) {
8847
+ // svg
8848
+ // .selectAll('.lib-xaxis-labels-texts-drilldown')
8849
+ // .attr('class', 'lib-display-hidden');
8850
+ // }
8369
8851
  if (this.isZoomedOut) {
8852
+ // svg
8853
+ // .selectAll('.lib-xaxis-labels-texts-drilldown')
8854
+ // .attr('transform', 'rotate(-30)')
8855
+ // .attr('text-anchor', 'end')
8856
+ // .attr('x', '-5')
8857
+ // .attr('dy', null)
8858
+ // .style('fill', 'var(--chart-text-color)');
8370
8859
  svg
8371
8860
  .selectAll('.lib-xaxis-labels-texts-drilldown')
8372
8861
  .each((d, i, nodes) => {
8373
8862
  const text = d3.select(nodes[i]);
8374
8863
  const label = text.text();
8864
+ // If label contains \n, split and use tspan for each line
8375
8865
  if (label.indexOf('\n') > -1) {
8376
8866
  const lines = label.split('\n');
8377
8867
  text.text(null);
@@ -8383,6 +8873,7 @@ class HorizontalGroupedBarWithScrollZoomComponent extends ComponentUniqueId {
8383
8873
  });
8384
8874
  }
8385
8875
  else {
8876
+ // Fallback: split by space for other labels
8386
8877
  const words = label.split(' ');
8387
8878
  text.text(null);
8388
8879
  words.forEach((word, index) => {
@@ -8391,11 +8882,15 @@ class HorizontalGroupedBarWithScrollZoomComponent extends ComponentUniqueId {
8391
8882
  }
8392
8883
  })
8393
8884
  .style('fill', 'var(--chart-text-color)')
8394
- .attr('transform', null);
8885
+ .attr('transform', null); // Remove rotate if using line breaks
8886
+ // Optional: Adjust bottom margin or chart layout
8395
8887
  svg
8396
8888
  .select('.x-axis')
8397
8889
  .attr('transform', `translate(0, ${height - margin.bottom + 10})`);
8398
8890
  }
8891
+ /**
8892
+ * used to write y labels based on configuration
8893
+ */
8399
8894
  if (metaData.yLabel) {
8400
8895
  const yPosition = isria ? 0 - margin.left / 2 - 30 : 0 - margin.left / 2 - 40;
8401
8896
  svgYAxisLeft
@@ -8431,6 +8926,13 @@ class HorizontalGroupedBarWithScrollZoomComponent extends ComponentUniqueId {
8431
8926
  .attr('y2', yZero)
8432
8927
  .style('stroke-dasharray', '5 5')
8433
8928
  .style('stroke', this.chartData.targetLineData.color);
8929
+ // svgYAxisRight
8930
+ // .append('line')
8931
+ // .attr('x1', 0)
8932
+ // .attr('x2', rightSvgWidth)
8933
+ // .attr('y1', yZero)
8934
+ // .attr('y2', yZero)
8935
+ // .style('stroke', this.chartData.targetLineData.color);
8434
8936
  svgYAxisRight
8435
8937
  .append('foreignObject')
8436
8938
  .attr('transform', 'translate(' + 0 + ',' + (yZero - 30) + ')')
@@ -8458,6 +8960,13 @@ class HorizontalGroupedBarWithScrollZoomComponent extends ComponentUniqueId {
8458
8960
  });
8459
8961
  }
8460
8962
  if (this.chartConfiguration.isDrilldownChart) {
8963
+ /**
8964
+ * used by drilldown charts
8965
+ */
8966
+ // svg
8967
+ // .selectAll('.lib-axis-group-label')
8968
+ // .attr('class', 'lib-ylabel-drilldowncharts')
8969
+ // .text(metaData.yLabel.toLowerCase());
8461
8970
  svg.selectAll('g.x1.axis1 g.tick line').style('display', 'none');
8462
8971
  }
8463
8972
  if (metaData.xLabel) {