All files / microchart-bar si-microchart-bar.component.ts

100% Statements 24/24
81.25% Branches 26/32
100% Functions 3/3
100% Lines 20/20

Press n or j to go to the next uncovered block, b, p or k for the previous block.

1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72                                                                18x   9x   9x                 9x   9x   9x 9x 9x 9x 9x 9x 9x 9x   9x   9x 34x 34x   34x 34x     9x      
/**
 * Copyright (c) Siemens 2016 - 2026
 * SPDX-License-Identifier: MIT
 */
import { ChangeDetectionStrategy, Component, computed, input } from '@angular/core';
 
export interface MicrochartBarSeries {
  /* Series values */
  values: number[];
  /**
   * Use a data-color. See: {@link https://element.siemens.io/fundamentals/colors/data-visualization-colors/#tokens}
   *
   * @example "element-data-10"
   */
  colorToken: string;
  /**
   * Color token for negative values
   */
  negativeColorToken?: string;
}
 
interface SeriesInternal {
  top: number;
  height: number;
  colorToken: string;
}
 
@Component({
  selector: 'si-microchart-bar',
  templateUrl: './si-microchart-bar.component.html',
  changeDetection: ChangeDetectionStrategy.OnPush
})
export class SiMicrochartBarComponent {
  /** @defaultValue 64 */
  readonly width = input<number>(64);
  /** @defaultValue 24 */
  readonly height = input<number>(24);
  /**
   * Microchart bar series.
   * Example series can be:
   * @example
   * ```ts
   * Series: MicrochartBarSeries = { values: [2, 4, 5, 3, 5, 7, 7, 9, 11, 10, 12, 9], colorToken: 'element-data-7'};
   * ```
   */
  readonly series = input.required<MicrochartBarSeries>();
 
  protected barWidth = 4;
 
  protected readonly internalSeries = computed<SeriesInternal[]>(() => {
    const series = this.series();
    const maxValue = Math.max(...series.values, 1);
    const minValue = Math.min(...series.values, 0);
    const allNegative = maxValue <= 0;
    const allPositive = minValue >= 0;
    const range = Math.abs(maxValue) + Math.abs(minValue);
    const zeroPosition = allNegative ? 0 : allPositive ? 100 : (Math.abs(maxValue) / range) * 100;
 
    const maxRange = allNegative ? Math.abs(minValue) : allPositive ? maxValue : range;
 
    const int = series.values.map<SeriesInternal>(value => {
      const height = (Math.abs(value) / maxRange) * 100;
      const top = value >= 0 ? zeroPosition - height : zeroPosition;
      const colorToken =
        value < 0 && series.negativeColorToken ? series.negativeColorToken : series.colorToken;
      return { top, height, colorToken };
    });
 
    return int;
  });
}