1
0
mirror of https://github.com/bitwarden/browser.git synced 2024-12-19 15:57:42 +01:00

[CL-135] Migrate component library to standalone components (#12389)

* Migrate component library to standalone components

* Fix tests
This commit is contained in:
Oscar Hinton 2024-12-17 23:29:48 +01:00 committed by GitHub
parent ac13cf7ce6
commit 5a582dfc6f
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
101 changed files with 330 additions and 216 deletions

View File

@ -6,7 +6,7 @@ import { BehaviorSubject } from "rxjs";
import { I18nPipe } from "@bitwarden/angular/platform/pipes/i18n.pipe"; import { I18nPipe } from "@bitwarden/angular/platform/pipes/i18n.pipe";
import { I18nService } from "@bitwarden/common/platform/abstractions/i18n.service"; import { I18nService } from "@bitwarden/common/platform/abstractions/i18n.service";
import { BitIconButtonComponent } from "@bitwarden/components/src/icon-button/icon-button.component"; import { IconButtonModule, NavigationModule } from "@bitwarden/components";
import { NavItemComponent } from "@bitwarden/components/src/navigation/nav-item.component"; import { NavItemComponent } from "@bitwarden/components/src/navigation/nav-item.component";
import { ProductSwitcherItem, ProductSwitcherService } from "../shared/product-switcher.service"; import { ProductSwitcherItem, ProductSwitcherService } from "../shared/product-switcher.service";
@ -45,13 +45,8 @@ describe("NavigationProductSwitcherComponent", () => {
mockProducts$.next({ bento: [], other: [] }); mockProducts$.next({ bento: [], other: [] });
await TestBed.configureTestingModule({ await TestBed.configureTestingModule({
imports: [RouterModule], imports: [RouterModule, NavigationModule, IconButtonModule],
declarations: [ declarations: [NavigationProductSwitcherComponent, I18nPipe],
NavigationProductSwitcherComponent,
NavItemComponent,
BitIconButtonComponent,
I18nPipe,
],
providers: [ providers: [
{ provide: ProductSwitcherService, useValue: productSwitcherService }, { provide: ProductSwitcherService, useValue: productSwitcherService },
{ {

View File

@ -13,7 +13,6 @@ import { I18nService } from "@bitwarden/common/platform/abstractions/i18n.servic
import { PasswordStrengthServiceAbstraction } from "@bitwarden/common/tools/password-strength"; import { PasswordStrengthServiceAbstraction } from "@bitwarden/common/tools/password-strength";
import { CipherService } from "@bitwarden/common/vault/abstractions/cipher.service"; import { CipherService } from "@bitwarden/common/vault/abstractions/cipher.service";
import { TableModule } from "@bitwarden/components"; import { TableModule } from "@bitwarden/components";
import { TableBodyDirective } from "@bitwarden/components/src/table/table.component";
import { LooseComponentsModule } from "@bitwarden/web-vault/app/shared"; import { LooseComponentsModule } from "@bitwarden/web-vault/app/shared";
import { PipesModule } from "@bitwarden/web-vault/app/vault/individual-vault/pipes/pipes.module"; import { PipesModule } from "@bitwarden/web-vault/app/vault/individual-vault/pipes/pipes.module";
@ -27,7 +26,7 @@ describe("PasswordHealthComponent", () => {
beforeEach(async () => { beforeEach(async () => {
await TestBed.configureTestingModule({ await TestBed.configureTestingModule({
imports: [PasswordHealthComponent, PipesModule, TableModule, LooseComponentsModule], imports: [PasswordHealthComponent, PipesModule, TableModule, LooseComponentsModule],
declarations: [TableBodyDirective], declarations: [],
providers: [ providers: [
{ provide: CipherService, useValue: mock<CipherService>() }, { provide: CipherService, useValue: mock<CipherService>() },
{ provide: I18nService, useValue: mock<I18nService>() }, { provide: I18nService, useValue: mock<I18nService>() },

View File

@ -1,14 +1,11 @@
import { NgModule } from "@angular/core"; import { NgModule } from "@angular/core";
import { SharedModule } from "../shared";
import { BitActionDirective } from "./bit-action.directive"; import { BitActionDirective } from "./bit-action.directive";
import { BitSubmitDirective } from "./bit-submit.directive"; import { BitSubmitDirective } from "./bit-submit.directive";
import { BitFormButtonDirective } from "./form-button.directive"; import { BitFormButtonDirective } from "./form-button.directive";
@NgModule({ @NgModule({
imports: [SharedModule], imports: [BitActionDirective, BitFormButtonDirective, BitSubmitDirective],
declarations: [BitActionDirective, BitFormButtonDirective, BitSubmitDirective],
exports: [BitActionDirective, BitFormButtonDirective, BitSubmitDirective], exports: [BitActionDirective, BitFormButtonDirective, BitSubmitDirective],
}) })
export class AsyncActionsModule {} export class AsyncActionsModule {}

View File

@ -15,6 +15,7 @@ import { FunctionReturningAwaitable, functionToObservable } from "../utils/funct
*/ */
@Directive({ @Directive({
selector: "[bitAction]", selector: "[bitAction]",
standalone: true,
}) })
export class BitActionDirective implements OnDestroy { export class BitActionDirective implements OnDestroy {
private destroy$ = new Subject<void>(); private destroy$ = new Subject<void>();

View File

@ -14,6 +14,7 @@ import { FunctionReturningAwaitable, functionToObservable } from "../utils/funct
*/ */
@Directive({ @Directive({
selector: "[formGroup][bitSubmit]", selector: "[formGroup][bitSubmit]",
standalone: true,
}) })
export class BitSubmitDirective implements OnInit, OnDestroy { export class BitSubmitDirective implements OnInit, OnDestroy {
private destroy$ = new Subject<void>(); private destroy$ = new Subject<void>();

View File

@ -25,6 +25,7 @@ import { BitSubmitDirective } from "./bit-submit.directive";
*/ */
@Directive({ @Directive({
selector: "button[bitFormButton]", selector: "button[bitFormButton]",
standalone: true,
}) })
export class BitFormButtonDirective implements OnDestroy { export class BitFormButtonDirective implements OnDestroy {
private destroy$ = new Subject<void>(); private destroy$ = new Subject<void>();

View File

@ -1,5 +1,6 @@
// FIXME: Update this file to be type safe and remove this and next line // FIXME: Update this file to be type safe and remove this and next line
// @ts-strict-ignore // @ts-strict-ignore
import { NgIf, NgClass } from "@angular/common";
import { Component, Input, OnChanges } from "@angular/core"; import { Component, Input, OnChanges } from "@angular/core";
import { DomSanitizer, SafeResourceUrl } from "@angular/platform-browser"; import { DomSanitizer, SafeResourceUrl } from "@angular/platform-browser";
@ -18,6 +19,8 @@ const SizeClasses: Record<SizeTypes, string[]> = {
@Component({ @Component({
selector: "bit-avatar", selector: "bit-avatar",
template: `<img *ngIf="src" [src]="src" title="{{ title || text }}" [ngClass]="classList" />`, template: `<img *ngIf="src" [src]="src" title="{{ title || text }}" [ngClass]="classList" />`,
standalone: true,
imports: [NgIf, NgClass],
}) })
export class AvatarComponent implements OnChanges { export class AvatarComponent implements OnChanges {
@Input() border = false; @Input() border = false;

View File

@ -1,11 +1,9 @@
import { CommonModule } from "@angular/common";
import { NgModule } from "@angular/core"; import { NgModule } from "@angular/core";
import { AvatarComponent } from "./avatar.component"; import { AvatarComponent } from "./avatar.component";
@NgModule({ @NgModule({
imports: [CommonModule], imports: [AvatarComponent],
exports: [AvatarComponent], exports: [AvatarComponent],
declarations: [AvatarComponent],
}) })
export class AvatarModule {} export class AvatarModule {}

View File

@ -1,12 +1,16 @@
// FIXME: Update this file to be type safe and remove this and next line // FIXME: Update this file to be type safe and remove this and next line
// @ts-strict-ignore // @ts-strict-ignore
import { CommonModule } from "@angular/common";
import { Component, Input, OnChanges } from "@angular/core"; import { Component, Input, OnChanges } from "@angular/core";
import { BadgeVariant } from "../badge"; import { BadgeModule, BadgeVariant } from "../badge";
import { I18nPipe } from "../shared/i18n.pipe";
@Component({ @Component({
selector: "bit-badge-list", selector: "bit-badge-list",
templateUrl: "badge-list.component.html", templateUrl: "badge-list.component.html",
standalone: true,
imports: [CommonModule, BadgeModule, I18nPipe],
}) })
export class BadgeListComponent implements OnChanges { export class BadgeListComponent implements OnChanges {
private _maxItems: number; private _maxItems: number;

View File

@ -1,13 +1,9 @@
import { NgModule } from "@angular/core"; import { NgModule } from "@angular/core";
import { BadgeModule } from "../badge";
import { SharedModule } from "../shared";
import { BadgeListComponent } from "./badge-list.component"; import { BadgeListComponent } from "./badge-list.component";
@NgModule({ @NgModule({
imports: [SharedModule, BadgeModule], imports: [BadgeListComponent],
exports: [BadgeListComponent], exports: [BadgeListComponent],
declarations: [BadgeListComponent],
}) })
export class BadgeListModule {} export class BadgeListModule {}

View File

@ -31,6 +31,7 @@ const hoverStyles: Record<BadgeVariant, string[]> = {
@Directive({ @Directive({
selector: "span[bitBadge], a[bitBadge], button[bitBadge]", selector: "span[bitBadge], a[bitBadge], button[bitBadge]",
providers: [{ provide: FocusableElement, useExisting: BadgeDirective }], providers: [{ provide: FocusableElement, useExisting: BadgeDirective }],
standalone: true,
}) })
export class BadgeDirective implements FocusableElement { export class BadgeDirective implements FocusableElement {
@HostBinding("class") get classList() { @HostBinding("class") get classList() {

View File

@ -1,11 +1,9 @@
import { CommonModule } from "@angular/common";
import { NgModule } from "@angular/core"; import { NgModule } from "@angular/core";
import { BadgeDirective } from "./badge.directive"; import { BadgeDirective } from "./badge.directive";
@NgModule({ @NgModule({
imports: [CommonModule], imports: [BadgeDirective],
exports: [BadgeDirective], exports: [BadgeDirective],
declarations: [BadgeDirective],
}) })
export class BadgeModule {} export class BadgeModule {}

View File

@ -2,7 +2,6 @@ import { ComponentFixture, TestBed } from "@angular/core/testing";
import { I18nService } from "@bitwarden/common/platform/abstractions/i18n.service"; import { I18nService } from "@bitwarden/common/platform/abstractions/i18n.service";
import { SharedModule } from "../shared/shared.module";
import { I18nMockService } from "../utils/i18n-mock.service"; import { I18nMockService } from "../utils/i18n-mock.service";
import { BannerComponent } from "./banner.component"; import { BannerComponent } from "./banner.component";
@ -13,8 +12,7 @@ describe("BannerComponent", () => {
beforeEach(async () => { beforeEach(async () => {
await TestBed.configureTestingModule({ await TestBed.configureTestingModule({
imports: [SharedModule], imports: [BannerComponent],
declarations: [BannerComponent],
providers: [ providers: [
{ {
provide: I18nService, provide: I18nService,

View File

@ -1,7 +1,11 @@
// FIXME: Update this file to be type safe and remove this and next line // FIXME: Update this file to be type safe and remove this and next line
// @ts-strict-ignore // @ts-strict-ignore
import { CommonModule } from "@angular/common";
import { Component, Input, OnInit, Output, EventEmitter } from "@angular/core"; import { Component, Input, OnInit, Output, EventEmitter } from "@angular/core";
import { IconButtonModule } from "../icon-button";
import { I18nPipe } from "../shared/i18n.pipe";
type BannerTypes = "premium" | "info" | "warning" | "danger"; type BannerTypes = "premium" | "info" | "warning" | "danger";
const defaultIcon: Record<BannerTypes, string> = { const defaultIcon: Record<BannerTypes, string> = {
@ -14,6 +18,8 @@ const defaultIcon: Record<BannerTypes, string> = {
@Component({ @Component({
selector: "bit-banner", selector: "bit-banner",
templateUrl: "./banner.component.html", templateUrl: "./banner.component.html",
standalone: true,
imports: [CommonModule, IconButtonModule, I18nPipe],
}) })
export class BannerComponent implements OnInit { export class BannerComponent implements OnInit {
@Input("bannerType") bannerType: BannerTypes = "info"; @Input("bannerType") bannerType: BannerTypes = "info";

View File

@ -1,14 +1,9 @@
import { CommonModule } from "@angular/common";
import { NgModule } from "@angular/core"; import { NgModule } from "@angular/core";
import { IconButtonModule } from "../icon-button";
import { SharedModule } from "../shared/shared.module";
import { BannerComponent } from "./banner.component"; import { BannerComponent } from "./banner.component";
@NgModule({ @NgModule({
imports: [CommonModule, SharedModule, IconButtonModule], imports: [BannerComponent],
exports: [BannerComponent], exports: [BannerComponent],
declarations: [BannerComponent],
}) })
export class BannerModule {} export class BannerModule {}

View File

@ -1,11 +1,14 @@
// FIXME: Update this file to be type safe and remove this and next line // FIXME: Update this file to be type safe and remove this and next line
// @ts-strict-ignore // @ts-strict-ignore
import { NgIf } from "@angular/common";
import { Component, EventEmitter, Input, Output, TemplateRef, ViewChild } from "@angular/core"; import { Component, EventEmitter, Input, Output, TemplateRef, ViewChild } from "@angular/core";
import { QueryParamsHandling } from "@angular/router"; import { QueryParamsHandling } from "@angular/router";
@Component({ @Component({
selector: "bit-breadcrumb", selector: "bit-breadcrumb",
templateUrl: "./breadcrumb.component.html", templateUrl: "./breadcrumb.component.html",
standalone: true,
imports: [NgIf],
}) })
export class BreadcrumbComponent { export class BreadcrumbComponent {
@Input() @Input()

View File

@ -1,10 +1,18 @@
import { CommonModule } from "@angular/common";
import { Component, ContentChildren, Input, QueryList } from "@angular/core"; import { Component, ContentChildren, Input, QueryList } from "@angular/core";
import { RouterModule } from "@angular/router";
import { IconButtonModule } from "../icon-button";
import { LinkModule } from "../link";
import { MenuModule } from "../menu";
import { BreadcrumbComponent } from "./breadcrumb.component"; import { BreadcrumbComponent } from "./breadcrumb.component";
@Component({ @Component({
selector: "bit-breadcrumbs", selector: "bit-breadcrumbs",
templateUrl: "./breadcrumbs.component.html", templateUrl: "./breadcrumbs.component.html",
standalone: true,
imports: [CommonModule, LinkModule, RouterModule, IconButtonModule, MenuModule],
}) })
export class BreadcrumbsComponent { export class BreadcrumbsComponent {
@Input() @Input()

View File

@ -1,17 +1,10 @@
import { CommonModule } from "@angular/common";
import { NgModule } from "@angular/core"; import { NgModule } from "@angular/core";
import { RouterModule } from "@angular/router";
import { IconButtonModule } from "../icon-button";
import { LinkModule } from "../link";
import { MenuModule } from "../menu";
import { BreadcrumbComponent } from "./breadcrumb.component"; import { BreadcrumbComponent } from "./breadcrumb.component";
import { BreadcrumbsComponent } from "./breadcrumbs.component"; import { BreadcrumbsComponent } from "./breadcrumbs.component";
@NgModule({ @NgModule({
imports: [CommonModule, LinkModule, IconButtonModule, MenuModule, RouterModule], imports: [BreadcrumbsComponent, BreadcrumbComponent],
declarations: [BreadcrumbsComponent, BreadcrumbComponent],
exports: [BreadcrumbsComponent, BreadcrumbComponent], exports: [BreadcrumbsComponent, BreadcrumbComponent],
}) })
export class BreadcrumbsModule {} export class BreadcrumbsModule {}

View File

@ -1,6 +1,7 @@
// FIXME: Update this file to be type safe and remove this and next line // FIXME: Update this file to be type safe and remove this and next line
// @ts-strict-ignore // @ts-strict-ignore
import { coerceBooleanProperty } from "@angular/cdk/coercion"; import { coerceBooleanProperty } from "@angular/cdk/coercion";
import { NgClass } from "@angular/common";
import { Input, HostBinding, Component } from "@angular/core"; import { Input, HostBinding, Component } from "@angular/core";
import { ButtonLikeAbstraction, ButtonType } from "../shared/button-like.abstraction"; import { ButtonLikeAbstraction, ButtonType } from "../shared/button-like.abstraction";
@ -46,6 +47,8 @@ const buttonStyles: Record<ButtonType, string[]> = {
selector: "button[bitButton], a[bitButton]", selector: "button[bitButton], a[bitButton]",
templateUrl: "button.component.html", templateUrl: "button.component.html",
providers: [{ provide: ButtonLikeAbstraction, useExisting: ButtonComponent }], providers: [{ provide: ButtonLikeAbstraction, useExisting: ButtonComponent }],
standalone: true,
imports: [NgClass],
}) })
export class ButtonComponent implements ButtonLikeAbstraction { export class ButtonComponent implements ButtonLikeAbstraction {
@HostBinding("class") get classList() { @HostBinding("class") get classList() {

View File

@ -1,11 +1,9 @@
import { CommonModule } from "@angular/common";
import { NgModule } from "@angular/core"; import { NgModule } from "@angular/core";
import { ButtonComponent } from "./button.component"; import { ButtonComponent } from "./button.component";
@NgModule({ @NgModule({
imports: [CommonModule], imports: [ButtonComponent],
exports: [ButtonComponent], exports: [ButtonComponent],
declarations: [ButtonComponent],
}) })
export class ButtonModule {} export class ButtonModule {}

View File

@ -9,6 +9,7 @@ import { BitFormControlAbstraction } from "../form-control";
selector: "input[type=checkbox][bitCheckbox]", selector: "input[type=checkbox][bitCheckbox]",
template: "", template: "",
providers: [{ provide: BitFormControlAbstraction, useExisting: CheckboxComponent }], providers: [{ provide: BitFormControlAbstraction, useExisting: CheckboxComponent }],
standalone: true,
}) })
export class CheckboxComponent implements BitFormControlAbstraction { export class CheckboxComponent implements BitFormControlAbstraction {
@HostBinding("class") @HostBinding("class")

View File

@ -1,14 +1,9 @@
import { CommonModule } from "@angular/common";
import { NgModule } from "@angular/core"; import { NgModule } from "@angular/core";
import { FormControlModule } from "../form-control";
import { SharedModule } from "../shared";
import { CheckboxComponent } from "./checkbox.component"; import { CheckboxComponent } from "./checkbox.component";
@NgModule({ @NgModule({
imports: [SharedModule, CommonModule, FormControlModule], imports: [CheckboxComponent],
declarations: [CheckboxComponent],
exports: [CheckboxComponent], exports: [CheckboxComponent],
}) })
export class CheckboxModule {} export class CheckboxModule {}

View File

@ -1,5 +1,6 @@
// FIXME: Update this file to be type safe and remove this and next line // FIXME: Update this file to be type safe and remove this and next line
// @ts-strict-ignore // @ts-strict-ignore
import { NgFor, NgIf } from "@angular/common";
import { Component, HostBinding, Input } from "@angular/core"; import { Component, HostBinding, Input } from "@angular/core";
import { Utils } from "@bitwarden/common/platform/misc/utils"; import { Utils } from "@bitwarden/common/platform/misc/utils";
@ -23,6 +24,8 @@ enum CharacterType {
}}</span> }}</span>
</span>`, </span>`,
preserveWhitespaces: false, preserveWhitespaces: false,
standalone: true,
imports: [NgFor, NgIf],
}) })
export class ColorPasswordComponent { export class ColorPasswordComponent {
@Input() password: string = null; @Input() password: string = null;

View File

@ -1,11 +1,9 @@
import { CommonModule } from "@angular/common";
import { NgModule } from "@angular/core"; import { NgModule } from "@angular/core";
import { ColorPasswordComponent } from "./color-password.component"; import { ColorPasswordComponent } from "./color-password.component";
@NgModule({ @NgModule({
imports: [CommonModule], imports: [ColorPasswordComponent],
exports: [ColorPasswordComponent], exports: [ColorPasswordComponent],
declarations: [ColorPasswordComponent],
}) })
export class ColorPasswordModule {} export class ColorPasswordModule {}

View File

@ -1,44 +1,25 @@
import { DialogModule as CdkDialogModule } from "@angular/cdk/dialog"; import { DialogModule as CdkDialogModule } from "@angular/cdk/dialog";
import { NgModule } from "@angular/core"; import { NgModule } from "@angular/core";
import { ReactiveFormsModule } from "@angular/forms";
import { AsyncActionsModule } from "../async-actions";
import { ButtonModule } from "../button";
import { IconButtonModule } from "../icon-button";
import { SharedModule } from "../shared";
import { TypographyModule } from "../typography";
import { DialogComponent } from "./dialog/dialog.component"; import { DialogComponent } from "./dialog/dialog.component";
import { DialogService } from "./dialog.service"; import { DialogService } 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 { SimpleConfigurableDialogComponent } from "./simple-dialog/simple-configurable-dialog/simple-configurable-dialog.component";
import { IconDirective, SimpleDialogComponent } from "./simple-dialog/simple-dialog.component"; import { IconDirective, SimpleDialogComponent } from "./simple-dialog/simple-dialog.component";
@NgModule({ @NgModule({
imports: [ imports: [
SharedModule,
AsyncActionsModule,
ButtonModule,
CdkDialogModule, CdkDialogModule,
IconButtonModule,
ReactiveFormsModule,
TypographyModule,
],
declarations: [
DialogCloseDirective, DialogCloseDirective,
DialogTitleContainerDirective,
DialogComponent, DialogComponent,
SimpleDialogComponent, SimpleDialogComponent,
SimpleConfigurableDialogComponent,
IconDirective, IconDirective,
], ],
exports: [ exports: [
CdkDialogModule, CdkDialogModule,
DialogComponent,
SimpleDialogComponent,
DialogCloseDirective, DialogCloseDirective,
DialogComponent,
IconDirective, IconDirective,
SimpleDialogComponent,
], ],
providers: [DialogService], providers: [DialogService],
}) })

View File

@ -1,14 +1,29 @@
// FIXME: Update this file to be type safe and remove this and next line // FIXME: Update this file to be type safe and remove this and next line
// @ts-strict-ignore // @ts-strict-ignore
import { coerceBooleanProperty } from "@angular/cdk/coercion"; import { coerceBooleanProperty } from "@angular/cdk/coercion";
import { CommonModule } from "@angular/common";
import { Component, HostBinding, Input } from "@angular/core"; import { Component, HostBinding, Input } from "@angular/core";
import { BitIconButtonComponent } from "../../icon-button/icon-button.component";
import { I18nPipe } from "../../shared/i18n.pipe";
import { TypographyDirective } from "../../typography/typography.directive";
import { fadeIn } from "../animations"; import { fadeIn } from "../animations";
import { DialogCloseDirective } from "../directives/dialog-close.directive";
import { DialogTitleContainerDirective } from "../directives/dialog-title-container.directive";
@Component({ @Component({
selector: "bit-dialog", selector: "bit-dialog",
templateUrl: "./dialog.component.html", templateUrl: "./dialog.component.html",
animations: [fadeIn], animations: [fadeIn],
standalone: true,
imports: [
CommonModule,
DialogTitleContainerDirective,
TypographyDirective,
BitIconButtonComponent,
DialogCloseDirective,
I18nPipe,
],
}) })
export class DialogComponent { export class DialogComponent {
/** Background color */ /** Background color */

View File

@ -3,6 +3,7 @@ import { Directive, HostBinding, HostListener, Input, Optional } from "@angular/
@Directive({ @Directive({
selector: "[bitDialogClose]", selector: "[bitDialogClose]",
standalone: true,
}) })
export class DialogCloseDirective { export class DialogCloseDirective {
@Input("bitDialogClose") dialogResult: any; @Input("bitDialogClose") dialogResult: any;

View File

@ -6,6 +6,7 @@ let nextId = 0;
@Directive({ @Directive({
selector: "[bitDialogTitleContainer]", selector: "[bitDialogTitleContainer]",
standalone: true,
}) })
export class DialogTitleContainerDirective implements OnInit { export class DialogTitleContainerDirective implements OnInit {
@HostBinding("id") id = `bit-dialog-title-${nextId++}`; @HostBinding("id") id = `bit-dialog-title-${nextId++}`;

View File

@ -1,12 +1,17 @@
// FIXME: Update this file to be type safe and remove this and next line // FIXME: Update this file to be type safe and remove this and next line
// @ts-strict-ignore // @ts-strict-ignore
import { DialogRef, DIALOG_DATA } from "@angular/cdk/dialog"; import { DialogRef, DIALOG_DATA } from "@angular/cdk/dialog";
import { NgIf } from "@angular/common";
import { Component, Inject } from "@angular/core"; import { Component, Inject } from "@angular/core";
import { FormGroup } from "@angular/forms"; import { FormGroup, ReactiveFormsModule } from "@angular/forms";
import { I18nService } from "@bitwarden/common/platform/abstractions/i18n.service"; import { I18nService } from "@bitwarden/common/platform/abstractions/i18n.service";
import { SimpleDialogOptions, SimpleDialogType, Translation } from "../.."; import { SimpleDialogOptions, SimpleDialogType, Translation } from "../..";
import { BitSubmitDirective } from "../../../async-actions/bit-submit.directive";
import { BitFormButtonDirective } from "../../../async-actions/form-button.directive";
import { ButtonComponent } from "../../../button/button.component";
import { SimpleDialogComponent, IconDirective } from "../simple-dialog.component";
const DEFAULT_ICON: Record<SimpleDialogType, string> = { const DEFAULT_ICON: Record<SimpleDialogType, string> = {
primary: "bwi-business", primary: "bwi-business",
@ -26,6 +31,16 @@ const DEFAULT_COLOR: Record<SimpleDialogType, string> = {
@Component({ @Component({
templateUrl: "./simple-configurable-dialog.component.html", templateUrl: "./simple-configurable-dialog.component.html",
standalone: true,
imports: [
ReactiveFormsModule,
BitSubmitDirective,
SimpleDialogComponent,
IconDirective,
ButtonComponent,
BitFormButtonDirective,
NgIf,
],
}) })
export class SimpleConfigurableDialogComponent { export class SimpleConfigurableDialogComponent {
get iconClasses() { get iconClasses() {

View File

@ -1,14 +1,22 @@
import { NgIf } from "@angular/common";
import { Component, ContentChild, Directive } from "@angular/core"; import { Component, ContentChild, Directive } from "@angular/core";
import { TypographyDirective } from "../../typography/typography.directive";
import { fadeIn } from "../animations"; import { fadeIn } from "../animations";
import { DialogTitleContainerDirective } from "../directives/dialog-title-container.directive";
@Directive({ selector: "[bitDialogIcon]" }) @Directive({
selector: "[bitDialogIcon]",
standalone: true,
})
export class IconDirective {} export class IconDirective {}
@Component({ @Component({
selector: "bit-simple-dialog", selector: "bit-simple-dialog",
templateUrl: "./simple-dialog.component.html", templateUrl: "./simple-dialog.component.html",
animations: [fadeIn], animations: [fadeIn],
standalone: true,
imports: [NgIf, DialogTitleContainerDirective, TypographyDirective],
}) })
export class SimpleDialogComponent { export class SimpleDialogComponent {
@ContentChild(IconDirective) icon!: IconDirective; @ContentChild(IconDirective) icon!: IconDirective;

View File

@ -1,15 +1,21 @@
// FIXME: Update this file to be type safe and remove this and next line // FIXME: Update this file to be type safe and remove this and next line
// @ts-strict-ignore // @ts-strict-ignore
import { coerceBooleanProperty } from "@angular/cdk/coercion"; import { coerceBooleanProperty } from "@angular/cdk/coercion";
import { NgClass, NgIf } from "@angular/common";
import { Component, ContentChild, HostBinding, Input } from "@angular/core"; import { Component, ContentChild, HostBinding, Input } from "@angular/core";
import { I18nService } from "@bitwarden/common/platform/abstractions/i18n.service"; import { I18nService } from "@bitwarden/common/platform/abstractions/i18n.service";
import { I18nPipe } from "../shared/i18n.pipe";
import { TypographyDirective } from "../typography/typography.directive";
import { BitFormControlAbstraction } from "./form-control.abstraction"; import { BitFormControlAbstraction } from "./form-control.abstraction";
@Component({ @Component({
selector: "bit-form-control", selector: "bit-form-control",
templateUrl: "form-control.component.html", templateUrl: "form-control.component.html",
standalone: true,
imports: [NgClass, TypographyDirective, NgIf, I18nPipe],
}) })
export class FormControlComponent { export class FormControlComponent {
@Input() label: string; @Input() label: string;

View File

@ -1,15 +1,11 @@
import { NgModule } from "@angular/core"; import { NgModule } from "@angular/core";
import { SharedModule } from "../shared";
import { TypographyModule } from "../typography";
import { FormControlComponent } from "./form-control.component"; import { FormControlComponent } from "./form-control.component";
import { BitHintComponent } from "./hint.component"; import { BitHintComponent } from "./hint.component";
import { BitLabel } from "./label.component"; import { BitLabel } from "./label.component";
@NgModule({ @NgModule({
imports: [SharedModule, BitLabel, TypographyModule], imports: [BitLabel, FormControlComponent, BitHintComponent],
declarations: [FormControlComponent, BitHintComponent],
exports: [FormControlComponent, BitLabel, BitHintComponent], exports: [FormControlComponent, BitLabel, BitHintComponent],
}) })
export class FormControlModule {} export class FormControlModule {}

View File

@ -8,6 +8,7 @@ let nextId = 0;
host: { host: {
class: "tw-text-muted tw-font-normal tw-inline-block tw-mt-1 tw-text-xs", class: "tw-text-muted tw-font-normal tw-inline-block tw-mt-1 tw-text-xs",
}, },
standalone: true,
}) })
export class BitHintComponent { export class BitHintComponent {
@HostBinding() id = `bit-hint-${nextId++}`; @HostBinding() id = `bit-hint-${nextId++}`;

View File

@ -1,8 +1,11 @@
// FIXME: Update this file to be type safe and remove this and next line // FIXME: Update this file to be type safe and remove this and next line
// @ts-strict-ignore // @ts-strict-ignore
import { NgIf } from "@angular/common";
import { Component, Input } from "@angular/core"; import { Component, Input } from "@angular/core";
import { AbstractControl, UntypedFormGroup } from "@angular/forms"; import { AbstractControl, UntypedFormGroup } from "@angular/forms";
import { I18nPipe } from "../shared/i18n.pipe";
@Component({ @Component({
selector: "bit-error-summary", selector: "bit-error-summary",
template: ` <ng-container *ngIf="errorCount > 0"> template: ` <ng-container *ngIf="errorCount > 0">
@ -12,6 +15,8 @@ import { AbstractControl, UntypedFormGroup } from "@angular/forms";
class: "tw-block tw-text-danger tw-mt-2", class: "tw-block tw-text-danger tw-mt-2",
"aria-live": "assertive", "aria-live": "assertive",
}, },
standalone: true,
imports: [NgIf, I18nPipe],
}) })
export class BitErrorSummary { export class BitErrorSummary {
@Input() @Input()

View File

@ -14,6 +14,7 @@ let nextId = 0;
class: "tw-block tw-mt-1 tw-text-danger tw-text-xs", class: "tw-block tw-mt-1 tw-text-danger tw-text-xs",
"aria-live": "assertive", "aria-live": "assertive",
}, },
standalone: true,
}) })
export class BitErrorComponent { export class BitErrorComponent {
@HostBinding() id = `bit-error-${nextId++}`; @HostBinding() id = `bit-error-${nextId++}`;

View File

@ -1,5 +1,6 @@
// FIXME: Update this file to be type safe and remove this and next line // FIXME: Update this file to be type safe and remove this and next line
// @ts-strict-ignore // @ts-strict-ignore
import { CommonModule } from "@angular/common";
import { import {
AfterContentChecked, AfterContentChecked,
booleanAttribute, booleanAttribute,
@ -16,6 +17,7 @@ import {
import { BitHintComponent } from "../form-control/hint.component"; import { BitHintComponent } from "../form-control/hint.component";
import { BitLabel } from "../form-control/label.component"; import { BitLabel } from "../form-control/label.component";
import { inputBorderClasses } from "../input/input.directive"; import { inputBorderClasses } from "../input/input.directive";
import { I18nPipe } from "../shared/i18n.pipe";
import { BitErrorComponent } from "./error.component"; import { BitErrorComponent } from "./error.component";
import { BitFormFieldControl } from "./form-field-control"; import { BitFormFieldControl } from "./form-field-control";
@ -23,6 +25,8 @@ import { BitFormFieldControl } from "./form-field-control";
@Component({ @Component({
selector: "bit-form-field", selector: "bit-form-field",
templateUrl: "./form-field.component.html", templateUrl: "./form-field.component.html",
standalone: true,
imports: [CommonModule, BitErrorComponent, I18nPipe],
}) })
export class BitFormFieldComponent implements AfterContentChecked { export class BitFormFieldComponent implements AfterContentChecked {
@ContentChild(BitFormFieldControl) input: BitFormFieldControl; @ContentChild(BitFormFieldControl) input: BitFormFieldControl;

View File

@ -1,11 +1,8 @@
import { NgModule } from "@angular/core"; import { NgModule } from "@angular/core";
import { FormControlModule } from "../form-control"; import { FormControlModule } from "../form-control";
import { BitInputDirective } from "../input/input.directive";
import { InputModule } from "../input/input.module"; import { InputModule } from "../input/input.module";
import { MultiSelectComponent } from "../multi-select/multi-select.component";
import { MultiSelectModule } from "../multi-select/multi-select.module"; import { MultiSelectModule } from "../multi-select/multi-select.module";
import { SharedModule } from "../shared";
import { BitErrorSummary } from "./error-summary.component"; import { BitErrorSummary } from "./error-summary.component";
import { BitErrorComponent } from "./error.component"; import { BitErrorComponent } from "./error.component";
@ -15,8 +12,11 @@ import { BitPrefixDirective } from "./prefix.directive";
import { BitSuffixDirective } from "./suffix.directive"; import { BitSuffixDirective } from "./suffix.directive";
@NgModule({ @NgModule({
imports: [SharedModule, FormControlModule, InputModule, MultiSelectModule], imports: [
declarations: [ FormControlModule,
InputModule,
MultiSelectModule,
BitErrorComponent, BitErrorComponent,
BitErrorSummary, BitErrorSummary,
BitFormFieldComponent, BitFormFieldComponent,
@ -25,15 +25,16 @@ import { BitSuffixDirective } from "./suffix.directive";
BitSuffixDirective, BitSuffixDirective,
], ],
exports: [ exports: [
FormControlModule,
InputModule,
MultiSelectModule,
BitErrorComponent, BitErrorComponent,
BitErrorSummary, BitErrorSummary,
BitFormFieldComponent, BitFormFieldComponent,
BitInputDirective,
BitPasswordInputToggleDirective, BitPasswordInputToggleDirective,
BitPrefixDirective, BitPrefixDirective,
BitSuffixDirective, BitSuffixDirective,
MultiSelectComponent,
FormControlModule,
], ],
}) })
export class FormFieldModule {} export class FormFieldModule {}

View File

@ -18,6 +18,7 @@ import { BitFormFieldComponent } from "./form-field.component";
@Directive({ @Directive({
selector: "[bitPasswordInputToggle]", selector: "[bitPasswordInputToggle]",
standalone: true,
}) })
export class BitPasswordInputToggleDirective implements AfterContentInit, OnChanges { export class BitPasswordInputToggleDirective implements AfterContentInit, OnChanges {
/** /**

View File

@ -4,6 +4,7 @@ import { BitIconButtonComponent } from "../icon-button/icon-button.component";
@Directive({ @Directive({
selector: "[bitPrefix]", selector: "[bitPrefix]",
standalone: true,
}) })
export class BitPrefixDirective implements OnInit { export class BitPrefixDirective implements OnInit {
@HostBinding("class") @Input() get classList() { @HostBinding("class") @Input() get classList() {

View File

@ -4,6 +4,7 @@ import { BitIconButtonComponent } from "../icon-button/icon-button.component";
@Directive({ @Directive({
selector: "[bitSuffix]", selector: "[bitSuffix]",
standalone: true,
}) })
export class BitSuffixDirective implements OnInit { export class BitSuffixDirective implements OnInit {
@HostBinding("class") @Input() get classList() { @HostBinding("class") @Input() get classList() {

View File

@ -1,5 +1,6 @@
// FIXME: Update this file to be type safe and remove this and next line // FIXME: Update this file to be type safe and remove this and next line
// @ts-strict-ignore // @ts-strict-ignore
import { NgClass } from "@angular/common";
import { Component, ElementRef, HostBinding, Input } from "@angular/core"; import { Component, ElementRef, HostBinding, Input } from "@angular/core";
import { ButtonLikeAbstraction, ButtonType } from "../shared/button-like.abstraction"; import { ButtonLikeAbstraction, ButtonType } from "../shared/button-like.abstraction";
@ -134,6 +135,8 @@ const sizes: Record<IconButtonSize, string[]> = {
{ provide: ButtonLikeAbstraction, useExisting: BitIconButtonComponent }, { provide: ButtonLikeAbstraction, useExisting: BitIconButtonComponent },
{ provide: FocusableElement, useExisting: BitIconButtonComponent }, { provide: FocusableElement, useExisting: BitIconButtonComponent },
], ],
standalone: true,
imports: [NgClass],
}) })
export class BitIconButtonComponent implements ButtonLikeAbstraction, FocusableElement { export class BitIconButtonComponent implements ButtonLikeAbstraction, FocusableElement {
@Input("bitIconButton") icon: string; @Input("bitIconButton") icon: string;

View File

@ -1,11 +1,9 @@
import { CommonModule } from "@angular/common";
import { NgModule } from "@angular/core"; import { NgModule } from "@angular/core";
import { BitIconButtonComponent } from "./icon-button.component"; import { BitIconButtonComponent } from "./icon-button.component";
@NgModule({ @NgModule({
imports: [CommonModule], imports: [BitIconButtonComponent],
declarations: [BitIconButtonComponent],
exports: [BitIconButtonComponent], exports: [BitIconButtonComponent],
}) })
export class IconButtonModule {} export class IconButtonModule {}

View File

@ -8,6 +8,7 @@ import { Icon, isIcon } from "./icon";
@Component({ @Component({
selector: "bit-icon", selector: "bit-icon",
template: ``, template: ``,
standalone: true,
}) })
export class BitIconComponent { export class BitIconComponent {
@Input() set icon(icon: Icon) { @Input() set icon(icon: Icon) {

View File

@ -9,7 +9,7 @@ describe("IconComponent", () => {
beforeEach(async () => { beforeEach(async () => {
await TestBed.configureTestingModule({ await TestBed.configureTestingModule({
declarations: [BitIconComponent], imports: [BitIconComponent],
}).compileComponents(); }).compileComponents();
fixture = TestBed.createComponent(BitIconComponent); fixture = TestBed.createComponent(BitIconComponent);

View File

@ -1,11 +1,9 @@
import { CommonModule } from "@angular/common";
import { NgModule } from "@angular/core"; import { NgModule } from "@angular/core";
import { BitIconComponent } from "./icon.component"; import { BitIconComponent } from "./icon.component";
@NgModule({ @NgModule({
imports: [CommonModule], imports: [BitIconComponent],
declarations: [BitIconComponent],
exports: [BitIconComponent], exports: [BitIconComponent],
}) })
export class IconModule {} export class IconModule {}

View File

@ -30,6 +30,7 @@ export function inputBorderClasses(error: boolean) {
@Directive({ @Directive({
selector: "input[bitInput], select[bitInput], textarea[bitInput]", selector: "input[bitInput], select[bitInput], textarea[bitInput]",
providers: [{ provide: BitFormFieldControl, useExisting: BitInputDirective }], providers: [{ provide: BitFormFieldControl, useExisting: BitInputDirective }],
standalone: true,
}) })
export class BitInputDirective implements BitFormFieldControl { export class BitInputDirective implements BitFormFieldControl {
@HostBinding("class") @Input() get classList() { @HostBinding("class") @Input() get classList() {

View File

@ -1,11 +1,9 @@
import { CommonModule } from "@angular/common";
import { NgModule } from "@angular/core"; import { NgModule } from "@angular/core";
import { BitInputDirective } from "./input.directive"; import { BitInputDirective } from "./input.directive";
@NgModule({ @NgModule({
imports: [CommonModule], imports: [BitInputDirective],
declarations: [BitInputDirective],
exports: [BitInputDirective], exports: [BitInputDirective],
}) })
export class InputModule {} export class InputModule {}

View File

@ -68,6 +68,7 @@ abstract class LinkDirective {
@Directive({ @Directive({
selector: "a[bitLink]", selector: "a[bitLink]",
standalone: true,
}) })
export class AnchorLinkDirective extends LinkDirective { export class AnchorLinkDirective extends LinkDirective {
@HostBinding("class") get classList() { @HostBinding("class") get classList() {
@ -79,6 +80,7 @@ export class AnchorLinkDirective extends LinkDirective {
@Directive({ @Directive({
selector: "button[bitLink]", selector: "button[bitLink]",
standalone: true,
}) })
export class ButtonLinkDirective extends LinkDirective { export class ButtonLinkDirective extends LinkDirective {
@HostBinding("class") get classList() { @HostBinding("class") get classList() {

View File

@ -1,11 +1,9 @@
import { CommonModule } from "@angular/common";
import { NgModule } from "@angular/core"; import { NgModule } from "@angular/core";
import { AnchorLinkDirective, ButtonLinkDirective } from "./link.directive"; import { AnchorLinkDirective, ButtonLinkDirective } from "./link.directive";
@NgModule({ @NgModule({
imports: [CommonModule], imports: [AnchorLinkDirective, ButtonLinkDirective],
exports: [AnchorLinkDirective, ButtonLinkDirective], exports: [AnchorLinkDirective, ButtonLinkDirective],
declarations: [AnchorLinkDirective, ButtonLinkDirective],
}) })
export class LinkModule {} export class LinkModule {}

View File

@ -3,5 +3,6 @@ import { Component } from "@angular/core";
@Component({ @Component({
selector: "bit-menu-divider", selector: "bit-menu-divider",
templateUrl: "./menu-divider.component.html", templateUrl: "./menu-divider.component.html",
standalone: true,
}) })
export class MenuDividerComponent {} export class MenuDividerComponent {}

View File

@ -1,10 +1,13 @@
import { FocusableOption } from "@angular/cdk/a11y"; import { FocusableOption } from "@angular/cdk/a11y";
import { coerceBooleanProperty } from "@angular/cdk/coercion"; import { coerceBooleanProperty } from "@angular/cdk/coercion";
import { NgClass } from "@angular/common";
import { Component, ElementRef, HostBinding, Input } from "@angular/core"; import { Component, ElementRef, HostBinding, Input } from "@angular/core";
@Component({ @Component({
selector: "[bitMenuItem]", selector: "[bitMenuItem]",
templateUrl: "menu-item.component.html", templateUrl: "menu-item.component.html",
standalone: true,
imports: [NgClass],
}) })
export class MenuItemDirective implements FocusableOption { export class MenuItemDirective implements FocusableOption {
@HostBinding("class") classList = [ @HostBinding("class") classList = [

View File

@ -19,6 +19,7 @@ import { MenuComponent } from "./menu.component";
@Directive({ @Directive({
selector: "[bitMenuTriggerFor]", selector: "[bitMenuTriggerFor]",
exportAs: "menuTrigger", exportAs: "menuTrigger",
standalone: true,
}) })
export class MenuTriggerForDirective implements OnDestroy { export class MenuTriggerForDirective implements OnDestroy {
@HostBinding("attr.aria-expanded") isOpen = false; @HostBinding("attr.aria-expanded") isOpen = false;

View File

@ -1,6 +1,6 @@
// FIXME: Update this file to be type safe and remove this and next line // FIXME: Update this file to be type safe and remove this and next line
// @ts-strict-ignore // @ts-strict-ignore
import { FocusKeyManager } from "@angular/cdk/a11y"; import { FocusKeyManager, CdkTrapFocus } from "@angular/cdk/a11y";
import { import {
Component, Component,
Output, Output,
@ -19,6 +19,8 @@ import { MenuItemDirective } from "./menu-item.directive";
selector: "bit-menu", selector: "bit-menu",
templateUrl: "./menu.component.html", templateUrl: "./menu.component.html",
exportAs: "menuComponent", exportAs: "menuComponent",
standalone: true,
imports: [CdkTrapFocus],
}) })
export class MenuComponent implements AfterContentInit { export class MenuComponent implements AfterContentInit {
@ViewChild(TemplateRef) templateRef: TemplateRef<any>; @ViewChild(TemplateRef) templateRef: TemplateRef<any>;

View File

@ -1,6 +1,3 @@
import { A11yModule } from "@angular/cdk/a11y";
import { OverlayModule } from "@angular/cdk/overlay";
import { CommonModule } from "@angular/common";
import { NgModule } from "@angular/core"; import { NgModule } from "@angular/core";
import { MenuDividerComponent } from "./menu-divider.component"; import { MenuDividerComponent } from "./menu-divider.component";
@ -9,8 +6,7 @@ import { MenuTriggerForDirective } from "./menu-trigger-for.directive";
import { MenuComponent } from "./menu.component"; import { MenuComponent } from "./menu.component";
@NgModule({ @NgModule({
imports: [A11yModule, CommonModule, OverlayModule], imports: [MenuComponent, MenuTriggerForDirective, MenuItemDirective, MenuDividerComponent],
declarations: [MenuComponent, MenuTriggerForDirective, MenuItemDirective, MenuDividerComponent],
exports: [MenuComponent, MenuTriggerForDirective, MenuItemDirective, MenuDividerComponent], exports: [MenuComponent, MenuTriggerForDirective, MenuItemDirective, MenuDividerComponent],
}) })
export class MenuModule {} export class MenuModule {}

View File

@ -3,23 +3,15 @@ import { Meta, StoryObj, moduleMetadata } from "@storybook/angular";
import { ButtonModule } from "../button/button.module"; import { ButtonModule } from "../button/button.module";
import { MenuDividerComponent } from "./menu-divider.component";
import { MenuItemDirective } from "./menu-item.directive";
import { MenuTriggerForDirective } from "./menu-trigger-for.directive"; import { MenuTriggerForDirective } from "./menu-trigger-for.directive";
import { MenuComponent } from "./menu.component"; import { MenuModule } from "./menu.module";
export default { export default {
title: "Component Library/Menu", title: "Component Library/Menu",
component: MenuTriggerForDirective, component: MenuTriggerForDirective,
decorators: [ decorators: [
moduleMetadata({ moduleMetadata({
declarations: [ imports: [MenuModule, OverlayModule, ButtonModule],
MenuTriggerForDirective,
MenuComponent,
MenuItemDirective,
MenuDividerComponent,
],
imports: [OverlayModule, ButtonModule],
}), }),
], ],
parameters: { parameters: {

View File

@ -2,6 +2,7 @@
// @ts-strict-ignore // @ts-strict-ignore
import { coerceBooleanProperty } from "@angular/cdk/coercion"; import { coerceBooleanProperty } from "@angular/cdk/coercion";
import { hasModifierKey } from "@angular/cdk/keycodes"; import { hasModifierKey } from "@angular/cdk/keycodes";
import { NgIf } from "@angular/common";
import { import {
Component, Component,
Input, Input,
@ -13,12 +14,20 @@ import {
Optional, Optional,
Self, Self,
} from "@angular/core"; } from "@angular/core";
import { ControlValueAccessor, NgControl, Validators } from "@angular/forms"; import {
import { NgSelectComponent } from "@ng-select/ng-select"; ControlValueAccessor,
NgControl,
Validators,
ReactiveFormsModule,
FormsModule,
} from "@angular/forms";
import { NgSelectComponent, NgSelectModule } from "@ng-select/ng-select";
import { I18nService } from "@bitwarden/common/platform/abstractions/i18n.service"; import { I18nService } from "@bitwarden/common/platform/abstractions/i18n.service";
import { BadgeModule } from "../badge";
import { BitFormFieldControl } from "../form-field/form-field-control"; import { BitFormFieldControl } from "../form-field/form-field-control";
import { I18nPipe } from "../shared/i18n.pipe";
import { SelectItemView } from "./models/select-item-view"; import { SelectItemView } from "./models/select-item-view";
@ -29,6 +38,8 @@ let nextId = 0;
selector: "bit-multi-select", selector: "bit-multi-select",
templateUrl: "./multi-select.component.html", templateUrl: "./multi-select.component.html",
providers: [{ provide: BitFormFieldControl, useExisting: MultiSelectComponent }], providers: [{ provide: BitFormFieldControl, useExisting: MultiSelectComponent }],
standalone: true,
imports: [NgSelectModule, ReactiveFormsModule, FormsModule, BadgeModule, NgIf, I18nPipe],
}) })
/** /**
* This component has been implemented to only support Multi-select list events * This component has been implemented to only support Multi-select list events

View File

@ -1,16 +1,9 @@
import { CommonModule } from "@angular/common";
import { NgModule } from "@angular/core"; import { NgModule } from "@angular/core";
import { FormsModule } from "@angular/forms";
import { NgSelectModule } from "@ng-select/ng-select";
import { BadgeModule } from "../badge";
import { SharedModule } from "../shared";
import { MultiSelectComponent } from "./multi-select.component"; import { MultiSelectComponent } from "./multi-select.component";
@NgModule({ @NgModule({
imports: [CommonModule, FormsModule, NgSelectModule, BadgeModule, SharedModule], imports: [MultiSelectComponent],
exports: [MultiSelectComponent], exports: [MultiSelectComponent],
declarations: [MultiSelectComponent],
}) })
export class MultiSelectModule {} export class MultiSelectModule {}

View File

@ -1,3 +1,4 @@
import { CommonModule } from "@angular/common";
import { Component } from "@angular/core"; import { Component } from "@angular/core";
import { SideNavService } from "./side-nav.service"; import { SideNavService } from "./side-nav.service";
@ -5,6 +6,8 @@ import { SideNavService } from "./side-nav.service";
@Component({ @Component({
selector: "bit-nav-divider", selector: "bit-nav-divider",
templateUrl: "./nav-divider.component.html", templateUrl: "./nav-divider.component.html",
standalone: true,
imports: [CommonModule],
}) })
export class NavDividerComponent { export class NavDividerComponent {
constructor(protected sideNavService: SideNavService) {} constructor(protected sideNavService: SideNavService) {}

View File

@ -1,3 +1,4 @@
import { CommonModule } from "@angular/common";
import { import {
AfterContentInit, AfterContentInit,
booleanAttribute, booleanAttribute,
@ -11,13 +12,22 @@ import {
SkipSelf, SkipSelf,
} from "@angular/core"; } from "@angular/core";
import { IconButtonModule } from "../icon-button";
import { I18nPipe } from "../shared/i18n.pipe";
import { NavBaseComponent } from "./nav-base.component"; import { NavBaseComponent } from "./nav-base.component";
import { NavGroupAbstraction, NavItemComponent } from "./nav-item.component";
import { SideNavService } from "./side-nav.service"; import { SideNavService } from "./side-nav.service";
@Component({ @Component({
selector: "bit-nav-group", selector: "bit-nav-group",
templateUrl: "./nav-group.component.html", templateUrl: "./nav-group.component.html",
providers: [{ provide: NavBaseComponent, useExisting: NavGroupComponent }], providers: [
{ provide: NavBaseComponent, useExisting: NavGroupComponent },
{ provide: NavGroupAbstraction, useExisting: NavGroupComponent },
],
standalone: true,
imports: [CommonModule, NavItemComponent, IconButtonModule, I18nPipe],
}) })
export class NavGroupComponent extends NavBaseComponent implements AfterContentInit { export class NavGroupComponent extends NavBaseComponent implements AfterContentInit {
@ContentChildren(NavBaseComponent, { @ContentChildren(NavBaseComponent, {

View File

@ -1,14 +1,24 @@
import { CommonModule } from "@angular/common";
import { Component, HostListener, Input, Optional } from "@angular/core"; import { Component, HostListener, Input, Optional } from "@angular/core";
import { RouterModule } from "@angular/router";
import { BehaviorSubject, map } from "rxjs"; import { BehaviorSubject, map } from "rxjs";
import { IconButtonModule } from "../icon-button";
import { NavBaseComponent } from "./nav-base.component"; import { NavBaseComponent } from "./nav-base.component";
import { NavGroupComponent } from "./nav-group.component";
import { SideNavService } from "./side-nav.service"; import { SideNavService } from "./side-nav.service";
// Resolves a circular dependency between `NavItemComponent` and `NavItemGroup` when using standalone components.
export abstract class NavGroupAbstraction {
abstract setOpen(open: boolean): void;
}
@Component({ @Component({
selector: "bit-nav-item", selector: "bit-nav-item",
templateUrl: "./nav-item.component.html", templateUrl: "./nav-item.component.html",
providers: [{ provide: NavBaseComponent, useExisting: NavItemComponent }], providers: [{ provide: NavBaseComponent, useExisting: NavItemComponent }],
standalone: true,
imports: [CommonModule, IconButtonModule, RouterModule],
}) })
export class NavItemComponent extends NavBaseComponent { export class NavItemComponent extends NavBaseComponent {
/** Forces active styles to be shown, regardless of the `routerLinkActiveOptions` */ /** Forces active styles to be shown, regardless of the `routerLinkActiveOptions` */
@ -52,7 +62,7 @@ export class NavItemComponent extends NavBaseComponent {
constructor( constructor(
protected sideNavService: SideNavService, protected sideNavService: SideNavService,
@Optional() private parentNavGroup: NavGroupComponent, @Optional() private parentNavGroup: NavGroupAbstraction,
) { ) {
super(); super();
} }

View File

@ -1,14 +1,20 @@
// FIXME: Update this file to be type safe and remove this and next line // FIXME: Update this file to be type safe and remove this and next line
// @ts-strict-ignore // @ts-strict-ignore
import { NgIf } from "@angular/common";
import { Component, Input } from "@angular/core"; import { Component, Input } from "@angular/core";
import { RouterLinkActive, RouterLink } from "@angular/router";
import { Icon } from "../icon"; import { Icon } from "../icon";
import { BitIconComponent } from "../icon/icon.component";
import { NavItemComponent } from "./nav-item.component";
import { SideNavService } from "./side-nav.service"; import { SideNavService } from "./side-nav.service";
@Component({ @Component({
selector: "bit-nav-logo", selector: "bit-nav-logo",
templateUrl: "./nav-logo.component.html", templateUrl: "./nav-logo.component.html",
standalone: true,
imports: [NgIf, RouterLinkActive, RouterLink, BitIconComponent, NavItemComponent],
}) })
export class NavLogoComponent { export class NavLogoComponent {
/** Icon that is displayed when the side nav is closed */ /** Icon that is displayed when the side nav is closed */

View File

@ -1,13 +1,4 @@
import { A11yModule } from "@angular/cdk/a11y";
import { OverlayModule } from "@angular/cdk/overlay";
import { CommonModule } from "@angular/common";
import { NgModule } from "@angular/core"; import { NgModule } from "@angular/core";
import { RouterModule } from "@angular/router";
import { IconModule } from "../icon";
import { IconButtonModule } from "../icon-button/icon-button.module";
import { LinkModule } from "../link";
import { SharedModule } from "../shared/shared.module";
import { NavDividerComponent } from "./nav-divider.component"; import { NavDividerComponent } from "./nav-divider.component";
import { NavGroupComponent } from "./nav-group.component"; import { NavGroupComponent } from "./nav-group.component";
@ -17,16 +8,6 @@ import { SideNavComponent } from "./side-nav.component";
@NgModule({ @NgModule({
imports: [ imports: [
CommonModule,
SharedModule,
IconButtonModule,
OverlayModule,
RouterModule,
IconModule,
A11yModule,
LinkModule,
],
declarations: [
NavDividerComponent, NavDividerComponent,
NavGroupComponent, NavGroupComponent,
NavItemComponent, NavItemComponent,

View File

@ -1,7 +1,13 @@
// FIXME: Update this file to be type safe and remove this and next line // FIXME: Update this file to be type safe and remove this and next line
// @ts-strict-ignore // @ts-strict-ignore
import { CdkTrapFocus } from "@angular/cdk/a11y";
import { CommonModule } from "@angular/common";
import { Component, ElementRef, Input, ViewChild } from "@angular/core"; import { Component, ElementRef, Input, ViewChild } from "@angular/core";
import { BitIconButtonComponent } from "../icon-button/icon-button.component";
import { I18nPipe } from "../shared/i18n.pipe";
import { NavDividerComponent } from "./nav-divider.component";
import { SideNavService } from "./side-nav.service"; import { SideNavService } from "./side-nav.service";
export type SideNavVariant = "primary" | "secondary"; export type SideNavVariant = "primary" | "secondary";
@ -9,6 +15,8 @@ export type SideNavVariant = "primary" | "secondary";
@Component({ @Component({
selector: "bit-side-nav", selector: "bit-side-nav",
templateUrl: "side-nav.component.html", templateUrl: "side-nav.component.html",
standalone: true,
imports: [CommonModule, CdkTrapFocus, NavDividerComponent, BitIconButtonComponent, I18nPipe],
}) })
export class SideNavComponent { export class SideNavComponent {
@Input() variant: SideNavVariant = "primary"; @Input() variant: SideNavVariant = "primary";

View File

@ -1,6 +1,7 @@
import { Component, Input } from "@angular/core"; import { Component, Input } from "@angular/core";
import { Icons } from ".."; import { Icons } from "..";
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.
@ -8,6 +9,8 @@ import { Icons } from "..";
@Component({ @Component({
selector: "bit-no-items", selector: "bit-no-items",
templateUrl: "./no-items.component.html", templateUrl: "./no-items.component.html",
standalone: true,
imports: [BitIconComponent],
}) })
export class NoItemsComponent { export class NoItemsComponent {
@Input() icon = Icons.Search; @Input() icon = Icons.Search;

View File

@ -1,13 +1,9 @@
import { CommonModule } from "@angular/common";
import { NgModule } from "@angular/core"; import { NgModule } from "@angular/core";
import { IconModule } from "../icon";
import { NoItemsComponent } from "./no-items.component"; import { NoItemsComponent } from "./no-items.component";
@NgModule({ @NgModule({
imports: [CommonModule, IconModule], imports: [NoItemsComponent],
exports: [NoItemsComponent], exports: [NoItemsComponent],
declarations: [NoItemsComponent],
}) })
export class NoItemsModule {} export class NoItemsModule {}

View File

@ -1,3 +1,4 @@
import { CommonModule } from "@angular/common";
import { Component, Input } from "@angular/core"; import { Component, Input } from "@angular/core";
type SizeTypes = "small" | "default" | "large"; type SizeTypes = "small" | "default" | "large";
@ -19,6 +20,8 @@ const BackgroundClasses: Record<BackgroundTypes, string[]> = {
@Component({ @Component({
selector: "bit-progress", selector: "bit-progress",
templateUrl: "./progress.component.html", templateUrl: "./progress.component.html",
standalone: true,
imports: [CommonModule],
}) })
export class ProgressComponent { export class ProgressComponent {
@Input() barWidth = 0; @Input() barWidth = 0;

View File

@ -1,11 +1,9 @@
import { CommonModule } from "@angular/common";
import { NgModule } from "@angular/core"; import { NgModule } from "@angular/core";
import { ProgressComponent } from "./progress.component"; import { ProgressComponent } from "./progress.component";
@NgModule({ @NgModule({
imports: [CommonModule], imports: [ProgressComponent],
exports: [ProgressComponent], exports: [ProgressComponent],
declarations: [ProgressComponent],
}) })
export class ProgressModule {} export class ProgressModule {}

View File

@ -1,12 +1,17 @@
import { Component, HostBinding, Input } from "@angular/core"; import { Component, HostBinding, Input } from "@angular/core";
import { FormControlModule } from "../form-control/form-control.module";
import { RadioGroupComponent } from "./radio-group.component"; import { RadioGroupComponent } from "./radio-group.component";
import { RadioInputComponent } from "./radio-input.component";
let nextId = 0; let nextId = 0;
@Component({ @Component({
selector: "bit-radio-button", selector: "bit-radio-button",
templateUrl: "radio-button.component.html", templateUrl: "radio-button.component.html",
standalone: true,
imports: [FormControlModule, RadioInputComponent],
}) })
export class RadioButtonComponent { export class RadioButtonComponent {
@HostBinding("attr.id") @Input() id = `bit-radio-button-${nextId++}`; @HostBinding("attr.id") @Input() id = `bit-radio-button-${nextId++}`;

View File

@ -1,16 +1,13 @@
import { CommonModule } from "@angular/common";
import { NgModule } from "@angular/core"; import { NgModule } from "@angular/core";
import { FormControlModule } from "../form-control"; import { FormControlModule } from "../form-control";
import { SharedModule } from "../shared";
import { RadioButtonComponent } from "./radio-button.component"; import { RadioButtonComponent } from "./radio-button.component";
import { RadioGroupComponent } from "./radio-group.component"; import { RadioGroupComponent } from "./radio-group.component";
import { RadioInputComponent } from "./radio-input.component"; import { RadioInputComponent } from "./radio-input.component";
@NgModule({ @NgModule({
imports: [CommonModule, SharedModule, FormControlModule], imports: [FormControlModule, RadioInputComponent, RadioButtonComponent, RadioGroupComponent],
declarations: [RadioInputComponent, RadioButtonComponent, RadioGroupComponent],
exports: [FormControlModule, RadioInputComponent, RadioButtonComponent, RadioGroupComponent], exports: [FormControlModule, RadioInputComponent, RadioButtonComponent, RadioGroupComponent],
}) })
export class RadioButtonModule {} export class RadioButtonModule {}

View File

@ -1,15 +1,19 @@
// FIXME: Update this file to be type safe and remove this and next line // FIXME: Update this file to be type safe and remove this and next line
// @ts-strict-ignore // @ts-strict-ignore
import { NgIf, NgTemplateOutlet } from "@angular/common";
import { Component, ContentChild, HostBinding, Input, Optional, Self } from "@angular/core"; import { Component, ContentChild, HostBinding, Input, Optional, Self } from "@angular/core";
import { ControlValueAccessor, NgControl, Validators } from "@angular/forms"; import { ControlValueAccessor, NgControl, Validators } from "@angular/forms";
import { BitLabel } from "../form-control/label.component"; import { BitLabel } from "../form-control/label.component";
import { I18nPipe } from "../shared/i18n.pipe";
let nextId = 0; let nextId = 0;
@Component({ @Component({
selector: "bit-radio-group", selector: "bit-radio-group",
templateUrl: "radio-group.component.html", templateUrl: "radio-group.component.html",
standalone: true,
imports: [NgIf, NgTemplateOutlet, I18nPipe],
}) })
export class RadioGroupComponent implements ControlValueAccessor { export class RadioGroupComponent implements ControlValueAccessor {
selected: unknown; selected: unknown;

View File

@ -11,6 +11,7 @@ let nextId = 0;
selector: "input[type=radio][bitRadio]", selector: "input[type=radio][bitRadio]",
template: "", template: "",
providers: [{ provide: BitFormControlAbstraction, useExisting: RadioInputComponent }], providers: [{ provide: BitFormControlAbstraction, useExisting: RadioInputComponent }],
standalone: true,
}) })
export class RadioInputComponent implements BitFormControlAbstraction { export class RadioInputComponent implements BitFormControlAbstraction {
@HostBinding("attr.id") @Input() id = `bit-radio-input-${nextId++}`; @HostBinding("attr.id") @Input() id = `bit-radio-input-${nextId++}`;

View File

@ -1,11 +1,18 @@
// FIXME: Update this file to be type safe and remove this and next line // FIXME: Update this file to be type safe and remove this and next line
// @ts-strict-ignore // @ts-strict-ignore
import { Component, ElementRef, Input, ViewChild } from "@angular/core"; import { Component, ElementRef, Input, ViewChild } from "@angular/core";
import { ControlValueAccessor, NG_VALUE_ACCESSOR } from "@angular/forms"; import {
ControlValueAccessor,
NG_VALUE_ACCESSOR,
ReactiveFormsModule,
FormsModule,
} from "@angular/forms";
import { isBrowserSafariApi } from "@bitwarden/platform"; import { isBrowserSafariApi } from "@bitwarden/platform";
import { InputModule } from "../input/input.module";
import { FocusableElement } from "../shared/focusable-element"; import { FocusableElement } from "../shared/focusable-element";
import { I18nPipe } from "../shared/i18n.pipe";
let nextId = 0; let nextId = 0;
@ -23,6 +30,8 @@ let nextId = 0;
useExisting: SearchComponent, useExisting: SearchComponent,
}, },
], ],
standalone: true,
imports: [InputModule, ReactiveFormsModule, FormsModule, I18nPipe],
}) })
export class SearchComponent implements ControlValueAccessor, FocusableElement { export class SearchComponent implements ControlValueAccessor, FocusableElement {
private notifyOnChange: (v: string) => void; private notifyOnChange: (v: string) => void;

View File

@ -1,14 +1,9 @@
import { NgModule } from "@angular/core"; import { NgModule } from "@angular/core";
import { FormsModule } from "@angular/forms";
import { InputModule } from "../input/input.module";
import { SharedModule } from "../shared";
import { SearchComponent } from "./search.component"; import { SearchComponent } from "./search.component";
@NgModule({ @NgModule({
imports: [SharedModule, InputModule, FormsModule], imports: [SearchComponent],
declarations: [SearchComponent],
exports: [SearchComponent], exports: [SearchComponent],
}) })
export class SearchModule {} export class SearchModule {}

View File

@ -7,6 +7,7 @@ import { Option } from "./option";
@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>`,
standalone: true,
}) })
export class OptionComponent<T = unknown> implements Option<T> { export class OptionComponent<T = unknown> implements Option<T> {
@Input() @Input()

View File

@ -1,5 +1,6 @@
// FIXME: Update this file to be type safe and remove this and next line // FIXME: Update this file to be type safe and remove this and next line
// @ts-strict-ignore // @ts-strict-ignore
import { NgIf } from "@angular/common";
import { import {
Component, Component,
ContentChildren, ContentChildren,
@ -12,8 +13,14 @@ import {
Output, Output,
EventEmitter, EventEmitter,
} from "@angular/core"; } from "@angular/core";
import { ControlValueAccessor, NgControl, Validators } from "@angular/forms"; import {
import { NgSelectComponent } from "@ng-select/ng-select"; ControlValueAccessor,
NgControl,
Validators,
ReactiveFormsModule,
FormsModule,
} from "@angular/forms";
import { NgSelectComponent, NgSelectModule } from "@ng-select/ng-select";
import { I18nService } from "@bitwarden/common/platform/abstractions/i18n.service"; import { I18nService } from "@bitwarden/common/platform/abstractions/i18n.service";
@ -28,6 +35,8 @@ let nextId = 0;
selector: "bit-select", selector: "bit-select",
templateUrl: "select.component.html", templateUrl: "select.component.html",
providers: [{ provide: BitFormFieldControl, useExisting: SelectComponent }], providers: [{ provide: BitFormFieldControl, useExisting: SelectComponent }],
standalone: true,
imports: [NgSelectModule, ReactiveFormsModule, FormsModule, NgIf],
}) })
export class SelectComponent<T> implements BitFormFieldControl, ControlValueAccessor { export class SelectComponent<T> implements BitFormFieldControl, ControlValueAccessor {
@ViewChild(NgSelectComponent) select: NgSelectComponent; @ViewChild(NgSelectComponent) select: NgSelectComponent;

View File

@ -1,14 +1,10 @@
import { CommonModule } from "@angular/common";
import { NgModule } from "@angular/core"; import { NgModule } from "@angular/core";
import { FormsModule } from "@angular/forms";
import { NgSelectModule } from "@ng-select/ng-select";
import { OptionComponent } from "./option.component"; import { OptionComponent } from "./option.component";
import { SelectComponent } from "./select.component"; import { SelectComponent } from "./select.component";
@NgModule({ @NgModule({
imports: [CommonModule, NgSelectModule, FormsModule], imports: [SelectComponent, OptionComponent],
declarations: [SelectComponent, OptionComponent],
exports: [SelectComponent, OptionComponent], exports: [SelectComponent, OptionComponent],
}) })
export class SelectModule {} export class SelectModule {}

View File

@ -7,6 +7,7 @@ import { I18nService } from "@bitwarden/common/platform/abstractions/i18n.servic
*/ */
@Pipe({ @Pipe({
name: "i18n", name: "i18n",
standalone: true,
}) })
export class I18nPipe implements PipeTransform { export class I18nPipe implements PipeTransform {
constructor(private i18nService: I18nService) {} constructor(private i18nService: I18nService) {}

View File

@ -4,8 +4,7 @@ import { NgModule } from "@angular/core";
import { I18nPipe } from "./i18n.pipe"; import { I18nPipe } from "./i18n.pipe";
@NgModule({ @NgModule({
imports: [CommonModule], imports: [CommonModule, I18nPipe],
declarations: [I18nPipe],
exports: [CommonModule, I18nPipe], exports: [CommonModule, I18nPipe],
}) })
export class SharedModule {} export class SharedModule {}

View File

@ -2,6 +2,7 @@ import { Directive, HostBinding } from "@angular/core";
@Directive({ @Directive({
selector: "th[bitCell], td[bitCell]", selector: "th[bitCell], td[bitCell]",
standalone: true,
}) })
export class CellDirective { export class CellDirective {
@HostBinding("class") get classList() { @HostBinding("class") get classList() {

View File

@ -2,6 +2,7 @@ import { Directive, HostBinding, Input } from "@angular/core";
@Directive({ @Directive({
selector: "tr[bitRow]", selector: "tr[bitRow]",
standalone: true,
}) })
export class RowDirective { export class RowDirective {
@Input() alignContent: "top" | "middle" | "bottom" | "baseline" = "middle"; @Input() alignContent: "top" | "middle" | "bottom" | "baseline" = "middle";

View File

@ -1,6 +1,7 @@
// FIXME: Update this file to be type safe and remove this and next line // FIXME: Update this file to be type safe and remove this and next line
// @ts-strict-ignore // @ts-strict-ignore
import { coerceBooleanProperty } from "@angular/cdk/coercion"; import { coerceBooleanProperty } from "@angular/cdk/coercion";
import { NgClass } from "@angular/common";
import { Component, HostBinding, Input, OnInit } from "@angular/core"; import { Component, HostBinding, Input, OnInit } from "@angular/core";
import type { SortDirection, SortFn } from "./table-data-source"; import type { SortDirection, SortFn } from "./table-data-source";
@ -14,6 +15,8 @@ import { TableComponent } from "./table.component";
<i class="bwi tw-ml-2" [ngClass]="icon"></i> <i class="bwi tw-ml-2" [ngClass]="icon"></i>
</button> </button>
`, `,
standalone: true,
imports: [NgClass],
}) })
export class SortableComponent implements OnInit { export class SortableComponent implements OnInit {
/** /**

View File

@ -1,5 +1,12 @@
// FIXME: Update this file to be type safe and remove this and next line // FIXME: Update this file to be type safe and remove this and next line
// @ts-strict-ignore // @ts-strict-ignore
import {
CdkVirtualScrollViewport,
CdkVirtualScrollableWindow,
CdkFixedSizeVirtualScroll,
CdkVirtualForOf,
} from "@angular/cdk/scrolling";
import { CommonModule } from "@angular/common";
import { import {
AfterContentChecked, AfterContentChecked,
Component, Component,
@ -14,6 +21,7 @@ import {
TrackByFunction, TrackByFunction,
} from "@angular/core"; } from "@angular/core";
import { RowDirective } from "./row.directive";
import { TableComponent } from "./table.component"; import { TableComponent } from "./table.component";
/** /**
@ -42,6 +50,15 @@ export class BitRowDef {
selector: "bit-table-scroll", selector: "bit-table-scroll",
templateUrl: "./table-scroll.component.html", templateUrl: "./table-scroll.component.html",
providers: [{ provide: TableComponent, useExisting: TableScrollComponent }], providers: [{ provide: TableComponent, useExisting: TableScrollComponent }],
standalone: true,
imports: [
CommonModule,
CdkVirtualScrollViewport,
CdkVirtualScrollableWindow,
CdkFixedSizeVirtualScroll,
CdkVirtualForOf,
RowDirective,
],
}) })
export class TableScrollComponent export class TableScrollComponent
extends TableComponent extends TableComponent

View File

@ -1,6 +1,7 @@
// FIXME: Update this file to be type safe and remove this and next line // FIXME: Update this file to be type safe and remove this and next line
// @ts-strict-ignore // @ts-strict-ignore
import { isDataSource } from "@angular/cdk/collections"; import { isDataSource } from "@angular/cdk/collections";
import { CommonModule } from "@angular/common";
import { import {
AfterContentChecked, AfterContentChecked,
Component, Component,
@ -16,6 +17,7 @@ import { TableDataSource } from "./table-data-source";
@Directive({ @Directive({
selector: "ng-template[body]", selector: "ng-template[body]",
standalone: true,
}) })
export class TableBodyDirective { export class TableBodyDirective {
// eslint-disable-next-line @typescript-eslint/explicit-member-accessibility // eslint-disable-next-line @typescript-eslint/explicit-member-accessibility
@ -25,6 +27,8 @@ export class TableBodyDirective {
@Component({ @Component({
selector: "bit-table", selector: "bit-table",
templateUrl: "./table.component.html", templateUrl: "./table.component.html",
standalone: true,
imports: [CommonModule],
}) })
export class TableComponent implements OnDestroy, AfterContentChecked { export class TableComponent implements OnDestroy, AfterContentChecked {
@Input() dataSource: TableDataSource<any>; @Input() dataSource: TableDataSource<any>;

View File

@ -9,8 +9,10 @@ import { BitRowDef, TableScrollComponent } from "./table-scroll.component";
import { TableBodyDirective, TableComponent } from "./table.component"; import { TableBodyDirective, TableComponent } from "./table.component";
@NgModule({ @NgModule({
imports: [CommonModule, ScrollingModule, BitRowDef], imports: [
declarations: [ CommonModule,
ScrollingModule,
BitRowDef,
CellDirective, CellDirective,
RowDirective, RowDirective,
SortableComponent, SortableComponent,

View File

@ -10,5 +10,6 @@ import { Component } from "@angular/core";
"tw-h-16 tw-pl-4 tw-bg-background-alt tw-flex tw-items-end tw-border-0 tw-border-b tw-border-solid tw-border-secondary-300", "tw-h-16 tw-pl-4 tw-bg-background-alt tw-flex tw-items-end tw-border-0 tw-border-b tw-border-solid tw-border-secondary-300",
}, },
template: `<ng-content></ng-content>`, template: `<ng-content></ng-content>`,
standalone: true,
}) })
export class TabHeaderComponent {} export class TabHeaderComponent {}

View File

@ -8,5 +8,6 @@ import { Directive } from "@angular/core";
host: { host: {
class: "tw-inline-flex tw-flex-wrap tw-leading-5", class: "tw-inline-flex tw-flex-wrap tw-leading-5",
}, },
standalone: true,
}) })
export class TabListContainerDirective {} export class TabListContainerDirective {}

View File

@ -7,7 +7,10 @@ import { Directive, ElementRef, HostBinding, Input } from "@angular/core";
* Directive used for styling tab header items for both nav links (anchor tags) * Directive used for styling tab header items for both nav links (anchor tags)
* and content tabs (button tags) * and content tabs (button tags)
*/ */
@Directive({ selector: "[bitTabListItem]" }) @Directive({
selector: "[bitTabListItem]",
standalone: true,
})
export class TabListItemDirective implements FocusableOption { export class TabListItemDirective implements FocusableOption {
@Input() active: boolean; @Input() active: boolean;
@Input() disabled: boolean; @Input() disabled: boolean;

View File

@ -1,11 +1,13 @@
// FIXME: Update this file to be type safe and remove this and next line // FIXME: Update this file to be type safe and remove this and next line
// @ts-strict-ignore // @ts-strict-ignore
import { TemplatePortal } from "@angular/cdk/portal"; import { TemplatePortal, CdkPortalOutlet } from "@angular/cdk/portal";
import { Component, HostBinding, Input } from "@angular/core"; import { Component, HostBinding, Input } from "@angular/core";
@Component({ @Component({
selector: "bit-tab-body", selector: "bit-tab-body",
templateUrl: "tab-body.component.html", templateUrl: "tab-body.component.html",
standalone: true,
imports: [CdkPortalOutlet],
}) })
export class TabBodyComponent { export class TabBodyComponent {
private _firstRender: boolean; private _firstRender: boolean;

View File

@ -2,6 +2,7 @@
// @ts-strict-ignore // @ts-strict-ignore
import { FocusKeyManager } from "@angular/cdk/a11y"; import { FocusKeyManager } from "@angular/cdk/a11y";
import { coerceNumberProperty } from "@angular/cdk/coercion"; import { coerceNumberProperty } from "@angular/cdk/coercion";
import { CommonModule } from "@angular/common";
import { import {
AfterContentChecked, AfterContentChecked,
AfterContentInit, AfterContentInit,
@ -17,8 +18,11 @@ import {
} from "@angular/core"; } from "@angular/core";
import { Subject, takeUntil } from "rxjs"; import { Subject, takeUntil } from "rxjs";
import { TabHeaderComponent } from "../shared/tab-header.component";
import { TabListContainerDirective } from "../shared/tab-list-container.directive";
import { TabListItemDirective } from "../shared/tab-list-item.directive"; import { TabListItemDirective } from "../shared/tab-list-item.directive";
import { TabBodyComponent } from "./tab-body.component";
import { TabComponent } from "./tab.component"; import { TabComponent } from "./tab.component";
/** Used to generate unique ID's for each tab component */ /** Used to generate unique ID's for each tab component */
@ -27,6 +31,14 @@ let nextId = 0;
@Component({ @Component({
selector: "bit-tab-group", selector: "bit-tab-group",
templateUrl: "./tab-group.component.html", templateUrl: "./tab-group.component.html",
standalone: true,
imports: [
CommonModule,
TabHeaderComponent,
TabListContainerDirective,
TabListItemDirective,
TabBodyComponent,
],
}) })
export class TabGroupComponent export class TabGroupComponent
implements AfterContentChecked, AfterContentInit, AfterViewInit, OnDestroy implements AfterContentChecked, AfterContentInit, AfterViewInit, OnDestroy

View File

@ -16,6 +16,7 @@ import { Directive, TemplateRef } from "@angular/core";
*/ */
@Directive({ @Directive({
selector: "[bitTabLabel]", selector: "[bitTabLabel]",
standalone: true,
}) })
export class TabLabelDirective { export class TabLabelDirective {
constructor(public templateRef: TemplateRef<unknown>) {} constructor(public templateRef: TemplateRef<unknown>) {}

View File

@ -19,6 +19,7 @@ import { TabLabelDirective } from "./tab-label.directive";
host: { host: {
role: "tabpanel", role: "tabpanel",
}, },
standalone: true,
}) })
export class TabComponent implements OnInit { export class TabComponent implements OnInit {
@Input() disabled = false; @Input() disabled = false;

View File

@ -2,7 +2,7 @@
// @ts-strict-ignore // @ts-strict-ignore
import { FocusableOption } from "@angular/cdk/a11y"; import { FocusableOption } from "@angular/cdk/a11y";
import { AfterViewInit, Component, HostListener, Input, OnDestroy, ViewChild } from "@angular/core"; import { AfterViewInit, Component, HostListener, Input, OnDestroy, ViewChild } from "@angular/core";
import { IsActiveMatchOptions, RouterLinkActive } from "@angular/router"; import { IsActiveMatchOptions, RouterLinkActive, RouterModule } from "@angular/router";
import { Subject, takeUntil } from "rxjs"; import { Subject, takeUntil } from "rxjs";
import { TabListItemDirective } from "../shared/tab-list-item.directive"; import { TabListItemDirective } from "../shared/tab-list-item.directive";
@ -12,6 +12,8 @@ import { TabNavBarComponent } from "./tab-nav-bar.component";
@Component({ @Component({
selector: "bit-tab-link", selector: "bit-tab-link",
templateUrl: "tab-link.component.html", templateUrl: "tab-link.component.html",
standalone: true,
imports: [TabListItemDirective, RouterModule],
}) })
export class TabLinkComponent implements FocusableOption, AfterViewInit, OnDestroy { export class TabLinkComponent implements FocusableOption, AfterViewInit, OnDestroy {
private destroy$ = new Subject<void>(); private destroy$ = new Subject<void>();

View File

@ -10,6 +10,9 @@ import {
QueryList, QueryList,
} from "@angular/core"; } from "@angular/core";
import { TabHeaderComponent } from "../shared/tab-header.component";
import { TabListContainerDirective } from "../shared/tab-list-container.directive";
import { TabLinkComponent } from "./tab-link.component"; import { TabLinkComponent } from "./tab-link.component";
@Component({ @Component({
@ -18,6 +21,8 @@ import { TabLinkComponent } from "./tab-link.component";
host: { host: {
class: "tw-block", class: "tw-block",
}, },
standalone: true,
imports: [TabHeaderComponent, TabListContainerDirective],
}) })
export class TabNavBarComponent implements AfterContentInit { export class TabNavBarComponent implements AfterContentInit {
@ContentChildren(forwardRef(() => TabLinkComponent)) tabLabels: QueryList<TabLinkComponent>; @ContentChildren(forwardRef(() => TabLinkComponent)) tabLabels: QueryList<TabLinkComponent>;

View File

@ -1,11 +1,6 @@
import { PortalModule } from "@angular/cdk/portal";
import { CommonModule } from "@angular/common"; import { CommonModule } from "@angular/common";
import { NgModule } from "@angular/core"; import { NgModule } from "@angular/core";
import { RouterModule } from "@angular/router";
import { TabHeaderComponent } from "./shared/tab-header.component";
import { TabListContainerDirective } from "./shared/tab-list-container.directive";
import { TabListItemDirective } from "./shared/tab-list-item.directive";
import { TabBodyComponent } from "./tab-group/tab-body.component"; import { TabBodyComponent } from "./tab-group/tab-body.component";
import { TabGroupComponent } from "./tab-group/tab-group.component"; import { TabGroupComponent } from "./tab-group/tab-group.component";
import { TabLabelDirective } from "./tab-group/tab-label.directive"; import { TabLabelDirective } from "./tab-group/tab-label.directive";
@ -14,7 +9,15 @@ import { TabLinkComponent } from "./tab-nav-bar/tab-link.component";
import { TabNavBarComponent } from "./tab-nav-bar/tab-nav-bar.component"; import { TabNavBarComponent } from "./tab-nav-bar/tab-nav-bar.component";
@NgModule({ @NgModule({
imports: [CommonModule, RouterModule, PortalModule], imports: [
CommonModule,
TabGroupComponent,
TabComponent,
TabLabelDirective,
TabNavBarComponent,
TabLinkComponent,
TabBodyComponent,
],
exports: [ exports: [
TabGroupComponent, TabGroupComponent,
TabComponent, TabComponent,
@ -22,16 +25,5 @@ import { TabNavBarComponent } from "./tab-nav-bar/tab-nav-bar.component";
TabNavBarComponent, TabNavBarComponent,
TabLinkComponent, TabLinkComponent,
], ],
declarations: [
TabGroupComponent,
TabComponent,
TabLabelDirective,
TabListContainerDirective,
TabListItemDirective,
TabHeaderComponent,
TabNavBarComponent,
TabLinkComponent,
TabBodyComponent,
],
}) })
export class TabsModule {} export class TabsModule {}

View File

@ -1,13 +1,10 @@
import { CommonModule } from "@angular/common";
import { ModuleWithProviders, NgModule } from "@angular/core"; import { ModuleWithProviders, NgModule } from "@angular/core";
import { DefaultNoComponentGlobalConfig, GlobalConfig, TOAST_CONFIG } from "ngx-toastr"; import { DefaultNoComponentGlobalConfig, GlobalConfig, TOAST_CONFIG } from "ngx-toastr";
import { ToastComponent } from "./toast.component";
import { BitwardenToastrComponent } from "./toastr.component"; import { BitwardenToastrComponent } from "./toastr.component";
@NgModule({ @NgModule({
imports: [CommonModule, ToastComponent], imports: [BitwardenToastrComponent],
declarations: [BitwardenToastrComponent],
exports: [BitwardenToastrComponent], exports: [BitwardenToastrComponent],
}) })
export class ToastModule { export class ToastModule {

View File

@ -2,6 +2,8 @@ import { animate, state, style, transition, trigger } from "@angular/animations"
import { Component } from "@angular/core"; import { Component } from "@angular/core";
import { Toast as BaseToastrComponent } from "ngx-toastr"; import { Toast as BaseToastrComponent } from "ngx-toastr";
import { ToastComponent } from "./toast.component";
@Component({ @Component({
template: ` template: `
<bit-toast <bit-toast
@ -22,5 +24,7 @@ import { Toast as BaseToastrComponent } from "ngx-toastr";
]), ]),
], ],
preserveWhitespaces: false, preserveWhitespaces: false,
standalone: true,
imports: [ToastComponent],
}) })
export class BitwardenToastrComponent extends BaseToastrComponent {} export class BitwardenToastrComponent extends BaseToastrComponent {}

View File

@ -13,6 +13,7 @@ let nextId = 0;
selector: "bit-toggle-group", selector: "bit-toggle-group",
templateUrl: "./toggle-group.component.html", templateUrl: "./toggle-group.component.html",
preserveWhitespaces: false, preserveWhitespaces: false,
standalone: true,
}) })
export class ToggleGroupComponent<TValue = unknown> { export class ToggleGroupComponent<TValue = unknown> {
private id = nextId++; private id = nextId++;

View File

@ -1,14 +1,10 @@
import { CommonModule } from "@angular/common";
import { NgModule } from "@angular/core"; import { NgModule } from "@angular/core";
import { BadgeModule } from "../badge";
import { ToggleGroupComponent } from "./toggle-group.component"; import { ToggleGroupComponent } from "./toggle-group.component";
import { ToggleComponent } from "./toggle.component"; import { ToggleComponent } from "./toggle.component";
@NgModule({ @NgModule({
imports: [CommonModule, BadgeModule], imports: [ToggleGroupComponent, ToggleComponent],
exports: [ToggleGroupComponent, ToggleComponent], exports: [ToggleGroupComponent, ToggleComponent],
declarations: [ToggleGroupComponent, ToggleComponent],
}) })
export class ToggleGroupModule {} export class ToggleGroupModule {}

View File

@ -1,5 +1,6 @@
// FIXME: Update this file to be type safe and remove this and next line // FIXME: Update this file to be type safe and remove this and next line
// @ts-strict-ignore // @ts-strict-ignore
import { NgClass } from "@angular/common";
import { import {
AfterContentChecked, AfterContentChecked,
AfterViewInit, AfterViewInit,
@ -19,6 +20,8 @@ let nextId = 0;
selector: "bit-toggle", selector: "bit-toggle",
templateUrl: "./toggle.component.html", templateUrl: "./toggle.component.html",
preserveWhitespaces: false, preserveWhitespaces: false,
standalone: true,
imports: [NgClass],
}) })
export class ToggleComponent<TValue> implements AfterContentChecked, AfterViewInit { export class ToggleComponent<TValue> implements AfterContentChecked, AfterViewInit {
id = nextId++; id = nextId++;

View File

@ -31,6 +31,7 @@ const margins: Record<TypographyType, string[]> = {
@Directive({ @Directive({
selector: "[bitTypography]", selector: "[bitTypography]",
standalone: true,
}) })
export class TypographyDirective { export class TypographyDirective {
@Input("bitTypography") bitTypography: TypographyType; @Input("bitTypography") bitTypography: TypographyType;

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