1
0
mirror of https://github.com/bitwarden/browser synced 2025-12-17 00:33:44 +00:00
Files
browser/libs/components/src/navigation/nav-group.component.ts
Oscar Hinton dc606847e4 [PM-16447] Disable preserve whitespaces (#12994)
Angular 6 changed the default to not preserve whitespaces. We've continued to opt into this pattern for backwards compatibility but we're experiencing issues with the new control flow syntax and would therefore like to switch and not preserve whitespace any longer.
2025-02-18 17:05:29 +01:00

112 lines
2.8 KiB
TypeScript

import { CommonModule } from "@angular/common";
import {
AfterContentInit,
booleanAttribute,
Component,
ContentChildren,
EventEmitter,
Input,
Optional,
Output,
QueryList,
SkipSelf,
} from "@angular/core";
import { I18nPipe } from "@bitwarden/ui-common";
import { IconButtonModule } from "../icon-button";
import { NavBaseComponent } from "./nav-base.component";
import { NavGroupAbstraction, NavItemComponent } from "./nav-item.component";
import { SideNavService } from "./side-nav.service";
@Component({
selector: "bit-nav-group",
templateUrl: "./nav-group.component.html",
providers: [
{ provide: NavBaseComponent, useExisting: NavGroupComponent },
{ provide: NavGroupAbstraction, useExisting: NavGroupComponent },
],
standalone: true,
imports: [CommonModule, NavItemComponent, IconButtonModule, I18nPipe],
})
export class NavGroupComponent extends NavBaseComponent implements AfterContentInit {
@ContentChildren(NavBaseComponent, {
descendants: true,
})
nestedNavComponents!: QueryList<NavBaseComponent>;
/** When the side nav is open, the parent nav item should not show active styles when open. */
protected get parentHideActiveStyles(): boolean {
return this.hideActiveStyles || (this.open && this.sideNavService.open);
}
/**
* UID for `[attr.aria-controls]`
*/
protected contentId = Math.random().toString(36).substring(2);
/**
* Is `true` if the expanded content is visible
*/
@Input()
open = false;
/**
* Automatically hide the nav group if there are no child buttons
*/
@Input({ transform: booleanAttribute })
hideIfEmpty = false;
@Output()
openChange = new EventEmitter<boolean>();
constructor(
protected sideNavService: SideNavService,
@Optional() @SkipSelf() private parentNavGroup: NavGroupComponent,
) {
super();
}
setOpen(isOpen: boolean) {
this.open = isOpen;
this.openChange.emit(this.open);
// FIXME: Remove when updating file. Eslint update
// eslint-disable-next-line @typescript-eslint/no-unused-expressions
this.open && this.parentNavGroup?.setOpen(this.open);
}
protected toggle(event?: MouseEvent) {
event?.stopPropagation();
this.setOpen(!this.open);
}
/**
* - For any nested NavGroupComponents or NavItemComponents, increment the `treeDepth` by 1.
*/
private initNestedStyles() {
if (this.variant !== "tree") {
return;
}
[...this.nestedNavComponents].forEach((navGroupOrItem) => {
navGroupOrItem.treeDepth += 1;
});
}
protected handleMainContentClicked() {
if (!this.sideNavService.open) {
if (!this.route) {
this.sideNavService.setOpen();
}
this.open = true;
} else {
this.toggle();
}
this.mainContentClicked.emit();
}
ngAfterContentInit(): void {
this.initNestedStyles();
}
}