axidio-styleguide-library1-v2 0.4.21 → 0.4.23

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.
@@ -3381,910 +3381,1029 @@ class GroupChartComponent extends ComponentUniqueId {
3381
3381
  super();
3382
3382
  this.clickEvent = new EventEmitter();
3383
3383
  this.headerMenuclickEvent = new EventEmitter();
3384
+ this.chartConfiguration = {};
3384
3385
  this.isHeaderVisible = true;
3385
- this.legendVisible = true;
3386
+ this.isTopCaptionVisible = true;
3387
+ this.uniqueId = this.getUniqueId();
3386
3388
  this.isTransparentBackground = false;
3387
- this.chartConfiguration = {};
3388
- this.objectKeys = Object.keys;
3389
+ this.isCC = false;
3390
+ this.isZoomedOut = true;
3391
+ this.CONSTANTS = {
3392
+ RIGHT_SVG_WIDTH: 60,
3393
+ LEFT_RIGHT_SPACES: 50,
3394
+ SHORT_TICK_LENGTH: 4,
3395
+ LONG_TICK_LENGTH: 16,
3396
+ SHORT_TICK_LENGTH_BG: 5,
3397
+ LONG_TICK_LENGTH_BG: 30,
3398
+ DESKTOP_BAR_WIDTH: 40, // Desktop bar width
3399
+ MOBILE_BAR_WIDTH: 25, // Mobile/Tablet bar width (reduced)
3400
+ BAR_GAP: 30, // Gap between bars (increased for better separation)
3401
+ ZOOM_THRESHOLD: 30,
3402
+ ZOOM_IN_THRESHOLD: 8,
3403
+ };
3389
3404
  this.defaultConfiguration = {
3390
- "margin": {
3391
- "top": 30,
3392
- "left": 110,
3393
- "right": 40,
3394
- "bottom": 50
3395
- },
3396
- labelFormatter: ChartHelper.defaultFormatter,
3405
+ margin: { top: 20, right: 20, bottom: 20, left: 40 },
3397
3406
  svgHeight: 70,
3407
+ legendHeight: '10%',
3398
3408
  numberOfYTicks: 5,
3399
- legendJustified: true,
3400
- yLineAxisLabelFomatter: ChartHelper.defaultFormatter,
3409
+ labelFormatter: ChartHelper.defaultFormatter,
3410
+ xAxisLabelFomatter: ChartHelper.defaultFormatter,
3401
3411
  yAxisLabelFomatter: ChartHelper.defaultFormatter,
3412
+ yLineAxisLabelFomatter: ChartHelper.defaultFormatter,
3402
3413
  lineGraphColor: '#F6D283',
3403
3414
  showLineChartAxis: true,
3404
- showValues: true,
3415
+ showLegend: false,
3416
+ forComparison: true,
3405
3417
  headerMenuOptions: HeaderConfigHelper.headerConfig.headerMenuOptions,
3406
- yAxisGrid: true,
3407
- legendVisible: true,
3408
- isYaxisLabelHidden: false,
3409
- backgroundColor: '#FFFFFF',
3410
- hideLegendOnTop: true,
3411
- isXaxisColor: '#999999',
3412
- labelOverlapMinorFix: true,
3413
- noHoverEffect: true,
3414
- noHoverDisplayData: true,
3415
- showXaxisTop: true,
3416
- howmanyBarDetailsToDisplay: 0,
3418
+ yAxisGrid: false,
3419
+ // Optional configs with undefined defaults
3420
+ isHeaderVisible: undefined,
3421
+ isTransparentBackground: undefined,
3422
+ isTopCaptionVisible: undefined,
3423
+ isMultiChartGridLine: undefined,
3424
+ isFullScreen: undefined,
3425
+ customYscale: undefined,
3426
+ isXaxisLabelHidden: undefined,
3427
+ isYaxisLabelHidden: undefined,
3428
+ isYaxisHidden: undefined,
3429
+ isYaxisDashed: undefined,
3430
+ isXaxisColor: undefined,
3431
+ textFormatter: undefined,
3432
+ showTotalOnTop: undefined,
3433
+ backendFormatterHasPriority: undefined,
3434
+ showAngledLabels: undefined,
3435
+ isNoAlternateXaxisText: undefined,
3436
+ isXgridBetweenLabels: undefined,
3437
+ showXaxisTop: undefined,
3438
+ xAxisGrid: undefined,
3439
+ xLabelsOnSameLine: undefined,
3440
+ hideXaxisTick: undefined,
3441
+ isDrilldownChart: undefined,
3442
+ isTargetLine: undefined,
3443
+ displayTitleOnTop: undefined,
3444
+ isToggleVisible: undefined,
3445
+ isTitleHidden: undefined,
3417
3446
  };
3418
- this.uniqueId = this.getUniqueId();
3419
- this.isZoomedOut = false;
3420
- this.isDD1Open = false;
3421
- this.isDD2Open = false;
3422
- this.keepOrder = (a, b) => a;
3423
3447
  }
