mirror of
https://github.com/bitwarden/browser
synced 2025-12-17 16:53:34 +00:00
[CL-707] Migrate CL codebase to signals (#15340)
This commit is contained in:
@@ -1,7 +1,7 @@
|
||||
// FIXME: Update this file to be type safe and remove this and next line
|
||||
// @ts-strict-ignore
|
||||
import { FocusableOption } from "@angular/cdk/a11y";
|
||||
import { Directive, ElementRef, HostBinding, Input } from "@angular/core";
|
||||
import { Directive, ElementRef, HostBinding, Input, input } from "@angular/core";
|
||||
|
||||
/**
|
||||
* Directive used for styling tab header items for both nav links (anchor tags)
|
||||
@@ -11,7 +11,10 @@ import { Directive, ElementRef, HostBinding, Input } from "@angular/core";
|
||||
selector: "[bitTabListItem]",
|
||||
})
|
||||
export class TabListItemDirective implements FocusableOption {
|
||||
@Input() active: boolean;
|
||||
readonly active = input<boolean>();
|
||||
// TODO: Skipped for signal migration because:
|
||||
// This input overrides a field from a superclass, while the superclass field
|
||||
// is not migrated.
|
||||
@Input() disabled: boolean;
|
||||
|
||||
@HostBinding("attr.disabled")
|
||||
@@ -32,7 +35,7 @@ export class TabListItemDirective implements FocusableOption {
|
||||
@HostBinding("class")
|
||||
get classList(): string[] {
|
||||
return this.baseClassList
|
||||
.concat(this.active ? this.activeClassList : [])
|
||||
.concat(this.active() ? this.activeClassList : [])
|
||||
.concat(this.disabled ? this.disabledClassList : [])
|
||||
.concat(this.textColorClassList);
|
||||
}
|
||||
@@ -45,7 +48,7 @@ export class TabListItemDirective implements FocusableOption {
|
||||
if (this.disabled) {
|
||||
return ["!tw-text-secondary-300", "hover:!tw-text-secondary-300"];
|
||||
}
|
||||
if (this.active) {
|
||||
if (this.active()) {
|
||||
return ["!tw-text-primary-600", "hover:!tw-text-primary-700"];
|
||||
}
|
||||
return ["!tw-text-main", "hover:!tw-text-main"];
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
// FIXME: Update this file to be type safe and remove this and next line
|
||||
// @ts-strict-ignore
|
||||
import { TemplatePortal, CdkPortalOutlet } from "@angular/cdk/portal";
|
||||
import { Component, HostBinding, Input } from "@angular/core";
|
||||
import { Component, effect, HostBinding, input } from "@angular/core";
|
||||
|
||||
@Component({
|
||||
selector: "bit-tab-body",
|
||||
@@ -11,24 +11,22 @@ import { Component, HostBinding, Input } from "@angular/core";
|
||||
export class TabBodyComponent {
|
||||
private _firstRender: boolean;
|
||||
|
||||
@Input() content: TemplatePortal;
|
||||
@Input() preserveContent = false;
|
||||
readonly content = input<TemplatePortal>();
|
||||
readonly preserveContent = input(false);
|
||||
|
||||
@HostBinding("attr.hidden") get hidden() {
|
||||
return !this.active || null;
|
||||
return !this.active() || null;
|
||||
}
|
||||
|
||||
@Input()
|
||||
get active() {
|
||||
return this._active;
|
||||
readonly active = input<boolean>();
|
||||
|
||||
constructor() {
|
||||
effect(() => {
|
||||
if (this.active()) {
|
||||
this._firstRender = true;
|
||||
}
|
||||
});
|
||||
}
|
||||
set active(value: boolean) {
|
||||
this._active = value;
|
||||
if (this._active) {
|
||||
this._firstRender = true;
|
||||
}
|
||||
}
|
||||
private _active: boolean;
|
||||
|
||||
/**
|
||||
* The tab content to render.
|
||||
@@ -37,11 +35,11 @@ export class TabBodyComponent {
|
||||
* then the content persists after the first time content is rendered.
|
||||
*/
|
||||
get tabContent() {
|
||||
if (this.active) {
|
||||
return this.content;
|
||||
if (this.active()) {
|
||||
return this.content();
|
||||
}
|
||||
if (this.preserveContent && this._firstRender) {
|
||||
return this.content;
|
||||
if (this.preserveContent() && this._firstRender) {
|
||||
return this.content();
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
@@ -2,7 +2,7 @@
|
||||
<div
|
||||
bitTabListContainer
|
||||
role="tablist"
|
||||
[attr.aria-label]="label"
|
||||
[attr.aria-label]="label()"
|
||||
(keydown)="keyManager.onKeydown($event)"
|
||||
>
|
||||
@for (tab of tabs; track tab; let i = $index) {
|
||||
@@ -12,7 +12,7 @@
|
||||
role="tab"
|
||||
[id]="getTabLabelId(i)"
|
||||
[active]="tab.isActive"
|
||||
[disabled]="tab.disabled"
|
||||
[disabled]="tab.disabled()"
|
||||
[attr.aria-selected]="selectedIndex === i"
|
||||
[attr.tabindex]="selectedIndex === i ? 0 : -1"
|
||||
(click)="selectTab(i)"
|
||||
@@ -22,7 +22,7 @@
|
||||
@if (tab.templateLabel) {
|
||||
<ng-container [ngTemplateOutlet]="tab.templateLabel.templateRef"></ng-container>
|
||||
} @else {
|
||||
{{ tab.textLabel }}
|
||||
{{ tab.textLabel() }}
|
||||
}
|
||||
</ng-template>
|
||||
</button>
|
||||
@@ -34,11 +34,11 @@
|
||||
<bit-tab-body
|
||||
role="tabpanel"
|
||||
[id]="getTabContentId(i)"
|
||||
[attr.tabindex]="tab.contentTabIndex"
|
||||
[attr.tabindex]="tab.contentTabIndex()"
|
||||
[attr.labeledby]="getTabLabelId(i)"
|
||||
[active]="tab.isActive"
|
||||
[content]="tab.content"
|
||||
[preserveContent]="preserveContent"
|
||||
[preserveContent]="preserveContent()"
|
||||
>
|
||||
</bit-tab-body>
|
||||
}
|
||||
|
||||
@@ -15,6 +15,7 @@ import {
|
||||
Output,
|
||||
QueryList,
|
||||
ViewChildren,
|
||||
input,
|
||||
} from "@angular/core";
|
||||
import { Subject, takeUntil } from "rxjs";
|
||||
|
||||
@@ -49,19 +50,21 @@ export class TabGroupComponent
|
||||
/**
|
||||
* Aria label for the tab list menu
|
||||
*/
|
||||
@Input() label = "";
|
||||
readonly label = input("");
|
||||
|
||||
/**
|
||||
* Keep the content of off-screen tabs in the DOM.
|
||||
* Useful for keeping <audio> or <video> elements from re-initializing
|
||||
* after navigating between tabs.
|
||||
*/
|
||||
@Input() preserveContent = false;
|
||||
readonly preserveContent = input(false);
|
||||
|
||||
@ContentChildren(TabComponent) tabs: QueryList<TabComponent>;
|
||||
@ViewChildren(TabListItemDirective) tabLabels: QueryList<TabListItemDirective>;
|
||||
|
||||
/** The index of the active tab. */
|
||||
// TODO: Skipped for signal migration because:
|
||||
// Accessor inputs cannot be migrated as they are too complex.
|
||||
@Input()
|
||||
get selectedIndex(): number | null {
|
||||
return this._selectedIndex;
|
||||
|
||||
@@ -4,11 +4,11 @@ import { TemplatePortal } from "@angular/cdk/portal";
|
||||
import {
|
||||
Component,
|
||||
ContentChild,
|
||||
Input,
|
||||
OnInit,
|
||||
TemplateRef,
|
||||
ViewChild,
|
||||
ViewContainerRef,
|
||||
input,
|
||||
} from "@angular/core";
|
||||
|
||||
import { TabLabelDirective } from "./tab-label.directive";
|
||||
@@ -21,8 +21,8 @@ import { TabLabelDirective } from "./tab-label.directive";
|
||||
},
|
||||
})
|
||||
export class TabComponent implements OnInit {
|
||||
@Input() disabled = false;
|
||||
@Input("label") textLabel = "";
|
||||
readonly disabled = input(false);
|
||||
readonly textLabel = input("", { alias: "label" });
|
||||
|
||||
/**
|
||||
* Optional tabIndex for the tabPanel that contains this tab's content.
|
||||
@@ -32,7 +32,7 @@ export class TabComponent implements OnInit {
|
||||
*
|
||||
* @remarks See note 4 of https://www.w3.org/WAI/ARIA/apg/patterns/tabpanel/
|
||||
*/
|
||||
@Input() contentTabIndex: number | undefined;
|
||||
readonly contentTabIndex = input<number | undefined>();
|
||||
|
||||
@ViewChild(TemplateRef, { static: true }) implicitContent: TemplateRef<unknown>;
|
||||
@ContentChild(TabLabelDirective) templateLabel: TabLabelDirective;
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
<a
|
||||
bitTabListItem
|
||||
[routerLink]="disabled ? null : route"
|
||||
[routerLink]="disabled ? null : route()"
|
||||
routerLinkActive
|
||||
[routerLinkActiveOptions]="routerLinkMatchOptions"
|
||||
#rla="routerLinkActive"
|
||||
|
||||
@@ -1,7 +1,15 @@
|
||||
// FIXME: Update this file to be type safe and remove this and next line
|
||||
// @ts-strict-ignore
|
||||
import { FocusableOption } from "@angular/cdk/a11y";
|
||||
import { AfterViewInit, Component, HostListener, Input, OnDestroy, ViewChild } from "@angular/core";
|
||||
import {
|
||||
AfterViewInit,
|
||||
Component,
|
||||
HostListener,
|
||||
Input,
|
||||
OnDestroy,
|
||||
ViewChild,
|
||||
input,
|
||||
} from "@angular/core";
|
||||
import { IsActiveMatchOptions, RouterLinkActive, RouterModule } from "@angular/router";
|
||||
import { Subject, takeUntil } from "rxjs";
|
||||
|
||||
@@ -27,7 +35,10 @@ export class TabLinkComponent implements FocusableOption, AfterViewInit, OnDestr
|
||||
fragment: "ignored",
|
||||
};
|
||||
|
||||
@Input() route: string | any[];
|
||||
readonly route = input<string | any[]>();
|
||||
// TODO: Skipped for signal migration because:
|
||||
// This input overrides a field from a superclass, while the superclass field
|
||||
// is not migrated.
|
||||
@Input() disabled = false;
|
||||
|
||||
@HostListener("keydown", ["$event"]) onKeyDown(event: KeyboardEvent) {
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
<bit-tab-header>
|
||||
<nav bitTabListContainer [attr.aria-label]="label" (keydown)="keyManager.onKeydown($event)">
|
||||
<nav bitTabListContainer [attr.aria-label]="label()" (keydown)="keyManager.onKeydown($event)">
|
||||
<ng-content></ng-content>
|
||||
</nav>
|
||||
</bit-tab-header>
|
||||
|
||||
@@ -6,8 +6,8 @@ import {
|
||||
Component,
|
||||
ContentChildren,
|
||||
forwardRef,
|
||||
Input,
|
||||
QueryList,
|
||||
input,
|
||||
} from "@angular/core";
|
||||
|
||||
import { TabHeaderComponent } from "../shared/tab-header.component";
|
||||
@@ -25,7 +25,7 @@ import { TabLinkComponent } from "./tab-link.component";
|
||||
})
|
||||
export class TabNavBarComponent implements AfterContentInit {
|
||||
@ContentChildren(forwardRef(() => TabLinkComponent)) tabLabels: QueryList<TabLinkComponent>;
|
||||
@Input() label = "";
|
||||
readonly label = input("");
|
||||
|
||||
/**
|
||||
* Focus key manager for keeping tab controls accessible.
|
||||
|
||||
@@ -44,14 +44,18 @@ export default {
|
||||
component: TabGroupComponent,
|
||||
decorators: [
|
||||
moduleMetadata({
|
||||
declarations: [
|
||||
imports: [
|
||||
CommonModule,
|
||||
TabsModule,
|
||||
ButtonModule,
|
||||
FormFieldModule,
|
||||
RouterModule,
|
||||
ActiveDummyComponent,
|
||||
ItemTwoDummyComponent,
|
||||
ItemThreeDummyComponent,
|
||||
ItemWithChildCounterDummyComponent,
|
||||
DisabledDummyComponent,
|
||||
],
|
||||
imports: [CommonModule, TabsModule, ButtonModule, FormFieldModule, RouterModule],
|
||||
}),
|
||||
applicationConfig({
|
||||
providers: [
|
||||
|
||||
Reference in New Issue
Block a user