All files / navbar-vertical si-navbar-vertical-item.component.ts

90.32% Statements 28/31
83.33% Branches 15/18
100% Functions 6/6
90.32% Lines 28/31

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 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127                                                                                                  1x 59x 59x     59x   59x 59x       59x       59x 59x         59x 115x           59x 43x 43x           59x 65x 65x 22x   43x 23x   20x       59x           9x 9x       9x 9x 3x         978x                    
/**
 * Copyright (c) Siemens 2016 - 2026
 * SPDX-License-Identifier: MIT
 */
import {
  ChangeDetectionStrategy,
  Component,
  computed,
  HostListener,
  inject,
  input,
  OnInit
} from '@angular/core';
import { RouterLinkActive } from '@angular/router';
import { elementDown2 } from '@siemens/element-icons';
import { MenuItem } from '@siemens/element-ng/common';
import { addIcons, SiIconComponent } from '@siemens/element-ng/icon';
import { SiLinkDirective } from '@siemens/element-ng/link';
 
import { SiNavbarVerticalGroupTriggerDirective } from './si-navbar-vertical-group-trigger.directive';
import {
  NavbarVerticalItemAction,
  NavbarVerticalItemGroup,
  NavbarVerticalItemLink,
  NavbarVerticalItemRouterLink
} from './si-navbar-vertical.model';
import { SI_NAVBAR_VERTICAL } from './si-navbar-vertical.provider';
 
type NavbarVerticalItemInteractive =
  | NavbarVerticalItemGroup
  | NavbarVerticalItemRouterLink
  | NavbarVerticalItemLink
  | NavbarVerticalItemAction;
 
@Component({
  // eslint-disable-next-line @angular-eslint/component-selector
  selector: 'a[si-navbar-vertical-item], button[si-navbar-vertical-item]',
  imports: [SiIconComponent],
  templateUrl: './si-navbar-vertical-item.component.html',
  styleUrl: './si-navbar-vertical-item.component.scss',
  changeDetection: ChangeDetectionStrategy.OnPush,
  host: {
    'class': 'focus-inside',
    '[class.dropdown-item]': 'this.parent?.group?.flyout()',
    '[class.navbar-vertical-item]': '!this.parent?.group?.flyout()',
    '[class.active]': 'active',
    '[class.hide-badge-collapsed]': 'hideBadgeCollapsed()'
  }
})
export class SiNavbarVerticalItemComponent implements OnInit {
  protected readonly icons = addIcons({ elementDown2 });
  readonly item = input.required<NavbarVerticalItemInteractive | MenuItem>({
    alias: 'si-navbar-vertical-item'
  });
  readonly activeOverride = input<boolean>();
 
  protected readonly navbar = inject(SI_NAVBAR_VERTICAL);
  protected readonly parent = inject(SiNavbarVerticalItemComponent, {
    skipSelf: true,
    optional: true
  });
  readonly group = inject(SiNavbarVerticalGroupTriggerDirective, {
    optional: true,
    self: true
  });
  private readonly routerLinkActive = inject(RouterLinkActive, { optional: true });
  private readonly siLink = inject(SiLinkDirective, { optional: true });
 
  /**
   * Hides the badge in collapsed state
   */
  protected readonly hideBadgeCollapsed = computed(
    () => !!(this.item() as NavbarVerticalItemInteractive).hideBadgeWhenCollapsed
  );
 
  /**
   * Determines if the badge contains text-only content (not numeric)
   */
  protected readonly textOnlyBadge = computed(() => {
    const badge = this.item().badge;
    return badge ? typeof badge !== 'number' : false;
  });
 
  /**
   * Formats badge value to limit display to "+99" for numbers greater than 99
   */
  protected readonly formattedBadge = computed(() => {
    const badge = this.item().badge;
    if (!badge) {
      return '';
    }
    if (typeof badge === 'number') {
      return badge > 99 ? '+99' : badge.toString();
    }
    return badge.toString();
  });
 
  ngOnInit(): void {
    Iif (this.group && this.active) {
      this.group.expanded.set(true);
    }
  }
 
  @HostListener('click') protected triggered(): void {
    const item = this.item();
    Iif (item.type === 'action') {
      item.action(item);
      return;
    }
    this.parent?.group?.hideFlyout();
    if (!this.group) {
      this.navbar.itemTriggered();
    }
  }
 
  get active(): boolean {
    return (
      this.activeOverride() ||
      this.routerLinkActive?.isActive ||
      this.siLink?.active() ||
      ((!this.group?.expanded() || this.navbar.collapsed()) && this.group?.active()) ||
      false
    );
    /* eslint-disable-enable @typescript-eslint/prefer-nullish-coalescing */
  }
}