3424
- ngOnInit() { }
3425
- get isAlertEnabled() {
3426
- return this.chartConfiguration?.headerMenuOptions?.some((option) => option.id === 'editAlert');
3448
+ ngOnChanges() {
3449
+ this.removeExistingChart();
3450
+ this.initializeStackedChart();
3427
3451
  }
3428
3452
  onResized(event) {
3429
3453
  setTimeout(() => {
3430
- d3.select('#' + this.uniqueId).remove();
3431
- this.initializegroupChart();
3454
+ this.removeExistingChart();
3455
+ this.initializeStackedChart();
3432
3456
  }, 10);
3433
3457
  }
3434
- isZoomOutSelected(isZoomOut, event) {
3458
+ isZoomOutSelected(isZoomOut) {
3435
3459
  this.isZoomedOut = isZoomOut;
3436
- this.onResized(event);
3437
- }
3438
- handleZoominZoomoutClick({ isZoomOut, event }) {
3439
- this.isZoomOutSelected(isZoomOut, event);
3440
- }
3441
- isLegendVisible() {
3442
- return !!(this.chartData?.metaData?.colors &&
3443
- Object.keys(this.chartData.metaData.colors).length > 1);
3460
+ this.ngOnChanges();
3444
3461
  }
3445
- initializegroupChart() {
3446
- this.mergeConfigurations();
3447
- const chartContext = this.prepareChartData();
3448
- const dimensions = this.calculateDimensions(chartContext);
3449
- const scales = this.createScales(chartContext, dimensions);
3450
- const svgElements = this.createSVGStructure(dimensions);
3451
- this.renderAxes(svgElements, scales, chartContext, dimensions);
3452
- this.renderBars(svgElements.svg, chartContext, scales, dimensions);
3453
- this.renderLabels(svgElements, scales, chartContext, dimensions);
3454
- this.renderTargetLine(svgElements, scales, chartContext, dimensions);
3455
- this.renderLineGraph(svgElements.svg, chartContext, scales);
3462
+ removeExistingChart() {
3463
+ d3.select('#' + this.uniqueId).remove();
3456
3464
  }
3457
3465
  mergeConfigurations() {
3458
3466
  for (const key in this.defaultConfiguration) {
3459
3467
  this.chartConfiguration[key] = ChartHelper.getValueByConfigurationType(key, this.defaultConfiguration, this.customChartConfiguration);
3460
3468
  }
3461
- if (this.chartConfiguration.isHeaderVisible !== undefined) {
3462
- this.isHeaderVisible = this.chartConfiguration.isHeaderVisible;
3463
- }
3464
- if (this.chartConfiguration.legendVisible !== undefined) {
3465
- this.legendVisible = this.chartConfiguration.legendVisible;
3469
+ }
3470
+ prepareMetaData(metaData) {
3471
+ if (!metaData.unit)
3472
+ metaData.unit = '';
3473
+ if (metaData.isCC)
3474
+ this.isCC = metaData.isCC;
3475
+ if (metaData.barWithoutClick?.length) {
3476
+ metaData.barWithoutClick = metaData.barWithoutClick.map(el => el.toLowerCase());
3466
3477
  }
3467
- if (this.chartConfiguration.isTransparentBackground !== undefined) {
3468
- this.isTransparentBackground = this.chartConfiguration.isTransparentBackground;
3478
+ else {
3479
+ metaData.barWithoutClick = [];
3469
3480
  }
3481
+ return metaData;
3470
3482
  }
3471
- prepareChartData() {
3472
- const data = this.chartData.data;
3473
- const metaData = this.chartData.metaData;
3474
- const lineData = this.chartData.lineData;
3475
- if (!metaData.colorAboveTarget) {
3476
- metaData.colorAboveTarget = metaData.colors;
3483
+ calculateDimensions(chartContainer, verticalContainer, margin, dataLength) {
3484
+ const containerWidth = chartContainer.node().getBoundingClientRect().width;
3485
+ const containerHeight = verticalContainer.node().getBoundingClientRect().height;
3486
+ const leftAxisWidth = 80;
3487
+ const rightAxisWidth = this.CONSTANTS.RIGHT_SVG_WIDTH;
3488
+ const availableWidth = containerWidth - leftAxisWidth - rightAxisWidth;
3489
+ let width = availableWidth;
3490
+ let height = containerHeight * (this.chartConfiguration.svgHeight / 100) - margin.top - margin.bottom;
3491
+ if (dataLength > this.CONSTANTS.ZOOM_THRESHOLD && this.isZoomedOut) {
3492
+ const minWidth = dataLength * 25;
3493
+ width = Math.max(width, minWidth);
3477
3494
  }
3478
- return {
3479
- data,
3480
- metaData,
3481
- lineData,
3482
- keyList: metaData.keyList,
3483
- colorMap: metaData.colors,
3484
- isRia: this.customChartConfiguration?.isRia || false,
3485
- };
3486
- }
3487
- calculateDimensions(chartContext) {
3488
- const chartContainer = d3.select(this.containerElt.nativeElement);
3489
- const verticalstackedcontainer = d3.select(this.groupcontainerElt.nativeElement);
3490
- const margin = this.chartConfiguration.margin;
3491
- let width = this.calculateWidth(chartContainer, margin);
3492
- let height = this.calculateHeight(verticalstackedcontainer, margin);
3493
- return { width, height, margin, chartContainer, verticalstackedcontainer };
3494
- }
3495
- calculateWidth(chartContainer, margin) {
3496
- const baseWidth = parseInt(chartContainer.style('width')) - margin.left - margin.right;
3497
- const dataLength = this.chartData.data.length;
3498
- let width = baseWidth;
3499
- if (dataLength > 30 && this.isZoomedOut) {
3500
- const multiplier = this.chartData.dropdownData1 ? 60 : 40;
3501
- width = Math.max(width, dataLength * multiplier);
3495
+ if (dataLength > this.CONSTANTS.ZOOM_IN_THRESHOLD && !this.isZoomedOut) {
3496
+ width = dataLength * 130;
3502
3497
  }
3503
- if (this.chartData.dropdownData2 && width < dataLength * 120 && this.isZoomedOut) {
3504
- width = dataLength * 120;
3498
+ if (this.chartConfiguration.isFullScreen) {
3499
+ height = this.chartConfiguration.svgHeight !== 80
3500
+ ? this.chartConfiguration.svgHeight
3501
+ : containerHeight;
3505
3502
  }
3506
- if (dataLength > 8 && !this.isZoomedOut) {
3507
- if (this.chartData.dropdownData2 && width < dataLength * 250) {
3508
- width = dataLength * 250;
3503
+ if (this.chartConfiguration.isDrilldownChart) {
3504
+ height = containerHeight - margin.top - margin.bottom - 130;
3505
+ }
3506
+ const isMobileOrTablet = window.innerWidth < 1024;
3507
+ let barWidth;
3508
+ let barPadding;
3509
+ if (isMobileOrTablet) {
3510
+ if (dataLength === 1) {
3511
+ barWidth = 60;
3512
+ barPadding = 0;
3513
+ }
3514
+ else if (dataLength === 2) {
3515
+ barWidth = 50;
3516
+ barPadding = 45;
3517
+ }
3518
+ else if (dataLength === 3) {
3519
+ barWidth = 45;
3520
+ barPadding = 40;
3521
+ }
3522
+ else if (dataLength <= 5) {
3523
+ barWidth = 35;
3524
+ barPadding = 30;
3509
3525
  }
3510
3526
  else {
3511
- width = dataLength * 160;
3527
+ barWidth = 25;
3528
+ barPadding = 25;
3512
3529
  }
3513
3530
  }
3514
- return width;
3515
- }
3516
- calculateHeight(verticalstackedcontainer, margin) {
3517
- let height = parseInt(verticalstackedcontainer.style('height')) *
3518
- (this.chartConfiguration.svgHeight / 100) -
3519
- margin.top -
3520
- margin.bottom;
3521
- if (this.chartConfiguration.isFullScreen && this.chartConfiguration.svgHeight !== 70) {
3522
- height = this.chartConfiguration.svgHeight;
3523
- }
3524
- else if (this.chartConfiguration.isFullScreen) {
3525
- height = parseInt(verticalstackedcontainer.style('height'));
3526
- }
3527
- if (this.chartConfiguration.isDrilldownChart && !this.isHeaderVisible) {
3528
- height = parseInt(verticalstackedcontainer.style('height')) - margin.top - margin.bottom - 130;
3529
- }
3530
- if (this.chartConfiguration.isHeaderVisible) {
3531
- height = parseInt(verticalstackedcontainer.style('height')) - margin.top - margin.bottom - 100;
3532
- }
3533
- return height;
3534
- }
3535
- createScales(chartContext, dimensions) {
3536
- const { data, metaData, lineData, keyList } = chartContext;
3537
- const { width, height, margin } = dimensions;
3538
- const leftAndRightSpaces = 50;
3539
- const rightSvgWidth = 60;
3540
- const groups = d3.map(data, (d) => d.name).keys();
3541
- let x;
3542
- if (this.chartConfiguration.isMultiChartGridLine !== undefined) {
3543
- x = d3
3544
- .scaleBand()
3545
- .rangeRound([width, 0])
3546
- .align(0.5)
3547
- .padding(0.5)
3548
- .domain(data.map((d) => d.name.toLowerCase()));
3549
- }
3550
3531
  else {
3551
- x = d3
3552
- .scaleBand()
3553
- .domain(groups)
3554
- .range([leftAndRightSpaces, width - rightSvgWidth - leftAndRightSpaces])
3555
- .padding(0.3);
3556
- }
3557
- const xScaleFromOrigin = d3.scaleBand().domain(groups).range([0, width - rightSvgWidth]);
3558
- const xSubgroup = d3.scaleBand().domain(keyList).range([0, x.bandwidth()]);
3559
- const maxValue = this.calculateMaxValue(data, keyList);
3560
- const y = d3.scaleLinear().domain([0, maxValue]).nice().rangeRound([height, 0]);
3561
- let lineYscale = null;
3562
- if (lineData) {
3563
- lineYscale = this.createLineYScale(lineData, height);
3532
+ barWidth = this.CONSTANTS.DESKTOP_BAR_WIDTH;
3533
+ barPadding = this.CONSTANTS.BAR_GAP;
3564
3534
  }
3565
- const color = d3.scaleOrdinal().domain(keyList).range(Object.values(metaData.colors));
3535
+ const totalBarsWidth = barWidth * dataLength;
3536
+ const totalGaps = barPadding * (dataLength - 1);
3537
+ const minRequiredWidth = totalBarsWidth + totalGaps + (this.CONSTANTS.LEFT_RIGHT_SPACES * 2);
3538
+ const requiredSvgWidth = Math.max(availableWidth, minRequiredWidth);
3566
3539
  return {
3567
- x,
3568
- xScaleFromOrigin,
3569
- xSubgroup,
3570
- y,
3571
- lineYscale,
3572
- color,
3573
- leftAndRightSpaces,
3574
- rightSvgWidth,
3540
+ width,
3541
+ height,
3542
+ containerWidth,
3543
+ containerHeight,
3544
+ barWidth,
3545
+ barPadding,
3546
+ requiredSvgWidth,
3575
3547
  };
3576
3548
  }
3577
- calculateMaxValue(data, keyList) {
3578
- let maxValue = d3.max(data, (d) => d3.max(keyList, (key) => +d[key])) || 0;
3579
- if (maxValue === 0) {
3580
- maxValue = this.chartData.targetLineData
3581
- ? this.chartData.targetLineData.target + 20
3582
- : 100;
3583
- }
3584
- if (this.chartConfiguration.customYscale) {
3585
- maxValue *= this.chartConfiguration.customYscale;
3586
- }
3587
- if (this.chartData.targetLineData && maxValue < this.chartData.targetLineData.target) {
3588
- const target = this.chartData.targetLineData.target;
3589
- maxValue = maxValue < 10 && target < 10 ? target + 3 : target + 20;
3590
- }
3591
- return maxValue;
3592
- }
3593
- createLineYScale(lineData, height) {
3594
- let maxLineValue = d3.max(lineData, (d) => +d.value) || 0;
3595
- maxLineValue *= this.chartConfiguration.customYscale || 1;
3596
- let minLineValue = d3.min(lineData, (d) => +d.value) || 0;
3597
- if (maxLineValue > 0)
3598
- minLineValue -= 3;
3599
- if (minLineValue > 0)
3600
- minLineValue = 0;
3601
- return d3.scaleLinear().domain([minLineValue, maxLineValue]).range([height, minLineValue]);
3602
- }
3603
- createSVGStructure(dimensions) {
3604
- const { chartContainer, height, margin } = dimensions;
3605
- const rightSvgWidth = 60;
3606
- // Calculate proper left SVG width to include label
3607
- const leftSvgWidth = margin.left + 20;
3608
- const outerContainer = chartContainer
3549
+ createSvgContainers(chartContainer, dimensions, margin, hasXLabel // Add this parameter
3550
+ ) {
3551
+ // Calculate total height including space for X-axis label if present
3552
+ const xLabelSpace = hasXLabel ? 30 : 0;
3553
+ const totalHeight = dimensions.height + margin.top + margin.bottom + xLabelSpace;
3554
+ // Main wrapper
3555
+ const chartWrapper = chartContainer
3609
3556
  .append('div')
3610
3557
  .attr('id', this.uniqueId)
3611
- .attr('class', 'outer-container')
3558
+ .attr('class', 'chart-wrapper-main')
3559
+ .style('position', 'relative')
3612
3560
  .style('width', '100%')
3613
- .style('height', `${height + margin.top + margin.bottom}px`)
3614
- .style('overflow', 'hidden') // FIXED: Prevent all overflow
3615
- .style('padding-left', `${margin.left}px`)
3616
- .style('padding-right', `${rightSvgWidth}px`)
3617
- .style('margin-left', '15px')
3618
- .style('position', 'relative'); // FIXED: For absolute positioning
3619
- // FIXED: Create proper Y-axis SVG with enough space for label
3620
- const svgYAxisLeft = outerContainer
3621
- .append('svg')
3622
- .attr('width', leftSvgWidth)
3623
- .attr('height', height + margin.top + margin.bottom)
3561
+ .style('height', `${totalHeight}px`); // Include X-label space
3562
+ const leftAxisContainer = chartWrapper
3563
+ .append('div')
3564
+ .attr('class', 'left-axis-container')
3624
3565
  .style('position', 'absolute')
3625
3566
  .style('left', '0')
3626
3567
  .style('top', '0')
3627
- .style('z-index', 1)
3628
- .append('g')
3629
- .attr('transform', `translate(${margin.left + 5},${margin.top})`);
3630
- const svgYAxisRight = outerContainer
3568
+ .style('width', '80px')
3569
+ .style('height', `${dimensions.height + margin.top + margin.bottom}px`)
3570
+ .style('background-color', 'var(--card-bg)')
3571
+ .style('z-index', '10');
3572
+ const svgYAxisLeft = leftAxisContainer
3631
3573
  .append('svg')
3632
- .attr('width', rightSvgWidth)
3633
- .attr('height', height + margin.top + margin.bottom)
3634
- .style('position', 'absolute')
3635
- .style('right', '12px')
3636
- .style('top', '0')
3637
- .style('z-index', 1)
3574
+ .attr('width', '80')
3575
+ .attr('height', dimensions.height + margin.top + margin.bottom)
3638
3576
  .append('g')
3639
- .attr('transform', `translate(0,${margin.top})`);
3640
- const innerContainer = outerContainer
3577
+ .attr('transform', `translate(79,${margin.top})`);
3578
+ // Right Y-axis - Fixed
3579
+ const rightAxisContainer = chartWrapper
3641
3580
  .append('div')
3642
- .attr('class', 'inner-container')
3643
- .style('width', '100%')
3644
- .style('height', '100%')
3581
+ .attr('class', 'right-axis-container')
3582
+ .style('position', 'absolute')
3583
+ .style('right', '0')
3584
+ .style('top', '0')
3585
+ .style('width', `${this.CONSTANTS.RIGHT_SVG_WIDTH}px`)
3586
+ .style('height', `${dimensions.height + margin.top + margin.bottom}px`) // Exclude X-label space
3587
+ .style('background-color', 'var(--card-bg)')
3588
+ .style('z-index', '10');
3589
+ const svgYAxisRight = rightAxisContainer
3590
+ .append('svg')
3591
+ .attr('width', this.CONSTANTS.RIGHT_SVG_WIDTH)
3592
+ .attr('height', dimensions.height + margin.top + margin.bottom)
3593
+ .append('g')
3594
+ .attr('transform', `translate(0,${margin.top})`);
3595
+ // Scrollable middle area
3596
+ const scrollableContainer = chartWrapper
3597
+ .append('div')
3598
+ .attr('class', 'scrollable-chart-container')
3599
+ .style('position', 'absolute')
3600
+ .style('left', '80px') // Exactly where left container ends
3601
+ .style('right', `${this.CONSTANTS.RIGHT_SVG_WIDTH}px`)
3602
+ .style('top', '0')
3603
+ .style('width', 'auto')
3604
+ .style('height', `${dimensions.height + margin.top + margin.bottom}px`)
3645
3605
  .style('overflow-x', 'auto')
3646
3606
  .style('overflow-y', 'hidden');
3607
+ const innerContainer = scrollableContainer
3608
+ .append('div')
3609
+ .attr('class', 'inner-chart-container')
3610
+ .style('min-width', '100%');
3647
3611
  const svg = innerContainer
3648
3612
  .append('svg')
3649
- .attr('width', dimensions.width - rightSvgWidth)
3650
- .attr('height', height + margin.top + margin.bottom)
3613
+ .attr('width', dimensions.requiredSvgWidth)
3614
+ .attr('height', dimensions.height + margin.top + margin.bottom + 30)
3651
3615
  .append('g')
3652
3616
  .attr('transform', `translate(0,${margin.top})`);
3653
- return { outerContainer, svgYAxisLeft, svgYAxisRight, svg };
3654
- }
3655
- renderAxes(svgElements, scales, chartContext, dimensions) {
3656
- const { svg, svgYAxisLeft, svgYAxisRight } = svgElements;
3657
- const { x, xScaleFromOrigin, y, lineYscale } = scales;
3658
- const { height } = dimensions;
3659
- const { metaData, lineData, keyList } = chartContext;
3660
- this.renderXAxis(svg, x, xScaleFromOrigin, height, chartContext, keyList);
3661
- this.renderYAxis(svg, svgYAxisLeft, svgYAxisRight, y, dimensions);
3662
- if (this.chartConfiguration.yAxisGrid) {
3663
- this.renderYAxisGrid(svg, y, dimensions.width);
3617
+ // Fixed bottom container for X-axis label
3618
+ const bottomLabelContainer = chartWrapper
3619
+ .append('div')
3620
+ .attr('class', 'bottom-label-container')
3621
+ .style('position', 'absolute')
3622
+ .style('left', '80px')
3623
+ .style('right', `${this.CONSTANTS.RIGHT_SVG_WIDTH}px`)
3624
+ .style('bottom', '0')
3625
+ .style('height', `${xLabelSpace}px`)
3626
+ .style('display', 'flex')
3627
+ .style('justify-content', 'center')
3628
+ .style('align-items', 'center')
3629
+ .style('background-color', 'var(--card-bg)')
3630
+ .style('z-index', '10');
3631
+ return { svg, svgYAxisLeft, svgYAxisRight, innerContainer, bottomLabelContainer };
3632
+ }
3633
+ createScales(data, layers, lineData, dimensions) {
3634
+ const { width, height, barWidth, barPadding } = dimensions;
3635
+ // Calculate bar positioning
3636
+ const totalBarsWidth = data.length * barWidth;
3637
+ const totalSpacing = (data.length - 1) * barPadding;
3638
+ const requiredWidth = totalBarsWidth + totalSpacing + (this.CONSTANTS.LEFT_RIGHT_SPACES * 2);
3639
+ const effectiveWidth = Math.max(width, requiredWidth);
3640
+ const paddingRatio = barPadding / (barWidth + barPadding);
3641
+ // X-scale starts from 0 (no left spacing for grid alignment)
3642
+ const xScale = d3
3643
+ .scaleBand()
3644
+ .rangeRound([0, dimensions.requiredSvgWidth])
3645
+ .domain(data.map(d => d.name).reverse())
3646
+ .paddingInner(paddingRatio)
3647
+ .paddingOuter(0.1) // Small padding for visual spacing
3648
+ .align(0.5);
3649
+ const xScaleFromOrigin = d3
3650
+ .scaleBand()
3651
+ .rangeRound([width, 0])
3652
+ .domain(data.map(d => d.name).reverse());
3653
+ const yScale = d3.scaleLinear().rangeRound([height, 0]);
3654
+ let maxValue = d3.max(layers, (d) => d3.max(d, (d) => d[1]));
3655
+ if (maxValue === 0) {
3656
+ maxValue = this.chartData.targetLineData
3657
+ ? Number(this.chartData.targetLineData.target) + 20
3658
+ : 100;
3664
3659
  }
3665
- if (this.chartConfiguration.isXgridBetweenLabels) {
3666
- this.renderXAxisGrid(svg, x, height);
3660
+ if (this.chartConfiguration.customYscale) {
3661
+ maxValue *= this.chartConfiguration.customYscale;
3662
+ }
3663
+ if (this.chartData.targetLineData && maxValue < Number(this.chartData.targetLineData.target)) {
3664
+ const target = Number(this.chartData.targetLineData.target);
3665
+ maxValue = maxValue < 10 && target < 10 ? target + 3 : target + 20;
3667
3666
  }
3668
- if (lineData && this.chartConfiguration.showLineChartAxis && lineYscale) {
3669
- this.renderLineYAxis(svgYAxisRight, lineYscale);
3667
+ yScale.domain([0, maxValue]).nice();
3668
+ let lineYscale = null;
3669
+ if (lineData) {
3670
+ lineYscale = d3
3671
+ .scaleLinear()
3672
+ .domain([0, d3.max(lineData, d => +d.value)])
3673
+ .range([height, 0]);
3670
3674
  }
3675
+ return { xScale, xScaleFromOrigin, yScale, lineYscale };
3671
3676
  }
3672
- renderXAxis(svg, x, xScaleFromOrigin, height, chartContext, keyList) {
3673
- const { data, metaData } = chartContext;
3674
- if (this.chartConfiguration.isMultiChartGridLine === undefined) {
3675
- const xAxis = svg
3676
- .append('g')
3677
- .attr('class', 'x1 axis1')
3678
- .attr('transform', `translate(0,${height})`)
3679
- .call(d3.axisBottom(x).tickSize(0));
3680
- // FIXED: Show X-axis line
3681
- xAxis
3682
- .select('.domain')
3683
- .style('stroke', 'var(--chart-axis-color, #CCCCCC)')
3684
- .style('stroke-width', '1px')
3685
- .style('display', 'block');
3686
- xAxis.selectAll('g.tick line').remove();
3687
- const textClass = 'lib-xaxis-labels-texts-drilldown';
3688
- const textSelection = xAxis
3689
- .selectAll('g.tick text')
3690
- .attr('class', textClass)
3691
- .style('fill', 'var(--chart-text-color, #666666)')
3692
- .style('font-size', '11px');
3693
- if (keyList.length > 1 && !metaData.xLabel) {
3694
- textSelection.attr('y', 28);
3677
+ createAxes(scales) {
3678
+ const xAxis = d3
3679
+ .axisBottom(scales.xScale)
3680
+ .tickSize(0)
3681
+ .tickFormat(this.chartConfiguration.xAxisLabelFomatter);
3682
+ const yAxis = d3
3683
+ .axisLeft(scales.yScale)
3684
+ .ticks(this.chartConfiguration.numberOfYTicks)
3685
+ .tickSize(0)
3686
+ .tickFormat(this.chartConfiguration.yAxisLabelFomatter);
3687
+ let yLineAxis = null;
3688
+ if (scales.lineYscale) {
3689
+ yLineAxis = d3
3690
+ .axisRight(scales.lineYscale)
3691
+ .ticks(this.chartConfiguration.numberOfYTicks)
3692
+ .tickSize(0)
3693
+ .tickFormat(this.chartConfiguration.yLineAxisLabelFomatter);
3694
+ }
3695
+ return { xAxis, yAxis, yLineAxis };
3696
+ }
3697
+ renderBars(svg, layers, scales, metaData, dimensions) {
3698
+ const layer = svg
3699
+ .selectAll('.layer')
3700
+ .data(layers)
3701
+ .enter()
3702
+ .append('g')
3703
+ .attr('class', 'layer')
3704
+ .style('fill', (d) => metaData.colors[d.key]);
3705
+ const rect = layer
3706
+ .selectAll('rect')
3707
+ .data((d) => d)
3708
+ .enter();
3709
+ this.appendRectangles(rect, scales, metaData, dimensions);
3710
+ this.addInteractions(rect, svg, metaData, scales);
3711
+ return rect;
3712
+ }
3713
+ appendRectangles(rect, scales, metaData, dimensions) {
3714
+ const { barWidth, barPadding } = dimensions;
3715
+ const { xScale, yScale } = scales;
3716
+ rect
3717
+ .append('rect')
3718
+ .on('click', (d) => {
3719
+ if (!this.chartData.lineData || this.chartConfiguration.forComparison) {
3720
+ if (!metaData.barWithoutClick?.includes(d.data.name.toLowerCase())) {
3721
+ this.handleClick(d.data.name);
3722
+ }
3723
+ }
3724
+ })
3725
+ .attr('y', (d) => {
3726
+ if (!isNaN(d[0]) && !isNaN(d[1])) {
3727
+ const actualHeight = yScale(d[0]) - yScale(d[1]);
3728
+ return actualHeight < 3 ? yScale(d[0]) - 3 : yScale(d[1]);
3729
+ }
3730
+ return 0;
3731
+ })
3732
+ .attr('x', (d) => {
3733
+ const xPosition = xScale(d.data.name);
3734
+ const bandwidth = xScale.bandwidth();
3735
+ if (!this.chartConfiguration.isMultiChartGridLine) {
3736
+ return xPosition + (bandwidth - barWidth) / 2;
3737
+ }
3738
+ if (this.chartConfiguration.isDrilldownChart && this.chartData.data.length <= 3) {
3739
+ return xPosition + bandwidth / 2 - 35;
3740
+ }
3741
+ const calculatedWidth = bandwidth * 0.8;
3742
+ return xPosition + (bandwidth - calculatedWidth) / 2;
3743
+ })
3744
+ .attr('height', (d) => {
3745
+ if (!isNaN(d[0]) && !isNaN(d[1])) {
3746
+ const actualHeight = yScale(d[0]) - yScale(d[1]);
3747
+ return actualHeight < 3 ? 3 : actualHeight;
3695
3748
  }
3749
+ return 0;
3750
+ })
3751
+ .attr('width', (d) => {
3752
+ if (!this.chartConfiguration.isMultiChartGridLine)
3753
+ return barWidth;
3754
+ if (this.chartConfiguration.isDrilldownChart && this.chartData.data.length <= 3) {
3755
+ return 70;
3756
+ }
3757
+ return xScale.bandwidth() * 0.8;
3758
+ })
3759
+ .style('cursor', (d) => {
3760
+ if (metaData.hasDrillDown) {
3761
+ if (metaData.barWithoutClick?.includes(d.data.name.toLowerCase())) {
3762
+ return 'default';
3763
+ }
3764
+ return 'pointer';
3765
+ }
3766
+ return 'default';
3767
+ })
3768
+ .style('fill', (d) => this.getBarColor(d, metaData));
3769
+ }
3770
+ getBarColor(d, metaData) {
3771
+ if (!isNaN(d[0]) &&
3772
+ !isNaN(d[1]) &&
3773
+ this.chartData.targetLineData &&
3774
+ parseFloat(d[1]) - parseFloat(d[0]) >= parseFloat(String(this.chartData.targetLineData.target))) {
3775
+ return this.chartData.targetLineData.barAboveTargetColor || metaData.colors[d.key];
3696
3776
  }
3697
- else {
3698
- this.renderMultiChartXAxis(svg, x, height, data, metaData);
3777
+ return metaData.colors[d.key];
3778
+ }
3779
+ addInteractions(rect, svg, metaData, scales) {
3780
+ rect
3781
+ .selectAll('rect')
3782
+ .on('mouseenter', (d) => this.handleMouseOver(d, svg, metaData, scales))
3783
+ .on('mouseout', (d) => this.handleMouseOut(svg, metaData));
3784
+ }
3785
+ handleMouseOver(d, svg, metaData, scales) {
3786
+ if (!this.chartConfiguration.displayTitleOnTop)
3787
+ return;
3788
+ svg.selectAll('rect')
3789
+ .filter((data) => data === d)
3790
+ .style('fill', (d) => this.getHoverColor(d, metaData));
3791
+ this.displayTooltip(d, svg, metaData, scales);
3792
+ }
3793
+ getHoverColor(d, metaData) {
3794
+ if (!isNaN(d[0]) &&
3795
+ !isNaN(d[1]) &&
3796
+ this.chartData.targetLineData &&
3797
+ parseFloat(d[1]) - parseFloat(d[0]) >= parseFloat(String(this.chartData.targetLineData.target))) {
3798
+ return this.chartData.targetLineData.barAboveTargetHoverColor ||
3799
+ this.chartData.targetLineData.barAboveTargetColor ||
3800
+ metaData.colors[d.key];
3699
3801
  }
3700
- if (this.chartConfiguration.xLabelsOnSameLine) {
3701
- this.renderXLabelsOnSameLine(svg, data, metaData);
3802
+ return metaData.hoverColor || metaData.colors[d.key];
3803
+ }
3804
+ displayTooltip(d, svg, metaData, scales) {
3805
+ const { xScale, yScale } = scales;
3806
+ const value = d[1] - d[0];
3807
+ if (isNaN(value))
3808
+ return;
3809
+ const bandwidth = xScale.bandwidth();
3810
+ // Fixed tooltip width for all resolutions
3811
+ const width = /week/i.test(d.data.name) && /\d{4}-\d{2}-\d{2}/.test(d.data.name)
3812
+ ? '250px'
3813
+ : bandwidth + this.CONSTANTS.LEFT_RIGHT_SPACES * 2 > 180
3814
+ ? '180px'
3815
+ : bandwidth + this.CONSTANTS.LEFT_RIGHT_SPACES * 2;
3816
+ svg
3817
+ .append('foreignObject')
3818
+ .attr('x', this.calculateTooltipX(d, xScale, width))
3819
+ .attr('class', 'lib-verticalstack-title-ontop')
3820
+ .attr('y', yScale(d[1]) - 51)
3821
+ .attr('width', width)
3822
+ .attr('height', 40)
3823
+ .append('xhtml:div')
3824
+ .attr('class', 'title')
3825
+ .style('z-index', 99)
3826
+ .html(this.generateTooltipHtml(d, metaData, value));
3827
+ }
3828
+ calculateTooltipX(d, xScale, width) {
3829
+ const bandwidth = xScale.bandwidth();
3830
+ const numericWidth = typeof width === 'string' ? parseInt(width) : width;
3831
+ if (bandwidth + this.CONSTANTS.LEFT_RIGHT_SPACES * 2 > 180) {
3832
+ return xScale(d.data.name) - this.CONSTANTS.LEFT_RIGHT_SPACES +
3833
+ (bandwidth + this.CONSTANTS.LEFT_RIGHT_SPACES * 2 - 180) / 2;
3834
+ }
3835
+ return xScale(d.data.name) - this.CONSTANTS.LEFT_RIGHT_SPACES;
3836
+ }
3837
+ generateTooltipHtml(d, metaData, value) {
3838
+ if (value === 0)
3839
+ return '<span class="title-top-text">0</span>';
3840
+ const dataType = metaData.dataType || '';
3841
+ const name = d.data.name ? `<span class="title-bar-name">${d.data.name}</span>` : '';
3842
+ const valueText = metaData.unit
3843
+ ? `${metaData.unit}${value} ${dataType}`
3844
+ : `${value} ${dataType}`;
3845
+ return `${name}<span class="title-top-text">${valueText}</span>`;
3846
+ }
3847
+ handleMouseOut(svg, metaData) {
3848
+ if (!this.chartConfiguration.displayTitleOnTop)
3849
+ return;
3850
+ svg.selectAll('rect')
3851
+ .style('fill', (d) => this.getBarColor(d, metaData));
3852
+ svg.selectAll('.lib-verticalstack-title-ontop').remove();
3853
+ }
3854
+ renderAxisLabels(svg, svgYAxisLeft, bottomLabelContainer, metaData, dimensions, margin) {
3855
+ if (metaData.yLabel) {
3856
+ this.addYAxisLabel(svgYAxisLeft, metaData.yLabel, dimensions.height, margin);
3857
+ }
3858
+ if (metaData.xLabel) {
3859
+ this.addXAxisLabel(bottomLabelContainer, metaData.xLabel);
3860
+ }
3861
+ }
3862
+ addYAxisLabel(svgYAxisLeft, label, height, margin) {
3863
+ const isria = this.customChartConfiguration?.isRia;
3864
+ const isAcronym = this.isAcronymLabel(label);
3865
+ const yPosition = isria ? -margin.left / 2 - 30 : -margin.left / 2 - 40;
3866
+ svgYAxisLeft.selectAll('.lib-axis-group-label, .lib-ylabel-drilldowncharts, .lib-ylabel-weeklyCharts').remove();
3867
+ svgYAxisLeft
3868
+ .append('text')
3869
+ .attr('class', this.getYAxisLabelClass())
3870
+ .attr('style', this.chartConfiguration.yAxisCustomlabelStyles)
3871
+ .attr('transform', 'rotate(-90)')
3872
+ .attr('y', yPosition)
3873
+ .attr('x', -height / 2)
3874
+ .attr('dy', '1em')
3875
+ .style('text-anchor', 'middle')
3876
+ .style('fill', 'var(--chart-text-color)')
3877
+ .text(isAcronym ? label.toUpperCase() : label.toLowerCase())
3878
+ .style('text-transform', isAcronym ? 'none' : 'capitalize');
3879
+ }
3880
+ addXAxisLabel(bottomLabelContainer, label) {
3881
+ const isAcronym = this.isAcronymLabel(label);
3882
+ bottomLabelContainer
3883
+ .append('div')
3884
+ .style('width', '100%')
3885
+ .style('text-align', 'center')
3886
+ .style('font-size', '12px')
3887
+ .style('font-weight', '600')
3888
+ .style('font-family', 'system-ui, -apple-system, BlinkMacSystemFont, "Segoe UI", Roboto')
3889
+ .style('color', 'var(--chart-text-color)')
3890
+ .style('text-transform', isAcronym ? 'none' : 'capitalize')
3891
+ .text(isAcronym ? label.toUpperCase() : label.toLowerCase());
3892
+ }
3893
+ isAcronymLabel(label) {
3894
+ const cleanLabel = label.replace(/[^A-Za-z]/g, '');
3895
+ return (label.length <= 4 && /^[A-Z]+$/.test(label)) ||
3896
+ (label === label.toUpperCase() && /[A-Z]/.test(label));
3897
+ }
3898
+ getYAxisLabelClass() {
3899
+ let baseClass = 'lib-axis-group-label font-size-1';
3900
+ if (this.chartConfiguration.isDrilldownChart) {
3901
+ return `${baseClass} lib-ylabel-drilldowncharts`;
3902
+ }
3903
+ if (this.chartConfiguration.isMultiChartGridLine !== undefined) {
3904
+ return `${baseClass} lib-ylabel-weeklyCharts`;
3905
+ }
3906
+ return `${baseClass} lib-axis-waterfall-label`;
3907
+ }
3908
+ getXAxisLabelClass() {
3909
+ let baseClass = 'lib-axis-group-label font-size-1';
3910
+ if (this.chartConfiguration.isDrilldownChart) {
3911
+ return `${baseClass} lib-xlabel-drilldowncharts`;
3702
3912
  }
3703
- // Bottom x-axis
3704
- const xAxis2 = svg
3913
+ if (this.chartConfiguration.isMultiChartGridLine !== undefined) {
3914
+ return `${baseClass} lib-xlabel-weeklyCharts`;
3915
+ }
3916
+ return `${baseClass} lib-axis-waterfall-label`;
3917
+ }
3918
+ renderGridsFromLeftAxis(svgMain, svgYAxisLeft, scales, dimensions) {
3919
+ if (!this.chartConfiguration.yAxisGrid)
3920
+ return;
3921
+ // We want horizontal grid lines to span the full visible width:
3922
+ // the inner SVG (requiredSvgWidth) plus the right axis width.
3923
+ const gridSpan = dimensions.requiredSvgWidth + this.CONSTANTS.RIGHT_SVG_WIDTH;
3924
+ // Append the grid to the main (inner) SVG so lines are rendered across the scrollable area.
3925
+ svgMain
3705
3926
  .append('g')
3706
- .attr('class', 'x2 axis2')
3707
- .attr('transform', `translate(0,${height})`)
3708
- .style('color', '#000')
3709
- .call(d3.axisBottom(xScaleFromOrigin).tickSize(0));
3710
- xAxis2
3711
- .select('.domain')
3712
- .style('stroke', 'var(--chart-axis-color, #CCCCCC)')
3713
- .style('stroke-width', '1px')
3714
- .attr('fill', 'none');
3715
- svg.selectAll('g.x2.axis2 g.tick text').style('display', 'none');
3716
- if (this.isZoomedOut) {
3717
- svg.selectAll('.lib-xaxis-labels-texts-drilldown').attr('class', 'lib-display-hidden');
3927
+ .attr('class', 'grid horizontal-grid-from-left')
3928
+ .attr('transform', 'translate(0,0)')
3929
+ .call(d3
3930
+ .axisLeft(scales.yScale)
3931
+ .ticks(this.chartConfiguration.numberOfYTicks)
3932
+ .tickSize(-gridSpan)
3933
+ .tickFormat(''))
3934
+ .style('color', 'var(--chart-grid-color)')
3935
+ .style('opacity', '1')
3936
+ .call((g) => {
3937
+ g.select('.domain').remove();
3938
+ g.selectAll('.tick line')
3939
+ .style('stroke', 'var(--chart-grid-color)')
3940
+ .style('stroke-width', '1px');
3941
+ });
3942
+ }
3943
+ applyConfigurationFlags() {
3944
+ if (this.chartConfiguration.isHeaderVisible !== undefined) {
3945
+ this.isHeaderVisible = this.chartConfiguration.isHeaderVisible;
3946
+ }
3947
+ if (this.chartConfiguration.isTopCaptionVisible !== undefined) {
3948
+ this.isTopCaptionVisible = this.chartConfiguration.isTopCaptionVisible;
3949
+ }
3950
+ if (this.chartConfiguration.isTransparentBackground !== undefined) {
3951
+ this.isTransparentBackground = this.chartConfiguration.isTransparentBackground;
3952
+ }
3953
+ }
3954
+ initializeStackedChart() {
3955
+ // Use fixed configuration for all resolutions
3956
+ this.chartConfiguration.margin = { top: 20, right: 20, bottom: 40, left: 40 };
3957
+ this.chartConfiguration.numberOfYTicks = 5;
3958
+ this.chartConfiguration.svgHeight = 70;
3959
+ this.mergeConfigurations();
3960
+ this.applyConfigurationFlags();
3961
+ const data = this.chartData.data;
3962
+ const metaData = this.prepareMetaData(this.chartData.metaData);
3963
+ const lineData = this.chartData.lineData;
3964
+ const colors = metaData.colors;
3965
+ const keyList = metaData.keyList;
3966
+ const chartContainer = d3.select(this.containerElt.nativeElement);
3967
+ const verticalstackedcontainer = d3.select(this.groupcontainerElt.nativeElement);
3968
+ const margin = this.chartConfiguration.margin;
3969
+ const dimensions = this.calculateDimensions(chartContainer, verticalstackedcontainer, margin, data.length);
3970
+ const hasXLabel = !!metaData.xLabel;
3971
+ const { svg, svgYAxisLeft, svgYAxisRight, bottomLabelContainer } = this.createSvgContainers(chartContainer, dimensions, margin, hasXLabel);
3972
+ const stack = d3.stack().keys(keyList).offset(d3.stackOffsetNone);
3973
+ const layers = stack(data);
3974
+ data.sort((a, b) => b.total - a.total);
3975
+ const scales = this.createScales(data, layers, lineData, dimensions);
3976
+ const axes = this.createAxes(scales);
3977
+ this.renderGridsFromLeftAxis(svg, svgYAxisLeft, scales, dimensions);
3978
+ this.renderGrids(svg, scales, dimensions);
3979
+ const rect = this.renderBars(svg, layers, scales, metaData, dimensions);
3980
+ this.renderAxes(svg, svgYAxisLeft, svgYAxisRight, axes, scales, dimensions, data);
3981
+ this.renderAxisLabels(svg, svgYAxisLeft, bottomLabelContainer, metaData, dimensions, margin);
3982
+ this.renderTargetLine(svg, svgYAxisRight, scales, dimensions, metaData);
3983
+ this.renderDataLabels(rect, scales, metaData, dimensions);
3984
+ this.renderLineChart(svg, lineData, scales, colors, metaData);
3985
+ }
3986
+ renderGrids(svg, scales, dimensions) {
3987
+ if (this.chartConfiguration.isXgridBetweenLabels) {
3988
+ svg
3989
+ .append('g')
3990
+ .attr('class', 'grid vertical-grid')
3991
+ .attr('transform', `translate(${scales.xScale.bandwidth() / 2},${dimensions.height})`)
3992
+ .call(d3.axisBottom(scales.xScale).tickSize(-dimensions.height).tickFormat(''))
3993
+ .style('stroke-dasharray', '5 5')
3994
+ .style('color', '#999999')
3995
+ .call((g) => g.select('.domain').remove());
3996
+ }
3997
+ if (this.chartConfiguration.xAxisGrid) {
3998
+ for (let j = 0; j < this.chartConfiguration.xAxisGrid.length; j++) {
3999
+ svg
4000
+ .append('g')
4001
+ .attr('class', `x${j + 2} axis${j + 2}`)
4002
+ .style('color', 'var(--chart-grid-color)')
4003
+ .attr('transform', `translate(0,${dimensions.height * this.chartConfiguration.xAxisGrid[j]})`)
4004
+ .call(d3.axisBottom(scales.xScale).tickSize(0).ticks(5).tickFormat(''))
4005
+ .style('fill', 'var(--chart-text-color)');
4006
+ }
4007
+ }
4008
+ }
4009
+ renderAxes(svg, svgYAxisLeft, svgYAxisRight, axes, scales, dimensions, data) {
4010
+ if (this.chartConfiguration.showXaxisTop) {
4011
+ svg
4012
+ .append('g')
4013
+ .attr('class', 'lib-line-axis-text lib-line-x-axis-text x-axis')
4014
+ .attr('style', this.chartConfiguration.xAxisCustomTextStyles)
4015
+ .call(d3.axisBottom(scales.xScale).tickSize(0));
4016
+ svg.selectAll('.x-axis > g > text').attr('class', 'lib-display-hidden');
4017
+ }
4018
+ if (!this.chartConfiguration.isMultiChartGridLine) {
4019
+ this.renderStandardAxes(svg, axes, scales, dimensions, data);
3718
4020
  }
4021
+ else if (this.chartConfiguration.isDrilldownChart) {
4022
+ this.renderDrilldownAxes(svg, svgYAxisLeft, svgYAxisRight, axes, scales, dimensions);
4023
+ }
4024
+ else {
4025
+ this.renderMultiChartAxes(svg, axes, scales, dimensions);
4026
+ }
4027
+ this.applyAxisStyling(svg, svgYAxisLeft, svgYAxisRight);
4028
+ this.applyAxisConfigurations(svg, scales, dimensions, data);
3719
4029
  }
3720
- renderMultiChartXAxis(svg, x, height, data, metaData) {
3721
- let alternate_text = false;
3722
- const short_tick_length_bg = 5;
3723
- const long_tick_length_bg = 30;
3724
- svg
4030
+ renderStandardAxes(svg, axes, scales, dimensions, data) {
4031
+ const isMobileOrTablet = window.innerWidth < 1024;
4032
+ // X-axis with labels
4033
+ const xAxisGroup = svg
3725
4034
  .append('g')
3726
- .attr('class', 'x1 axis1')
3727
- .attr('transform', `translate(0,${height})`)
3728
- .call(d3.axisBottom(x).tickSize(0))
3729
- .call((g) => g.select('.domain').attr('fill', 'none'));
3730
- svg.selectAll('g.x1.axis1 g.tick line').attr('y2', () => {
3731
- if (alternate_text && !this.chartConfiguration.isNoAlternateXaxisText) {
3732
- alternate_text = false;
3733
- return long_tick_length_bg - 7;
3734
- }
3735
- else {
3736
- alternate_text = true;
3737
- return short_tick_length_bg - 4;
3738
- }
3739
- });
3740
- alternate_text = false;
3741
- svg.selectAll('g.x1.axis1 g.tick text').attr('class', 'lib-xaxis-labels-texts-weeklycharts').attr('y', () => {
3742
- if (alternate_text) {
3743
- alternate_text = false;
3744
- return long_tick_length_bg;
3745
- }
3746
- else {
3747
- alternate_text = true;
3748
- return short_tick_length_bg;
3749
- }
3750
- });
3751
- }
3752
- renderXLabelsOnSameLine(svg, data, metaData) {
3753
- const short_tick_length_bg = 5;
3754
- const long_tick_length_bg = 30;
3755
- svg
3756
- .selectAll('g.x1.axis1 g.tick text')
3757
- .attr('class', 'lib-xaxis-labels-texts-drilldown')
3758
- .attr('y', short_tick_length_bg)
3759
- .text((d) => {
3760
- const isValueToBeIgnored = data.some((indiv) => indiv.name.toLowerCase() === d.trim().toLowerCase() &&
3761
- indiv[metaData.keyList[0]] === -1);
3762
- if (isValueToBeIgnored)
3763
- return '';
3764
- if (d.trim().indexOf(' ') > -1) {
3765
- return d.trim().substring(0, d.indexOf(' ')).toLowerCase();
4035
+ .attr('transform', `translate(0,${dimensions.height})`)
4036
+ .attr('class', 'lib-stacked-x-axis-text')
4037
+ .call(axes.xAxis);
4038
+ // Style X-axis labels
4039
+ xAxisGroup
4040
+ .selectAll('text')
4041
+ .style('fill', 'var(--chart-text-color)')
4042
+ .style('font-size', isMobileOrTablet ? '10px' : '12px')
4043
+ .attr('text-anchor', 'middle')
4044
+ .attr('dy', '1em')
4045
+ .each(function (d) {
4046
+ const textElement = d3.select(this);
4047
+ const text = textElement.text();
4048
+ if (isMobileOrTablet && text.length > 12) {
4049
+ textElement.text(text.substring(0, 10) + '...');
3766
4050
  }
3767
- return d.toLowerCase();
3768
4051
  });
4052
+ // Ensure X-axis line starts exactly at x=0
4053
+ xAxisGroup
4054
+ .select('.domain')
4055
+ .style('stroke', 'var(--chart-axis-color)')
4056
+ .style('stroke-width', '1px')
4057
+ .attr('d', `M0,0.5H${dimensions.requiredSvgWidth}`);
4058
+ // Y-axis
3769
4059
  svg
3770
- .selectAll('g.x1.axis1 g.tick')
3771
- .append('text')
3772
- .attr('class', 'lib-xaxis-labels-texts-drilldown')
3773
- .attr('y', long_tick_length_bg)
3774
- .attr('fill', 'currentColor')
3775
- .text((d) => {
3776
- if (d.trim().indexOf(' ') > -1) {
3777
- return d.trim().substring(d.indexOf(' ')).toLowerCase();
3778
- }
3779
- return '';
3780
- });
4060
+ .append('g')
4061
+ .attr('class', 'lib-stacked-y-axis-text')
4062
+ .attr('style', this.chartConfiguration.yAxisCustomTextStyles)
4063
+ .call(axes.yAxis)
4064
+ .selectAll('text')
4065
+ .style('fill', 'var(--chart-text-color)');
3781
4066
  }
3782
- renderYAxis(svg, svgYAxisLeft, svgYAxisRight, y, dimensions) {
3783
- // Main Y-axis in chart area (hidden)
4067
+ renderDrilldownAxes(svg, svgYAxisLeft, svgYAxisRight, axes, scales, dimensions) {
3784
4068
  svg
3785
4069
  .append('g')
3786
- .attr('class', 'lib-stacked-y-axis-text yaxis-dashed')
3787
- .attr('style', this.chartConfiguration.yAxisCustomTextStyles)
3788
- .attr('transform', 'translate(0,0)')
3789
- .call(y)
4070
+ .attr('transform', `translate(0,${dimensions.height})`)
4071
+ .attr('class', 'lib-stacked-x-axis-text multichart1')
4072
+ .call(axes.xAxis)
3790
4073
  .style('display', 'none');
3791
- // FIXED: Left Y-axis with visible line
3792
- const yAxisLeft = d3
3793
- .axisLeft(y)
3794
- .tickSize(0)
3795
- .ticks(this.chartConfiguration.numberOfYTicks)
3796
- .tickFormat(this.chartConfiguration.yAxisLabelFomatter);
3797
- const yAxisGroup = svgYAxisLeft
4074
+ svgYAxisLeft
3798
4075
  .append('g')
3799
4076
  .attr('class', 'lib-yaxis-labels-texts-drilldown yaxis-dashed')
3800
4077
  .attr('style', this.chartConfiguration.yAxisCustomTextStyles)
3801
- .attr('transform', 'translate(0,0)')
3802
- .call(yAxisLeft);
3803
- // FIXED: Show Y-axis vertical line
3804
- yAxisGroup
3805
- .select('.domain')
3806
- .style('stroke', 'var(--chart-axis-color, #CCCCCC)')
3807
- .style('stroke-width', '1px')
3808
- .style('display', 'block');
3809
- // FIXED: Position Y-axis values with proper spacing
3810
- yAxisGroup
4078
+ .call(axes.yAxis)
3811
4079
  .selectAll('text')
3812
- .style('fill', 'var(--chart-text-color, #666666)')
3813
- .style('font-size', '11px')
3814
- .style('font-weight', '400')
3815
- .attr('x', -6) // FIXED: Small gap from axis line
3816
- .attr('text-anchor', 'end')
3817
- .attr('dy', '0.32em');
3818
- // Right Y-axis (hidden)
4080
+ .style('fill', 'var(--chart-text-color)');
3819
4081
  svgYAxisRight
3820
4082
  .append('g')
3821
4083
  .attr('class', 'lib-yaxis-labels-texts-drilldown yaxis-dashed')
3822
4084
  .attr('style', this.chartConfiguration.yAxisCustomTextStyles)
3823
- .attr('transform', 'translate(0,0)')
3824
- .call(y)
4085
+ .call(axes.yAxis)
3825
4086
  .style('display', 'none');
3826
- this.applyAxisVisibilitySettings();
3827
- }
3828
- applyAxisVisibilitySettings() {
3829
- if (this.chartConfiguration.isXaxisLabelHidden) {
3830
- d3.selectAll('g.lib-line-x-axis-text > g > text').attr('class', 'lib-display-hidden');
3831
- }
3832
- if (this.chartConfiguration.isYaxisLabelHidden) {
3833
- d3.selectAll('.yaxis-dashed > g > text').attr('class', 'lib-display-hidden');
3834
- // FIXED: Don't hide the Y-axis label element
3835
- d3.selectAll('.lib-ylabel-visible').style('display', 'block');
3836
- }
3837
- if (this.chartConfiguration.isYaxisHidden) {
3838
- d3.selectAll('.yaxis-dashed').attr('class', 'lib-display-hidden');
3839
- // FIXED: Keep Y-axis label visible
3840
- d3.selectAll('.lib-ylabel-visible').style('display', 'block');
3841
- }
3842
- if (this.chartConfiguration.isYaxisDashed) {
3843
- d3.selectAll('.yaxis-dashed .domain').style('stroke-dasharray', '5 5').style('color', '#999999');
3844
- }
3845
4087
  }
3846
- renderYAxisGrid(svg, y, width) {
4088
+ renderMultiChartAxes(svg, axes, scales, dimensions) {
3847
4089
  svg
3848
4090
  .append('g')
3849
- .attr('class', 'y-axis-grid')
3850
- .call(d3.axisLeft(y)
3851
- .ticks(this.chartConfiguration.numberOfYTicks)
3852
- .tickSize(-width)
3853
- .tickFormat(''))
3854
- .style('color', '#EEEEEE') // FIXED: Lighter grid
3855
- .style('opacity', '0.7')
3856
- .style('stroke-dasharray', 'none')
3857
- .call((g) => g.select('.domain').remove())
3858
- .selectAll('line')
3859
- .style('stroke-width', '0.5px');
3860
- }
3861
- renderXAxisGrid(svg, x, height) {
4091
+ .attr('transform', `translate(0,${dimensions.height})`)
4092
+ .attr('class', 'lib-stacked-x-axis-text multichart')
4093
+ .call(axes.xAxis)
4094
+ .selectAll('text')
4095
+ .style('fill', 'var(--chart-text-color)');
3862
4096
  svg
3863
4097
  .append('g')
3864
- .attr('class', 'grid')
3865
- .attr('transform', `translate(${x.bandwidth() / 2},${height})`)
3866
- .call(d3.axisBottom(x).tickSize(-height).tickFormat(''))
3867
- .style('stroke-dasharray', '5 5')
3868
- .style('color', 'var(--chart-grid-color, #999999)')
3869
- .call((g) => g.select('.domain').remove());
3870
- }
3871
- renderLineYAxis(svgYAxisRight, lineYscale) {
3872
- const yLineAxis = d3
3873
- .axisRight(lineYscale)
3874
- .ticks(this.chartConfiguration.numberOfYTicks)
3875
- .tickSize(0)
3876
- .tickFormat(this.chartConfiguration.yLineAxisLabelFomatter);
3877
- svgYAxisRight
3878
- .append('g')
3879
- .attr('class', 'lib-stacked-y-axis-text1')
4098
+ .attr('class', 'lib-stacked-y-axis-text yaxis-dashed')
3880
4099
  .attr('style', this.chartConfiguration.yAxisCustomTextStyles)
3881
- .attr('transform', 'translate(0,0)')
3882
- .call(yLineAxis);
3883
- }
3884
- renderBars(svg, chartContext, scales, dimensions) {
3885
- const { data, metaData, keyList, isRia } = chartContext;
3886
- const { x, xSubgroup, y } = scales;
3887
- const { height } = dimensions;
3888
- const state = svg
3889
- .append('g')
3890
- .selectAll('.state')
3891
- .data(data)
3892
- .enter()
3893
- .append('g')
3894
- .attr('transform', (d) => `translate(${x(d.name)},0)`);
3895
- state
3896
- .selectAll('rect')
3897
- .data((d) => this.prepareBarData(d, keyList))
3898
- .enter()
3899
- .append('rect')
3900
- .attr('class', 'bars')
3901
- .on('click', (d) => this.handleBarClick(d, metaData))
3902
- .attr('x', (d) => this.getBarX(d, data, x, xSubgroup))
3903
- .attr('y', (d) => y(d.value))
3904
- .attr('width', (d) => this.getBarWidth(d, data, x, xSubgroup))
3905
- .attr('height', (d) => this.getBarHeight(d, y, height))
3906
- .style('cursor', (d) => (metaData.hasDrillDown && !isRia ? 'pointer' : 'default'))
3907
- .attr('fill', (d) => this.getBarColor(d, metaData));
3908
- if (!isRia && (this.chartConfiguration.displayTitleOnTop || (!this.chartConfiguration.textsOnBar && !this.chartConfiguration.displayTitleOnTop))) {
3909
- state.selectAll('rect').on('mouseout', (d, i) => this.handleMouseOut(svg)).on('mouseover', (d, i) => this.handleMouseOver(svg, d, data, metaData, x, y, scales.leftAndRightSpaces));
3910
- }
3911
- if (this.chartConfiguration.textsOnBar && !this.isZoomedOut) {
3912
- this.renderBarTexts(state, data, metaData, keyList, x, xSubgroup, y, isRia, svg);
3913
- }
3914
- if (this.chartConfiguration.isDrilldownChart) {
3915
- svg.selectAll('g.x1.axis1 g.tick line').style('display', 'none');
3916
- }
3917
- }
3918
- prepareBarData(d, keyList) {
3919
- return keyList.map((key) => ({ key, value: d[key], name: d.name }));
4100
+ .call(axes.yAxis)
4101
+ .selectAll('text')
4102
+ .style('fill', 'var(--chart-text-color)');
3920
4103
  }
3921
- handleBarClick(d, metaData) {
3922
- if (d.key === 'Target')
3923
- return;
3924
- if (!metaData.barWithoutClick?.length ||
3925
- (!metaData.barWithoutClick.includes(d?.name) && !metaData.barWithoutClick.includes(d?.key))) {
3926
- this.handleClick(d);
4104
+ applyAxisStyling(svg, svgYAxisLeft, svgYAxisRight) {
4105
+ const styleAxisDomain = (container) => {
4106
+ container.selectAll('.domain')
4107
+ .style('stroke', 'var(--chart-axis-color)')
4108
+ .style('stroke-width', '1px');
4109
+ };
4110
+ styleAxisDomain(svg);
4111
+ styleAxisDomain(svgYAxisLeft);
4112
+ styleAxisDomain(svgYAxisRight);
4113
+ if (this.chartConfiguration.isYaxisDashed) {
4114
+ d3.selectAll('.yaxis-dashed')
4115
+ .style('stroke-dasharray', '5 5')
4116
+ .style('color', 'var(--chart-grid-color)');
3927
4117
  }
3928
- }
3929
- getBarX(d, data, x, xSubgroup) {
3930
- if (this.chartConfiguration.isDrilldownChart) {
3931
- return this.calculateDrilldownBarX(d, data, x);
4118
+ if (this.chartConfiguration.isXaxisColor) {
4119
+ d3.selectAll('.multichart').style('color', this.chartConfiguration.isXaxisColor || 'var(--chart-text-color)');
3932
4120
  }
3933
- return xSubgroup(d.key);
3934
- }
3935
- calculateDrilldownBarX(d, data, x) {
3936
- let tempScale;
3937
- data.forEach((indiv) => {
3938
- if (indiv.name === d.name) {
3939
- const keys = Object.keys(indiv).filter((temp, i) => i !== 0);
3940
- tempScale = d3.scaleBand().domain(keys).range([0, x.bandwidth()]);
3941
- if (x.bandwidth() > 100) {
3942
- tempScale = this.adjustDrilldownScale(tempScale, data, x);
3943
- }
3944
- }
3945
- });
3946
- return tempScale ? tempScale(d.key) : 0;
3947
4121
  }
3948
- adjustDrilldownScale(tempScale, data, x) {
3949
- if (this.chartData.data.length === 1) {
3950
- const keysLength = Object.keys(this.chartData.data[0]).length;
3951
- const offset = keysLength === 2 ? 200 : 300;
3952
- tempScale.range([
3953
- 0 + (x.bandwidth() - offset) / 2,
3954
- x.bandwidth() - (x.bandwidth() - offset) / 2,
3955
- ]);
4122
+ applyAxisConfigurations(svg, scales, dimensions, data) {
4123
+ if (this.chartConfiguration.isMultiChartGridLine !== undefined) {
4124
+ d3.selectAll('.multichart > g > text').attr('class', 'lib-display-hidden');
3956
4125
  }
3957
- else {
3958
- tempScale.range([
3959
- 0 + (x.bandwidth() - 125) / 2,
3960
- x.bandwidth() - (x.bandwidth() - 125) / 2,
3961
- ]);
4126
+ if (this.chartConfiguration.isXaxisLabelHidden) {
4127
+ d3.selectAll('.multichart > g > text').attr('class', 'lib-display-hidden');
3962
4128
  }
3963
- return tempScale;
3964
- }
3965
- getBarWidth(d, data, x, xSubgroup) {
3966
- if (this.chartConfiguration.isDrilldownChart) {
3967
- let tempScale;
3968
- data.forEach((indiv) => {
3969
- if (indiv.name === d.name) {
3970
- const keys = Object.keys(indiv).filter((temp, i) => i !== 0);
3971
- tempScale = d3.scaleBand().domain(keys).range([0, x.bandwidth()]);
3972
- if (x.bandwidth() > 100) {
3973
- tempScale = this.adjustDrilldownScale(tempScale, data, x);
3974
- }
3975
- }
3976
- });
3977
- return tempScale ? tempScale.bandwidth() : 0;
4129
+ else if (this.chartConfiguration.isXaxisLabelHidden !== undefined) {
4130
+ this.renderCustomXAxis(svg, scales, dimensions, data);
3978
4131
  }
3979
- return xSubgroup.bandwidth();
3980
- }
3981
- getBarHeight(d, y, height) {
3982
- if (d.value === -1)
3983
- return height - y(0);
3984
- if (d.value)
3985
- return height - y(d.value);
3986
- return height - y(0);
3987
- }
3988
- getBarColor(d, metaData) {
3989
- if (d.value &&
3990
- this.chartData.targetLineData &&
3991
- d.value >= parseInt(this.chartData.targetLineData.target) &&
3992
- this.chartData.metaData.colorAboveTarget) {
3993
- return this.chartData.metaData.colorAboveTarget[d.key];
4132
+ if (this.chartConfiguration.isYaxisLabelHidden) {
4133
+ svg.selectAll('.yaxis-dashed > g > text').attr('class', 'lib-display-hidden');
3994
4134
  }
3995
- return this.chartData.metaData.colors[d.key];
3996
- }
3997
- renderBarTexts(state, data, metaData, keyList, x, xSubgroup, y, isRia, svg) {
3998
- state
3999
- .selectAll('text')
4000
- .data((d) => this.prepareBarData(d, keyList))
4001
- .enter()
4002
- .append('text')
4003
- .attr('x', 0)
4004
- .attr('y', 0)
4005
- .attr('class', 'lib-data-labels-weeklycharts')
4006
- .text((d) => this.getBarTextLabel(d))
4007
- .style('fill', '#000')
4008
- .style('font-weight', 'bold')
4009
- .style('font-size', () => this.getBarTextFontSize())
4010
- .attr('transform', (d) => this.getBarTextTransform(d, data, x, xSubgroup, y))
4011
- .on('click', (d) => this.handleBarClick(d, metaData));
4012
- if (!isRia) {
4013
- state
4014
- .selectAll('.lib-data-labels-weeklycharts')
4015
- .on('mouseout', (d, i) => this.handleMouseOut(svg))
4016
- .on('mouseover', (d, i) => this.handleMouseOver(svg, d, data, metaData, x, y, x.bandwidth()));
4135
+ if (this.chartConfiguration.isYaxisHidden) {
4136
+ d3.selectAll('.yaxis-dashed').attr('class', 'lib-display-hidden');
4017
4137
  }
4018
- }
4019
- getBarTextLabel(d) {
4020
- if (!d.key || !d.value)
4021
- return '';
4022
- return d.key.length > 20 ? d.key.substring(0, 17) + '...' : d.key;
4023
- }
4024
- getBarTextFontSize() {
4025
- if (this.chartConfiguration.isDrilldownChart) {
4026
- if (window.innerWidth > 1900)
4027
- return '18px';
4028
- if (window.innerWidth < 1400)
4029
- return '10px';
4030
- return '14px';
4138
+ if (this.isZoomedOut && data.length > 9) {
4139
+ svg
4140
+ .selectAll('.lib-xaxis-labels-texts-drilldown')
4141
+ .attr('transform', 'rotate(-90)')
4142
+ .attr('text-anchor', 'end')
4143
+ .attr('x', '-5')
4144
+ .attr('dy', null);
4031
4145
  }
4032
- return '14px';
4033
4146
  }
4034
- getBarTextTransform(d, data, x, xSubgroup, y) {
4035
- let tempScale;
4036
- data.forEach((indiv) => {
4037
- if (indiv.name === d.name) {
4038
- const keys = Object.keys(indiv).filter((temp, i) => i !== 0);
4039
- tempScale = d3.scaleBand().domain(keys).range([0, x.bandwidth()]);
4040
- if (x.bandwidth() > 100) {
4041
- tempScale = this.adjustDrilldownScale(tempScale, data, x);
4042
- }
4043
- }
4044
- });
4045
- if (this.chartConfiguration.textAlwaysHorizontal) {
4046
- return `translate(${xSubgroup(d.key)},${y(d.value) - 3})`;
4047
- }
4048
- if (tempScale && !isNaN(tempScale(d.key))) {
4049
- return `translate(${tempScale(d.key) + tempScale.bandwidth() * 0.55},${y(0) - 10}) rotate(270)`;
4147
+ renderCustomXAxis(svg, scales, dimensions, data) {
4148
+ svg
4149
+ .append('g')
4150
+ .attr('class', 'x1 axis1')
4151
+ .attr('transform', `translate(0,${dimensions.height})`)
4152
+ .style('color', '#000')
4153
+ .call(d3.axisBottom(scales.xScale).tickSize(0))
4154
+ .call((g) => g.select('.domain').attr('fill', 'none'));
4155
+ this.styleCustomXAxisTicks(svg, data);
4156
+ if (this.chartConfiguration.xLabelsOnSameLine) {
4157
+ this.applyXLabelsOnSameLine(svg);
4050
4158
  }
4051
- return 'translate(0,0)';
4052
4159
  }
4053
- handleMouseOver(svg, d, data, metaData, x, y, leftAndRightSpaces) {
4054
- svg.selectAll('.lib-verticalstack-title-ontop').remove();
4055
- let tempScale;
4056
- data.forEach((indiv) => {
4057
- if (indiv.name === d.name) {
4058
- const keys = Object.keys(indiv).filter((temp, i) => i !== 0);
4059
- tempScale = d3.scaleBand().domain(keys).range([0, x.bandwidth()]);
4060
- if (x.bandwidth() > 100) {
4061
- tempScale = this.adjustDrilldownScale(tempScale, data, x);
4062
- }
4160
+ styleCustomXAxisTicks(svg, data) {
4161
+ let alternateText = false;
4162
+ svg.selectAll('.x1.axis1 .tick line').attr('y2', () => {
4163
+ if (this.chartConfiguration.hideXaxisTick)
4164
+ return 0;
4165
+ if (alternateText && !this.chartConfiguration.isNoAlternateXaxisText) {
4166
+ alternateText = false;
4167
+ return this.CONSTANTS.LONG_TICK_LENGTH_BG - 7;
4063
4168
  }
4169
+ alternateText = true;
4170
+ return this.CONSTANTS.SHORT_TICK_LENGTH_BG - 4;
4064
4171
  });
4065
- const foreignObject = svg
4066
- .append('foreignObject')
4067
- .attr('x', () => this.calculateTooltipX(d, x, tempScale, metaData, leftAndRightSpaces))
4068
- .attr('y', () => y(d.value) - 43)
4069
- .attr('class', 'lib-verticalstack-title-ontop')
4070
- .attr('width', () => this.calculateTooltipWidth(tempScale, metaData, leftAndRightSpaces))
4071
- .attr('height', 40);
4072
- foreignObject
4073
- .append('xhtml:div')
4074
- .attr('class', 'title')
4075
- .style('z-index', 99)
4076
- .html(() => this.getTooltipHTML(d, metaData));
4077
- }
4078
- calculateTooltipX(d, x, tempScale, metaData, leftAndRightSpaces) {
4079
- if (metaData.hasDrillDown) {
4080
- if (tempScale.bandwidth() + leftAndRightSpaces * 2 > 180) {
4081
- return x(d.name) + tempScale(d.key) + tempScale.bandwidth() / 2 - 90;
4172
+ alternateText = false;
4173
+ svg
4174
+ .selectAll('g.x1.axis1 g.tick text')
4175
+ .attr('class', () => {
4176
+ if (this.chartConfiguration.isDrilldownChart) {
4177
+ return data.length > 8
4178
+ ? 'lib-xaxis-labels-texts-drilldown-alt'
4179
+ : 'lib-xaxis-labels-texts-drilldown';
4082
4180
  }
4083
- return (x(d.name) +
4084
- tempScale(d.key) -
4085
- (tempScale.bandwidth() + leftAndRightSpaces * 2) / 2 +
4086
- tempScale.bandwidth() / 2);
4087
- }
4088
- return (x(d.name) +
4089
- tempScale(d.key) -
4090
- (tempScale.bandwidth() + leftAndRightSpaces * 2) / 2 +
4091
- tempScale.bandwidth() / 2);
4092
- }
4093
- calculateTooltipWidth(tempScale, metaData, leftAndRightSpaces) {
4094
- if (metaData.hasDrillDown) {
4095
- if (tempScale.bandwidth() + leftAndRightSpaces * 2 > 180) {
4096
- return '180px';
4181
+ return 'lib-xaxis-labels-texts-weeklycharts';
4182
+ })
4183
+ .attr('y', () => {
4184
+ if (alternateText) {
4185
+ alternateText = false;
4186
+ return this.CONSTANTS.LONG_TICK_LENGTH_BG;
4097
4187
  }
4098
- return tempScale.bandwidth() + leftAndRightSpaces * 2;
4099
- }
4100
- return tempScale.bandwidth() + leftAndRightSpaces * 2;
4101
- }
4102
- getTooltipHTML(d, metaData) {
4103
- const dataType = metaData.dataType || '';
4104
- if (!this.isZoomedOut) {
4105
- return `<span class="title-bar-name">${d.name}</span><span class="title-bar-value"><span>${d.value}</span>${dataType}</span>`;
4106
- }
4107
- else {
4108
- const tempKey = d.name.length <= 8 ? d.name : d.name.substring(0, 5) + '...';
4109
- return `<span class="title-bar-name">${tempKey}:${d.value}${dataType}</span><span class="title-bar-value">${d.name}</span>`;
4110
- }
4111
- }
4112
- handleMouseOut(svg) {
4113
- svg.selectAll('.lib-verticalstack-title-ontop').remove();
4114
- }
4115
- renderLabels(svgElements, scales, chartContext, dimensions) {
4116
- const { svg, svgYAxisLeft, svgYAxisRight } = svgElements;
4117
- const { metaData } = chartContext;
4118
- const { width, height, margin } = dimensions;
4119
- if (metaData.yLabel) {
4120
- this.renderYAxisLabel(svgYAxisLeft, metaData.yLabel, height, margin);
4121
- }
4122
- if (metaData.xLabel) {
4123
- this.renderXAxisLabel(svg, metaData.xLabel, width, height, margin);
4124
- }
4125
- if (metaData.lineyLabel) {
4126
- this.renderLineYAxisLabel(svgYAxisRight, metaData.lineyLabel);
4127
- }
4188
+ alternateText = true;
4189
+ return this.CONSTANTS.SHORT_TICK_LENGTH_BG;
4190
+ });
4128
4191
  }
4129
- renderYAxisLabel(svgYAxisLeft, yLabel, height, margin) {
4130
- // FIXED: Proper Y-axis label with correct positioning
4131
- svgYAxisLeft
4192
+ applyXLabelsOnSameLine(svg) {
4193
+ svg
4194
+ .selectAll('g.x1.axis1 g.tick text')
4195
+ .attr('class', 'lib-xaxis-labels-texts-drilldown')
4196
+ .attr('y', this.CONSTANTS.SHORT_TICK_LENGTH_BG)
4197
+ .text((d) => {
4198
+ const trimmed = d.trim();
4199
+ const spaceIndex = trimmed.indexOf(' ');
4200
+ return spaceIndex > -1
4201
+ ? trimmed.substring(0, spaceIndex).toLowerCase()
4202
+ : trimmed.toLowerCase();
4203
+ });
4204
+ svg
4205
+ .selectAll('g.x1.axis1 g.tick')
4132
4206
  .append('text')
4133
- .attr('class', 'lib-axis-group-label lib-ylabel-visible')
4134
- .attr('style', this.chartConfiguration.yAxisCustomlabelStyles)
4135
- .attr('transform', 'rotate(-90)')
4136
- .attr('y', -margin.left)
4137
- .attr('x', 0 - height / 2)
4138
- .attr('dy', '1em')
4139
- .style('text-anchor', 'middle')
4140
- .style('font-size', '11px')
4141
- .style('font-weight', '400')
4142
- .style('fill', 'var(--chart-text-color, #666666)');
4143
- if (this.chartConfiguration.isMultiChartGridLine === undefined) {
4144
- svgYAxisLeft.selectAll('.lib-axis-group-label').text(yLabel);
4145
- }
4146
- else {
4147
- svgYAxisLeft
4148
- .selectAll('.lib-axis-group-label')
4149
- .attr('class', 'lib-ylabel-weeklyCharts lib-ylabel-visible')
4150
- .text(yLabel.toLowerCase());
4151
- }
4207
+ .attr('class', 'lib-xaxis-labels-texts-drilldown')
4208
+ .attr('y', this.CONSTANTS.LONG_TICK_LENGTH_BG)
4209
+ .attr('fill', 'currentColor')
4210
+ .text((d) => {
4211
+ const trimmed = d.trim();
4212
+ const spaceIndex = trimmed.indexOf(' ');
4213
+ return spaceIndex > -1
4214
+ ? trimmed.substring(spaceIndex).toLowerCase()
4215
+ : '';
4216
+ });
4152
4217
  }
4153
- renderXAxisLabel(svg, xLabel, width, height, margin) {
4154
- const isAcronym = this.isAcronym(xLabel.replace(/[^A-Za-z]/g, ''));
4155
- let baseClass = 'lib-axis-group-label font-size-1';
4156
- if (this.chartConfiguration.isDrilldownChart) {
4157
- baseClass += ' lib-xlabel-drilldowncharts';
4218
+ renderDataLabels(rect, scales, metaData, dimensions) {
4219
+ if (!this.isCC && !this.chartConfiguration.isMultiChartGridLine) {
4220
+ rect.append('svg:title').text((d) => d[1] - d[0]);
4158
4221
  }
4159
- else if (this.chartConfiguration.isMultiChartGridLine !== undefined) {
4160
- baseClass += ' lib-xlabel-weeklyCharts';
4222
+ if (this.chartConfiguration.showTotalOnTop) {
4223
+ this.renderTopLabels(rect, scales, metaData);
4161
4224
  }
4162
- else {
4163
- baseClass += ' lib-axis-waterfall-label';
4225
+ if (this.chartConfiguration.showAngledLabels) {
4226
+ this.renderAngledLabels(rect, scales, metaData);
4164
4227
  }
4165
- svg
4166
- .append('text')
4167
- .attr('class', baseClass)
4168
- .attr('style', this.chartConfiguration.xAxisCustomlabelStyles)
4169
- // FIXED: Adjusted for reduced bottom margin
4170
- .attr('transform', `translate(${width / 2},${height + 32})`)
4171
- .style('text-anchor', 'middle')
4172
- .style('fill', 'var(--chart-text-color, #666666)')
4173
- .style('font-size', '11px')
4174
- .text(isAcronym ? xLabel.toUpperCase() : xLabel.toLowerCase())
4175
- .style('text-transform', isAcronym ? 'none' : 'capitalize');
4176
4228
  }
4177
- isAcronym(label) {
4178
- return ((label.length <= 4 && /^[A-Z]+$/.test(label)) ||
4179
- (label === label.toUpperCase() && /[A-Z]/.test(label)));
4229
+ renderTopLabels(rect, scales, metaData) {
4230
+ const formatFromBackend = this.chartConfiguration.textFormatter
4231
+ ? ChartHelper.dataValueFormatter(this.chartConfiguration.textFormatter)
4232
+ : (d) => d;
4233
+ const formatForHugeNumbers = ChartHelper.dataValueFormatter('.2s');
4234
+ rect
4235
+ .append('text')
4236
+ .attr('x', (d) => scales.xScale(d.data.name) + scales.xScale.bandwidth() / 2)
4237
+ .attr('class', 'lib-verticalstack-labels-ontop-weklycharts')
4238
+ .attr('y', (d) => scales.yScale(d[1]) - 3)
4239
+ .text((d) => {
4240
+ const value = d[1] - d[0];
4241
+ if (isNaN(value) || value === 0)
4242
+ return;
4243
+ const formattedValue = value <= 999
4244
+ ? formatFromBackend(value)
4245
+ : formatForHugeNumbers(value);
4246
+ return metaData.unit ? metaData.unit + formattedValue : formattedValue;
4247
+ });
4180
4248
  }
4181
- renderLineYAxisLabel(svgYAxisRight, lineyLabel) {
4182
- svgYAxisRight
4249
+ renderAngledLabels(rect, scales, metaData) {
4250
+ const formatFromBackend = this.chartConfiguration.textFormatter
4251
+ ? ChartHelper.dataValueFormatter(this.chartConfiguration.textFormatter)
4252
+ : (d) => d;
4253
+ const formatForHugeNumbers = ChartHelper.dataValueFormatter('.2s');
4254
+ const tempObjectHolder = {};
4255
+ rect
4183
4256
  .append('text')
4184
- .attr('class', 'lib-axis-group-label lib-line-axis')
4185
- .attr('style', this.chartConfiguration.yAxisCustomlabelStyles)
4186
- .attr('transform', 'translate(0,0) rotate(90)')
4187
- .attr('y', -100)
4188
- .attr('x', 100)
4189
- .attr('dy', '5em')
4190
- .style('text-anchor', 'middle')
4191
- .style('font-size', 'smaller')
4192
- .text(lineyLabel);
4257
+ .attr('x', 0)
4258
+ .attr('y', 0)
4259
+ .attr('fill', (d) => metaData.colors[d.key])
4260
+ .attr('class', 'lib-data-labels-angled-weeklycharts')
4261
+ .text((d) => {
4262
+ const value = d[1] - d[0];
4263
+ if (isNaN(value) || value <= 0)
4264
+ return;
4265
+ const formattedValue = value <= 999
4266
+ ? formatFromBackend(value)
4267
+ : formatForHugeNumbers(value);
4268
+ return metaData.unit ? metaData.unit + formattedValue : formattedValue;
4269
+ })
4270
+ .attr('transform', (d) => {
4271
+ const value = d[1] - d[0];
4272
+ if (isNaN(value) || value <= 0)
4273
+ return 'rotate(0)';
4274
+ let total = 0;
4275
+ let incrementer = 1;
4276
+ metaData.keyList.forEach(key => {
4277
+ if (d.data[key]) {
4278
+ total += d.data[key];
4279
+ }
4280
+ else {
4281
+ incrementer = 2;
4282
+ }
4283
+ });
4284
+ tempObjectHolder[d.data.name] = (tempObjectHolder[d.data.name] || 0) + incrementer;
4285
+ const position = tempObjectHolder[d.data.name];
4286
+ const xPos = scales.xScale(d.data.name);
4287
+ const bandwidth = scales.xScale.bandwidth();
4288
+ const yPos = scales.yScale(total) - 3;
4289
+ switch (position) {
4290
+ case 1:
4291
+ return `translate(${xPos + bandwidth / 3},${yPos}) rotate(270)`;
4292
+ case 2:
4293
+ return `translate(${xPos + bandwidth / 2 + 2},${yPos}) rotate(270)`;
4294
+ default:
4295
+ return `translate(${xPos + (bandwidth * 3) / 4},${yPos}) rotate(270)`;
4296
+ }
4297
+ });
4193
4298
  }
4194
- renderTargetLine(svgElements, scales, chartContext, dimensions) {
4299
+ renderTargetLine(svg, svgYAxisRight, scales, dimensions, metaData) {
4195
4300
  if (!this.chartData.targetLineData)
4196
4301
  return;
4197
- const { svg, svgYAxisRight } = svgElements;
4198
- const { y } = scales;
4199
- const { width } = dimensions;
4200
- const { metaData } = chartContext;
4201
- const targetData = this.chartData.targetLineData;
4202
- const yZero = y(targetData.target);
4302
+ const parsedTarget = this.parseTargetValue(this.chartData.targetLineData.target);
4303
+ const yZero = scales.yScale(parsedTarget);
4203
4304
  svg
4204
4305
  .append('line')
4205
4306
  .attr('x1', 0)
4206
- .attr('x2', width)
4307
+ .attr('x2', dimensions.width)
4207
4308
  .attr('y1', yZero)
4208
4309
  .attr('y2', yZero)
4209
4310
  .style('stroke-dasharray', '5 5')
4210
- .style('stroke', targetData.color);
4211
- const rightSvgWidth = 60;
4311
+ .style('stroke', this.chartData.targetLineData.color);
4312
+ this.renderTargetLabel(svgYAxisRight, yZero, metaData);
4313
+ }
4314
+ parseTargetValue(target) {
4315
+ const parsed = parseFloat(String(target));
4316
+ if (isNaN(parsed))
4317
+ return 0;
4318
+ return Number.isInteger(parsed) ? parseInt(String(target)) : parsed;
4319
+ }
4320
+ renderTargetLabel(svgYAxisRight, yZero, metaData) {
4321
+ const dataType = metaData.dataType || '';
4322
+ const targetName = this.chartData.targetLineData.targetName || 'target';
4212
4323
  svgYAxisRight
4213
4324
  .append('foreignObject')
4214
- .attr('transform', `translate(0,${yZero - 30})`)
4215
- .attr('width', rightSvgWidth)
4325
+ .attr('transform', `translate(0,${yZero - 13})`)
4326
+ .attr('width', this.CONSTANTS.RIGHT_SVG_WIDTH)
4216
4327
  .attr('height', 50)
4217
4328
  .append('xhtml:div')
4218
4329
  .attr('class', 'target-display')
4219
4330
  .style('color', 'var(--chart-text-color)')
4220
- .html(() => {
4221
- const dataType = metaData.dataType || '';
4222
- const targetName = targetData.targetName || 'target';
4223
- return `<div>${targetName}</div><div>${targetData.target}${dataType}</div>`;
4224
- });
4331
+ .html(`<div>${targetName}</div><div>${this.chartData.targetLineData.target}${dataType}</div>`);
4225
4332
  }
4226
- renderLineGraph(svg, chartContext, scales) {
4227
- const { lineData, metaData } = chartContext;
4228
- if (!lineData)
4333
+ renderLineChart(svg, lineData, scales, colors, metaData) {
4334
+ if (!lineData || !colors)
4229
4335
  return;
4230
- const { x, lineYscale } = scales;
4231
- svg
4232
- .append('path')
4233
- .datum(lineData)
4234
- .attr('fill', 'none')
4235
- .attr('stroke', this.chartConfiguration.lineGraphColor)
4236
- .attr('stroke-width', 1.5)
4237
- .attr('d', d3
4336
+ const dataGroup = d3
4337
+ .nest()
4338
+ .key((d) => d.category)
4339
+ .entries(lineData);
4340
+ const lineGen = d3
4238
4341
  .line()
4239
- .x((d) => x(d.name) + x.bandwidth() / 2)
4240
- .y((d) => lineYscale(d.value)));
4342
+ .x((d) => scales.xScale(d.name) + scales.xScale.bandwidth() / 2)
4343
+ .y((d) => scales.lineYscale(d.value));
4344
+ dataGroup.forEach((group) => {
4345
+ svg
4346
+ .append('path')
4347
+ .datum(group.values)
4348
+ .attr('fill', 'none')
4349
+ .attr('stroke', (d) => {
4350
+ return d[0]?.category
4351
+ ? colors[d[0].category]
4352
+ : this.chartConfiguration.lineGraphColor;
4353
+ })
4354
+ .attr('stroke-width', 2.5)
4355
+ .attr('d', lineGen);
4356
+ this.renderLineDots(svg, group.values, scales, colors);
4357
+ });
4358
+ }
4359
+ renderLineDots(svg, values, scales, colors) {
4241
4360
  const dot = svg
4242
- .selectAll('myCircles')
4243
- .data(lineData)
4361
+ .selectAll('.line-dots')
4362
+ .data(values)
4244
4363
  .enter()
4245
4364
  .append('g')
4246
- .on('click', (d) => this.handleBarClick(d, metaData));
4365
+ .on('click', (d) => this.handleClick(d));
4247
4366
  dot
4248
4367
  .append('circle')
4249
- .attr('fill', this.chartConfiguration.lineGraphColor)
4368
+ .attr('fill', (d) => {
4369
+ return d.category
4370
+ ? colors[d.category]
4371
+ : this.chartConfiguration.lineGraphColor;
4372
+ })
4250
4373
  .attr('stroke', 'none')
4251
- .attr('cx', (d) => x(d.name) + x.bandwidth() / 2)
4252
- .attr('cy', (d) => lineYscale(d.value))
4253
- .style('cursor', 'pointer')
4254
- .attr('r', 3);
4374
+ .attr('cx', (d) => scales.xScale(d.name) + scales.xScale.bandwidth() / 2)
4375
+ .attr('cy', (d) => scales.lineYscale(d.value))
4376
+ .attr('r', 3)
4377
+ .style('cursor', 'pointer');
4255
4378
  if (this.chartConfiguration.lineGraphColor) {
4256
4379
  dot
4257
4380
  .append('text')
4258
- .attr('class', 'dot')
4259
- .attr('color', this.chartConfiguration.lineGraphColor)
4260
- .attr('style', 'font-size: .85em')
4261
- .attr('x', (d) => x(d.name) + x.bandwidth() / 2)
4262
- .attr('y', (d) => lineYscale(d.value))
4381
+ .attr('class', 'dots')
4382
+ .attr('fill', this.chartConfiguration.lineGraphColor)
4383
+ .style('font-size', '.85em')
4384
+ .style('font-weight', 'bold')
4385
+ .attr('x', (d) => scales.xScale(d.name) + scales.xScale.bandwidth() / 2)
4386
+ .attr('y', (d) => scales.lineYscale(d.value))
4263
4387
  .attr('dy', '-1em')
4264
4388
  .text((d) => this.chartConfiguration.labelFormatter(d.value));
4265
4389
  }
4266
4390
  }
4267
4391
  handleClick(d) {
4268
- if (this.chartData.metaData.hasDrillDown || d?.toggleFrom) {
4392
+ if (this.chartData?.metaData?.hasDrillDown || d?.toggleFrom) {
4269
4393
  this.clickEvent.emit(d);
4270
4394
  }
4271
4395
  }
4272
4396
  handleHeaderMenuClick(id) {
4273
4397
  this.headerMenuclickEvent.emit(id);
4274
4398
  }
4275
- handleDD1Click(event) {
4276
- this.isDD1Open = true;
4277
- this.isDD2Open = false;
4278
- }
4279
- handleDD2Click(event) {
4280
- this.isDD2Open = true;
4281
- this.isDD1Open = false;
4282
- }
4283
4399
  handleCompareByFilterSelection(event) {
4284
4400
  this.clickEvent.emit(event);
4285
4401
  }
4402
+ handleZoominZoomoutClick({ isZoomOut, event }) {
4403
+ this.isZoomOutSelected(isZoomOut);
4404
+ }
4286
4405
  static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "17.3.12", ngImport: i0, type: GroupChartComponent, deps: [], target: i0.ɵɵFactoryTarget.Component }); }
4287
- static { this.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "14.0.0", version: "17.3.12", type: GroupChartComponent, selector: "lib-group-chart", inputs: { chartData: "chartData", customChartConfiguration: "customChartConfiguration" }, outputs: { clickEvent: "clickEvent", headerMenuclickEvent: "headerMenuclickEvent" }, viewQueries: [{ propertyName: "containerElt", first: true, predicate: ["groupchartcontainer"], descendants: true, static: true }, { propertyName: "groupcontainerElt", first: true, predicate: ["groupcontainer"], descendants: true, static: true }], usesInheritance: true, ngImport: i0, template: "<div\r\n #groupcontainer\r\n class=\"lib-chart-wrapper\"\r\n [ngClass]=\"{ 'lib-no-background': isTransparentBackground }\"\r\n style=\"background-color: var(--card-bg);\"\r\n (resized)=\"onResized($event)\"\r\n>\r\n\r\n<div class=\"header-alt\" *ngIf=\"!isHeaderVisible\">\r\n <lib-chart-header-v2\r\n [chartData]=\"chartData\"\r\n [chartConfiguration]=\"chartConfiguration\"\r\n (clickEvent)=\"handleClick($event)\"\r\n ></lib-chart-header-v2>\r\n <lib-chart-header-v3\r\n [chartData]=\"chartData\"\r\n [chartConfiguration]=\"chartConfiguration\"\r\n (compareByFilterSelection)=\"handleCompareByFilterSelection($event)\"\r\n (zoomInZoomOutClick)=\"handleZoominZoomoutClick($event)\"\r\n ></lib-chart-header-v3>\r\n</div>\r\n\r\n <lib-chart-header-v1\r\n [title]=\"chartData.metaData.title\"\r\n [hasDrillDown]=\"chartData.metaData.hasDrillDown\"\r\n [isEditEnabled]=\"chartData.metaData.isEditEnabled\"\r\n [menuOptions]=\"chartConfiguration.headerMenuOptions\"\r\n [isria]=\"customChartConfiguration.isRia\"\r\n [selectedKpiTooltop]=\"chartConfiguration.selectedKpiTooltop\"\r\n (menuOptionClickEvent)=\"handleHeaderMenuClick($event)\"\r\n [isAlertEnabled]=\"isAlertEnabled\"\r\n *ngIf=\"isHeaderVisible\"\r\n></lib-chart-header-v1>\r\n\r\n <div\r\n [style.height]=\"chartConfiguration.svgHeight\"\r\n id=\"groupchartcontainer\"\r\n #groupchartcontainer\r\n class=\"lib-chart-svg\"\r\n ></div>\r\n</div>\r\n", styles: [".lib-stacked-y-axis-text text,.lib-stacked-x-axis-text text{font-family:system-ui,-apple-system,BlinkMacSystemFont,Segoe UI,Roboto;font-weight:400;letter-spacing:0px;color:#000;opacity:1;font-size:1.2em}.lib-axis-group-label{font-size:.85em;font-weight:600;font-family:system-ui,-apple-system,BlinkMacSystemFont,Segoe UI,Roboto;letter-spacing:0px;color:#000;opacity:1}.dots{font-size:10px}.inline__display{display:flex;justify-content:space-around;padding-top:2%}.verticalbar__text{font-style:normal;font-variant:normal;font-weight:400;font-size:13px;line-height:20px;font-family:system-ui,-apple-system,BlinkMacSystemFont,Segoe UI,Roboto;letter-spacing:0px;opacity:1}.lib-line-label-item{display:inline-block!important;font-size:.85em;margin-right:10px;font-weight:600}.lib-line-label-wrapper-vertical{display:flex;justify-content:center}.target-display{font-size:12px;line-height:14.52px;font-weight:700;text-transform:uppercase;float:right}.title{background-color:#d9d9d9;height:35px;display:flex;flex-direction:column;justify-content:center;align-items:center;border-radius:3px;line-height:1}.title:after{content:\"\";position:absolute;bottom:0;left:50%;margin-left:-10px;width:0;height:0;border-top:solid 10px #d3d3d3;border-left:solid 10px transparent;border-right:solid 10px transparent}.title-top-text{color:#000;font-size:14px;font-weight:600}.title-bar-name{color:#000;font-size:12px;font-weight:700;text-transform:capitalize}.title-bottom-text{color:#4f4f4f;font-size:12px}.zoomIcons-holder{display:flex;align-items:center;margin-right:15px}.zoomIcons{border:.5px solid #b6b6b6;cursor:pointer;display:flex;justify-content:center;align-items:center;width:30px;height:30px;color:var(--color)!important}.zoom-active{background-color:#2d5ca0;opacity:1}.zoom-inactive{background-color:#d9d9d9;opacity:.5}@media screen and (min-width: 1024px) and (min-height: 400px){.lib-stacked-y-axis-text text,.lib-stacked-x-axis-text text{font-size:10px!important}.dots{font-size:10px!important}}@media screen and (min-width: 1024px) and (min-height: 1000px){.lib-stacked-y-axis-text text,.lib-stacked-x-axis-text text{font-size:10px!important}.dots{font-size:10px!important}}@media screen and (min-width: 1024px) and (min-height: 1500px){.lib-stacked-y-axis-text text,.lib-stacked-x-axis-text text{font-size:10px!important}.dots{font-size:10px!important}}@media screen and (min-width: 1366px) and (min-height: 400px){.lib-stacked-y-axis-text text,.lib-stacked-x-axis-text text{font-size:12px!important}.dots{font-size:12px!important}}@media screen and (min-width: 1366px) and (min-height: 1000px){.lib-stacked-y-axis-text text,.lib-stacked-x-axis-text text{font-size:12px!important}.dots{font-size:12px!important}}@media screen and (min-width: 1366px) and (min-height: 1500px){.lib-stacked-y-axis-text text,.lib-stacked-x-axis-text text{font-size:12px!important}.dots{font-size:12px!important}}@media screen and (min-width: 1920px) and (min-height: 400px){.lib-stacked-y-axis-text text,.lib-stacked-x-axis-text text{font-size:14px!important}.dots{font-size:14px!important}}@media screen and (min-width: 1920px) and (min-height: 1000px){.lib-stacked-y-axis-text text,.lib-stacked-x-axis-text text{font-size:14px!important}.dots{font-size:14px!important}}@media screen and (min-width: 1920px) and (min-height: 1500px){.lib-stacked-y-axis-text text,.lib-stacked-x-axis-text text{font-size:14px!important}.dots{font-size:14px!important}}@media screen and (min-width: 2560px) and (min-height: 500px){.lib-stacked-y-axis-text text,.lib-stacked-x-axis-text text{font-size:16px!important}.dots{font-size:16px!important}}@media screen and (min-width: 2560px) and (min-height: 1000px){.lib-stacked-y-axis-text text,.lib-stacked-x-axis-text text{font-size:16px!important}.dots{font-size:16px!important}}@media screen and (min-width: 2560px) and (min-height: 1500px){.lib-stacked-y-axis-text text,.lib-stacked-x-axis-text text{font-size:16px!important}}.bottom__text{position:absolute!important;bottom:0!important;display:flex!important;justify-content:center!important;align-items:center!important;width:100%!important}.box__heightwidth{opacity:1;height:10px;width:10px;border:none!important;border-radius:50%}.label__text{margin-right:10px;display:flex;justify-content:center;align-items:center;font-style:normal;font-variant:normal;font-weight:400;font-size:10px;line-height:13px;font-family:system-ui,-apple-system,BlinkMacSystemFont,Segoe UI,Roboto,Oxygen,Ubuntu,Cantarell,Open Sans,Helvetica Neue,sans-serif;letter-spacing:.2px;color:#707070!important}.lib-verticalstack-labels-ontop-weklycharts{font-style:normal;font-variant:normal;font-weight:700;font-size:10px;line-height:11px;font-family:system-ui,-apple-system,BlinkMacSystemFont,Segoe UI,Roboto;letter-spacing:-.05px;text-anchor:middle;fill:#000}.lib-verticalstack-title-ontop{font-style:normal;font-variant:normal;font-size:14px;font-family:system-ui,-apple-system,BlinkMacSystemFont,Segoe UI,Roboto;letter-spacing:-.05px;text-anchor:middle;fill:#000}.marginLeft-20{margin-left:20px}.flex-inline{display:flex;justify-content:center;align-items:center;font-size:14px}\n", ".lib-chart-wrapper{width:100%;height:100%;font-family:system-ui,-apple-system,BlinkMacSystemFont,Segoe UI,Roboto;background:#fff 0% 0% no-repeat padding-box;position:relative}.lib-chart-wrapper-wo-shadow{width:100%;height:100%;font-family:system-ui,-apple-system,BlinkMacSystemFont,Segoe UI,Roboto}.lib-chart-wrapper:hover .chart-header-v1:not(.header-no-background){background-color:#2e3640}.lib-chart-wrapper:hover .chart-header-v1:not(.header-no-background) .chart-title{color:#fff}.lib-chart-svg{width:100%}.lib-chart-header{text-align:center;background-color:#052340;color:#fff;width:100%;height:17%;word-spacing:.5px;line-height:1.8;font-weight:700;padding-top:2%;letter-spacing:0;font-size:1.2em}.lib-donut-chart-footer{width:100%;text-align:right}.lib-donut-label-text{font-size:.9em;font-family:system-ui,-apple-system,BlinkMacSystemFont,Segoe UI,Roboto;font-weight:400;letter-spacing:0px;color:#000;opacity:1}.lib-donut-label-icon{display:inline-block;width:10px;height:10px;margin-right:20px;border-radius:3px}.lib-donut-label-item{font-weight:400;font-size:.85em;color:#2f2f2f}.lib-donut-justified-label-wrapper{width:100%;display:inline-block;text-align:center;list-style-type:none}.lib-donut-justified-label-item{font-weight:400;font-size:.85em;color:#2f2f2f;display:inline-block;text-align:left;padding:0 10px}.lib-donut-justified-label-icon{display:inline-block;width:10px;height:10px;margin-right:5px;border-radius:3px}.lib-no-background{background:none!important}.lib-display-hidden{display:none}.lib-ylabel-weeklyCharts{font-style:normal;font-variant:normal;font-weight:800;font-size:10px;line-height:12px;font-family:system-ui,-apple-system,BlinkMacSystemFont,Segoe UI,Roboto;letter-spacing:-.07px;text-transform:capitalize;color:#000}.lib-data-labels-weeklycharts{font-style:normal;font-variant:normal;font-weight:400;font-size:12px;line-height:14px;font-family:system-ui,-apple-system,BlinkMacSystemFont,Segoe UI,Roboto;letter-spacing:-.06px;color:#000}.lib-data-labels-angled-weeklycharts{font-style:normal;font-variant:normal;font-weight:800;font-size:9.5px;line-height:11px;font-family:system-ui,-apple-system,BlinkMacSystemFont,Segoe UI,Roboto;letter-spacing:.4px;text-anchor:start}.lib-xaxis-labels-texts-weeklycharts{font-style:normal;font-variant:normal;font-weight:800;font-size:10px;line-height:11px;letter-spacing:-.05px;fill:#000}.lib-xaxis-labels-texts-drilldown{font-family:system-ui,-apple-system,BlinkMacSystemFont,Segoe UI,Roboto;font-size:14px;letter-spacing:-1px;color:#000;opacity:1;text-transform:capitalize}.lib-white-space-nowrap{white-space:nowrap}.lib-xaxis-labels-texts-drilldown-alt{font-family:system-ui,-apple-system,BlinkMacSystemFont,Segoe UI,Roboto;font-size:10px;letter-spacing:0px;color:#000;opacity:1;text-transform:capitalize}.lib-yaxis-labels-texts-drilldown{font-family:system-ui,-apple-system,BlinkMacSystemFont,Segoe UI,Roboto;font-size:14px;letter-spacing:0px;color:#000!important;opacity:1}.lib-ylabel-drilldowncharts,.lib-xlabel-drilldowncharts{font-family:system-ui,-apple-system,BlinkMacSystemFont,Segoe UI,Roboto;font-size:16px;letter-spacing:-.1px;color:#000!important;opacity:1}.lib-donut-justified-label-icon-drilldown{display:inline-block;width:14px;height:14px;margin-right:10px;border-radius:50%}.marginright-2{margin-right:2%}.margintop-5{margin-top:5%}.width-100{width:100%}.float-right{float:right}.marginBottom-10{margin-bottom:10px}.header-alt{align-items:center;margin-bottom:10px}input::placeholder{font-size:20px;font-family:system-ui,-apple-system,BlinkMacSystemFont,Segoe UI,Roboto;letter-spacing:0px;color:#000;opacity:1}.padding-5{padding:5px}.hidden{visibility:hidden}.font-weight-bold{font-weight:900}.textalign-center{text-align:center}.cursor-pointer{cursor:pointer}.cursor-default{cursor:default}.font-weight-600{font-weight:600}.marginRight-15{margin-right:15px}.marginRight-20{margin-right:20px}.switch{position:relative;display:inline-block;width:46px;height:24px;margin-left:5px;margin-right:5px}.switch input{opacity:0;width:0;height:0}.slider{position:absolute;cursor:pointer;inset:0;background-color:#2d5ca0;-webkit-transition:.4s;transition:.4s}.slider:before{position:absolute;content:\"\";height:18px;width:18px;right:3px;bottom:3px;background-color:#fff;-webkit-transition:.4s;transition:.4s}.slider.round{border-radius:18px}.slider.round:before{border-radius:50%}.slider1{position:absolute;cursor:pointer;inset:0;background-color:#015ba2cf;-webkit-transition:.4s;transition:.4s}.slider1:before{position:absolute;content:\"\";height:18px;width:18px;left:3px;bottom:3px;background-color:#fff;-webkit-transition:.4s;transition:.4s}.slider1.round1{border-radius:18px}.slider1.round1:before{border-radius:50%}.lib-display-flex{display:flex}.lib-align-items-center{align-items:center}.lib-flex-direction-column{flex-direction:column}.lib-justify-content-space-between{justify-content:space-between}.lib-justify-content-space-around{justify-content:space-around}.lib-justify-content-center{justify-content:center}.lib-justify-content-start{justify-content:start}.lib-justify-content-end{justify-content:end}.lib-ml-20{margin-left:20px}.lib-position-absolute{position:absolute}.lib-z-index-9{z-index:9}.marginright-3{margin-right:3px}@media (min-height: 900px){.lib-chart-wrapper{border-radius:8px}.header-font-size-1{font-size:18px!important}.font-size-1{font-size:14px!important}.font-size-2{font-size:16px!important}.font-size-3{font-size:14px!important}.font-size-4{font-size:22px!important}.font-size-5{font-size:24px!important}}\n"], dependencies: [{ kind: "directive", type: i1.NgClass, selector: "[ngClass]", inputs: ["class", "ngClass"] }, { kind: "directive", type: i1.NgIf, selector: "[ngIf]", inputs: ["ngIf", "ngIfThen", "ngIfElse"] }, { kind: "directive", type: i2.ResizedDirective, selector: "[resized]", outputs: ["resized"] }, { kind: "component", type: ChartHeaderV1Component, selector: "lib-chart-header-v1", inputs: ["isAlertEnabled", "title", "menuOptions", "isEditEnabled", "isria", "hasDrillDown", "selectedKpiTooltop"], outputs: ["menuOptionClickEvent"] }, { kind: "component", type: ChartHeaderV2Component, selector: "lib-chart-header-v2", inputs: ["chartData", "chartConfiguration"], outputs: ["clickEvent", "zoomInZoomOutClick"] }, { kind: "component", type: ChartHeaderV3Component, selector: "lib-chart-header-v3", inputs: ["chartData", "chartConfiguration"], outputs: ["compareByFilterSelection", "zoomInZoomOutClick"] }], encapsulation: i0.ViewEncapsulation.None }); }
4406
+ static { this.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "14.0.0", version: "17.3.12", type: GroupChartComponent, selector: "lib-group-chart", inputs: { chartData: "chartData", customChartConfiguration: "customChartConfiguration" }, outputs: { clickEvent: "clickEvent", headerMenuclickEvent: "headerMenuclickEvent" }, viewQueries: [{ propertyName: "containerElt", first: true, predicate: ["groupchartcontainer"], descendants: true, static: true }, { propertyName: "groupcontainerElt", first: true, predicate: ["groupcontainer"], descendants: true, static: true }], usesInheritance: true, usesOnChanges: true, ngImport: i0, template: "<div\r\n #groupcontainer\r\n class=\"lib-chart-wrapper\"\r\n [ngClass]=\"{ 'lib-no-background': isTransparentBackground }\"\r\n style=\"background-color: var(--card-bg);\"\r\n (resized)=\"onResized($event)\"\r\n>\r\n\r\n<div class=\"header-alt\" *ngIf=\"!isHeaderVisible\">\r\n <lib-chart-header-v2\r\n [chartData]=\"chartData\"\r\n [chartConfiguration]=\"chartConfiguration\"\r\n (clickEvent)=\"handleClick($event)\"\r\n ></lib-chart-header-v2>\r\n <lib-chart-header-v3\r\n [chartData]=\"chartData\"\r\n [chartConfiguration]=\"chartConfiguration\"\r\n (compareByFilterSelection)=\"handleCompareByFilterSelection($event)\"\r\n (zoomInZoomOutClick)=\"handleZoominZoomoutClick($event)\"\r\n ></lib-chart-header-v3>\r\n</div>\r\n\r\n <lib-chart-header-v1\r\n [title]=\"chartData.metaData.title\"\r\n [hasDrillDown]=\"chartData.metaData.hasDrillDown\"\r\n [isEditEnabled]=\"chartData.metaData.isEditEnabled\"\r\n [menuOptions]=\"chartConfiguration.headerMenuOptions\"\r\n [isria]=\"customChartConfiguration.isRia\"\r\n [selectedKpiTooltop]=\"chartConfiguration.selectedKpiTooltop\"\r\n (menuOptionClickEvent)=\"handleHeaderMenuClick($event)\"\r\n [isAlertEnabled]=\"isAlertEnabled\"\r\n *ngIf=\"isHeaderVisible\"\r\n></lib-chart-header-v1>\r\n\r\n <div\r\n [style.height]=\"chartConfiguration.svgHeight\"\r\n id=\"groupchartcontainer\"\r\n #groupchartcontainer\r\n class=\"lib-chart-svg\"\r\n ></div>\r\n</div>\r\n", styles: [".lib-stacked-y-axis-text text,.lib-stacked-x-axis-text text{font-family:system-ui,-apple-system,BlinkMacSystemFont,Segoe UI,Roboto;font-weight:400;letter-spacing:0px;color:#000;opacity:1;font-size:1.2em}.lib-axis-group-label{font-size:.85em;font-weight:600;font-family:system-ui,-apple-system,BlinkMacSystemFont,Segoe UI,Roboto;letter-spacing:0px;color:#000;opacity:1}.dots{font-size:10px}.inline__display{display:flex;justify-content:space-around;padding-top:2%}.verticalbar__text{font-style:normal;font-variant:normal;font-weight:400;font-size:13px;line-height:20px;font-family:system-ui,-apple-system,BlinkMacSystemFont,Segoe UI,Roboto;letter-spacing:0px;opacity:1}.lib-line-label-item{display:inline-block!important;font-size:.85em;margin-right:10px;font-weight:600}.lib-line-label-wrapper-vertical{display:flex;justify-content:center}.target-display{font-size:12px;line-height:14.52px;font-weight:700;text-transform:uppercase;float:right}.title{background-color:#d9d9d9;height:35px;display:flex;flex-direction:column;justify-content:center;align-items:center;border-radius:3px;line-height:1}.title:after{content:\"\";position:absolute;bottom:0;left:50%;margin-left:-10px;width:0;height:0;border-top:solid 10px #d3d3d3;border-left:solid 10px transparent;border-right:solid 10px transparent}.title-top-text{color:#000;font-size:14px;font-weight:600}.title-bar-name{color:#000;font-size:12px;font-weight:700;text-transform:capitalize}.title-bottom-text{color:#4f4f4f;font-size:12px}.zoomIcons-holder{display:flex;align-items:center;margin-right:15px}.zoomIcons{border:.5px solid #b6b6b6;cursor:pointer;display:flex;justify-content:center;align-items:center;width:30px;height:30px;color:var(--color)!important}.zoom-active{background-color:#2d5ca0;opacity:1}.zoom-inactive{background-color:#d9d9d9;opacity:.5}@media screen and (min-width: 1024px) and (min-height: 400px){.lib-stacked-y-axis-text text,.lib-stacked-x-axis-text text{font-size:10px!important}.dots{font-size:10px!important}}@media screen and (min-width: 1024px) and (min-height: 1000px){.lib-stacked-y-axis-text text,.lib-stacked-x-axis-text text{font-size:10px!important}.dots{font-size:10px!important}}@media screen and (min-width: 1024px) and (min-height: 1500px){.lib-stacked-y-axis-text text,.lib-stacked-x-axis-text text{font-size:10px!important}.dots{font-size:10px!important}}@media screen and (min-width: 1366px) and (min-height: 400px){.lib-stacked-y-axis-text text,.lib-stacked-x-axis-text text{font-size:12px!important}.dots{font-size:12px!important}}@media screen and (min-width: 1366px) and (min-height: 1000px){.lib-stacked-y-axis-text text,.lib-stacked-x-axis-text text{font-size:12px!important}.dots{font-size:12px!important}}@media screen and (min-width: 1366px) and (min-height: 1500px){.lib-stacked-y-axis-text text,.lib-stacked-x-axis-text text{font-size:12px!important}.dots{font-size:12px!important}}@media screen and (min-width: 1920px) and (min-height: 400px){.lib-stacked-y-axis-text text,.lib-stacked-x-axis-text text{font-size:14px!important}.dots{font-size:14px!important}}@media screen and (min-width: 1920px) and (min-height: 1000px){.lib-stacked-y-axis-text text,.lib-stacked-x-axis-text text{font-size:14px!important}.dots{font-size:14px!important}}@media screen and (min-width: 1920px) and (min-height: 1500px){.lib-stacked-y-axis-text text,.lib-stacked-x-axis-text text{font-size:14px!important}.dots{font-size:14px!important}}@media screen and (min-width: 2560px) and (min-height: 500px){.lib-stacked-y-axis-text text,.lib-stacked-x-axis-text text{font-size:16px!important}.dots{font-size:16px!important}}@media screen and (min-width: 2560px) and (min-height: 1000px){.lib-stacked-y-axis-text text,.lib-stacked-x-axis-text text{font-size:16px!important}.dots{font-size:16px!important}}@media screen and (min-width: 2560px) and (min-height: 1500px){.lib-stacked-y-axis-text text,.lib-stacked-x-axis-text text{font-size:16px!important}}.bottom__text{position:absolute!important;bottom:0!important;display:flex!important;justify-content:center!important;align-items:center!important;width:100%!important}.box__heightwidth{opacity:1;height:10px;width:10px;border:none!important;border-radius:50%}.label__text{margin-right:10px;display:flex;justify-content:center;align-items:center;font-style:normal;font-variant:normal;font-weight:400;font-size:10px;line-height:13px;font-family:system-ui,-apple-system,BlinkMacSystemFont,Segoe UI,Roboto,Oxygen,Ubuntu,Cantarell,Open Sans,Helvetica Neue,sans-serif;letter-spacing:.2px;color:#707070!important}.lib-verticalstack-labels-ontop-weklycharts{font-style:normal;font-variant:normal;font-weight:700;font-size:10px;line-height:11px;font-family:system-ui,-apple-system,BlinkMacSystemFont,Segoe UI,Roboto;letter-spacing:-.05px;text-anchor:middle;fill:#000}.lib-verticalstack-title-ontop{font-style:normal;font-variant:normal;font-size:14px;font-family:system-ui,-apple-system,BlinkMacSystemFont,Segoe UI,Roboto;letter-spacing:-.05px;text-anchor:middle;fill:#000}.marginLeft-20{margin-left:20px}.flex-inline{display:flex;justify-content:center;align-items:center;font-size:14px}\n", ".lib-chart-wrapper{width:100%;height:100%;font-family:system-ui,-apple-system,BlinkMacSystemFont,Segoe UI,Roboto;background:#fff 0% 0% no-repeat padding-box;position:relative}.lib-chart-wrapper-wo-shadow{width:100%;height:100%;font-family:system-ui,-apple-system,BlinkMacSystemFont,Segoe UI,Roboto}.lib-chart-wrapper:hover .chart-header-v1:not(.header-no-background){background-color:#2e3640}.lib-chart-wrapper:hover .chart-header-v1:not(.header-no-background) .chart-title{color:#fff}.lib-chart-svg{width:100%}.lib-chart-header{text-align:center;background-color:#052340;color:#fff;width:100%;height:17%;word-spacing:.5px;line-height:1.8;font-weight:700;padding-top:2%;letter-spacing:0;font-size:1.2em}.lib-donut-chart-footer{width:100%;text-align:right}.lib-donut-label-text{font-size:.9em;font-family:system-ui,-apple-system,BlinkMacSystemFont,Segoe UI,Roboto;font-weight:400;letter-spacing:0px;color:#000;opacity:1}.lib-donut-label-icon{display:inline-block;width:10px;height:10px;margin-right:20px;border-radius:3px}.lib-donut-label-item{font-weight:400;font-size:.85em;color:#2f2f2f}.lib-donut-justified-label-wrapper{width:100%;display:inline-block;text-align:center;list-style-type:none}.lib-donut-justified-label-item{font-weight:400;font-size:.85em;color:#2f2f2f;display:inline-block;text-align:left;padding:0 10px}.lib-donut-justified-label-icon{display:inline-block;width:10px;height:10px;margin-right:5px;border-radius:3px}.lib-no-background{background:none!important}.lib-display-hidden{display:none}.lib-ylabel-weeklyCharts{font-style:normal;font-variant:normal;font-weight:800;font-size:10px;line-height:12px;font-family:system-ui,-apple-system,BlinkMacSystemFont,Segoe UI,Roboto;letter-spacing:-.07px;text-transform:capitalize;color:#000}.lib-data-labels-weeklycharts{font-style:normal;font-variant:normal;font-weight:400;font-size:12px;line-height:14px;font-family:system-ui,-apple-system,BlinkMacSystemFont,Segoe UI,Roboto;letter-spacing:-.06px;color:#000}.lib-data-labels-angled-weeklycharts{font-style:normal;font-variant:normal;font-weight:800;font-size:9.5px;line-height:11px;font-family:system-ui,-apple-system,BlinkMacSystemFont,Segoe UI,Roboto;letter-spacing:.4px;text-anchor:start}.lib-xaxis-labels-texts-weeklycharts{font-style:normal;font-variant:normal;font-weight:800;font-size:10px;line-height:11px;letter-spacing:-.05px;fill:#000}.lib-xaxis-labels-texts-drilldown{font-family:system-ui,-apple-system,BlinkMacSystemFont,Segoe UI,Roboto;font-size:14px;letter-spacing:-1px;color:#000;opacity:1;text-transform:capitalize}.lib-white-space-nowrap{white-space:nowrap}.lib-xaxis-labels-texts-drilldown-alt{font-family:system-ui,-apple-system,BlinkMacSystemFont,Segoe UI,Roboto;font-size:10px;letter-spacing:0px;color:#000;opacity:1;text-transform:capitalize}.lib-yaxis-labels-texts-drilldown{font-family:system-ui,-apple-system,BlinkMacSystemFont,Segoe UI,Roboto;font-size:14px;letter-spacing:0px;color:#000!important;opacity:1}.lib-ylabel-drilldowncharts,.lib-xlabel-drilldowncharts{font-family:system-ui,-apple-system,BlinkMacSystemFont,Segoe UI,Roboto;font-size:16px;letter-spacing:-.1px;color:#000!important;opacity:1}.lib-donut-justified-label-icon-drilldown{display:inline-block;width:14px;height:14px;margin-right:10px;border-radius:50%}.marginright-2{margin-right:2%}.margintop-5{margin-top:5%}.width-100{width:100%}.float-right{float:right}.marginBottom-10{margin-bottom:10px}.header-alt{align-items:center;margin-bottom:10px}input::placeholder{font-size:20px;font-family:system-ui,-apple-system,BlinkMacSystemFont,Segoe UI,Roboto;letter-spacing:0px;color:#000;opacity:1}.padding-5{padding:5px}.hidden{visibility:hidden}.font-weight-bold{font-weight:900}.textalign-center{text-align:center}.cursor-pointer{cursor:pointer}.cursor-default{cursor:default}.font-weight-600{font-weight:600}.marginRight-15{margin-right:15px}.marginRight-20{margin-right:20px}.switch{position:relative;display:inline-block;width:46px;height:24px;margin-left:5px;margin-right:5px}.switch input{opacity:0;width:0;height:0}.slider{position:absolute;cursor:pointer;inset:0;background-color:#2d5ca0;-webkit-transition:.4s;transition:.4s}.slider:before{position:absolute;content:\"\";height:18px;width:18px;right:3px;bottom:3px;background-color:#fff;-webkit-transition:.4s;transition:.4s}.slider.round{border-radius:18px}.slider.round:before{border-radius:50%}.slider1{position:absolute;cursor:pointer;inset:0;background-color:#015ba2cf;-webkit-transition:.4s;transition:.4s}.slider1:before{position:absolute;content:\"\";height:18px;width:18px;left:3px;bottom:3px;background-color:#fff;-webkit-transition:.4s;transition:.4s}.slider1.round1{border-radius:18px}.slider1.round1:before{border-radius:50%}.lib-display-flex{display:flex}.lib-align-items-center{align-items:center}.lib-flex-direction-column{flex-direction:column}.lib-justify-content-space-between{justify-content:space-between}.lib-justify-content-space-around{justify-content:space-around}.lib-justify-content-center{justify-content:center}.lib-justify-content-start{justify-content:start}.lib-justify-content-end{justify-content:end}.lib-ml-20{margin-left:20px}.lib-position-absolute{position:absolute}.lib-z-index-9{z-index:9}.marginright-3{margin-right:3px}@media (min-height: 900px){.lib-chart-wrapper{border-radius:8px}.header-font-size-1{font-size:18px!important}.font-size-1{font-size:14px!important}.font-size-2{font-size:16px!important}.font-size-3{font-size:14px!important}.font-size-4{font-size:22px!important}.font-size-5{font-size:24px!important}}\n"], dependencies: [{ kind: "directive", type: i1.NgClass, selector: "[ngClass]", inputs: ["class", "ngClass"] }, { kind: "directive", type: i1.NgIf, selector: "[ngIf]", inputs: ["ngIf", "ngIfThen", "ngIfElse"] }, { kind: "directive", type: i2.ResizedDirective, selector: "[resized]", outputs: ["resized"] }, { kind: "component", type: ChartHeaderV1Component, selector: "lib-chart-header-v1", inputs: ["isAlertEnabled", "title", "menuOptions", "isEditEnabled", "isria", "hasDrillDown", "selectedKpiTooltop"], outputs: ["menuOptionClickEvent"] }, { kind: "component", type: ChartHeaderV2Component, selector: "lib-chart-header-v2", inputs: ["chartData", "chartConfiguration"], outputs: ["clickEvent", "zoomInZoomOutClick"] }, { kind: "component", type: ChartHeaderV3Component, selector: "lib-chart-header-v3", inputs: ["chartData", "chartConfiguration"], outputs: ["compareByFilterSelection", "zoomInZoomOutClick"] }], encapsulation: i0.ViewEncapsulation.None }); }
4288
4407
  }
4289
4408
  i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "17.3.12", ngImport: i0, type: GroupChartComponent, decorators: [{
4290
4409
  type: Component,