1
0
mirror of https://github.com/bitwarden/browser synced 2025-12-11 13:53:34 +00:00

UIF - Prefer signal & change detection (#16940)

This commit is contained in:
Oscar Hinton
2025-10-21 18:52:40 +02:00
committed by GitHub
parent d3fc20f8b9
commit 65da23feaa
135 changed files with 503 additions and 51 deletions

View File

@@ -1,5 +1,7 @@
import { Component } from "@angular/core"; import { Component } from "@angular/core";
// FIXME(https://bitwarden.atlassian.net/browse/CL-764): Migrate to OnPush
// eslint-disable-next-line @angular-eslint/prefer-on-push-component-change-detection
@Component({ @Component({
selector: "popup-footer", selector: "popup-footer",
templateUrl: "popup-footer.component.html", templateUrl: "popup-footer.component.html",

View File

@@ -16,6 +16,8 @@ import { PopupRouterCacheService } from "../view-cache/popup-router-cache.servic
import { PopupPageComponent } from "./popup-page.component"; import { PopupPageComponent } from "./popup-page.component";
// FIXME(https://bitwarden.atlassian.net/browse/CL-764): Migrate to OnPush
// eslint-disable-next-line @angular-eslint/prefer-on-push-component-change-detection
@Component({ @Component({
selector: "popup-header", selector: "popup-header",
templateUrl: "popup-header.component.html", templateUrl: "popup-header.component.html",
@@ -23,13 +25,19 @@ import { PopupPageComponent } from "./popup-page.component";
}) })
export class PopupHeaderComponent { export class PopupHeaderComponent {
private popupRouterCacheService = inject(PopupRouterCacheService); private popupRouterCacheService = inject(PopupRouterCacheService);
// FIXME(https://bitwarden.atlassian.net/browse/CL-903): Migrate to Signals
// eslint-disable-next-line @angular-eslint/prefer-signals
protected pageContentScrolled: Signal<boolean> = inject(PopupPageComponent).isScrolled; protected pageContentScrolled: Signal<boolean> = inject(PopupPageComponent).isScrolled;
/** Background color */ /** Background color */
// FIXME(https://bitwarden.atlassian.net/browse/CL-903): Migrate to Signals
// eslint-disable-next-line @angular-eslint/prefer-signals
@Input() @Input()
background: "default" | "alt" = "default"; background: "default" | "alt" = "default";
/** Display the back button, which uses Location.back() to go back one page in history */ /** Display the back button, which uses Location.back() to go back one page in history */
// FIXME(https://bitwarden.atlassian.net/browse/CL-903): Migrate to Signals
// eslint-disable-next-line @angular-eslint/prefer-signals
@Input() @Input()
get showBackButton() { get showBackButton() {
return this._showBackButton; return this._showBackButton;
@@ -41,6 +49,8 @@ export class PopupHeaderComponent {
private _showBackButton = false; private _showBackButton = false;
/** Title string that will be inserted as an h1 */ /** Title string that will be inserted as an h1 */
// FIXME(https://bitwarden.atlassian.net/browse/CL-903): Migrate to Signals
// eslint-disable-next-line @angular-eslint/prefer-signals
@Input({ required: true }) pageTitle: string; @Input({ required: true }) pageTitle: string;
/** /**
@@ -48,6 +58,8 @@ export class PopupHeaderComponent {
* *
* If unset, will call `location.back()` * If unset, will call `location.back()`
**/ **/
// FIXME(https://bitwarden.atlassian.net/browse/CL-903): Migrate to Signals
// eslint-disable-next-line @angular-eslint/prefer-signals
@Input() @Input()
backAction: FunctionReturningAwaitable = async () => { backAction: FunctionReturningAwaitable = async () => {
return this.popupRouterCacheService.back(); return this.popupRouterCacheService.back();

View File

@@ -41,6 +41,8 @@ import { PopupHeaderComponent } from "./popup-header.component";
import { PopupPageComponent } from "./popup-page.component"; import { PopupPageComponent } from "./popup-page.component";
import { PopupTabNavigationComponent } from "./popup-tab-navigation.component"; import { PopupTabNavigationComponent } from "./popup-tab-navigation.component";
// FIXME(https://bitwarden.atlassian.net/browse/CL-764): Migrate to OnPush
// eslint-disable-next-line @angular-eslint/prefer-on-push-component-change-detection
@Component({ @Component({
selector: "extension-container", selector: "extension-container",
template: ` template: `
@@ -51,6 +53,8 @@ import { PopupTabNavigationComponent } from "./popup-tab-navigation.component";
}) })
class ExtensionContainerComponent {} class ExtensionContainerComponent {}
// FIXME(https://bitwarden.atlassian.net/browse/CL-764): Migrate to OnPush
// eslint-disable-next-line @angular-eslint/prefer-on-push-component-change-detection
@Component({ @Component({
selector: "extension-popped-container", selector: "extension-popped-container",
template: ` template: `
@@ -62,6 +66,8 @@ class ExtensionContainerComponent {}
}) })
class ExtensionPoppedContainerComponent {} class ExtensionPoppedContainerComponent {}
// FIXME(https://bitwarden.atlassian.net/browse/CL-764): Migrate to OnPush
// eslint-disable-next-line @angular-eslint/prefer-on-push-component-change-detection
@Component({ @Component({
selector: "vault-placeholder", selector: "vault-placeholder",
template: /*html*/ ` template: /*html*/ `
@@ -95,6 +101,8 @@ class VaultComponent {
protected data = Array.from(Array(20).keys()); protected data = Array.from(Array(20).keys());
} }
// FIXME(https://bitwarden.atlassian.net/browse/CL-764): Migrate to OnPush
// eslint-disable-next-line @angular-eslint/prefer-on-push-component-change-detection
@Component({ @Component({
selector: "mock-add-button", selector: "mock-add-button",
template: ` template: `
@@ -107,6 +115,8 @@ class VaultComponent {
}) })
class MockAddButtonComponent {} class MockAddButtonComponent {}
// FIXME(https://bitwarden.atlassian.net/browse/CL-764): Migrate to OnPush
// eslint-disable-next-line @angular-eslint/prefer-on-push-component-change-detection
@Component({ @Component({
selector: "mock-popout-button", selector: "mock-popout-button",
template: ` template: `
@@ -116,6 +126,8 @@ class MockAddButtonComponent {}
}) })
class MockPopoutButtonComponent {} class MockPopoutButtonComponent {}
// FIXME(https://bitwarden.atlassian.net/browse/CL-764): Migrate to OnPush
// eslint-disable-next-line @angular-eslint/prefer-on-push-component-change-detection
@Component({ @Component({
selector: "mock-current-account", selector: "mock-current-account",
template: ` template: `
@@ -127,6 +139,8 @@ class MockPopoutButtonComponent {}
}) })
class MockCurrentAccountComponent {} class MockCurrentAccountComponent {}
// FIXME(https://bitwarden.atlassian.net/browse/CL-764): Migrate to OnPush
// eslint-disable-next-line @angular-eslint/prefer-on-push-component-change-detection
@Component({ @Component({
selector: "mock-search", selector: "mock-search",
template: ` <bit-search placeholder="Search"> </bit-search> `, template: ` <bit-search placeholder="Search"> </bit-search> `,
@@ -134,6 +148,8 @@ class MockCurrentAccountComponent {}
}) })
class MockSearchComponent {} class MockSearchComponent {}
// FIXME(https://bitwarden.atlassian.net/browse/CL-764): Migrate to OnPush
// eslint-disable-next-line @angular-eslint/prefer-on-push-component-change-detection
@Component({ @Component({
selector: "mock-banner", selector: "mock-banner",
template: ` template: `
@@ -145,6 +161,8 @@ class MockSearchComponent {}
}) })
class MockBannerComponent {} class MockBannerComponent {}
// FIXME(https://bitwarden.atlassian.net/browse/CL-764): Migrate to OnPush
// eslint-disable-next-line @angular-eslint/prefer-on-push-component-change-detection
@Component({ @Component({
selector: "mock-vault-page", selector: "mock-vault-page",
template: ` template: `
@@ -172,6 +190,8 @@ class MockBannerComponent {}
}) })
class MockVaultPageComponent {} class MockVaultPageComponent {}
// FIXME(https://bitwarden.atlassian.net/browse/CL-764): Migrate to OnPush
// eslint-disable-next-line @angular-eslint/prefer-on-push-component-change-detection
@Component({ @Component({
selector: "mock-vault-page-popped", selector: "mock-vault-page-popped",
template: ` template: `
@@ -195,6 +215,8 @@ class MockVaultPageComponent {}
}) })
class MockVaultPagePoppedComponent {} class MockVaultPagePoppedComponent {}
// FIXME(https://bitwarden.atlassian.net/browse/CL-764): Migrate to OnPush
// eslint-disable-next-line @angular-eslint/prefer-on-push-component-change-detection
@Component({ @Component({
selector: "mock-generator-page", selector: "mock-generator-page",
template: ` template: `
@@ -219,6 +241,8 @@ class MockVaultPagePoppedComponent {}
}) })
class MockGeneratorPageComponent {} class MockGeneratorPageComponent {}
// FIXME(https://bitwarden.atlassian.net/browse/CL-764): Migrate to OnPush
// eslint-disable-next-line @angular-eslint/prefer-on-push-component-change-detection
@Component({ @Component({
selector: "mock-send-page", selector: "mock-send-page",
template: ` template: `
@@ -243,6 +267,8 @@ class MockGeneratorPageComponent {}
}) })
class MockSendPageComponent {} class MockSendPageComponent {}
// FIXME(https://bitwarden.atlassian.net/browse/CL-764): Migrate to OnPush
// eslint-disable-next-line @angular-eslint/prefer-on-push-component-change-detection
@Component({ @Component({
selector: "mock-settings-page", selector: "mock-settings-page",
template: ` template: `
@@ -267,6 +293,8 @@ class MockSendPageComponent {}
}) })
class MockSettingsPageComponent {} class MockSettingsPageComponent {}
// FIXME(https://bitwarden.atlassian.net/browse/CL-764): Migrate to OnPush
// eslint-disable-next-line @angular-eslint/prefer-on-push-component-change-detection
@Component({ @Component({
selector: "mock-vault-subpage", selector: "mock-vault-subpage",
template: ` template: `

View File

@@ -4,6 +4,8 @@ import { booleanAttribute, Component, inject, Input, signal } from "@angular/cor
import { I18nService } from "@bitwarden/common/platform/abstractions/i18n.service"; import { I18nService } from "@bitwarden/common/platform/abstractions/i18n.service";
import { ScrollLayoutHostDirective } from "@bitwarden/components"; import { ScrollLayoutHostDirective } from "@bitwarden/components";
// FIXME(https://bitwarden.atlassian.net/browse/CL-764): Migrate to OnPush
// eslint-disable-next-line @angular-eslint/prefer-on-push-component-change-detection
@Component({ @Component({
selector: "popup-page", selector: "popup-page",
templateUrl: "popup-page.component.html", templateUrl: "popup-page.component.html",
@@ -15,15 +17,23 @@ import { ScrollLayoutHostDirective } from "@bitwarden/components";
export class PopupPageComponent { export class PopupPageComponent {
protected i18nService = inject(I18nService); protected i18nService = inject(I18nService);
// FIXME(https://bitwarden.atlassian.net/browse/CL-903): Migrate to Signals
// eslint-disable-next-line @angular-eslint/prefer-signals
@Input() loading = false; @Input() loading = false;
// FIXME(https://bitwarden.atlassian.net/browse/CL-903): Migrate to Signals
// eslint-disable-next-line @angular-eslint/prefer-signals
@Input({ transform: booleanAttribute }) @Input({ transform: booleanAttribute })
disablePadding = false; disablePadding = false;
// FIXME(https://bitwarden.atlassian.net/browse/CL-903): Migrate to Signals
// eslint-disable-next-line @angular-eslint/prefer-signals
protected scrolled = signal(false); protected scrolled = signal(false);
isScrolled = this.scrolled.asReadonly(); isScrolled = this.scrolled.asReadonly();
/** Accessible loading label for the spinner. Defaults to "loading" */ /** Accessible loading label for the spinner. Defaults to "loading" */
// FIXME(https://bitwarden.atlassian.net/browse/CL-903): Migrate to Signals
// eslint-disable-next-line @angular-eslint/prefer-signals
@Input() loadingText?: string = this.i18nService.t("loading"); @Input() loadingText?: string = this.i18nService.t("loading");
handleScroll(event: Event) { handleScroll(event: Event) {

View File

@@ -15,6 +15,8 @@ export type NavButton = {
showBerry?: boolean; showBerry?: boolean;
}; };
// FIXME(https://bitwarden.atlassian.net/browse/CL-764): Migrate to OnPush
// eslint-disable-next-line @angular-eslint/prefer-on-push-component-change-detection
@Component({ @Component({
selector: "popup-tab-navigation", selector: "popup-tab-navigation",
templateUrl: "popup-tab-navigation.component.html", templateUrl: "popup-tab-navigation.component.html",
@@ -24,6 +26,8 @@ export type NavButton = {
}, },
}) })
export class PopupTabNavigationComponent { export class PopupTabNavigationComponent {
// FIXME(https://bitwarden.atlassian.net/browse/CL-903): Migrate to Signals
// eslint-disable-next-line @angular-eslint/prefer-signals
@Input() navButtons: NavButton[] = []; @Input() navButtons: NavButton[] = [];
constructor(private i18nService: I18nService) {} constructor(private i18nService: I18nService) {}

View File

@@ -29,6 +29,8 @@ export interface ExtensionAnonLayoutWrapperData extends AnonLayoutWrapperData {
hideFooter?: boolean; hideFooter?: boolean;
} }
// FIXME(https://bitwarden.atlassian.net/browse/CL-764): Migrate to OnPush
// eslint-disable-next-line @angular-eslint/prefer-on-push-component-change-detection
@Component({ @Component({
templateUrl: "extension-anon-layout-wrapper.component.html", templateUrl: "extension-anon-layout-wrapper.component.html",
imports: [ imports: [

View File

@@ -164,6 +164,8 @@ type Story = StoryObj<ExtensionAnonLayoutWrapperComponent>;
// Default Example // Default Example
// FIXME(https://bitwarden.atlassian.net/browse/CL-764): Migrate to OnPush
// eslint-disable-next-line @angular-eslint/prefer-on-push-component-change-detection
@Component({ @Component({
selector: "bit-default-primary-outlet-example-component", selector: "bit-default-primary-outlet-example-component",
template: "<p>Primary Outlet Example: <br> your primary component goes here</p>", template: "<p>Primary Outlet Example: <br> your primary component goes here</p>",
@@ -171,6 +173,8 @@ type Story = StoryObj<ExtensionAnonLayoutWrapperComponent>;
}) })
class DefaultPrimaryOutletExampleComponent {} class DefaultPrimaryOutletExampleComponent {}
// FIXME(https://bitwarden.atlassian.net/browse/CL-764): Migrate to OnPush
// eslint-disable-next-line @angular-eslint/prefer-on-push-component-change-detection
@Component({ @Component({
selector: "bit-default-secondary-outlet-example-component", selector: "bit-default-secondary-outlet-example-component",
template: "<p>Secondary Outlet Example: <br> your secondary component goes here</p>", template: "<p>Secondary Outlet Example: <br> your secondary component goes here</p>",
@@ -178,6 +182,8 @@ class DefaultPrimaryOutletExampleComponent {}
}) })
class DefaultSecondaryOutletExampleComponent {} class DefaultSecondaryOutletExampleComponent {}
// FIXME(https://bitwarden.atlassian.net/browse/CL-764): Migrate to OnPush
// eslint-disable-next-line @angular-eslint/prefer-on-push-component-change-detection
@Component({ @Component({
selector: "bit-default-env-selector-outlet-example-component", selector: "bit-default-env-selector-outlet-example-component",
template: "<p>Env Selector Outlet Example: <br> your env selector component goes here</p>", template: "<p>Env Selector Outlet Example: <br> your env selector component goes here</p>",
@@ -261,6 +267,8 @@ const changedData: ExtensionAnonLayoutWrapperData = {
showLogo: false, showLogo: false,
}; };
// FIXME(https://bitwarden.atlassian.net/browse/CL-764): Migrate to OnPush
// eslint-disable-next-line @angular-eslint/prefer-on-push-component-change-detection
@Component({ @Component({
selector: "bit-dynamic-content-example-component", selector: "bit-dynamic-content-example-component",
template: ` template: `

View File

@@ -7,6 +7,8 @@ import { PlatformUtilsService } from "@bitwarden/common/platform/abstractions/pl
import { EnvironmentSelectorComponent } from "../components/environment-selector/environment-selector.component"; import { EnvironmentSelectorComponent } from "../components/environment-selector/environment-selector.component";
import { SharedModule } from "../shared"; import { SharedModule } from "../shared";
// FIXME(https://bitwarden.atlassian.net/browse/CL-764): Migrate to OnPush
// eslint-disable-next-line @angular-eslint/prefer-on-push-component-change-detection
@Component({ @Component({
selector: "app-frontend-layout", selector: "app-frontend-layout",
templateUrl: "frontend-layout.component.html", templateUrl: "frontend-layout.component.html",

View File

@@ -14,6 +14,8 @@ import { MessagingService } from "@bitwarden/common/platform/abstractions/messag
import { PlatformUtilsService } from "@bitwarden/common/platform/abstractions/platform-utils.service"; import { PlatformUtilsService } from "@bitwarden/common/platform/abstractions/platform-utils.service";
import { UserId } from "@bitwarden/common/types/guid"; import { UserId } from "@bitwarden/common/types/guid";
// FIXME(https://bitwarden.atlassian.net/browse/CL-764): Migrate to OnPush
// eslint-disable-next-line @angular-eslint/prefer-on-push-component-change-detection
@Component({ @Component({
selector: "app-header", selector: "app-header",
templateUrl: "./web-header.component.html", templateUrl: "./web-header.component.html",
@@ -23,11 +25,15 @@ export class WebHeaderComponent {
/** /**
* Custom title that overrides the route data `titleId` * Custom title that overrides the route data `titleId`
*/ */
// FIXME(https://bitwarden.atlassian.net/browse/CL-903): Migrate to Signals
// eslint-disable-next-line @angular-eslint/prefer-signals
@Input() title: string; @Input() title: string;
/** /**
* Icon to show before the title * Icon to show before the title
*/ */
// FIXME(https://bitwarden.atlassian.net/browse/CL-903): Migrate to Signals
// eslint-disable-next-line @angular-eslint/prefer-signals
@Input() icon: string; @Input() icon: string;
protected routeData$: Observable<{ titleId: string }>; protected routeData$: Observable<{ titleId: string }>;

View File

@@ -46,6 +46,8 @@ class MockStateService {
accounts$ = new BehaviorSubject({ "1": { profile: { name: "Foo" } } }).asObservable(); accounts$ = new BehaviorSubject({ "1": { profile: { name: "Foo" } } }).asObservable();
} }
// FIXME(https://bitwarden.atlassian.net/browse/CL-764): Migrate to OnPush
// eslint-disable-next-line @angular-eslint/prefer-on-push-component-change-detection
@Component({ @Component({
selector: "product-switcher", selector: "product-switcher",
template: `<button type="button" bitIconButton="bwi-filter" label="Switch products"></button>`, template: `<button type="button" bitIconButton="bwi-filter" label="Switch products"></button>`,
@@ -53,6 +55,8 @@ class MockStateService {
}) })
class MockProductSwitcher {} class MockProductSwitcher {}
// FIXME(https://bitwarden.atlassian.net/browse/CL-764): Migrate to OnPush
// eslint-disable-next-line @angular-eslint/prefer-on-push-component-change-detection
@Component({ @Component({
selector: "dynamic-avatar", selector: "dynamic-avatar",
template: `<bit-avatar [text]="name$ | async"></bit-avatar>`, template: `<bit-avatar [text]="name$ | async"></bit-avatar>`,
@@ -68,6 +72,8 @@ class MockDynamicAvatar implements Partial<DynamicAvatarComponent> {
), ),
); );
// FIXME(https://bitwarden.atlassian.net/browse/CL-903): Migrate to Signals
// eslint-disable-next-line @angular-eslint/prefer-signals
@Input() @Input()
text?: string; text?: string;

View File

@@ -14,6 +14,8 @@ import { DialogService, NavigationModule } from "@bitwarden/components";
import { OrganizationWarningsModule } from "@bitwarden/web-vault/app/billing/organizations/warnings/organization-warnings.module"; import { OrganizationWarningsModule } from "@bitwarden/web-vault/app/billing/organizations/warnings/organization-warnings.module";
import { OrganizationWarningsService } from "@bitwarden/web-vault/app/billing/organizations/warnings/services"; import { OrganizationWarningsService } from "@bitwarden/web-vault/app/billing/organizations/warnings/services";
// FIXME(https://bitwarden.atlassian.net/browse/CL-764): Migrate to OnPush
// eslint-disable-next-line @angular-eslint/prefer-on-push-component-change-detection
@Component({ @Component({
selector: "org-switcher", selector: "org-switcher",
templateUrl: "org-switcher.component.html", templateUrl: "org-switcher.component.html",
@@ -43,20 +45,28 @@ export class OrgSwitcherComponent {
* const smFilter = (org: Organization) => org.canAccessSecretsManager * const smFilter = (org: Organization) => org.canAccessSecretsManager
* // <org-switcher [filter]="smFilter"> * // <org-switcher [filter]="smFilter">
*/ */
// FIXME(https://bitwarden.atlassian.net/browse/CL-903): Migrate to Signals
// eslint-disable-next-line @angular-eslint/prefer-signals
@Input() @Input()
filter: (org: Organization) => boolean = () => true; filter: (org: Organization) => boolean = () => true;
/** /**
* Is `true` if the expanded content is visible * Is `true` if the expanded content is visible
*/ */
// FIXME(https://bitwarden.atlassian.net/browse/CL-903): Migrate to Signals
// eslint-disable-next-line @angular-eslint/prefer-signals
@Input() @Input()
open = false; open = false;
// FIXME(https://bitwarden.atlassian.net/browse/CL-903): Migrate to Signals
// eslint-disable-next-line @angular-eslint/prefer-output-emitter-ref
@Output() @Output()
openChange = new EventEmitter<boolean>(); openChange = new EventEmitter<boolean>();
/** /**
* Visibility of the New Organization button * Visibility of the New Organization button
*/ */
// FIXME(https://bitwarden.atlassian.net/browse/CL-903): Migrate to Signals
// eslint-disable-next-line @angular-eslint/prefer-signals
@Input() @Input()
hideNewButton = false; hideNewButton = false;

View File

@@ -16,6 +16,8 @@ import { ProductSwitcherItem, ProductSwitcherService } from "../shared/product-s
import { NavigationProductSwitcherComponent } from "./navigation-switcher.component"; import { NavigationProductSwitcherComponent } from "./navigation-switcher.component";
// FIXME(https://bitwarden.atlassian.net/browse/CL-764): Migrate to OnPush
// eslint-disable-next-line @angular-eslint/prefer-on-push-component-change-detection
@Component({ @Component({
selector: "app-upgrade-nav-button", selector: "app-upgrade-nav-button",
template: "<div>Upgrade Nav Button</div>", template: "<div>Upgrade Nav Button</div>",

View File

@@ -3,6 +3,8 @@ import { map, Observable } from "rxjs";
import { ProductSwitcherItem, ProductSwitcherService } from "../shared/product-switcher.service"; import { ProductSwitcherItem, ProductSwitcherService } from "../shared/product-switcher.service";
// FIXME(https://bitwarden.atlassian.net/browse/CL-764): Migrate to OnPush
// eslint-disable-next-line @angular-eslint/prefer-on-push-component-change-detection
@Component({ @Component({
selector: "navigation-product-switcher", selector: "navigation-product-switcher",
templateUrl: "./navigation-switcher.component.html", templateUrl: "./navigation-switcher.component.html",

View File

@@ -37,6 +37,8 @@ class MockOrganizationService implements Partial<OrganizationService> {
return MockOrganizationService._orgs.asObservable(); return MockOrganizationService._orgs.asObservable();
} }
// FIXME(https://bitwarden.atlassian.net/browse/CL-903): Migrate to Signals
// eslint-disable-next-line @angular-eslint/prefer-signals
@Input() @Input()
set mockOrgs(orgs: Organization[]) { set mockOrgs(orgs: Organization[]) {
MockOrganizationService._orgs.next(orgs); MockOrganizationService._orgs.next(orgs);
@@ -54,6 +56,8 @@ class MockProviderService implements Partial<ProviderService> {
return MockProviderService._providers.asObservable(); return MockProviderService._providers.asObservable();
} }
// FIXME(https://bitwarden.atlassian.net/browse/CL-903): Migrate to Signals
// eslint-disable-next-line @angular-eslint/prefer-signals
@Input() @Input()
set mockProviders(providers: Provider[]) { set mockProviders(providers: Provider[]) {
MockProviderService._providers.next(providers); MockProviderService._providers.next(providers);
@@ -93,6 +97,8 @@ class MockConfigService implements Partial<ConfigService> {
} }
} }
// FIXME(https://bitwarden.atlassian.net/browse/CL-764): Migrate to OnPush
// eslint-disable-next-line @angular-eslint/prefer-on-push-component-change-detection
@Component({ @Component({
selector: "story-layout", selector: "story-layout",
template: `<ng-content></ng-content>`, template: `<ng-content></ng-content>`,
@@ -100,6 +106,8 @@ class MockConfigService implements Partial<ConfigService> {
}) })
class StoryLayoutComponent {} class StoryLayoutComponent {}
// FIXME(https://bitwarden.atlassian.net/browse/CL-764): Migrate to OnPush
// eslint-disable-next-line @angular-eslint/prefer-on-push-component-change-detection
@Component({ @Component({
selector: "story-content", selector: "story-content",
template: ``, template: ``,

View File

@@ -6,12 +6,16 @@ import { MenuComponent } from "@bitwarden/components";
import { ProductSwitcherService } from "./shared/product-switcher.service"; import { ProductSwitcherService } from "./shared/product-switcher.service";
// FIXME(https://bitwarden.atlassian.net/browse/CL-764): Migrate to OnPush
// eslint-disable-next-line @angular-eslint/prefer-on-push-component-change-detection
@Component({ @Component({
selector: "product-switcher-content", selector: "product-switcher-content",
templateUrl: "./product-switcher-content.component.html", templateUrl: "./product-switcher-content.component.html",
standalone: false, standalone: false,
}) })
export class ProductSwitcherContentComponent { export class ProductSwitcherContentComponent {
// FIXME(https://bitwarden.atlassian.net/browse/CL-903): Migrate to Signals
// eslint-disable-next-line @angular-eslint/prefer-signals
@ViewChild("menu") @ViewChild("menu")
menu: MenuComponent; menu: MenuComponent;

View File

@@ -5,6 +5,8 @@ import { AfterViewInit, ChangeDetectorRef, Component, Input } from "@angular/cor
import { IconButtonType } from "@bitwarden/components/src/icon-button/icon-button.component"; import { IconButtonType } from "@bitwarden/components/src/icon-button/icon-button.component";
import { ProductSwitcherService } from "./shared/product-switcher.service"; import { ProductSwitcherService } from "./shared/product-switcher.service";
// FIXME(https://bitwarden.atlassian.net/browse/CL-764): Migrate to OnPush
// eslint-disable-next-line @angular-eslint/prefer-on-push-component-change-detection
@Component({ @Component({
selector: "product-switcher", selector: "product-switcher",
templateUrl: "./product-switcher.component.html", templateUrl: "./product-switcher.component.html",
@@ -14,6 +16,8 @@ export class ProductSwitcherComponent implements AfterViewInit {
/** /**
* Passed to the product switcher's `bitIconButton` * Passed to the product switcher's `bitIconButton`
*/ */
// FIXME(https://bitwarden.atlassian.net/browse/CL-903): Migrate to Signals
// eslint-disable-next-line @angular-eslint/prefer-signals
@Input() @Input()
buttonType: IconButtonType = "main"; buttonType: IconButtonType = "main";

View File

@@ -37,6 +37,8 @@ class MockOrganizationService implements Partial<OrganizationService> {
return MockOrganizationService._orgs.asObservable(); return MockOrganizationService._orgs.asObservable();
} }
// FIXME(https://bitwarden.atlassian.net/browse/CL-903): Migrate to Signals
// eslint-disable-next-line @angular-eslint/prefer-signals
@Input() @Input()
set mockOrgs(orgs: Organization[]) { set mockOrgs(orgs: Organization[]) {
MockOrganizationService._orgs.next(orgs); MockOrganizationService._orgs.next(orgs);
@@ -54,6 +56,8 @@ class MockProviderService implements Partial<ProviderService> {
return MockProviderService._providers.asObservable(); return MockProviderService._providers.asObservable();
} }
// FIXME(https://bitwarden.atlassian.net/browse/CL-903): Migrate to Signals
// eslint-disable-next-line @angular-eslint/prefer-signals
@Input() @Input()
set mockProviders(providers: Provider[]) { set mockProviders(providers: Provider[]) {
MockProviderService._providers.next(providers); MockProviderService._providers.next(providers);
@@ -93,6 +97,8 @@ class MockConfigService implements Partial<ConfigService> {
} }
} }
// FIXME(https://bitwarden.atlassian.net/browse/CL-764): Migrate to OnPush
// eslint-disable-next-line @angular-eslint/prefer-on-push-component-change-detection
@Component({ @Component({
selector: "story-layout", selector: "story-layout",
template: `<ng-content></ng-content>`, template: `<ng-content></ng-content>`,
@@ -100,6 +106,8 @@ class MockConfigService implements Partial<ConfigService> {
}) })
class StoryLayoutComponent {} class StoryLayoutComponent {}
// FIXME(https://bitwarden.atlassian.net/browse/CL-764): Migrate to OnPush
// eslint-disable-next-line @angular-eslint/prefer-on-push-component-change-detection
@Component({ @Component({
selector: "story-content", selector: "story-content",
template: ``, template: ``,

View File

@@ -4,6 +4,8 @@ import { Component } from "@angular/core";
import { PlatformUtilsService } from "@bitwarden/common/platform/abstractions/platform-utils.service"; import { PlatformUtilsService } from "@bitwarden/common/platform/abstractions/platform-utils.service";
import { NavigationModule } from "@bitwarden/components"; import { NavigationModule } from "@bitwarden/components";
// FIXME(https://bitwarden.atlassian.net/browse/CL-764): Migrate to OnPush
// eslint-disable-next-line @angular-eslint/prefer-on-push-component-change-detection
@Component({ @Component({
selector: "app-toggle-width", selector: "app-toggle-width",
template: `<bit-nav-item template: `<bit-nav-item

View File

@@ -16,6 +16,8 @@ import { BillingFreeFamiliesNavItemComponent } from "../billing/shared/billing-f
import { WebLayoutModule } from "./web-layout.module"; import { WebLayoutModule } from "./web-layout.module";
// FIXME(https://bitwarden.atlassian.net/browse/CL-764): Migrate to OnPush
// eslint-disable-next-line @angular-eslint/prefer-on-push-component-change-detection
@Component({ @Component({
selector: "app-user-layout", selector: "app-user-layout",
templateUrl: "user-layout.component.html", templateUrl: "user-layout.component.html",

View File

@@ -5,6 +5,8 @@ import { LayoutComponent } from "@bitwarden/components";
import { ProductSwitcherModule } from "./product-switcher/product-switcher.module"; import { ProductSwitcherModule } from "./product-switcher/product-switcher.module";
// FIXME(https://bitwarden.atlassian.net/browse/CL-764): Migrate to OnPush
// eslint-disable-next-line @angular-eslint/prefer-on-push-component-change-detection
@Component({ @Component({
selector: "app-layout", selector: "app-layout",
templateUrl: "web-layout.component.html", templateUrl: "web-layout.component.html",

View File

@@ -6,11 +6,15 @@ import { SideNavVariant, NavigationModule } from "@bitwarden/components";
import { ProductSwitcherModule } from "./product-switcher/product-switcher.module"; import { ProductSwitcherModule } from "./product-switcher/product-switcher.module";
import { ToggleWidthComponent } from "./toggle-width.component"; import { ToggleWidthComponent } from "./toggle-width.component";
// FIXME(https://bitwarden.atlassian.net/browse/CL-764): Migrate to OnPush
// eslint-disable-next-line @angular-eslint/prefer-on-push-component-change-detection
@Component({ @Component({
selector: "app-side-nav", selector: "app-side-nav",
templateUrl: "web-side-nav.component.html", templateUrl: "web-side-nav.component.html",
imports: [CommonModule, NavigationModule, ProductSwitcherModule, ToggleWidthComponent], imports: [CommonModule, NavigationModule, ProductSwitcherModule, ToggleWidthComponent],
}) })
export class WebSideNavComponent { export class WebSideNavComponent {
// FIXME(https://bitwarden.atlassian.net/browse/CL-903): Migrate to Signals
// eslint-disable-next-line @angular-eslint/prefer-signals
@Input() variant: SideNavVariant = "primary"; @Input() variant: SideNavVariant = "primary";
} }

View File

@@ -6,7 +6,7 @@ import { setA11yTitleAndAriaLabel } from "./set-a11y-title-and-aria-label";
selector: "[appA11yTitle]", selector: "[appA11yTitle]",
}) })
export class A11yTitleDirective { export class A11yTitleDirective {
title = input.required<string>({ alias: "appA11yTitle" }); readonly title = input.required<string>({ alias: "appA11yTitle" });
constructor(private el: ElementRef) { constructor(private el: ElementRef) {
const originalTitle = this.el.nativeElement.getAttribute("title"); const originalTitle = this.el.nativeElement.getAttribute("title");

View File

@@ -46,6 +46,8 @@ export interface AnonLayoutWrapperData {
hideBackgroundIllustration?: boolean; hideBackgroundIllustration?: boolean;
} }
// FIXME(https://bitwarden.atlassian.net/browse/CL-764): Migrate to OnPush
// eslint-disable-next-line @angular-eslint/prefer-on-push-component-change-detection
@Component({ @Component({
templateUrl: "anon-layout-wrapper.component.html", templateUrl: "anon-layout-wrapper.component.html",
imports: [AnonLayoutComponent, RouterModule], imports: [AnonLayoutComponent, RouterModule],

View File

@@ -103,6 +103,8 @@ type Story = StoryObj<AnonLayoutWrapperComponent>;
// Default Example // Default Example
// FIXME(https://bitwarden.atlassian.net/browse/CL-764): Migrate to OnPush
// eslint-disable-next-line @angular-eslint/prefer-on-push-component-change-detection
@Component({ @Component({
selector: "bit-default-primary-outlet-example-component", selector: "bit-default-primary-outlet-example-component",
template: "<p>Primary Outlet Example: <br> your primary component goes here</p>", template: "<p>Primary Outlet Example: <br> your primary component goes here</p>",
@@ -110,6 +112,8 @@ type Story = StoryObj<AnonLayoutWrapperComponent>;
}) })
export class DefaultPrimaryOutletExampleComponent {} export class DefaultPrimaryOutletExampleComponent {}
// FIXME(https://bitwarden.atlassian.net/browse/CL-764): Migrate to OnPush
// eslint-disable-next-line @angular-eslint/prefer-on-push-component-change-detection
@Component({ @Component({
selector: "bit-default-secondary-outlet-example-component", selector: "bit-default-secondary-outlet-example-component",
template: "<p>Secondary Outlet Example: <br> your secondary component goes here</p>", template: "<p>Secondary Outlet Example: <br> your secondary component goes here</p>",
@@ -117,6 +121,8 @@ export class DefaultPrimaryOutletExampleComponent {}
}) })
export class DefaultSecondaryOutletExampleComponent {} export class DefaultSecondaryOutletExampleComponent {}
// FIXME(https://bitwarden.atlassian.net/browse/CL-764): Migrate to OnPush
// eslint-disable-next-line @angular-eslint/prefer-on-push-component-change-detection
@Component({ @Component({
selector: "bit-default-env-selector-outlet-example-component", selector: "bit-default-env-selector-outlet-example-component",
template: "<p>Env Selector Outlet Example: <br> your env selector component goes here</p>", template: "<p>Env Selector Outlet Example: <br> your env selector component goes here</p>",
@@ -192,6 +198,8 @@ const changedData: AnonLayoutWrapperData = {
pageIcon: RegistrationCheckEmailIcon, pageIcon: RegistrationCheckEmailIcon,
}; };
// FIXME(https://bitwarden.atlassian.net/browse/CL-764): Migrate to OnPush
// eslint-disable-next-line @angular-eslint/prefer-on-push-component-change-detection
@Component({ @Component({
selector: "bit-dynamic-content-example-component", selector: "bit-dynamic-content-example-component",
template: ` template: `

View File

@@ -27,6 +27,8 @@ import { TypographyModule } from "../typography";
export type AnonLayoutMaxWidth = "md" | "lg" | "xl" | "2xl" | "3xl" | "4xl"; export type AnonLayoutMaxWidth = "md" | "lg" | "xl" | "2xl" | "3xl" | "4xl";
// FIXME(https://bitwarden.atlassian.net/browse/CL-764): Migrate to OnPush
// eslint-disable-next-line @angular-eslint/prefer-on-push-component-change-detection
@Component({ @Component({
selector: "auth-anon-layout", selector: "auth-anon-layout",
templateUrl: "./anon-layout.component.html", templateUrl: "./anon-layout.component.html",

View File

@@ -1,5 +1,7 @@
import { Component } from "@angular/core"; import { Component } from "@angular/core";
// FIXME(https://bitwarden.atlassian.net/browse/CL-764): Migrate to OnPush
// eslint-disable-next-line @angular-eslint/prefer-on-push-component-change-detection
@Component({ @Component({
selector: "app-root", selector: "app-root",
template: "", template: "",

View File

@@ -39,6 +39,8 @@ const template = `
<button class="tw-me-2" type="button" buttonType="muted" bitIconButton="bwi-star" label="Delete" bitFormButton [bitAction]="delete">Delete</button> <button class="tw-me-2" type="button" buttonType="muted" bitIconButton="bwi-star" label="Delete" bitFormButton [bitAction]="delete">Delete</button>
</form>`; </form>`;
// FIXME(https://bitwarden.atlassian.net/browse/CL-764): Migrate to OnPush
// eslint-disable-next-line @angular-eslint/prefer-on-push-component-change-detection
@Component({ @Component({
selector: "app-promise-example", selector: "app-promise-example",
template, template,
@@ -84,6 +86,8 @@ class PromiseExampleComponent {
}; };
} }
// FIXME(https://bitwarden.atlassian.net/browse/CL-764): Migrate to OnPush
// eslint-disable-next-line @angular-eslint/prefer-on-push-component-change-detection
@Component({ @Component({
selector: "app-observable-example", selector: "app-observable-example",
template, template,

View File

@@ -20,6 +20,8 @@ const template = /*html*/ `
</button> </button>
<button type="button" label="Delete" bitIconButton="bwi-trash" buttonType="danger" [bitAction]="action"></button>`; <button type="button" label="Delete" bitIconButton="bwi-trash" buttonType="danger" [bitAction]="action"></button>`;
// FIXME(https://bitwarden.atlassian.net/browse/CL-764): Migrate to OnPush
// eslint-disable-next-line @angular-eslint/prefer-on-push-component-change-detection
@Component({ @Component({
template, template,
selector: "app-promise-example", selector: "app-promise-example",
@@ -37,6 +39,8 @@ class PromiseExampleComponent {
}; };
} }
// FIXME(https://bitwarden.atlassian.net/browse/CL-764): Migrate to OnPush
// eslint-disable-next-line @angular-eslint/prefer-on-push-component-change-detection
@Component({ @Component({
template, template,
selector: "app-action-resolves-quickly", selector: "app-action-resolves-quickly",
@@ -55,6 +59,8 @@ class ActionResolvesQuicklyComponent {
}; };
} }
// FIXME(https://bitwarden.atlassian.net/browse/CL-764): Migrate to OnPush
// eslint-disable-next-line @angular-eslint/prefer-on-push-component-change-detection
@Component({ @Component({
template, template,
selector: "app-observable-example", selector: "app-observable-example",
@@ -66,6 +72,8 @@ class ObservableExampleComponent {
}; };
} }
// FIXME(https://bitwarden.atlassian.net/browse/CL-764): Migrate to OnPush
// eslint-disable-next-line @angular-eslint/prefer-on-push-component-change-detection
@Component({ @Component({
template, template,
selector: "app-rejected-promise-example", selector: "app-rejected-promise-example",

View File

@@ -19,6 +19,8 @@ const SizeClasses: Record<SizeTypes, string[]> = {
* A variance in color across the avatar component is important as it is used in Account Switching as a * A variance in color across the avatar component is important as it is used in Account Switching as a
* visual indicator to recognize which of a personal or work account a user is logged into. * visual indicator to recognize which of a personal or work account a user is logged into.
*/ */
// FIXME(https://bitwarden.atlassian.net/browse/CL-764): Migrate to OnPush
// eslint-disable-next-line @angular-eslint/prefer-on-push-component-change-detection
@Component({ @Component({
selector: "bit-avatar", selector: "bit-avatar",
template: ` template: `

View File

@@ -8,6 +8,8 @@ function transformMaxItems(value: number | undefined) {
return value == undefined ? undefined : Math.max(1, value); return value == undefined ? undefined : Math.max(1, value);
} }
// FIXME(https://bitwarden.atlassian.net/browse/CL-764): Migrate to OnPush
// eslint-disable-next-line @angular-eslint/prefer-on-push-component-change-detection
@Component({ @Component({
selector: "bit-badge-list", selector: "bit-badge-list",
templateUrl: "badge-list.component.html", templateUrl: "badge-list.component.html",

View File

@@ -55,6 +55,8 @@ const hoverStyles: Record<BadgeVariant, string[]> = {
* > `NOTE:` The `disabled` state only applies to buttons. * > `NOTE:` The `disabled` state only applies to buttons.
* *
*/ */
// FIXME(https://bitwarden.atlassian.net/browse/CL-764): Migrate to OnPush
// eslint-disable-next-line @angular-eslint/prefer-on-push-component-change-detection
@Component({ @Component({
selector: "span[bitBadge], a[bitBadge], button[bitBadge]", selector: "span[bitBadge], a[bitBadge], button[bitBadge]",
providers: [{ provide: FocusableElement, useExisting: BadgeComponent }], providers: [{ provide: FocusableElement, useExisting: BadgeComponent }],

View File

@@ -23,6 +23,8 @@ const defaultIcon: Record<BannerType, string> = {
* - Avoid stacking multiple banners. * - Avoid stacking multiple banners.
* - Banners can contain a button or anchor that uses the `bitLink` directive with `linkType="secondary"`. * - Banners can contain a button or anchor that uses the `bitLink` directive with `linkType="secondary"`.
*/ */
// FIXME(https://bitwarden.atlassian.net/browse/CL-764): Migrate to OnPush
// eslint-disable-next-line @angular-eslint/prefer-on-push-component-change-detection
@Component({ @Component({
selector: "bit-banner", selector: "bit-banner",
templateUrl: "./banner.component.html", templateUrl: "./banner.component.html",
@@ -40,6 +42,8 @@ export class BannerComponent implements OnInit {
readonly useAlertRole = input(true); readonly useAlertRole = input(true);
readonly showClose = input(true); readonly showClose = input(true);
// FIXME(https://bitwarden.atlassian.net/browse/CL-903): Migrate to Signals
// eslint-disable-next-line @angular-eslint/prefer-output-emitter-ref
@Output() onClose = new EventEmitter<void>(); @Output() onClose = new EventEmitter<void>();
ngOnInit(): void { ngOnInit(): void {

View File

@@ -1,6 +1,8 @@
import { Component, EventEmitter, Output, TemplateRef, input, viewChild } from "@angular/core"; import { Component, EventEmitter, Output, TemplateRef, input, viewChild } from "@angular/core";
import { QueryParamsHandling } from "@angular/router"; import { QueryParamsHandling } from "@angular/router";
// FIXME(https://bitwarden.atlassian.net/browse/CL-764): Migrate to OnPush
// eslint-disable-next-line @angular-eslint/prefer-on-push-component-change-detection
@Component({ @Component({
selector: "bit-breadcrumb", selector: "bit-breadcrumb",
templateUrl: "./breadcrumb.component.html", templateUrl: "./breadcrumb.component.html",
@@ -14,6 +16,8 @@ export class BreadcrumbComponent {
readonly queryParamsHandling = input<QueryParamsHandling>(); readonly queryParamsHandling = input<QueryParamsHandling>();
// FIXME(https://bitwarden.atlassian.net/browse/CL-903): Migrate to Signals
// eslint-disable-next-line @angular-eslint/prefer-output-emitter-ref
@Output() @Output()
click = new EventEmitter(); click = new EventEmitter();

View File

@@ -15,6 +15,8 @@ import { BreadcrumbComponent } from "./breadcrumb.component";
* Bitwarden uses this component to indicate the user's current location in a set of data organized in * Bitwarden uses this component to indicate the user's current location in a set of data organized in
* containers (Collections, Folders, or Projects). * containers (Collections, Folders, or Projects).
*/ */
// FIXME(https://bitwarden.atlassian.net/browse/CL-764): Migrate to OnPush
// eslint-disable-next-line @angular-eslint/prefer-on-push-component-change-detection
@Component({ @Component({
selector: "bit-breadcrumbs", selector: "bit-breadcrumbs",
templateUrl: "./breadcrumbs.component.html", templateUrl: "./breadcrumbs.component.html",
@@ -25,6 +27,8 @@ export class BreadcrumbsComponent {
private breadcrumbs: BreadcrumbComponent[] = []; private breadcrumbs: BreadcrumbComponent[] = [];
// FIXME(https://bitwarden.atlassian.net/browse/CL-903): Migrate to Signals
// eslint-disable-next-line @angular-eslint/prefer-signals
@ContentChildren(BreadcrumbComponent) @ContentChildren(BreadcrumbComponent)
protected set breadcrumbList(value: QueryList<BreadcrumbComponent>) { protected set breadcrumbList(value: QueryList<BreadcrumbComponent>) {
this.breadcrumbs = value.toArray(); this.breadcrumbs = value.toArray();

View File

@@ -18,6 +18,8 @@ interface Breadcrumb {
route: string; route: string;
} }
// FIXME(https://bitwarden.atlassian.net/browse/CL-764): Migrate to OnPush
// eslint-disable-next-line @angular-eslint/prefer-on-push-component-change-detection
@Component({ @Component({
template: "", template: "",
}) })

View File

@@ -56,6 +56,8 @@ describe("Button", () => {
}); });
}); });
// FIXME(https://bitwarden.atlassian.net/browse/CL-764): Migrate to OnPush
// eslint-disable-next-line @angular-eslint/prefer-on-push-component-change-detection
@Component({ @Component({
selector: "test-app", selector: "test-app",
template: ` template: `

View File

@@ -57,6 +57,8 @@ const buttonStyles: Record<ButtonType, string[]> = {
unstyled: [], unstyled: [],
}; };
// FIXME(https://bitwarden.atlassian.net/browse/CL-764): Migrate to OnPush
// eslint-disable-next-line @angular-eslint/prefer-on-push-component-change-detection
@Component({ @Component({
selector: "button[bitButton], a[bitButton]", selector: "button[bitButton], a[bitButton]",
templateUrl: "button.component.html", templateUrl: "button.component.html",
@@ -97,7 +99,7 @@ export class ButtonComponent implements ButtonLikeAbstraction {
.concat(buttonSizeStyles[this.size() || "default"]); .concat(buttonSizeStyles[this.size() || "default"]);
} }
protected disabledAttr = computed(() => { protected readonly disabledAttr = computed(() => {
const disabled = this.disabled() != null && this.disabled() !== false; const disabled = this.disabled() != null && this.disabled() !== false;
return disabled || this.loading(); return disabled || this.loading();
}); });
@@ -110,7 +112,7 @@ export class ButtonComponent implements ButtonLikeAbstraction {
* We can't use `disabledAttr` for this, because it returns `true` when `loading` is `true`. * We can't use `disabledAttr` for this, because it returns `true` when `loading` is `true`.
* We only want to show disabled styles during loading if `showLoadingStyles` is `true`. * We only want to show disabled styles during loading if `showLoadingStyles` is `true`.
*/ */
protected showDisabledStyles = computed(() => { protected readonly showDisabledStyles = computed(() => {
return this.showLoadingStyle() || (this.disabledAttr() && this.loading() === false); return this.showLoadingStyle() || (this.disabledAttr() && this.loading() === false);
}); });
@@ -134,11 +136,11 @@ export class ButtonComponent implements ButtonLikeAbstraction {
* This pattern of converting a signal to an observable and back to a signal is not * This pattern of converting a signal to an observable and back to a signal is not
* recommended. TODO -- find better way to use debounce with signals (CL-596) * recommended. TODO -- find better way to use debounce with signals (CL-596)
*/ */
protected showLoadingStyle = toSignal( protected readonly showLoadingStyle = toSignal(
toObservable(this.loading).pipe(debounce((isLoading) => interval(isLoading ? 75 : 0))), toObservable(this.loading).pipe(debounce((isLoading) => interval(isLoading ? 75 : 0))),
); );
disabled = model<boolean>(false); readonly disabled = model<boolean>(false);
private el = inject(ElementRef<HTMLButtonElement>); private el = inject(ElementRef<HTMLButtonElement>);
constructor() { constructor() {

View File

@@ -28,6 +28,8 @@ let nextId = 0;
* sparingly, as they command a large amount of visual attention. Avoid using more than 1 callout in * sparingly, as they command a large amount of visual attention. Avoid using more than 1 callout in
* the same location. * the same location.
*/ */
// FIXME(https://bitwarden.atlassian.net/browse/CL-764): Migrate to OnPush
// eslint-disable-next-line @angular-eslint/prefer-on-push-component-change-detection
@Component({ @Component({
selector: "bit-callout", selector: "bit-callout",
templateUrl: "callout.component.html", templateUrl: "callout.component.html",

View File

@@ -3,6 +3,8 @@ import { NgControl, Validators } from "@angular/forms";
import { BitFormControlAbstraction } from "../form-control"; import { BitFormControlAbstraction } from "../form-control";
// FIXME(https://bitwarden.atlassian.net/browse/CL-764): Migrate to OnPush
// eslint-disable-next-line @angular-eslint/prefer-on-push-component-change-detection
@Component({ @Component({
selector: "input[type=checkbox][bitCheckbox]", selector: "input[type=checkbox][bitCheckbox]",
template: "", template: "",

View File

@@ -28,6 +28,8 @@ const template = /*html*/ `
</form> </form>
`; `;
// FIXME(https://bitwarden.atlassian.net/browse/CL-764): Migrate to OnPush
// eslint-disable-next-line @angular-eslint/prefer-on-push-component-change-detection
@Component({ @Component({
selector: "app-example", selector: "app-example",
template, template,
@@ -38,10 +40,14 @@ class ExampleComponent {
checkbox: [false, Validators.requiredTrue], checkbox: [false, Validators.requiredTrue],
}); });
// FIXME(https://bitwarden.atlassian.net/browse/CL-903): Migrate to Signals
// eslint-disable-next-line @angular-eslint/prefer-signals
@Input() set checked(value: boolean) { @Input() set checked(value: boolean) {
this.formObj.patchValue({ checkbox: value }); this.formObj.patchValue({ checkbox: value });
} }
// FIXME(https://bitwarden.atlassian.net/browse/CL-903): Migrate to Signals
// eslint-disable-next-line @angular-eslint/prefer-signals
@Input() set disabled(disable: boolean) { @Input() set disabled(disable: boolean) {
if (disable) { if (disable) {
this.formObj.disable(); this.formObj.disable();

View File

@@ -35,6 +35,8 @@ export type ChipSelectOption<T> = Option<T> & {
/** /**
* `<bit-chip-select>` is a select element that is commonly used to filter items in lists or tables. * `<bit-chip-select>` is a select element that is commonly used to filter items in lists or tables.
*/ */
// FIXME(https://bitwarden.atlassian.net/browse/CL-764): Migrate to OnPush
// eslint-disable-next-line @angular-eslint/prefer-on-push-component-change-detection
@Component({ @Component({
selector: "bit-chip-select", selector: "bit-chip-select",
templateUrl: "chip-select.component.html", templateUrl: "chip-select.component.html",
@@ -49,6 +51,8 @@ export type ChipSelectOption<T> = Option<T> & {
}) })
export class ChipSelectComponent<T = unknown> implements ControlValueAccessor, AfterViewInit { export class ChipSelectComponent<T = unknown> implements ControlValueAccessor, AfterViewInit {
readonly menu = viewChild(MenuComponent); readonly menu = viewChild(MenuComponent);
// FIXME(https://bitwarden.atlassian.net/browse/CL-903): Migrate to Signals
// eslint-disable-next-line @angular-eslint/prefer-signals
@ViewChildren(MenuItemDirective) menuItems?: QueryList<MenuItemDirective>; @ViewChildren(MenuItemDirective) menuItems?: QueryList<MenuItemDirective>;
readonly chipSelectButton = viewChild<ElementRef<HTMLButtonElement>>("chipSelectButton"); readonly chipSelectButton = viewChild<ElementRef<HTMLButtonElement>>("chipSelectButton");
@@ -63,6 +67,8 @@ export class ChipSelectComponent<T = unknown> implements ControlValueAccessor, A
// TODO: Skipped for signal migration because: // TODO: Skipped for signal migration because:
// Accessor inputs cannot be migrated as they are too complex. // Accessor inputs cannot be migrated as they are too complex.
/** The select options to render */ /** The select options to render */
// FIXME(https://bitwarden.atlassian.net/browse/CL-903): Migrate to Signals
// eslint-disable-next-line @angular-eslint/prefer-signals
@Input({ required: true }) @Input({ required: true })
get options(): ChipSelectOption<T>[] { get options(): ChipSelectOption<T>[] {
return this._options; return this._options;
@@ -75,6 +81,8 @@ export class ChipSelectComponent<T = unknown> implements ControlValueAccessor, A
/** Disables the entire chip */ /** Disables the entire chip */
// TODO: Skipped for signal migration because: // TODO: Skipped for signal migration because:
// Your application code writes to the input. This prevents migration. // Your application code writes to the input. This prevents migration.
// FIXME(https://bitwarden.atlassian.net/browse/CL-903): Migrate to Signals
// eslint-disable-next-line @angular-eslint/prefer-signals
@Input({ transform: booleanAttribute }) disabled = false; @Input({ transform: booleanAttribute }) disabled = false;
/** Chip will stretch to full width of its container */ /** Chip will stretch to full width of its container */
@@ -83,7 +91,7 @@ export class ChipSelectComponent<T = unknown> implements ControlValueAccessor, A
/** /**
* We have `:focus-within` and `:focus-visible` but no `:focus-visible-within` * We have `:focus-within` and `:focus-visible` but no `:focus-visible-within`
*/ */
protected focusVisibleWithin = signal(false); protected readonly focusVisibleWithin = signal(false);
@HostListener("focusin", ["$event.target"]) @HostListener("focusin", ["$event.target"])
onFocusIn(target: HTMLElement) { onFocusIn(target: HTMLElement) {
this.focusVisibleWithin.set(target.matches("[data-fvw-target]:focus-visible")); this.focusVisibleWithin.set(target.matches("[data-fvw-target]:focus-visible"));

View File

@@ -9,6 +9,8 @@ type CharacterType = "letter" | "emoji" | "special" | "number";
* the logic for displaying letters as `text-main`, numbers as `primary`, and special symbols as * the logic for displaying letters as `text-main`, numbers as `primary`, and special symbols as
* `danger`. * `danger`.
*/ */
// FIXME(https://bitwarden.atlassian.net/browse/CL-764): Migrate to OnPush
// eslint-disable-next-line @angular-eslint/prefer-on-push-component-change-detection
@Component({ @Component({
selector: "bit-color-password", selector: "bit-color-password",
template: `@for (character of passwordCharArray(); track $index; let i = $index) { template: `@for (character of passwordCharArray(); track $index; let i = $index) {
@@ -21,11 +23,11 @@ type CharacterType = "letter" | "emoji" | "special" | "number";
}`, }`,
}) })
export class ColorPasswordComponent { export class ColorPasswordComponent {
password = input<string>(""); readonly password = input<string>("");
showCount = input<boolean>(false); readonly showCount = input<boolean>(false);
// Convert to an array to handle cases that strings have special characters, i.e.: emoji. // Convert to an array to handle cases that strings have special characters, i.e.: emoji.
passwordCharArray = computed(() => { readonly passwordCharArray = computed(() => {
return Array.from(this.password() ?? ""); return Array.from(this.password() ?? "");
}); });

View File

@@ -3,6 +3,8 @@ import { Component } from "@angular/core";
/** /**
* bit-container is a minimally styled component that limits the max width of its content to the tailwind theme variable '4xl'. '4xl' is equal to the value of 56rem * bit-container is a minimally styled component that limits the max width of its content to the tailwind theme variable '4xl'. '4xl' is equal to the value of 56rem
*/ */
// FIXME(https://bitwarden.atlassian.net/browse/CL-764): Migrate to OnPush
// eslint-disable-next-line @angular-eslint/prefer-on-push-component-change-detection
@Component({ @Component({
selector: "bit-container", selector: "bit-container",
templateUrl: "container.component.html", templateUrl: "container.component.html",

View File

@@ -9,6 +9,8 @@ import { ToastService, CopyClickListener, COPY_CLICK_LISTENER } from "../";
import { CopyClickDirective } from "./copy-click.directive"; import { CopyClickDirective } from "./copy-click.directive";
// FIXME(https://bitwarden.atlassian.net/browse/CL-764): Migrate to OnPush
// eslint-disable-next-line @angular-eslint/prefer-on-push-component-change-detection
@Component({ @Component({
template: ` template: `
<button type="button" appCopyClick="no toast shown" #noToast></button> <button type="button" appCopyClick="no toast shown" #noToast></button>
@@ -25,9 +27,17 @@ import { CopyClickDirective } from "./copy-click.directive";
imports: [CopyClickDirective], imports: [CopyClickDirective],
}) })
class TestCopyClickComponent { class TestCopyClickComponent {
// FIXME(https://bitwarden.atlassian.net/browse/CL-903): Migrate to Signals
// eslint-disable-next-line @angular-eslint/prefer-signals
@ViewChild("noToast") noToastButton!: ElementRef<HTMLButtonElement>; @ViewChild("noToast") noToastButton!: ElementRef<HTMLButtonElement>;
// FIXME(https://bitwarden.atlassian.net/browse/CL-903): Migrate to Signals
// eslint-disable-next-line @angular-eslint/prefer-signals
@ViewChild("infoToast") infoToastButton!: ElementRef<HTMLButtonElement>; @ViewChild("infoToast") infoToastButton!: ElementRef<HTMLButtonElement>;
// FIXME(https://bitwarden.atlassian.net/browse/CL-903): Migrate to Signals
// eslint-disable-next-line @angular-eslint/prefer-signals
@ViewChild("successToast") successToastButton!: ElementRef<HTMLButtonElement>; @ViewChild("successToast") successToastButton!: ElementRef<HTMLButtonElement>;
// FIXME(https://bitwarden.atlassian.net/browse/CL-903): Migrate to Signals
// eslint-disable-next-line @angular-eslint/prefer-signals
@ViewChild("toastWithLabel") toastWithLabelButton!: ElementRef<HTMLButtonElement>; @ViewChild("toastWithLabel") toastWithLabelButton!: ElementRef<HTMLButtonElement>;
} }

View File

@@ -26,11 +26,11 @@ export const COPY_CLICK_LISTENER = new InjectionToken<CopyClickListener>("CopyCl
selector: "[appCopyClick]", selector: "[appCopyClick]",
}) })
export class CopyClickDirective { export class CopyClickDirective {
private _showToast = computed(() => { private readonly _showToast = computed(() => {
return this.showToast() !== undefined; return this.showToast() !== undefined;
}); });
private toastVariant = computed(() => { private readonly toastVariant = computed(() => {
const showToast = this.showToast(); const showToast = this.showToast();
// When the `showToast` is set without a value, an empty string will be passed // When the `showToast` is set without a value, an empty string will be passed
if (showToast === "" || showToast === undefined) { if (showToast === "" || showToast === undefined) {
@@ -68,7 +68,7 @@ export class CopyClickDirective {
* <app-component [appCopyClick]="value to copy" showToast="info"/></app-component> * <app-component [appCopyClick]="value to copy" showToast="info"/></app-component>
* ``` * ```
*/ */
showToast = input<ToastVariant | "">(); readonly showToast = input<ToastVariant | "">();
@HostListener("click") onClick() { @HostListener("click") onClick() {
const valueToCopy = this.valueToCopy(); const valueToCopy = this.valueToCopy();

View File

@@ -21,6 +21,8 @@ interface Animal {
animal: string; animal: string;
} }
// FIXME(https://bitwarden.atlassian.net/browse/CL-764): Migrate to OnPush
// eslint-disable-next-line @angular-eslint/prefer-on-push-component-change-detection
@Component({ @Component({
template: ` template: `
<bit-layout> <bit-layout>
@@ -62,6 +64,8 @@ class StoryDialogComponent {
} }
} }
// FIXME(https://bitwarden.atlassian.net/browse/CL-764): Migrate to OnPush
// eslint-disable-next-line @angular-eslint/prefer-on-push-component-change-detection
@Component({ @Component({
template: ` template: `
<bit-dialog title="Dialog Title" dialogSize="large"> <bit-dialog title="Dialog Title" dialogSize="large">
@@ -91,6 +95,8 @@ class StoryDialogContentComponent {
} }
} }
// FIXME(https://bitwarden.atlassian.net/browse/CL-764): Migrate to OnPush
// eslint-disable-next-line @angular-eslint/prefer-on-push-component-change-detection
@Component({ @Component({
template: ` template: `
<bit-dialog <bit-dialog

View File

@@ -26,6 +26,8 @@ import { DialogRef } from "../dialog.service";
import { DialogCloseDirective } from "../directives/dialog-close.directive"; import { DialogCloseDirective } from "../directives/dialog-close.directive";
import { DialogTitleContainerDirective } from "../directives/dialog-title-container.directive"; import { DialogTitleContainerDirective } from "../directives/dialog-title-container.directive";
// FIXME(https://bitwarden.atlassian.net/browse/CL-764): Migrate to OnPush
// eslint-disable-next-line @angular-eslint/prefer-on-push-component-change-detection
@Component({ @Component({
selector: "bit-dialog", selector: "bit-dialog",
templateUrl: "./dialog.component.html", templateUrl: "./dialog.component.html",
@@ -47,8 +49,8 @@ import { DialogTitleContainerDirective } from "../directives/dialog-title-contai
}) })
export class DialogComponent { export class DialogComponent {
private readonly destroyRef = inject(DestroyRef); private readonly destroyRef = inject(DestroyRef);
private scrollableBody = viewChild.required(CdkScrollable); private readonly scrollableBody = viewChild.required(CdkScrollable);
private scrollBottom = viewChild.required<ElementRef<HTMLDivElement>>("scrollBottom"); private readonly scrollBottom = viewChild.required<ElementRef<HTMLDivElement>>("scrollBottom");
protected dialogRef = inject(DialogRef, { optional: true }); protected dialogRef = inject(DialogRef, { optional: true });
protected bodyHasScrolledFrom = hasScrolledFrom(this.scrollableBody); protected bodyHasScrolledFrom = hasScrolledFrom(this.scrollableBody);

View File

@@ -26,6 +26,8 @@ const DEFAULT_COLOR: Record<SimpleDialogType, string> = {
danger: "tw-text-danger", danger: "tw-text-danger",
}; };
// FIXME(https://bitwarden.atlassian.net/browse/CL-764): Migrate to OnPush
// eslint-disable-next-line @angular-eslint/prefer-on-push-component-change-detection
@Component({ @Component({
templateUrl: "./simple-configurable-dialog.component.html", templateUrl: "./simple-configurable-dialog.component.html",
imports: [ imports: [

View File

@@ -10,6 +10,8 @@ import { CalloutModule } from "../../../callout";
import { I18nMockService } from "../../../utils/i18n-mock.service"; import { I18nMockService } from "../../../utils/i18n-mock.service";
import { DialogModule } from "../../dialog.module"; import { DialogModule } from "../../dialog.module";
// FIXME(https://bitwarden.atlassian.net/browse/CL-764): Migrate to OnPush
// eslint-disable-next-line @angular-eslint/prefer-on-push-component-change-detection
@Component({ @Component({
template: ` template: `
@for (group of dialogs; track group) { @for (group of dialogs; track group) {

View File

@@ -9,6 +9,8 @@ import { DialogTitleContainerDirective } from "../directives/dialog-title-contai
}) })
export class IconDirective {} export class IconDirective {}
// FIXME(https://bitwarden.atlassian.net/browse/CL-764): Migrate to OnPush
// eslint-disable-next-line @angular-eslint/prefer-on-push-component-change-detection
@Component({ @Component({
selector: "bit-simple-dialog", selector: "bit-simple-dialog",
templateUrl: "./simple-dialog.component.html", templateUrl: "./simple-dialog.component.html",
@@ -16,12 +18,14 @@ export class IconDirective {}
imports: [DialogTitleContainerDirective, TypographyDirective], imports: [DialogTitleContainerDirective, TypographyDirective],
}) })
export class SimpleDialogComponent { export class SimpleDialogComponent {
// FIXME(https://bitwarden.atlassian.net/browse/CL-903): Migrate to Signals
// eslint-disable-next-line @angular-eslint/prefer-signals
@ContentChild(IconDirective) icon!: IconDirective; @ContentChild(IconDirective) icon!: IconDirective;
/** /**
* Optional flag to hide the dialog's center icon. Defaults to false. * Optional flag to hide the dialog's center icon. Defaults to false.
*/ */
hideIcon = input(false, { transform: booleanAttribute }); readonly hideIcon = input(false, { transform: booleanAttribute });
get hasIcon() { get hasIcon() {
return this.icon != null; return this.icon != null;

View File

@@ -15,6 +15,8 @@ interface Animal {
animal: string; animal: string;
} }
// FIXME(https://bitwarden.atlassian.net/browse/CL-764): Migrate to OnPush
// eslint-disable-next-line @angular-eslint/prefer-on-push-component-change-detection
@Component({ @Component({
template: ` template: `
<button type="button" bitButton (click)="openSimpleDialog()">Open Simple Dialog</button> <button type="button" bitButton (click)="openSimpleDialog()">Open Simple Dialog</button>
@@ -57,6 +59,8 @@ class StoryDialogComponent {
} }
} }
// FIXME(https://bitwarden.atlassian.net/browse/CL-764): Migrate to OnPush
// eslint-disable-next-line @angular-eslint/prefer-on-push-component-change-detection
@Component({ @Component({
template: ` template: `
<bit-simple-dialog> <bit-simple-dialog>
@@ -87,6 +91,8 @@ class SimpleDialogContent {
} }
} }
// FIXME(https://bitwarden.atlassian.net/browse/CL-764): Migrate to OnPush
// eslint-disable-next-line @angular-eslint/prefer-on-push-component-change-detection
@Component({ @Component({
template: ` template: `
<bit-simple-dialog> <bit-simple-dialog>
@@ -116,6 +122,8 @@ class NonDismissableWithPrimaryButtonContent {
} }
} }
// FIXME(https://bitwarden.atlassian.net/browse/CL-764): Migrate to OnPush
// eslint-disable-next-line @angular-eslint/prefer-on-push-component-change-detection
@Component({ @Component({
template: ` template: `
<bit-simple-dialog> <bit-simple-dialog>

View File

@@ -34,12 +34,16 @@ let nextId = 0;
* ``` * ```
* *
*/ */
// FIXME(https://bitwarden.atlassian.net/browse/CL-764): Migrate to OnPush
// eslint-disable-next-line @angular-eslint/prefer-on-push-component-change-detection
@Component({ @Component({
selector: "bit-disclosure", selector: "bit-disclosure",
template: `<ng-content></ng-content>`, template: `<ng-content></ng-content>`,
}) })
export class DisclosureComponent { export class DisclosureComponent {
/** Emits the visibility of the disclosure content */ /** Emits the visibility of the disclosure content */
// FIXME(https://bitwarden.atlassian.net/browse/CL-903): Migrate to Signals
// eslint-disable-next-line @angular-eslint/prefer-output-emitter-ref
@Output() openChange = new EventEmitter<boolean>(); @Output() openChange = new EventEmitter<boolean>();
private _open?: boolean; private _open?: boolean;
@@ -48,6 +52,8 @@ export class DisclosureComponent {
*/ */
// TODO: Skipped for signal migration because: // TODO: Skipped for signal migration because:
// Accessor inputs cannot be migrated as they are too complex. // Accessor inputs cannot be migrated as they are too complex.
// FIXME(https://bitwarden.atlassian.net/browse/CL-903): Migrate to Signals
// eslint-disable-next-line @angular-eslint/prefer-signals
@Input({ transform: booleanAttribute }) set open(isOpen: boolean) { @Input({ transform: booleanAttribute }) set open(isOpen: boolean) {
this._open = isOpen; this._open = isOpen;
this.openChange.emit(isOpen); this.openChange.emit(isOpen);

View File

@@ -24,7 +24,7 @@ export class DrawerHeaderComponent {
/** /**
* The title to display * The title to display
*/ */
title = input.required<string>(); readonly title = input.required<string>();
/** We don't want to set the HTML title attribute with `this.title` */ /** We don't want to set the HTML title attribute with `this.title` */
@HostBinding("attr.title") @HostBinding("attr.title")

View File

@@ -10,7 +10,7 @@ import { Directive, signal } from "@angular/core";
selector: "[bitDrawerHost]", selector: "[bitDrawerHost]",
}) })
export class DrawerHostDirective { export class DrawerHostDirective {
private _portal = signal<Portal<unknown> | undefined>(undefined); private readonly _portal = signal<Portal<unknown> | undefined>(undefined);
/** The portal to display */ /** The portal to display */
portal = this._portal.asReadonly(); portal = this._portal.asReadonly();

View File

@@ -25,7 +25,7 @@ import { DrawerService } from "./drawer.service";
}) })
export class DrawerComponent { export class DrawerComponent {
private drawerHost = inject(DrawerService); private drawerHost = inject(DrawerService);
private portal = viewChild.required(CdkPortal); private readonly portal = viewChild.required(CdkPortal);
/** /**
* Whether or not the drawer is open. * Whether or not the drawer is open.
@@ -33,7 +33,7 @@ export class DrawerComponent {
* Note: Does not support implicit boolean transform due to Angular limitation. Must be bound explicitly `[open]="true"` instead of just `open`. * Note: Does not support implicit boolean transform due to Angular limitation. Must be bound explicitly `[open]="true"` instead of just `open`.
* https://github.com/angular/angular/issues/55166#issuecomment-2032150999 * https://github.com/angular/angular/issues/55166#issuecomment-2032150999
**/ **/
open = model<boolean>(false); readonly open = model<boolean>(false);
/** /**
* The ARIA role of the drawer. * The ARIA role of the drawer.
@@ -43,7 +43,7 @@ export class DrawerComponent {
* - [navigation](https://developer.mozilla.org/en-US/docs/Web/Accessibility/ARIA/Roles/navigation_role) * - [navigation](https://developer.mozilla.org/en-US/docs/Web/Accessibility/ARIA/Roles/navigation_role)
* - For drawers that primary contain links to other content. * - For drawers that primary contain links to other content.
*/ */
role = input<"complementary" | "navigation">("complementary"); readonly role = input<"complementary" | "navigation">("complementary");
constructor() { constructor() {
effect( effect(

View File

@@ -3,7 +3,7 @@ import { Injectable, signal } from "@angular/core";
@Injectable({ providedIn: "root" }) @Injectable({ providedIn: "root" })
export class DrawerService { export class DrawerService {
private _portal = signal<Portal<unknown> | undefined>(undefined); private readonly _portal = signal<Portal<unknown> | undefined>(undefined);
/** The portal to display */ /** The portal to display */
portal = this._portal.asReadonly(); portal = this._portal.asReadonly();

View File

@@ -8,6 +8,8 @@ import { TypographyDirective } from "../typography/typography.directive";
import { BitFormControlAbstraction } from "./form-control.abstraction"; import { BitFormControlAbstraction } from "./form-control.abstraction";
// FIXME(https://bitwarden.atlassian.net/browse/CL-764): Migrate to OnPush
// eslint-disable-next-line @angular-eslint/prefer-on-push-component-change-detection
@Component({ @Component({
selector: "bit-form-control", selector: "bit-form-control",
templateUrl: "form-control.component.html", templateUrl: "form-control.component.html",

View File

@@ -6,6 +6,8 @@ import { FormControlComponent } from "./form-control.component";
// Increments for each instance of this component // Increments for each instance of this component
let nextId = 0; let nextId = 0;
// FIXME(https://bitwarden.atlassian.net/browse/CL-764): Migrate to OnPush
// eslint-disable-next-line @angular-eslint/prefer-on-push-component-change-detection
@Component({ @Component({
selector: "bit-label", selector: "bit-label",
templateUrl: "label.component.html", templateUrl: "label.component.html",

View File

@@ -3,6 +3,8 @@ import { AbstractControl, UntypedFormGroup } from "@angular/forms";
import { I18nPipe } from "@bitwarden/ui-common"; import { I18nPipe } from "@bitwarden/ui-common";
// FIXME(https://bitwarden.atlassian.net/browse/CL-764): Migrate to OnPush
// eslint-disable-next-line @angular-eslint/prefer-on-push-component-change-detection
@Component({ @Component({
selector: "bit-error-summary", selector: "bit-error-summary",
template: ` @if (errorCount > 0) { template: ` @if (errorCount > 0) {

View File

@@ -5,6 +5,8 @@ import { I18nService } from "@bitwarden/common/platform/abstractions/i18n.servic
// Increments for each instance of this component // Increments for each instance of this component
let nextId = 0; let nextId = 0;
// FIXME(https://bitwarden.atlassian.net/browse/CL-764): Migrate to OnPush
// eslint-disable-next-line @angular-eslint/prefer-on-push-component-change-detection
@Component({ @Component({
selector: "bit-error", selector: "bit-error",
template: `<i class="bwi bwi-error"></i> {{ displayError }}`, template: `<i class="bwi bwi-error"></i> {{ displayError }}`,

View File

@@ -22,6 +22,8 @@ import { inputBorderClasses } from "../input/input.directive";
import { BitErrorComponent } from "./error.component"; import { BitErrorComponent } from "./error.component";
import { BitFormFieldControl } from "./form-field-control"; import { BitFormFieldControl } from "./form-field-control";
// FIXME(https://bitwarden.atlassian.net/browse/CL-764): Migrate to OnPush
// eslint-disable-next-line @angular-eslint/prefer-on-push-component-change-detection
@Component({ @Component({
selector: "bit-form-field", selector: "bit-form-field",
templateUrl: "./form-field.component.html", templateUrl: "./form-field.component.html",
@@ -42,11 +44,13 @@ export class BitFormFieldComponent implements AfterContentChecked {
/** If `true`, remove the bottom border for `readonly` inputs */ /** If `true`, remove the bottom border for `readonly` inputs */
// TODO: Skipped for signal migration because: // TODO: Skipped for signal migration because:
// Your application code writes to the input. This prevents migration. // Your application code writes to the input. This prevents migration.
// FIXME(https://bitwarden.atlassian.net/browse/CL-903): Migrate to Signals
// eslint-disable-next-line @angular-eslint/prefer-signals
@Input({ transform: booleanAttribute }) @Input({ transform: booleanAttribute })
disableReadOnlyBorder = false; disableReadOnlyBorder = false;
protected prefixHasChildren = signal(false); protected readonly prefixHasChildren = signal(false);
protected suffixHasChildren = signal(false); protected readonly suffixHasChildren = signal(false);
get inputBorderClasses(): string { get inputBorderClasses(): string {
const shouldFocusBorderAppear = this.defaultContentIsFocused(); const shouldFocusBorderAppear = this.defaultContentIsFocused();
@@ -87,7 +91,7 @@ export class BitFormFieldComponent implements AfterContentChecked {
* This is necessary because the `tw-group/bit-form-field` wraps the input and any prefix/suffix * This is necessary because the `tw-group/bit-form-field` wraps the input and any prefix/suffix
* buttons * buttons
*/ */
protected defaultContentIsFocused = signal(false); protected readonly defaultContentIsFocused = signal(false);
@HostListener("focusin", ["$event.target"]) @HostListener("focusin", ["$event.target"])
onFocusIn(target: HTMLElement) { onFocusIn(target: HTMLElement) {
this.defaultContentIsFocused.set(target.matches("[data-default-content] *:focus-visible")); this.defaultContentIsFocused.set(target.matches("[data-default-content] *:focus-visible"));

View File

@@ -27,6 +27,8 @@ export class BitPasswordInputToggleDirective implements AfterContentInit, OnChan
* Whether the input is toggled to show the password. * Whether the input is toggled to show the password.
*/ */
readonly toggled = model(false); readonly toggled = model(false);
// FIXME(https://bitwarden.atlassian.net/browse/CL-903): Migrate to Signals
// eslint-disable-next-line @angular-eslint/prefer-output-emitter-ref
@Output() toggledChange = new EventEmitter<boolean>(); @Output() toggledChange = new EventEmitter<boolean>();
@HostBinding("attr.title") title = this.i18nService.t("toggleVisibility"); @HostBinding("attr.title") title = this.i18nService.t("toggleVisibility");

View File

@@ -13,6 +13,8 @@ import { BitFormFieldComponent } from "./form-field.component";
import { FormFieldModule } from "./form-field.module"; import { FormFieldModule } from "./form-field.module";
import { BitPasswordInputToggleDirective } from "./password-input-toggle.directive"; import { BitPasswordInputToggleDirective } from "./password-input-toggle.directive";
// FIXME(https://bitwarden.atlassian.net/browse/CL-764): Migrate to OnPush
// eslint-disable-next-line @angular-eslint/prefer-on-push-component-change-detection
@Component({ @Component({
selector: "test-form-field", selector: "test-form-field",
template: ` template: `

View File

@@ -81,6 +81,8 @@ const sizes: Record<IconButtonSize, string[]> = {
* Similar to the main button components, spacing between multiple icon buttons should be .5rem. * Similar to the main button components, spacing between multiple icon buttons should be .5rem.
*/ */
// FIXME(https://bitwarden.atlassian.net/browse/CL-764): Migrate to OnPush
// eslint-disable-next-line @angular-eslint/prefer-on-push-component-change-detection
@Component({ @Component({
selector: "button[bitIconButton]:not(button[bitButton])", selector: "button[bitIconButton]:not(button[bitButton])",
templateUrl: "icon-button.component.html", templateUrl: "icon-button.component.html",
@@ -143,7 +145,7 @@ export class BitIconButtonComponent implements ButtonLikeAbstraction, FocusableE
return [this.icon(), "!tw-m-0"]; return [this.icon(), "!tw-m-0"];
} }
protected disabledAttr = computed(() => { protected readonly disabledAttr = computed(() => {
const disabled = this.disabled() != null && this.disabled() !== false; const disabled = this.disabled() != null && this.disabled() !== false;
return disabled || this.loading(); return disabled || this.loading();
}); });
@@ -156,7 +158,7 @@ export class BitIconButtonComponent implements ButtonLikeAbstraction, FocusableE
* We can't use `disabledAttr` for this, because it returns `true` when `loading` is `true`. * We can't use `disabledAttr` for this, because it returns `true` when `loading` is `true`.
* We only want to show disabled styles during loading if `showLoadingStyles` is `true`. * We only want to show disabled styles during loading if `showLoadingStyles` is `true`.
*/ */
protected showDisabledStyles = computed(() => { protected readonly showDisabledStyles = computed(() => {
return this.showLoadingStyle() || (this.disabledAttr() && this.loading() === false); return this.showLoadingStyle() || (this.disabledAttr() && this.loading() === false);
}); });
@@ -174,7 +176,7 @@ export class BitIconButtonComponent implements ButtonLikeAbstraction, FocusableE
* This pattern of converting a signal to an observable and back to a signal is not * This pattern of converting a signal to an observable and back to a signal is not
* recommended. TODO -- find better way to use debounce with signals (CL-596) * recommended. TODO -- find better way to use debounce with signals (CL-596)
*/ */
protected showLoadingStyle = toSignal( protected readonly showLoadingStyle = toSignal(
toObservable(this.loading).pipe(debounce((isLoading) => interval(isLoading ? 75 : 0))), toObservable(this.loading).pipe(debounce((isLoading) => interval(isLoading ? 75 : 0))),
); );

View File

@@ -56,6 +56,8 @@ const shapeStyles: Record<IconTileShape, Record<IconTileSize, string[]>> = {
* - Create visual hierarchy in lists or cards * - Create visual hierarchy in lists or cards
* - Show app or service icons in a consistent format * - Show app or service icons in a consistent format
*/ */
// FIXME(https://bitwarden.atlassian.net/browse/CL-764): Migrate to OnPush
// eslint-disable-next-line @angular-eslint/prefer-on-push-component-change-detection
@Component({ @Component({
selector: "bit-icon-tile", selector: "bit-icon-tile",
templateUrl: "icon-tile.component.html", templateUrl: "icon-tile.component.html",

View File

@@ -3,6 +3,8 @@ import { DomSanitizer, SafeHtml } from "@angular/platform-browser";
import { Icon, isIcon } from "@bitwarden/assets/svg"; import { Icon, isIcon } from "@bitwarden/assets/svg";
// FIXME(https://bitwarden.atlassian.net/browse/CL-764): Migrate to OnPush
// eslint-disable-next-line @angular-eslint/prefer-on-push-component-change-detection
@Component({ @Component({
selector: "bit-icon", selector: "bit-icon",
host: { host: {

View File

@@ -74,6 +74,8 @@ export class BitInputDirective implements BitFormFieldControl {
// TODO: Skipped for signal migration because: // TODO: Skipped for signal migration because:
// Accessor inputs cannot be migrated as they are too complex. // Accessor inputs cannot be migrated as they are too complex.
@HostBinding() @HostBinding()
// FIXME(https://bitwarden.atlassian.net/browse/CL-903): Migrate to Signals
// eslint-disable-next-line @angular-eslint/prefer-signals
@Input() @Input()
get required() { get required() {
return this._required ?? this.ngControl?.control?.hasValidator(Validators.required) ?? false; return this._required ?? this.ngControl?.control?.hasValidator(Validators.required) ?? false;

View File

@@ -1,5 +1,7 @@
import { Component } from "@angular/core"; import { Component } from "@angular/core";
// FIXME(https://bitwarden.atlassian.net/browse/CL-764): Migrate to OnPush
// eslint-disable-next-line @angular-eslint/prefer-on-push-component-change-detection
@Component({ @Component({
selector: "bit-item-action", selector: "bit-item-action",
imports: [], imports: [],

View File

@@ -29,7 +29,7 @@ import { TypographyModule } from "../typography";
export class ItemContentComponent implements AfterContentChecked { export class ItemContentComponent implements AfterContentChecked {
readonly endSlot = viewChild<ElementRef<HTMLDivElement>>("endSlot"); readonly endSlot = viewChild<ElementRef<HTMLDivElement>>("endSlot");
protected endSlotHasChildren = signal(false); protected readonly endSlotHasChildren = signal(false);
/** /**
* Determines whether text will truncate or wrap. * Determines whether text will truncate or wrap.

View File

@@ -22,7 +22,7 @@ export class ItemComponent {
/** /**
* We have `:focus-within` and `:focus-visible` but no `:focus-visible-within` * We have `:focus-within` and `:focus-visible` but no `:focus-visible-within`
*/ */
protected focusVisibleWithin = signal(false); protected readonly focusVisibleWithin = signal(false);
@HostListener("focusin", ["$event.target"]) @HostListener("focusin", ["$event.target"])
onFocusIn(target: HTMLElement) { onFocusIn(target: HTMLElement) {
this.focusVisibleWithin.set(target.matches("[data-fvw-target]:focus-visible")); this.focusVisibleWithin.set(target.matches("[data-fvw-target]:focus-visible"));

View File

@@ -12,6 +12,8 @@ import { SharedModule } from "../shared";
import { ScrollLayoutHostDirective } from "./scroll-layout.directive"; import { ScrollLayoutHostDirective } from "./scroll-layout.directive";
// FIXME(https://bitwarden.atlassian.net/browse/CL-764): Migrate to OnPush
// eslint-disable-next-line @angular-eslint/prefer-on-push-component-change-detection
@Component({ @Component({
selector: "bit-layout", selector: "bit-layout",
templateUrl: "layout.component.html", templateUrl: "layout.component.html",
@@ -34,7 +36,7 @@ export class LayoutComponent {
protected sideNavService = inject(SideNavService); protected sideNavService = inject(SideNavService);
protected drawerPortal = inject(DrawerService).portal; protected drawerPortal = inject(DrawerService).portal;
private mainContent = viewChild.required<ElementRef<HTMLElement>>("main"); private readonly mainContent = viewChild.required<ElementRef<HTMLElement>>("main");
protected focusMainContent() { protected focusMainContent() {
this.mainContent().nativeElement.focus(); this.mainContent().nativeElement.focus();
} }
@@ -45,7 +47,7 @@ export class LayoutComponent {
* *
* @see https://github.com/angular/components/issues/10247#issuecomment-384060265 * @see https://github.com/angular/components/issues/10247#issuecomment-384060265
**/ **/
private skipLink = viewChild.required<ElementRef<HTMLElement>>("skipLink"); private readonly skipLink = viewChild.required<ElementRef<HTMLElement>>("skipLink");
handleKeydown(ev: KeyboardEvent) { handleKeydown(ev: KeyboardEvent) {
if (isNothingFocused()) { if (isNothingFocused()) {
ev.preventDefault(); ev.preventDefault();

View File

@@ -17,7 +17,7 @@ import { filter, fromEvent, Observable, switchMap } from "rxjs";
**/ **/
@Injectable({ providedIn: "root" }) @Injectable({ providedIn: "root" })
export class ScrollLayoutService { export class ScrollLayoutService {
scrollableRef = signal<ElementRef<HTMLElement> | null>(null); readonly scrollableRef = signal<ElementRef<HTMLElement> | null>(null);
scrollableRef$ = toObservable(this.scrollableRef); scrollableRef$ = toObservable(this.scrollableRef);
} }

View File

@@ -99,7 +99,7 @@ export class AnchorLinkDirective extends LinkDirective {
export class ButtonLinkDirective extends LinkDirective { export class ButtonLinkDirective extends LinkDirective {
private el = inject(ElementRef<HTMLButtonElement>); private el = inject(ElementRef<HTMLButtonElement>);
disabled = input(false, { transform: booleanAttribute }); readonly disabled = input(false, { transform: booleanAttribute });
@HostBinding("class") get classList() { @HostBinding("class") get classList() {
return ["before:-tw-inset-y-[0.25rem]"] return ["before:-tw-inset-y-[0.25rem]"]

View File

@@ -1,5 +1,7 @@
import { Component } from "@angular/core"; import { Component } from "@angular/core";
// FIXME(https://bitwarden.atlassian.net/browse/CL-764): Migrate to OnPush
// eslint-disable-next-line @angular-eslint/prefer-on-push-component-change-detection
@Component({ @Component({
selector: "bit-menu-divider", selector: "bit-menu-divider",
templateUrl: "./menu-divider.component.html", templateUrl: "./menu-divider.component.html",

View File

@@ -3,6 +3,8 @@ import { coerceBooleanProperty } from "@angular/cdk/coercion";
import { NgClass } from "@angular/common"; import { NgClass } from "@angular/common";
import { Component, ElementRef, HostBinding, Input } from "@angular/core"; import { Component, ElementRef, HostBinding, Input } from "@angular/core";
// FIXME(https://bitwarden.atlassian.net/browse/CL-764): Migrate to OnPush
// eslint-disable-next-line @angular-eslint/prefer-on-push-component-change-detection
@Component({ @Component({
selector: "[bitMenuItem]", selector: "[bitMenuItem]",
templateUrl: "menu-item.component.html", templateUrl: "menu-item.component.html",
@@ -42,6 +44,8 @@ export class MenuItemDirective implements FocusableOption {
// TODO: Skipped for signal migration because: // TODO: Skipped for signal migration because:
// This input overrides a field from a superclass, while the superclass field // This input overrides a field from a superclass, while the superclass field
// is not migrated. // is not migrated.
// FIXME(https://bitwarden.atlassian.net/browse/CL-903): Migrate to Signals
// eslint-disable-next-line @angular-eslint/prefer-signals
@Input({ transform: coerceBooleanProperty }) disabled?: boolean = false; @Input({ transform: coerceBooleanProperty }) disabled?: boolean = false;
constructor(public elementRef: ElementRef<HTMLButtonElement>) {} constructor(public elementRef: ElementRef<HTMLButtonElement>) {}

View File

@@ -68,6 +68,8 @@ describe("Menu", () => {
}); });
}); });
// FIXME(https://bitwarden.atlassian.net/browse/CL-764): Migrate to OnPush
// eslint-disable-next-line @angular-eslint/prefer-on-push-component-change-detection
@Component({ @Component({
selector: "test-app", selector: "test-app",
template: ` template: `

View File

@@ -12,6 +12,8 @@ import {
import { MenuItemDirective } from "./menu-item.directive"; import { MenuItemDirective } from "./menu-item.directive";
// FIXME(https://bitwarden.atlassian.net/browse/CL-764): Migrate to OnPush
// eslint-disable-next-line @angular-eslint/prefer-on-push-component-change-detection
@Component({ @Component({
selector: "bit-menu", selector: "bit-menu",
templateUrl: "./menu.component.html", templateUrl: "./menu.component.html",
@@ -20,6 +22,8 @@ import { MenuItemDirective } from "./menu-item.directive";
}) })
export class MenuComponent implements AfterContentInit { export class MenuComponent implements AfterContentInit {
readonly templateRef = viewChild.required(TemplateRef); readonly templateRef = viewChild.required(TemplateRef);
// FIXME(https://bitwarden.atlassian.net/browse/CL-903): Migrate to Signals
// eslint-disable-next-line @angular-eslint/prefer-output-emitter-ref
@Output() closed = new EventEmitter<void>(); @Output() closed = new EventEmitter<void>();
readonly menuItems = contentChildren(MenuItemDirective, { descendants: true }); readonly menuItems = contentChildren(MenuItemDirective, { descendants: true });
keyManager?: FocusKeyManager<MenuItemDirective>; keyManager?: FocusKeyManager<MenuItemDirective>;

View File

@@ -34,6 +34,8 @@ import { SelectItemView } from "./models/select-item-view";
// Increments for each instance of this component // Increments for each instance of this component
let nextId = 0; let nextId = 0;
// FIXME(https://bitwarden.atlassian.net/browse/CL-764): Migrate to OnPush
// eslint-disable-next-line @angular-eslint/prefer-on-push-component-change-detection
@Component({ @Component({
selector: "bit-multi-select", selector: "bit-multi-select",
templateUrl: "./multi-select.component.html", templateUrl: "./multi-select.component.html",
@@ -64,6 +66,8 @@ export class MultiSelectComponent implements OnInit, BitFormFieldControl, Contro
readonly loading = input(false); readonly loading = input(false);
// TODO: Skipped for signal migration because: // TODO: Skipped for signal migration because:
// Your application code writes to the input. This prevents migration. // Your application code writes to the input. This prevents migration.
// FIXME(https://bitwarden.atlassian.net/browse/CL-903): Migrate to Signals
// eslint-disable-next-line @angular-eslint/prefer-signals
@Input({ transform: booleanAttribute }) disabled?: boolean; @Input({ transform: booleanAttribute }) disabled?: boolean;
// Internal tracking of selected items // Internal tracking of selected items
@@ -79,6 +83,8 @@ export class MultiSelectComponent implements OnInit, BitFormFieldControl, Contro
/**Implemented as part of NG_VALUE_ACCESSOR */ /**Implemented as part of NG_VALUE_ACCESSOR */
private notifyOnTouched?: () => void; private notifyOnTouched?: () => void;
// FIXME(https://bitwarden.atlassian.net/browse/CL-903): Migrate to Signals
// eslint-disable-next-line @angular-eslint/prefer-output-emitter-ref
@Output() onItemsConfirmed = new EventEmitter<any[]>(); @Output() onItemsConfirmed = new EventEmitter<any[]>();
constructor( constructor(
@@ -208,6 +214,8 @@ export class MultiSelectComponent implements OnInit, BitFormFieldControl, Contro
// TODO: Skipped for signal migration because: // TODO: Skipped for signal migration because:
// Accessor inputs cannot be migrated as they are too complex. // Accessor inputs cannot be migrated as they are too complex.
@HostBinding("attr.required") @HostBinding("attr.required")
// FIXME(https://bitwarden.atlassian.net/browse/CL-903): Migrate to Signals
// eslint-disable-next-line @angular-eslint/prefer-signals
@Input() @Input()
get required() { get required() {
return this._required ?? this.ngControl?.control?.hasValidator(Validators.required) ?? false; return this._required ?? this.ngControl?.control?.hasValidator(Validators.required) ?? false;

View File

@@ -61,5 +61,7 @@ export abstract class NavBaseComponent {
/** /**
* Fires when main content is clicked * Fires when main content is clicked
*/ */
// FIXME(https://bitwarden.atlassian.net/browse/CL-903): Migrate to Signals
// eslint-disable-next-line @angular-eslint/prefer-output-emitter-ref
@Output() mainContentClicked: EventEmitter<MouseEvent> = new EventEmitter(); @Output() mainContentClicked: EventEmitter<MouseEvent> = new EventEmitter();
} }

View File

@@ -3,6 +3,8 @@ import { Component } from "@angular/core";
import { SideNavService } from "./side-nav.service"; import { SideNavService } from "./side-nav.service";
// FIXME(https://bitwarden.atlassian.net/browse/CL-764): Migrate to OnPush
// eslint-disable-next-line @angular-eslint/prefer-on-push-component-change-detection
@Component({ @Component({
selector: "bit-nav-divider", selector: "bit-nav-divider",
templateUrl: "./nav-divider.component.html", templateUrl: "./nav-divider.component.html",

View File

@@ -19,6 +19,8 @@ import { NavBaseComponent } from "./nav-base.component";
import { NavGroupAbstraction, NavItemComponent } from "./nav-item.component"; import { NavGroupAbstraction, NavItemComponent } from "./nav-item.component";
import { SideNavService } from "./side-nav.service"; import { SideNavService } from "./side-nav.service";
// FIXME(https://bitwarden.atlassian.net/browse/CL-764): Migrate to OnPush
// eslint-disable-next-line @angular-eslint/prefer-on-push-component-change-detection
@Component({ @Component({
selector: "bit-nav-group", selector: "bit-nav-group",
templateUrl: "./nav-group.component.html", templateUrl: "./nav-group.component.html",
@@ -51,6 +53,8 @@ export class NavGroupComponent extends NavBaseComponent {
*/ */
readonly hideIfEmpty = input(false, { transform: booleanAttribute }); readonly hideIfEmpty = input(false, { transform: booleanAttribute });
// FIXME(https://bitwarden.atlassian.net/browse/CL-903): Migrate to Signals
// eslint-disable-next-line @angular-eslint/prefer-output-emitter-ref
@Output() @Output()
openChange = new EventEmitter<boolean>(); openChange = new EventEmitter<boolean>();

View File

@@ -12,6 +12,8 @@ import { I18nMockService } from "../utils/i18n-mock.service";
import { NavGroupComponent } from "./nav-group.component"; import { NavGroupComponent } from "./nav-group.component";
import { NavigationModule } from "./navigation.module"; import { NavigationModule } from "./navigation.module";
// FIXME(https://bitwarden.atlassian.net/browse/CL-764): Migrate to OnPush
// eslint-disable-next-line @angular-eslint/prefer-on-push-component-change-detection
@Component({ @Component({
template: "", template: "",
}) })

View File

@@ -13,6 +13,8 @@ export abstract class NavGroupAbstraction {
abstract setOpen(open: boolean): void; abstract setOpen(open: boolean): void;
} }
// FIXME(https://bitwarden.atlassian.net/browse/CL-764): Migrate to OnPush
// eslint-disable-next-line @angular-eslint/prefer-on-push-component-change-detection
@Component({ @Component({
selector: "bit-nav-item", selector: "bit-nav-item",
templateUrl: "./nav-item.component.html", templateUrl: "./nav-item.component.html",

View File

@@ -8,6 +8,8 @@ import { BitIconComponent } from "../icon/icon.component";
import { SideNavService } from "./side-nav.service"; import { SideNavService } from "./side-nav.service";
// FIXME(https://bitwarden.atlassian.net/browse/CL-764): Migrate to OnPush
// eslint-disable-next-line @angular-eslint/prefer-on-push-component-change-detection
@Component({ @Component({
selector: "bit-nav-logo", selector: "bit-nav-logo",
templateUrl: "./nav-logo.component.html", templateUrl: "./nav-logo.component.html",

View File

@@ -11,6 +11,8 @@ import { SideNavService } from "./side-nav.service";
export type SideNavVariant = "primary" | "secondary"; export type SideNavVariant = "primary" | "secondary";
// FIXME(https://bitwarden.atlassian.net/browse/CL-764): Migrate to OnPush
// eslint-disable-next-line @angular-eslint/prefer-on-push-component-change-detection
@Component({ @Component({
selector: "bit-side-nav", selector: "bit-side-nav",
templateUrl: "side-nav.component.html", templateUrl: "side-nav.component.html",

View File

@@ -7,6 +7,8 @@ import { BitIconComponent } from "../icon/icon.component";
/** /**
* Component for displaying a message when there are no items to display. Expects title, description and button slots. * Component for displaying a message when there are no items to display. Expects title, description and button slots.
*/ */
// FIXME(https://bitwarden.atlassian.net/browse/CL-764): Migrate to OnPush
// eslint-disable-next-line @angular-eslint/prefer-on-push-component-change-detection
@Component({ @Component({
selector: "bit-no-items", selector: "bit-no-items",
templateUrl: "./no-items.component.html", templateUrl: "./no-items.component.html",

View File

@@ -5,6 +5,8 @@ import { IconButtonModule } from "../icon-button/icon-button.module";
import { SharedModule } from "../shared/shared.module"; import { SharedModule } from "../shared/shared.module";
import { TypographyModule } from "../typography"; import { TypographyModule } from "../typography";
// FIXME(https://bitwarden.atlassian.net/browse/CL-764): Migrate to OnPush
// eslint-disable-next-line @angular-eslint/prefer-on-push-component-change-detection
@Component({ @Component({
selector: "bit-popover", selector: "bit-popover",
imports: [A11yModule, IconButtonModule, SharedModule, TypographyModule], imports: [A11yModule, IconButtonModule, SharedModule, TypographyModule],
@@ -14,5 +16,7 @@ import { TypographyModule } from "../typography";
export class PopoverComponent { export class PopoverComponent {
readonly templateRef = viewChild.required(TemplateRef); readonly templateRef = viewChild.required(TemplateRef);
readonly title = input(""); readonly title = input("");
// FIXME(https://bitwarden.atlassian.net/browse/CL-903): Migrate to Signals
// eslint-disable-next-line @angular-eslint/prefer-output-emitter-ref
@Output() closed = new EventEmitter(); @Output() closed = new EventEmitter();
} }

View File

@@ -20,6 +20,8 @@ const BackgroundClasses: Record<BackgroundType, string[]> = {
/** /**
* Progress indicators may be used to visually indicate progress or to visually measure some other value, such as a password strength indicator. * Progress indicators may be used to visually indicate progress or to visually measure some other value, such as a password strength indicator.
*/ */
// FIXME(https://bitwarden.atlassian.net/browse/CL-764): Migrate to OnPush
// eslint-disable-next-line @angular-eslint/prefer-on-push-component-change-detection
@Component({ @Component({
selector: "bit-progress", selector: "bit-progress",
templateUrl: "./progress.component.html", templateUrl: "./progress.component.html",

View File

@@ -53,6 +53,8 @@ describe("RadioButton", () => {
}); });
}); });
// FIXME(https://bitwarden.atlassian.net/browse/CL-764): Migrate to OnPush
// eslint-disable-next-line @angular-eslint/prefer-on-push-component-change-detection
@Component({ @Component({
selector: "test-component", selector: "test-component",
template: ` template: `

View File

@@ -7,6 +7,8 @@ import { RadioInputComponent } from "./radio-input.component";
let nextId = 0; let nextId = 0;
// FIXME(https://bitwarden.atlassian.net/browse/CL-764): Migrate to OnPush
// eslint-disable-next-line @angular-eslint/prefer-on-push-component-change-detection
@Component({ @Component({
selector: "bit-radio-button", selector: "bit-radio-button",
templateUrl: "radio-button.component.html", templateUrl: "radio-button.component.html",

View File

@@ -63,6 +63,8 @@ describe("RadioGroupComponent", () => {
}); });
}); });
// FIXME(https://bitwarden.atlassian.net/browse/CL-764): Migrate to OnPush
// eslint-disable-next-line @angular-eslint/prefer-on-push-component-change-detection
@Component({ @Component({
selector: "test-app", selector: "test-app",
template: ` template: `

View File

@@ -8,6 +8,8 @@ import { BitLabel } from "../form-control/label.component";
let nextId = 0; let nextId = 0;
// FIXME(https://bitwarden.atlassian.net/browse/CL-764): Migrate to OnPush
// eslint-disable-next-line @angular-eslint/prefer-on-push-component-change-detection
@Component({ @Component({
selector: "bit-radio-group", selector: "bit-radio-group",
templateUrl: "radio-group.component.html", templateUrl: "radio-group.component.html",

View File

@@ -5,6 +5,8 @@ import { BitFormControlAbstraction } from "../form-control";
let nextId = 0; let nextId = 0;
// FIXME(https://bitwarden.atlassian.net/browse/CL-764): Migrate to OnPush
// eslint-disable-next-line @angular-eslint/prefer-on-push-component-change-detection
@Component({ @Component({
selector: "input[type=radio][bitRadio]", selector: "input[type=radio][bitRadio]",
template: "", template: "",

View File

@@ -13,6 +13,8 @@ export class ResizeObserverDirective implements OnDestroy {
} }
}); });
// FIXME(https://bitwarden.atlassian.net/browse/CL-903): Migrate to Signals
// eslint-disable-next-line @angular-eslint/prefer-output-emitter-ref
@Output() @Output()
resize = new EventEmitter(); resize = new EventEmitter();

View File

@@ -18,6 +18,8 @@ let nextId = 0;
/** /**
* Do not nest Search components inside another `<form>`, as they already contain their own standalone `<form>` element for searching. * Do not nest Search components inside another `<form>`, as they already contain their own standalone `<form>` element for searching.
*/ */
// FIXME(https://bitwarden.atlassian.net/browse/CL-764): Migrate to OnPush
// eslint-disable-next-line @angular-eslint/prefer-on-push-component-change-detection
@Component({ @Component({
selector: "bit-search", selector: "bit-search",
templateUrl: "./search.component.html", templateUrl: "./search.component.html",
@@ -45,10 +47,12 @@ export class SearchComponent implements ControlValueAccessor, FocusableElement {
// Use `type="text"` for Safari to improve rendering performance // Use `type="text"` for Safari to improve rendering performance
protected inputType = isBrowserSafariApi() ? ("text" as const) : ("search" as const); protected inputType = isBrowserSafariApi() ? ("text" as const) : ("search" as const);
protected isInputFocused = signal(false); protected readonly isInputFocused = signal(false);
protected isFormHovered = signal(false); protected readonly isFormHovered = signal(false);
protected showResetButton = computed(() => this.isInputFocused() || this.isFormHovered()); protected readonly showResetButton = computed(
() => this.isInputFocused() || this.isFormHovered(),
);
readonly disabled = model<boolean>(); readonly disabled = model<boolean>();
readonly placeholder = input<string>(); readonly placeholder = input<string>();

View File

@@ -2,6 +2,8 @@ import { Component } from "@angular/core";
import { TypographyModule } from "../typography"; import { TypographyModule } from "../typography";
// FIXME(https://bitwarden.atlassian.net/browse/CL-764): Migrate to OnPush
// eslint-disable-next-line @angular-eslint/prefer-on-push-component-change-detection
@Component({ @Component({
selector: "bit-section-header", selector: "bit-section-header",
templateUrl: "./section-header.component.html", templateUrl: "./section-header.component.html",

View File

@@ -2,6 +2,8 @@ import { coerceBooleanProperty } from "@angular/cdk/coercion";
import { CommonModule } from "@angular/common"; import { CommonModule } from "@angular/common";
import { Component, input } from "@angular/core"; import { Component, input } from "@angular/core";
// FIXME(https://bitwarden.atlassian.net/browse/CL-764): Migrate to OnPush
// eslint-disable-next-line @angular-eslint/prefer-on-push-component-change-detection
@Component({ @Component({
selector: "bit-section", selector: "bit-section",
imports: [CommonModule], imports: [CommonModule],

View File

@@ -2,6 +2,8 @@ import { Component, booleanAttribute, input } from "@angular/core";
import { MappedOptionComponent } from "./option"; import { MappedOptionComponent } from "./option";
// FIXME(https://bitwarden.atlassian.net/browse/CL-764): Migrate to OnPush
// eslint-disable-next-line @angular-eslint/prefer-on-push-component-change-detection
@Component({ @Component({
selector: "bit-option", selector: "bit-option",
template: `<ng-template><ng-content></ng-content></ng-template>`, template: `<ng-template><ng-content></ng-content></ng-template>`,

View File

@@ -9,6 +9,8 @@ import { I18nService } from "@bitwarden/common/platform/abstractions/i18n.servic
import { SelectComponent } from "./select.component"; import { SelectComponent } from "./select.component";
import { SelectModule } from "./select.module"; import { SelectModule } from "./select.module";
// FIXME(https://bitwarden.atlassian.net/browse/CL-764): Migrate to OnPush
// eslint-disable-next-line @angular-eslint/prefer-on-push-component-change-detection
@Component({ @Component({
imports: [SelectModule, ReactiveFormsModule], imports: [SelectModule, ReactiveFormsModule],
template: ` template: `

View File

@@ -34,6 +34,8 @@ import { OptionComponent } from "./option.component";
let nextId = 0; let nextId = 0;
// FIXME(https://bitwarden.atlassian.net/browse/CL-764): Migrate to OnPush
// eslint-disable-next-line @angular-eslint/prefer-on-push-component-change-detection
@Component({ @Component({
selector: "bit-select", selector: "bit-select",
templateUrl: "select.component.html", templateUrl: "select.component.html",
@@ -50,10 +52,12 @@ export class SelectComponent<T> implements BitFormFieldControl, ControlValueAcce
readonly items = model<Option<T>[] | undefined>(); readonly items = model<Option<T>[] | undefined>();
readonly placeholder = input(this.i18nService.t("selectPlaceholder")); readonly placeholder = input(this.i18nService.t("selectPlaceholder"));
// FIXME(https://bitwarden.atlassian.net/browse/CL-903): Migrate to Signals
// eslint-disable-next-line @angular-eslint/prefer-output-emitter-ref
@Output() closed = new EventEmitter(); @Output() closed = new EventEmitter();
protected selectedValue = signal<T | undefined | null>(undefined); protected readonly selectedValue = signal<T | undefined | null>(undefined);
selectedOption: Signal<Option<T> | null | undefined> = computed(() => readonly selectedOption: Signal<Option<T> | null | undefined> = computed(() =>
this.findSelectedOption(this.items(), this.selectedValue()), this.findSelectedOption(this.items(), this.selectedValue()),
); );
protected searchInputId = `bit-select-search-input-${nextId++}`; protected searchInputId = `bit-select-search-input-${nextId++}`;
@@ -70,6 +74,8 @@ export class SelectComponent<T> implements BitFormFieldControl, ControlValueAcce
} }
} }
// FIXME(https://bitwarden.atlassian.net/browse/CL-903): Migrate to Signals
// eslint-disable-next-line @angular-eslint/prefer-signals
@ContentChildren(OptionComponent) @ContentChildren(OptionComponent)
protected set options(value: QueryList<OptionComponent<T>>) { protected set options(value: QueryList<OptionComponent<T>>) {
if (value == null || value.length == 0) { if (value == null || value.length == 0) {
@@ -94,6 +100,8 @@ export class SelectComponent<T> implements BitFormFieldControl, ControlValueAcce
} }
// TODO: Skipped for signal migration because: // TODO: Skipped for signal migration because:
// Accessor inputs cannot be migrated as they are too complex. // Accessor inputs cannot be migrated as they are too complex.
// FIXME(https://bitwarden.atlassian.net/browse/CL-903): Migrate to Signals
// eslint-disable-next-line @angular-eslint/prefer-signals
@Input() @Input()
get disabled() { get disabled() {
return this._disabled ?? this.ngControl?.disabled ?? false; return this._disabled ?? this.ngControl?.disabled ?? false;
@@ -166,6 +174,8 @@ export class SelectComponent<T> implements BitFormFieldControl, ControlValueAcce
// TODO: Skipped for signal migration because: // TODO: Skipped for signal migration because:
// Accessor inputs cannot be migrated as they are too complex. // Accessor inputs cannot be migrated as they are too complex.
@HostBinding("attr.required") @HostBinding("attr.required")
// FIXME(https://bitwarden.atlassian.net/browse/CL-903): Migrate to Signals
// eslint-disable-next-line @angular-eslint/prefer-signals
@Input() @Input()
get required() { get required() {
return this._required ?? this.ngControl?.control?.hasValidator(Validators.required) ?? false; return this._required ?? this.ngControl?.control?.hasValidator(Validators.required) ?? false;

Some files were not shown because too many files have changed in this diff Show More