From 1463fc804d439c27c10c931cbbc294f19c2da2d4 Mon Sep 17 00:00:00 2001 From: Bernd Schoolmann Date: Thu, 21 Aug 2025 09:45:49 +0200 Subject: [PATCH 01/44] Remove platform keygen service re-exports (#16081) --- libs/common/src/platform/abstractions/key-generation.service.ts | 2 -- libs/common/src/platform/services/key-generation.service.ts | 2 -- 2 files changed, 4 deletions(-) delete mode 100644 libs/common/src/platform/abstractions/key-generation.service.ts delete mode 100644 libs/common/src/platform/services/key-generation.service.ts diff --git a/libs/common/src/platform/abstractions/key-generation.service.ts b/libs/common/src/platform/abstractions/key-generation.service.ts deleted file mode 100644 index 8a230fb5b86..00000000000 --- a/libs/common/src/platform/abstractions/key-generation.service.ts +++ /dev/null @@ -1,2 +0,0 @@ -/** Temporary re-export. This should not be used for new imports */ -export { KeyGenerationService } from "../../key-management/crypto/key-generation/key-generation.service"; diff --git a/libs/common/src/platform/services/key-generation.service.ts b/libs/common/src/platform/services/key-generation.service.ts deleted file mode 100644 index 55d1f96e7df..00000000000 --- a/libs/common/src/platform/services/key-generation.service.ts +++ /dev/null @@ -1,2 +0,0 @@ -/** Temporary re-export. This should not be used for new imports */ -export { DefaultKeyGenerationService as KeyGenerationService } from "../../key-management/crypto/key-generation/default-key-generation.service"; From 89bae6bb74917fca420a91b4bec352eaa0de42c0 Mon Sep 17 00:00:00 2001 From: cyprain-okeke <108260115+cyprain-okeke@users.noreply.github.com> Date: Thu, 21 Aug 2025 10:25:48 +0100 Subject: [PATCH 02/44] Remove the VAT field for family plan (#16098) --- .../trial-initiation/trial-billing-step.component.html | 1 + .../trial-initiation/trial-billing-step.component.ts | 9 +++++++++ 2 files changed, 10 insertions(+) diff --git a/apps/web/src/app/billing/accounts/trial-initiation/trial-billing-step.component.html b/apps/web/src/app/billing/accounts/trial-initiation/trial-billing-step.component.html index 64a9781b7cf..0c1a4270662 100644 --- a/apps/web/src/app/billing/accounts/trial-initiation/trial-billing-step.component.html +++ b/apps/web/src/app/billing/accounts/trial-initiation/trial-billing-step.component.html @@ -51,6 +51,7 @@

{{ "paymentType" | i18n }}

diff --git a/apps/web/src/app/billing/accounts/trial-initiation/trial-billing-step.component.ts b/apps/web/src/app/billing/accounts/trial-initiation/trial-billing-step.component.ts index e13fac41f75..7e25a422477 100644 --- a/apps/web/src/app/billing/accounts/trial-initiation/trial-billing-step.component.ts +++ b/apps/web/src/app/billing/accounts/trial-initiation/trial-billing-step.component.ts @@ -259,6 +259,15 @@ export class TrialBillingStepComponent implements OnInit, OnDestroy { return planType ? this.applicablePlans.find((plan) => plan.type === planType) : null; } + protected get showTaxIdField(): boolean { + switch (this.organizationInfo.type) { + case ProductTierType.Families: + return false; + default: + return true; + } + } + private getBillingInformationFromTaxInfoComponent(): BillingInformation { return { postalCode: this.taxInfoComponent.getTaxInformation()?.postalCode, From 0daa6913d2f6529f489c5127c16215a1270f8fe5 Mon Sep 17 00:00:00 2001 From: Andreas Coroiu Date: Thu, 21 Aug 2025 14:42:56 +0200 Subject: [PATCH 03/44] feat: add ipc service usage docs (#16000) --- libs/common/src/platform/ipc/ipc.service.ts | 123 +++++++++++++++++++- 1 file changed, 120 insertions(+), 3 deletions(-) diff --git a/libs/common/src/platform/ipc/ipc.service.ts b/libs/common/src/platform/ipc/ipc.service.ts index 2fba4380706..0da13c8f3d8 100644 --- a/libs/common/src/platform/ipc/ipc.service.ts +++ b/libs/common/src/platform/ipc/ipc.service.ts @@ -2,25 +2,136 @@ import { Observable, shareReplay } from "rxjs"; import { IpcClient, IncomingMessage, OutgoingMessage } from "@bitwarden/sdk-internal"; +/** + * Entry point for inter-process communication (IPC). + * + * - {@link IpcService.init} should be called in the initialization phase of the client. + * - This service owns the underlying {@link IpcClient} lifecycle and starts it during initialization. + * + * ## Usage + * + * ### Publish / Subscribe + * There are 2 main ways of sending and receiving messages over IPC in TypeScript: + * + * #### 1. TypeScript only JSON-based messages + * This is the simplest form of IPC, where messages are sent as untyped JSON objects. + * This is useful for simple message passing without the need for Rust code. + * + * ```typescript + * // Send a message + * await ipcService.send(OutgoingMessage.new_json_payload({ my: "data" }, "BrowserBackground", "my-topic")); + * + * // Receive messages + * ipcService.messages$.subscribe((message: IncomingMessage) => { + * if (message.topic === "my-topic") { + * const data = incomingMessage.parse_payload_as_json(); + * console.log("Received message:", data); + * } + * }); + * ``` + * + * #### 2. Rust compatible messages + * If you need to send messages that can also be handled by Rust code you can use typed Rust structs + * together with Rust functions to send and receive messages. For more information on typed structs + * refer to `TypedOutgoingMessage` and `TypedIncomingMessage` in the SDK. + * + * For examples on how to use the RPC framework with Rust see the section below. + * + * ### RPC (Request / Response) + * The RPC functionality is more complex than simple message passing and requires Rust code + * to send and receive calls. For this reason, the service also exposes the underlying + * {@link IpcClient} so it can be passed directly into Rust code. + * + * #### Rust code + * ```rust + * #[wasm_bindgen(js_name = ipcRegisterPingHandler)] + * pub async fn ipc_register_ping_handler(ipc_client: &JsIpcClient) { + * ipc_client + * .client + * // See Rust docs for more information on how to implement a handler + * .register_rpc_handler(PingHandler::new()) + * .await; + * } + * + * #[wasm_bindgen(js_name = ipcRequestPing)] + * pub async fn ipc_request_ping( + * ipc_client: &JsIpcClient, + * destination: Endpoint, + * abort_signal: Option, + * ) -> Result { + * ipc_client + * .client + * .request( + * PingRequest, + * destination, + * abort_signal.map(|c| c.to_cancellation_token()), + * ) + * .await + * } + * ``` + * + * #### TypeScript code + * ```typescript + * import { IpcService } from "@bitwarden/common/platform/ipc"; + * import { IpcClient, ipcRegisterPingHandler, ipcRequestPing } from "@bitwarden/sdk-internal"; + * + * class MyService { + * constructor(private ipcService: IpcService) {} + * + * async init() { + * await ipcRegisterPingHandler(this.ipcService.client); + * } + * + * async ping(destination: Endpoint): Promise { + * return await ipcRequestPing(this.ipcService.client, destination); + * } + * } + */ export abstract class IpcService { private _client?: IpcClient; + + /** + * Access to the underlying {@link IpcClient} for advanced/Rust RPC usage. + * + * @throws If the service has not been initialized. + */ get client(): IpcClient { if (!this._client) { - throw new Error("IpcService not initialized"); + throw new Error("IpcService not initialized. Call init() first."); } return this._client; } private _messages$?: Observable; - protected get messages$(): Observable { + + /** + * Hot stream of {@link IncomingMessage} from the IPC layer. + * + * @remarks + * - Uses `shareReplay({ bufferSize: 0, refCount: true })`, so no events are replayed to late subscribers. + * Subscribe early if you must not miss messages. + * + * @throws If the service has not been initialized. + */ + get messages$(): Observable { if (!this._messages$) { - throw new Error("IpcService not initialized"); + throw new Error("IpcService not initialized. Call init() first."); } return this._messages$; } + /** + * Initializes the service and starts the IPC client. + */ abstract init(): Promise; + /** + * Wires the provided {@link IpcClient}, starts it, and sets up the message stream. + * + * - Starts the client via `client.start()`. + * - Subscribes to the client's receive loop and exposes it through {@link messages$}. + * - Implementations may override `init` but should call this helper exactly once. + */ protected async initWithClient(client: IpcClient): Promise { this._client = client; await this._client.start(); @@ -47,6 +158,12 @@ export abstract class IpcService { }).pipe(shareReplay({ bufferSize: 0, refCount: true })); } + /** + * Sends an {@link OutgoingMessage} over IPC. + * + * @param message The message to send. + * @throws If the service is not initialized or the underlying client fails to send. + */ async send(message: OutgoingMessage) { await this.client.send(message); } From b0f46004ff0ef30323ff4a181178eae752543020 Mon Sep 17 00:00:00 2001 From: Bryan Cunningham Date: Thu, 21 Aug 2025 09:14:08 -0400 Subject: [PATCH 04/44] [CL-796] unrevert aria disabled buttons (#15924) * Use aria-disabled for button disabled state * remove import from testing story * use aria-disabled attr on bitLink button * remove unnecessary story attrs * remove disabled attr if on button element * create caprture click util * use caprture click util and fix tests * fix lint errors * fix event type * combine click capture and attr modification * fix lint error. Commit spec changes left out of last commit in error * inject element ref * move aria-disabled styles to common * move disabled logic into util * fix broken async actions stories * fix broken tests asserting disabled attr * have test check for string true vlalue * fix Signal type * fix form-field story import * remove injector left in error * aria-disable icon buttons * update form component css selector to look for aria-disabled buttons * use correct types. pass nativeElement directly * add JSDoc comment for util function * WIP * WIP * inject service in directive * remove console log * remove disabled attr left in error * update comments * remove unnecessary logic * remove :disabled psuedo selector as its apparently not needed * fix event type * coerce disabled attr to boolean * remove duplicate style concat left by conflict resolution * add back buttonStyles default * move reactive logic back to helper * add test to ensure menu button doesn't open when trigger is disabled * remove menu toggle to fix tests * remove disabled menu story * Fix usage of bitLink in verify email component * Update varaible name * no longer pass destroyRef --- .../vault-generator-dialog.component.spec.ts | 18 +++----- .../auth/settings/verify-email.component.html | 3 +- .../web-generator-dialog.component.spec.ts | 18 +++----- .../src/a11y/aria-disable.directive.ts | 12 ++++++ .../aria-disabled-click-capture.service.ts | 30 ++++++++++++++ libs/components/src/a11y/index.ts | 2 + .../src/button/button.component.spec.ts | 14 ++++--- .../components/src/button/button.component.ts | 41 +++++++++++++------ .../src/form-field/form-field.component.html | 2 +- .../src/icon-button/icon-button.component.ts | 29 ++++++++++--- libs/components/src/link/link.directive.ts | 20 ++++++++- .../src/menu/menu.component.spec.ts | 8 ++++ libs/components/src/toast/toast.stories.ts | 1 + .../src/utils/aria-disable-element.ts | 19 +++++++++ libs/components/src/utils/index.ts | 1 + 15 files changed, 165 insertions(+), 53 deletions(-) create mode 100644 libs/components/src/a11y/aria-disable.directive.ts create mode 100644 libs/components/src/a11y/aria-disabled-click-capture.service.ts create mode 100644 libs/components/src/utils/aria-disable-element.ts diff --git a/apps/browser/src/vault/popup/components/vault-v2/vault-generator-dialog/vault-generator-dialog.component.spec.ts b/apps/browser/src/vault/popup/components/vault-v2/vault-generator-dialog/vault-generator-dialog.component.spec.ts index b5d35e2005e..b65138dac3a 100644 --- a/apps/browser/src/vault/popup/components/vault-v2/vault-generator-dialog/vault-generator-dialog.component.spec.ts +++ b/apps/browser/src/vault/popup/components/vault-v2/vault-generator-dialog/vault-generator-dialog.component.spec.ts @@ -76,10 +76,8 @@ describe("VaultGeneratorDialogComponent", () => { component.onValueGenerated("test-password"); fixture.detectChanges(); - const button = fixture.debugElement.query( - By.css("[data-testid='select-button']"), - ).nativeElement; - expect(button.disabled).toBe(false); + const button = fixture.debugElement.query(By.css("[data-testid='select-button']")); + expect(button.attributes["aria-disabled"]).toBe(undefined); }); it("should disable the button if no value has been generated", () => { @@ -90,10 +88,8 @@ describe("VaultGeneratorDialogComponent", () => { generator.algorithmSelected.emit({ useGeneratedValue: "Use Password" } as any); fixture.detectChanges(); - const button = fixture.debugElement.query( - By.css("[data-testid='select-button']"), - ).nativeElement; - expect(button.disabled).toBe(true); + const button = fixture.debugElement.query(By.css("[data-testid='select-button']")); + expect(button.attributes["aria-disabled"]).toBe("true"); }); it("should disable the button if no algorithm is selected", () => { @@ -104,10 +100,8 @@ describe("VaultGeneratorDialogComponent", () => { generator.valueGenerated.emit("test-password"); fixture.detectChanges(); - const button = fixture.debugElement.query( - By.css("[data-testid='select-button']"), - ).nativeElement; - expect(button.disabled).toBe(true); + const button = fixture.debugElement.query(By.css("[data-testid='select-button']")); + expect(button.attributes["aria-disabled"]).toBe("true"); }); it("should update button text when algorithm is selected", () => { diff --git a/apps/web/src/app/auth/settings/verify-email.component.html b/apps/web/src/app/auth/settings/verify-email.component.html index a691c30695c..42a546fc281 100644 --- a/apps/web/src/app/auth/settings/verify-email.component.html +++ b/apps/web/src/app/auth/settings/verify-email.component.html @@ -4,10 +4,9 @@ id="sendBtn" bitLink linkType="secondary" - bitButton type="button" buttonType="unstyled" - [bitAction]="send" + (click)="send()" > {{ "sendEmail" | i18n }} diff --git a/apps/web/src/app/vault/components/web-generator-dialog/web-generator-dialog.component.spec.ts b/apps/web/src/app/vault/components/web-generator-dialog/web-generator-dialog.component.spec.ts index 085a3d0d4b0..afb32738901 100644 --- a/apps/web/src/app/vault/components/web-generator-dialog/web-generator-dialog.component.spec.ts +++ b/apps/web/src/app/vault/components/web-generator-dialog/web-generator-dialog.component.spec.ts @@ -70,10 +70,8 @@ describe("WebVaultGeneratorDialogComponent", () => { generator.valueGenerated.emit("test-password"); fixture.detectChanges(); - const button = fixture.debugElement.query( - By.css("[data-testid='select-button']"), - ).nativeElement; - expect(button.disabled).toBe(false); + const button = fixture.debugElement.query(By.css("[data-testid='select-button']")); + expect(button.attributes["aria-disabled"]).toBe(undefined); }); it("should disable the button if no value has been generated", () => { @@ -84,10 +82,8 @@ describe("WebVaultGeneratorDialogComponent", () => { generator.algorithmSelected.emit({ useGeneratedValue: "Use Password" } as any); fixture.detectChanges(); - const button = fixture.debugElement.query( - By.css("[data-testid='select-button']"), - ).nativeElement; - expect(button.disabled).toBe(true); + const button = fixture.debugElement.query(By.css("[data-testid='select-button']")); + expect(button.attributes["aria-disabled"]).toBe("true"); }); it("should disable the button if no algorithm is selected", () => { @@ -98,10 +94,8 @@ describe("WebVaultGeneratorDialogComponent", () => { generator.valueGenerated.emit("test-password"); fixture.detectChanges(); - const button = fixture.debugElement.query( - By.css("[data-testid='select-button']"), - ).nativeElement; - expect(button.disabled).toBe(true); + const button = fixture.debugElement.query(By.css("[data-testid='select-button']")); + expect(button.attributes["aria-disabled"]).toBe("true"); }); it("should close with selected value when confirmed", () => { diff --git a/libs/components/src/a11y/aria-disable.directive.ts b/libs/components/src/a11y/aria-disable.directive.ts new file mode 100644 index 00000000000..8236e178994 --- /dev/null +++ b/libs/components/src/a11y/aria-disable.directive.ts @@ -0,0 +1,12 @@ +import { Directive, inject } from "@angular/core"; + +import { AriaDisabledClickCaptureService } from "./aria-disabled-click-capture.service"; + +@Directive({ + host: { + "[attr.bit-aria-disable]": "true", + }, +}) +export class AriaDisableDirective { + protected ariaDisabledClickCaptureService = inject(AriaDisabledClickCaptureService); +} diff --git a/libs/components/src/a11y/aria-disabled-click-capture.service.ts b/libs/components/src/a11y/aria-disabled-click-capture.service.ts new file mode 100644 index 00000000000..d828d15c873 --- /dev/null +++ b/libs/components/src/a11y/aria-disabled-click-capture.service.ts @@ -0,0 +1,30 @@ +import { DOCUMENT } from "@angular/common"; +import { Injectable, Inject, NgZone, OnDestroy } from "@angular/core"; + +@Injectable({ providedIn: "root" }) +export class AriaDisabledClickCaptureService implements OnDestroy { + private listener!: (e: MouseEvent | KeyboardEvent) => void; + + constructor( + @Inject(DOCUMENT) private document: Document, + private ngZone: NgZone, + ) { + this.ngZone.runOutsideAngular(() => { + this.listener = (e: MouseEvent | KeyboardEvent) => { + const btn = (e.target as HTMLElement).closest( + '[aria-disabled="true"][bit-aria-disable="true"]', + ); + if (btn) { + e.stopPropagation(); + e.preventDefault(); + return false; + } + }; + this.document.addEventListener("click", this.listener, /* capture */ true); + }); + } + + ngOnDestroy() { + this.document.removeEventListener("click", this.listener, true); + } +} diff --git a/libs/components/src/a11y/index.ts b/libs/components/src/a11y/index.ts index 6090fb65d4e..2a723f14c93 100644 --- a/libs/components/src/a11y/index.ts +++ b/libs/components/src/a11y/index.ts @@ -1 +1,3 @@ export * from "./a11y-title.directive"; +export * from "./aria-disabled-click-capture.service"; +export * from "./aria-disable.directive"; diff --git a/libs/components/src/button/button.component.spec.ts b/libs/components/src/button/button.component.spec.ts index 6ddbc172803..1651b6cf12a 100644 --- a/libs/components/src/button/button.component.spec.ts +++ b/libs/components/src/button/button.component.spec.ts @@ -34,23 +34,25 @@ describe("Button", () => { expect(buttonDebugElement.nativeElement.disabled).toBeFalsy(); }); - it("should be disabled when disabled is true", () => { + it("should be aria-disabled and not html attribute disabled when disabled is true", () => { testAppComponent.disabled = true; fixture.detectChanges(); - - expect(buttonDebugElement.nativeElement.disabled).toBeTruthy(); + expect(buttonDebugElement.attributes["aria-disabled"]).toBe("true"); + expect(buttonDebugElement.nativeElement.disabled).toBeFalsy(); // Anchor tags cannot be disabled. }); - it("should be disabled when attribute disabled is true", () => { - expect(disabledButtonDebugElement.nativeElement.disabled).toBeTruthy(); + it("should be aria-disabled not html attribute disabled when attribute disabled is true", () => { + fixture.detectChanges(); + expect(disabledButtonDebugElement.attributes["aria-disabled"]).toBe("true"); + expect(disabledButtonDebugElement.nativeElement.disabled).toBeFalsy(); }); it("should be disabled when loading is true", () => { testAppComponent.loading = true; fixture.detectChanges(); - expect(buttonDebugElement.nativeElement.disabled).toBeTruthy(); + expect(buttonDebugElement.attributes["aria-disabled"]).toBe("true"); }); }); diff --git a/libs/components/src/button/button.component.ts b/libs/components/src/button/button.component.ts index 635c269bd0f..1dce792c963 100644 --- a/libs/components/src/button/button.component.ts +++ b/libs/components/src/button/button.component.ts @@ -1,9 +1,20 @@ import { NgClass } from "@angular/common"; -import { input, HostBinding, Component, model, computed, booleanAttribute } from "@angular/core"; +import { + input, + HostBinding, + Component, + model, + computed, + booleanAttribute, + inject, + ElementRef, +} from "@angular/core"; import { toObservable, toSignal } from "@angular/core/rxjs-interop"; import { debounce, interval } from "rxjs"; +import { AriaDisableDirective } from "../a11y"; import { ButtonLikeAbstraction, ButtonType, ButtonSize } from "../shared/button-like.abstraction"; +import { ariaDisableElement } from "../utils"; const focusRing = [ "focus-visible:tw-ring-2", @@ -50,9 +61,7 @@ const buttonStyles: Record = { templateUrl: "button.component.html", providers: [{ provide: ButtonLikeAbstraction, useExisting: ButtonComponent }], imports: [NgClass], - host: { - "[attr.disabled]": "disabledAttr()", - }, + hostDirectives: [AriaDisableDirective], }) export class ButtonComponent implements ButtonLikeAbstraction { @HostBinding("class") get classList() { @@ -72,14 +81,15 @@ export class ButtonComponent implements ButtonLikeAbstraction { .concat( this.showDisabledStyles() || this.disabled() ? [ - "disabled:tw-bg-secondary-300", - "disabled:hover:tw-bg-secondary-300", - "disabled:tw-border-secondary-300", - "disabled:hover:tw-border-secondary-300", - "disabled:!tw-text-muted", - "disabled:hover:!tw-text-muted", - "disabled:tw-cursor-not-allowed", - "disabled:hover:tw-no-underline", + "aria-disabled:!tw-bg-secondary-300", + "hover:tw-bg-secondary-300", + "aria-disabled:tw-border-secondary-300", + "hover:tw-border-secondary-300", + "aria-disabled:!tw-text-muted", + "hover:!tw-text-muted", + "aria-disabled:tw-cursor-not-allowed", + "hover:tw-no-underline", + "aria-disabled:tw-pointer-events-none", ] : [], ) @@ -88,7 +98,7 @@ export class ButtonComponent implements ButtonLikeAbstraction { protected disabledAttr = computed(() => { const disabled = this.disabled() != null && this.disabled() !== false; - return disabled || this.loading() ? true : null; + return disabled || this.loading(); }); /** @@ -128,4 +138,9 @@ export class ButtonComponent implements ButtonLikeAbstraction { ); disabled = model(false); + private el = inject(ElementRef); + + constructor() { + ariaDisableElement(this.el.nativeElement, this.disabledAttr); + } } diff --git a/libs/components/src/form-field/form-field.component.html b/libs/components/src/form-field/form-field.component.html index b40e16d4cd4..ae3bad40698 100644 --- a/libs/components/src/form-field/form-field.component.html +++ b/libs/components/src/form-field/form-field.component.html @@ -46,7 +46,7 @@
= { ], imports: [NgClass], host: { - "[attr.disabled]": "disabledAttr()", /** * When the `bitIconButton` input is dynamic from a consumer, Angular doesn't put the * `bitIconButton` attribute into the DOM. We use the attribute as a css selector in @@ -87,6 +97,7 @@ const sizes: Record = { */ "[attr.bitIconButton]": "icon()", }, + hostDirectives: [AriaDisableDirective], }) export class BitIconButtonComponent implements ButtonLikeAbstraction, FocusableElement { readonly icon = model.required({ alias: "bitIconButton" }); @@ -118,7 +129,7 @@ export class BitIconButtonComponent implements ButtonLikeAbstraction, FocusableE .concat(sizes[this.size()]) .concat( this.showDisabledStyles() || this.disabled() - ? ["disabled:tw-opacity-60", "disabled:hover:!tw-bg-transparent"] + ? ["aria-disabled:tw-opacity-60", "aria-disabled:hover:!tw-bg-transparent"] : [], ); } @@ -129,7 +140,7 @@ export class BitIconButtonComponent implements ButtonLikeAbstraction, FocusableE protected disabledAttr = computed(() => { const disabled = this.disabled() != null && this.disabled() !== false; - return disabled || this.loading() ? true : null; + return disabled || this.loading(); }); /** @@ -168,8 +179,14 @@ export class BitIconButtonComponent implements ButtonLikeAbstraction, FocusableE return this.elementRef.nativeElement; } - constructor(private elementRef: ElementRef) { - const originalTitle = this.elementRef.nativeElement.getAttribute("title"); + private elementRef = inject(ElementRef); + + constructor() { + const element = this.elementRef.nativeElement; + + ariaDisableElement(element, this.disabledAttr); + + const originalTitle = element.getAttribute("title"); effect(() => { setA11yTitleAndAriaLabel({ diff --git a/libs/components/src/link/link.directive.ts b/libs/components/src/link/link.directive.ts index f2eb44bc3a4..7c93b185a79 100644 --- a/libs/components/src/link/link.directive.ts +++ b/libs/components/src/link/link.directive.ts @@ -1,4 +1,7 @@ -import { input, HostBinding, Directive } from "@angular/core"; +import { input, HostBinding, Directive, inject, ElementRef, booleanAttribute } from "@angular/core"; + +import { AriaDisableDirective } from "../a11y"; +import { ariaDisableElement } from "../utils"; export type LinkType = "primary" | "secondary" | "contrast" | "light"; @@ -58,6 +61,11 @@ const commonStyles = [ "before:tw-transition", "focus-visible:before:tw-ring-2", "focus-visible:tw-z-10", + "aria-disabled:tw-no-underline", + "aria-disabled:tw-pointer-events-none", + "aria-disabled:!tw-text-secondary-300", + "aria-disabled:hover:!tw-text-secondary-300", + "aria-disabled:hover:tw-no-underline", ]; @Directive() @@ -86,11 +94,21 @@ export class AnchorLinkDirective extends LinkDirective { @Directive({ selector: "button[bitLink]", + hostDirectives: [AriaDisableDirective], }) export class ButtonLinkDirective extends LinkDirective { + private el = inject(ElementRef); + + disabled = input(false, { transform: booleanAttribute }); + @HostBinding("class") get classList() { return ["before:-tw-inset-y-[0.25rem]"] .concat(commonStyles) .concat(linkStyles[this.linkType()] ?? []); } + + constructor() { + super(); + ariaDisableElement(this.el.nativeElement, this.disabled); + } } diff --git a/libs/components/src/menu/menu.component.spec.ts b/libs/components/src/menu/menu.component.spec.ts index c6a54f1afae..3153fd4eb37 100644 --- a/libs/components/src/menu/menu.component.spec.ts +++ b/libs/components/src/menu/menu.component.spec.ts @@ -58,6 +58,14 @@ describe("Menu", () => { expect(getBitMenuPanel()).toBeFalsy(); }); + + it("should not open when the trigger button is disabled", () => { + const buttonDebugElement = fixture.debugElement.query(By.directive(MenuTriggerForDirective)); + buttonDebugElement.nativeElement.setAttribute("disabled", "true"); + (buttonDebugElement.nativeElement as HTMLButtonElement).click(); + + expect(getBitMenuPanel()).toBeFalsy(); + }); }); @Component({ diff --git a/libs/components/src/toast/toast.stories.ts b/libs/components/src/toast/toast.stories.ts index bd2c59a191b..dee31f1d6ac 100644 --- a/libs/components/src/toast/toast.stories.ts +++ b/libs/components/src/toast/toast.stories.ts @@ -20,6 +20,7 @@ const toastServiceExampleTemplate = ` @Component({ selector: "toast-service-example", template: toastServiceExampleTemplate, + imports: [ButtonModule], }) export class ToastServiceExampleComponent { @Input() diff --git a/libs/components/src/utils/aria-disable-element.ts b/libs/components/src/utils/aria-disable-element.ts new file mode 100644 index 00000000000..0f7fb4ca205 --- /dev/null +++ b/libs/components/src/utils/aria-disable-element.ts @@ -0,0 +1,19 @@ +import { Signal } from "@angular/core"; +import { toObservable, takeUntilDestroyed } from "@angular/core/rxjs-interop"; + +/** + * a11y helper util used to `aria-disable` elements as opposed to using the HTML `disabled` attr. + * - Removes HTML `disabled` attr and replaces it with `aria-disabled="true"` + */ +export function ariaDisableElement(el: HTMLElement, disabled: Signal) { + toObservable(disabled) + .pipe(takeUntilDestroyed()) + .subscribe((isDisabled) => { + if (isDisabled) { + el.removeAttribute("disabled"); + el.setAttribute("aria-disabled", "true"); + } else { + el.removeAttribute("aria-disabled"); + } + }); +} diff --git a/libs/components/src/utils/index.ts b/libs/components/src/utils/index.ts index afadd6b3b41..91fa71cf0e0 100644 --- a/libs/components/src/utils/index.ts +++ b/libs/components/src/utils/index.ts @@ -1,2 +1,3 @@ +export * from "./aria-disable-element"; export * from "./function-to-observable"; export * from "./i18n-mock.service"; From f07518084f0f34a578565f7b86f5d73a3a9b1024 Mon Sep 17 00:00:00 2001 From: Kyle Denney <4227399+kdenney@users.noreply.github.com> Date: Thu, 21 Aug 2025 09:36:57 -0500 Subject: [PATCH 05/44] [PM-24554] remove code for feature flag (#16092) --- .../complete-trial-initiation.component.ts | 14 ++++---------- libs/common/src/enums/feature-flag.enum.ts | 2 -- 2 files changed, 4 insertions(+), 12 deletions(-) diff --git a/apps/web/src/app/billing/trial-initiation/complete-trial-initiation/complete-trial-initiation.component.ts b/apps/web/src/app/billing/trial-initiation/complete-trial-initiation/complete-trial-initiation.component.ts index ce02ee8715a..799577fc7c4 100644 --- a/apps/web/src/app/billing/trial-initiation/complete-trial-initiation/complete-trial-initiation.component.ts +++ b/apps/web/src/app/billing/trial-initiation/complete-trial-initiation/complete-trial-initiation.component.ts @@ -4,7 +4,7 @@ import { StepperSelectionEvent } from "@angular/cdk/stepper"; import { Component, OnDestroy, OnInit, ViewChild } from "@angular/core"; import { FormBuilder, Validators } from "@angular/forms"; import { ActivatedRoute, Router } from "@angular/router"; -import { combineLatest, firstValueFrom, map, Subject, switchMap, takeUntil } from "rxjs"; +import { firstValueFrom, map, Subject, switchMap, takeUntil } from "rxjs"; import { InputPasswordFlow, @@ -101,9 +101,6 @@ export class CompleteTrialInitiationComponent implements OnInit, OnDestroy { protected trialPaymentOptional$ = this.configService.getFeatureFlag$( FeatureFlag.TrialPaymentOptional, ); - protected allowTrialLengthZero$ = this.configService.getFeatureFlag$( - FeatureFlag.AllowTrialLengthZero, - ); constructor( protected router: Router, @@ -337,14 +334,11 @@ export class CompleteTrialInitiationComponent implements OnInit, OnDestroy { return this.productTier; } - readonly showBillingStep$ = combineLatest([ - this.trialPaymentOptional$, - this.allowTrialLengthZero$, - ]).pipe( - map(([trialPaymentOptional, allowTrialLengthZero]) => { + readonly showBillingStep$ = this.trialPaymentOptional$.pipe( + map((trialPaymentOptional) => { return ( (!trialPaymentOptional && !this.isSecretsManagerFree) || - (trialPaymentOptional && allowTrialLengthZero && this.trialLength === 0) + (trialPaymentOptional && this.trialLength === 0) ); }), ); diff --git a/libs/common/src/enums/feature-flag.enum.ts b/libs/common/src/enums/feature-flag.enum.ts index 81cc3b305dc..a36eb68dc71 100644 --- a/libs/common/src/enums/feature-flag.enum.ts +++ b/libs/common/src/enums/feature-flag.enum.ts @@ -28,7 +28,6 @@ export enum FeatureFlag { PM12276_BreadcrumbEventLogs = "pm-12276-breadcrumbing-for-business-features", PM17772_AdminInitiatedSponsorships = "pm-17772-admin-initiated-sponsorships", UseOrganizationWarningsService = "use-organization-warnings-service", - AllowTrialLengthZero = "pm-20322-allow-trial-length-0", PM21881_ManagePaymentDetailsOutsideCheckout = "pm-21881-manage-payment-details-outside-checkout", PM21821_ProviderPortalTakeover = "pm-21821-provider-portal-takeover", PM22415_TaxIDWarnings = "pm-22415-tax-id-warnings", @@ -104,7 +103,6 @@ export const DefaultFeatureFlagValue = { [FeatureFlag.PM12276_BreadcrumbEventLogs]: FALSE, [FeatureFlag.PM17772_AdminInitiatedSponsorships]: FALSE, [FeatureFlag.UseOrganizationWarningsService]: FALSE, - [FeatureFlag.AllowTrialLengthZero]: FALSE, [FeatureFlag.PM21881_ManagePaymentDetailsOutsideCheckout]: FALSE, [FeatureFlag.PM21821_ProviderPortalTakeover]: FALSE, [FeatureFlag.PM22415_TaxIDWarnings]: FALSE, From 805b6fe7aaf812fad0f9063023011223c01a85fc Mon Sep 17 00:00:00 2001 From: Vicki League Date: Thu, 21 Aug 2025 12:35:59 -0400 Subject: [PATCH 06/44] [CL-573] Move all svg icons to new libs/assets (#16020) * create libs/assets * treeshake lib and filter out non-icons from icon story * update docs * fix icon colors in browser and desktop * better name for vault icon * move illustrations --- .github/CODEOWNERS | 1 + .../autofill/popup/fido2/fido2.component.ts | 4 +- .../popup/layout/popup-layout.stories.ts | 27 ++++--- .../layout/popup-tab-navigation.component.ts | 3 +- apps/browser/src/popup/app-routing.module.ts | 19 ++--- ...extension-anon-layout-wrapper.component.ts | 5 +- .../extension-anon-layout-wrapper.stories.ts | 12 ++-- apps/browser/src/popup/tabs-v2.component.ts | 27 ++++--- .../send-created/send-created.component.ts | 2 +- .../tools/popup/send-v2/send-v2.component.ts | 6 +- .../intro-carousel.component.ts | 11 +-- .../components/vault-v2/vault-v2.component.ts | 10 +-- .../popup/settings/folders-v2.component.ts | 5 +- .../vault/popup/settings/trash.component.ts | 4 +- apps/browser/tailwind.config.js | 1 + apps/desktop/src/app/app-routing.module.ts | 21 +++--- apps/desktop/tailwind.config.js | 1 + apps/web/src/app/admin-console/icons/index.ts | 1 - .../collection-access-restricted.component.ts | 10 +-- .../collections/vault.component.ts | 4 +- .../layouts/organization-layout.component.ts | 3 +- .../accept-family-sponsorship.component.ts | 5 +- .../login-via-webauthn.component.ts | 8 ++- .../create-credential-dialog.component.ts | 9 +-- .../create-passkey-failed.icon.ts | 28 -------- ...ganization-subscription-cloud.component.ts | 2 +- .../subscription-hidden.component.ts | 25 +------ .../billing/shared/sm-subscribe.component.ts | 5 +- apps/web/src/app/dirt/reports/reports.ts | 17 +++-- .../reports/shared/models/report-entry.ts | 2 +- .../report-card/report-card.component.ts | 2 +- .../src/app/layouts/password-manager-logo.ts | 5 -- .../src/app/layouts/user-layout.component.ts | 3 +- apps/web/src/app/oss-routing.module.ts | 29 ++++---- .../send/send-access/access.component.ts | 2 +- .../src/app/tools/send/send-access/routes.ts | 2 +- apps/web/src/app/tools/send/send.component.ts | 2 +- .../manually-open-extension.component.ts | 4 +- .../setup-extension.component.spec.ts | 4 +- .../setup-extension.component.ts | 6 +- .../vault/individual-vault/vault.component.ts | 5 +- apps/web/tailwind.config.js | 1 + .../device-approvals.component.ts | 2 +- .../manage/accept-provider.component.ts | 4 +- .../providers/providers-layout.component.ts | 8 +-- .../setup/setup-provider.component.ts | 4 +- .../providers/clients/no-clients.component.ts | 23 +----- .../setup/setup-business-unit.component.ts | 4 +- .../all-applications.component.ts | 4 +- .../critical-applications.component.ts | 11 +-- .../layout/navigation.component.ts | 2 +- .../shared/org-suspended.component.ts | 4 +- .../components/two-factor-icon.component.ts | 5 +- .../src/auth/icons/create-passkey.icon.ts | 26 ------- .../change-password.component.ts | 6 +- .../set-initial-password.component.ts | 5 +- .../invoices/no-invoices.component.ts | 26 +------ libs/assets/README.md | 16 +++++ libs/assets/eslint.config.mjs | 3 + libs/assets/jest.config.js | 10 +++ libs/assets/package.json | 15 ++++ libs/assets/project.json | 33 +++++++++ .../src/svg/icon-service.spec.ts} | 4 +- .../src/svg/icon-service.ts} | 0 libs/assets/src/svg/index.ts | 2 + .../src/svg/svgs}/active-send.icon.ts | 2 +- .../src/svg/svgs}/admin-console.ts | 2 +- .../svg/svgs/background-left-illustration.ts} | 4 +- .../svgs/background-right-illustration.ts} | 4 +- .../src/svg/svgs}/bitwarden-icon.ts | 2 +- .../src/svg/svgs}/bitwarden-logo.icon.ts | 2 +- .../src/svg/svgs}/browser-extension.ts | 2 +- .../src/svg/svgs}/business-unit-portal.ts | 2 +- .../src/svg/svgs}/carousel-icon.ts | 2 +- .../svg/svgs}/create-passkey-failed.icon.ts | 2 +- .../src/svg/svgs}/create-passkey.icon.ts | 2 +- .../src/svg/svgs}/deactivated-org.ts | 2 +- .../src/svg/svgs}/device-verification.icon.ts | 4 +- .../src/svg/svgs}/devices.icon.ts | 4 +- .../assets/src/svg/svgs}/devices.ts | 2 +- .../src/svg/svgs}/email.icon.ts | 3 +- .../src/svg/svgs}/empty-trash.ts | 2 +- .../src/svg/svgs}/expired-send.icon.ts | 2 +- .../svgs}/extension-bitwarden-logo.icon.ts | 2 +- libs/assets/src/svg/svgs/gear.ts | 20 ++++++ .../src/svg/svgs}/generator.ts | 2 +- libs/assets/src/svg/svgs/index.ts | 72 +++++++++++++++++++ .../src/svg/svgs}/lock.icon.ts | 2 +- .../src/svg/svgs}/login-cards.ts | 2 +- .../src/svg/svgs}/no-access.ts | 2 +- .../src/svg/svgs}/no-credentials.icon.ts | 2 +- .../src/svg/svgs}/no-folders.ts | 2 +- .../src/svg/svgs}/no-results.ts | 2 +- .../src/svg/svgs}/no-send.icon.ts | 2 +- libs/assets/src/svg/svgs/partner-trust.ts | 23 ++++++ .../icons => assets/src/svg/svgs}/party.ts | 2 +- .../src/svg/svgs}/password-manager.ts | 2 +- .../src/svg/svgs}/provider-portal.ts | 2 +- .../src/svg/svgs}/recovery.icon.ts | 2 +- .../svgs}/registration-check-email.icon.ts | 2 +- .../svgs}/registration-expired-link.icon.ts | 4 +- .../svg/svgs}/registration-lock-alt.icon.ts | 4 +- .../svg/svgs}/registration-user-add.icon.ts | 4 +- .../src/svg/svgs}/report-breach.icon.ts | 2 +- .../svgs}/report-exposed-passwords.icon.ts | 2 +- .../svgs}/report-inactive-two-factor.icon.ts | 2 +- .../svg/svgs}/report-member-access.icon.ts | 2 +- .../svg/svgs}/report-reused-passwords.icon.ts | 2 +- .../svgs}/report-unsecured-websites.icon.ts | 2 +- .../svg/svgs}/report-weak-passwords.icon.ts | 2 +- libs/assets/src/svg/svgs/restricted-view.ts | 6 ++ .../icons => assets/src/svg/svgs}/search.ts | 2 +- .../src/svg/svgs/secrets-manager-alt.ts | 4 +- .../src/svg/svgs}/secrets-manager.ts | 2 +- .../src/svg/svgs}/secure-devices.ts | 2 +- .../src/svg/svgs}/secure-user.ts | 2 +- .../src/svg/svgs}/security-handshake.ts | 2 +- .../icons => assets/src/svg/svgs}/security.ts | 2 +- .../icons => assets/src/svg/svgs}/send.ts | 2 +- .../icons => assets/src/svg/svgs}/settings.ts | 2 +- .../src/svg/svgs}/shield.ts | 2 +- .../src/svg/svgs}/sso-key.icon.ts | 4 +- .../src/svg/svgs/subscription-hidden.ts | 4 +- .../src/svg/svgs}/totp.icon.ts | 2 +- .../two-factor-auth-authenticator.icon.ts | 4 +- .../src/svg/svgs}/two-factor-auth-duo.icon.ts | 4 +- .../svg/svgs}/two-factor-auth-email.icon.ts | 4 +- .../two-factor-auth-security-key.icon.ts | 4 +- .../svgs}/two-factor-auth-webauthn.icon.ts | 4 +- .../svg/svgs}/two-factor-auth-yubico.icon.ts | 4 +- .../src/svg/svgs}/two-factor-timeout.icon.ts | 4 +- .../src/svg/svgs}/user-lock.icon.ts | 4 +- ...erification-biometrics-fingerprint.icon.ts | 4 +- .../src/svg/svgs/vault-open.ts} | 4 +- .../src/svg/svgs}/vault.icon.ts | 4 +- .../icons => assets/src/svg/svgs}/vault.ts | 2 +- .../src/svg/svgs}/wave.icon.ts | 4 +- .../src/svg/svgs}/webauthn.icon.ts | 2 +- libs/assets/tsconfig.eslint.json | 6 ++ libs/assets/tsconfig.json | 13 ++++ libs/assets/tsconfig.lib.json | 10 +++ libs/assets/tsconfig.spec.json | 10 +++ libs/auth/src/angular/icons/index.ts | 11 --- .../angular/icons/two-factor-auth/index.ts | 6 -- libs/auth/src/angular/index.ts | 3 - .../auth/src/angular/login/login.component.ts | 3 +- .../registration-link-expired.component.ts | 3 +- .../registration-start.component.ts | 5 +- .../two-factor-auth.component.ts | 15 ++-- .../two-factor-options.component.ts | 15 ++-- .../user-verification-form-input.component.ts | 3 +- .../anon-layout-wrapper.component.ts | 2 +- .../anon-layout-wrapper.stories.ts | 2 +- .../src/anon-layout/anon-layout.component.ts | 17 +++-- .../src/anon-layout/anon-layout.mdx | 9 ++- .../src/anon-layout/anon-layout.stories.ts | 3 +- .../src/anon-layout/illustrations/index.ts | 2 - libs/components/src/icon/icon.component.ts | 2 +- .../src/icon/icon.components.spec.ts | 3 +- libs/components/src/icon/icon.mdx | 9 +-- libs/components/src/icon/icon.stories.ts | 13 ++-- libs/components/src/icon/icons/index.ts | 12 ---- libs/components/src/icon/index.ts | 9 --- .../src/icon/logos/bitwarden/index.ts | 6 -- libs/components/src/icon/logos/index.ts | 1 - .../src/navigation/nav-logo.component.ts | 4 +- .../src/no-items/no-items.component.ts | 5 +- .../kitchen-sink/kitchen-sink.stories.ts | 2 +- libs/components/tailwind.config.base.js | 1 + libs/components/tailwind.config.js | 1 + .../src/empty-credential-history.component.ts | 3 +- libs/tools/send/send-ui/src/icons/index.ts | 3 - libs/tools/send/send-ui/src/index.ts | 1 - .../carousel-button.component.ts | 2 +- libs/vault/src/icons/index.ts | 11 --- libs/vault/src/index.ts | 2 - package-lock.json | 9 +++ tailwind.config.js | 1 + tsconfig.base.json | 2 + 179 files changed, 579 insertions(+), 525 deletions(-) delete mode 100644 apps/web/src/app/admin-console/icons/index.ts delete mode 100644 apps/web/src/app/auth/settings/webauthn-login-settings/create-credential-dialog/create-passkey-failed.icon.ts delete mode 100644 apps/web/src/app/layouts/password-manager-logo.ts delete mode 100644 libs/angular/src/auth/icons/create-passkey.icon.ts create mode 100644 libs/assets/README.md create mode 100644 libs/assets/eslint.config.mjs create mode 100644 libs/assets/jest.config.js create mode 100644 libs/assets/package.json create mode 100644 libs/assets/project.json rename libs/{components/src/icon/icon.spec.ts => assets/src/svg/icon-service.spec.ts} (94%) rename libs/{components/src/icon/icon.ts => assets/src/svg/icon-service.ts} (100%) create mode 100644 libs/assets/src/svg/index.ts rename libs/{tools/send/send-ui/src/icons => assets/src/svg/svgs}/active-send.icon.ts (98%) rename libs/{components/src/icon/logos/bitwarden => assets/src/svg/svgs}/admin-console.ts (99%) rename libs/{components/src/anon-layout/illustrations/left-illustration.ts => assets/src/svg/svgs/background-left-illustration.ts} (99%) rename libs/{components/src/anon-layout/illustrations/right-illustration.ts => assets/src/svg/svgs/background-right-illustration.ts} (99%) rename libs/{vault/src/icons => assets/src/svg/svgs}/bitwarden-icon.ts (97%) rename libs/{components/src/icon/icons => assets/src/svg/svgs}/bitwarden-logo.icon.ts (99%) rename libs/{vault/src/icons => assets/src/svg/svgs}/browser-extension.ts (97%) rename libs/{components/src/icon/logos/bitwarden => assets/src/svg/svgs}/business-unit-portal.ts (99%) rename libs/{vault/src/components/carousel/carousel-icons => assets/src/svg/svgs}/carousel-icon.ts (85%) rename libs/{angular/src/auth/icons => assets/src/svg/svgs}/create-passkey-failed.icon.ts (98%) rename {apps/web/src/app/auth/settings/webauthn-login-settings/create-credential-dialog => libs/assets/src/svg/svgs}/create-passkey.icon.ts (98%) rename libs/{vault/src/icons => assets/src/svg/svgs}/deactivated-org.ts (98%) rename libs/{auth/src/angular/icons => assets/src/svg/svgs}/device-verification.icon.ts (89%) rename libs/{auth/src/angular/icons => assets/src/svg/svgs}/devices.icon.ts (91%) rename {apps/web/src/app/admin-console/icons => libs/assets/src/svg/svgs}/devices.ts (98%) rename libs/{angular/src/auth/icons => assets/src/svg/svgs}/email.icon.ts (92%) rename libs/{vault/src/icons => assets/src/svg/svgs}/empty-trash.ts (99%) rename libs/{tools/send/send-ui/src/icons => assets/src/svg/svgs}/expired-send.icon.ts (98%) rename libs/{components/src/icon/icons => assets/src/svg/svgs}/extension-bitwarden-logo.icon.ts (99%) create mode 100644 libs/assets/src/svg/svgs/gear.ts rename libs/{components/src/icon/icons => assets/src/svg/svgs}/generator.ts (98%) create mode 100644 libs/assets/src/svg/svgs/index.ts rename libs/{components/src/icon/icons => assets/src/svg/svgs}/lock.icon.ts (98%) rename libs/{vault/src/icons => assets/src/svg/svgs}/login-cards.ts (98%) rename libs/{components/src/icon/icons => assets/src/svg/svgs}/no-access.ts (96%) rename libs/{tools/generator/components/src/icons => assets/src/svg/svgs}/no-credentials.icon.ts (99%) rename libs/{vault/src/icons => assets/src/svg/svgs}/no-folders.ts (98%) rename libs/{components/src/icon/icons => assets/src/svg/svgs}/no-results.ts (98%) rename libs/{tools/send/send-ui/src/icons => assets/src/svg/svgs}/no-send.icon.ts (97%) create mode 100644 libs/assets/src/svg/svgs/partner-trust.ts rename libs/{vault/src/icons => assets/src/svg/svgs}/party.ts (99%) rename libs/{components/src/icon/logos/bitwarden => assets/src/svg/svgs}/password-manager.ts (99%) rename libs/{components/src/icon/logos/bitwarden => assets/src/svg/svgs}/provider-portal.ts (99%) rename libs/{angular/src/auth/icons => assets/src/svg/svgs}/recovery.icon.ts (98%) rename libs/{components/src/icon/icons => assets/src/svg/svgs}/registration-check-email.icon.ts (97%) rename libs/{auth/src/angular/icons => assets/src/svg/svgs}/registration-expired-link.icon.ts (83%) rename libs/{auth/src/angular/icons => assets/src/svg/svgs}/registration-lock-alt.icon.ts (94%) rename libs/{auth/src/angular/icons => assets/src/svg/svgs}/registration-user-add.icon.ts (93%) rename {apps/web/src/app/dirt/reports/icons => libs/assets/src/svg/svgs}/report-breach.icon.ts (96%) rename {apps/web/src/app/dirt/reports/icons => libs/assets/src/svg/svgs}/report-exposed-passwords.icon.ts (97%) rename {apps/web/src/app/dirt/reports/icons => libs/assets/src/svg/svgs}/report-inactive-two-factor.icon.ts (94%) rename {apps/web/src/app/dirt/reports/icons => libs/assets/src/svg/svgs}/report-member-access.icon.ts (96%) rename {apps/web/src/app/dirt/reports/icons => libs/assets/src/svg/svgs}/report-reused-passwords.icon.ts (96%) rename {apps/web/src/app/dirt/reports/icons => libs/assets/src/svg/svgs}/report-unsecured-websites.icon.ts (94%) rename {apps/web/src/app/dirt/reports/icons => libs/assets/src/svg/svgs}/report-weak-passwords.icon.ts (95%) create mode 100644 libs/assets/src/svg/svgs/restricted-view.ts rename libs/{components/src/icon/icons => assets/src/svg/svgs}/search.ts (98%) rename apps/web/src/app/layouts/secrets-manager-logo.ts => libs/assets/src/svg/svgs/secrets-manager-alt.ts (99%) rename libs/{components/src/icon/logos/bitwarden => assets/src/svg/svgs}/secrets-manager.ts (99%) rename libs/{vault/src/icons => assets/src/svg/svgs}/secure-devices.ts (97%) rename libs/{vault/src/icons => assets/src/svg/svgs}/secure-user.ts (98%) rename libs/{vault/src/icons => assets/src/svg/svgs}/security-handshake.ts (99%) rename libs/{components/src/icon/icons => assets/src/svg/svgs}/security.ts (99%) rename libs/{components/src/icon/icons => assets/src/svg/svgs}/send.ts (97%) rename libs/{components/src/icon/icons => assets/src/svg/svgs}/settings.ts (99%) rename libs/{components/src/icon/logos/bitwarden => assets/src/svg/svgs}/shield.ts (98%) rename libs/{auth/src/angular/icons => assets/src/svg/svgs}/sso-key.icon.ts (92%) rename apps/web/src/app/billing/organizations/icons/subscription-hidden.icon.ts => libs/assets/src/svg/svgs/subscription-hidden.ts (99%) rename libs/{angular/src/auth/icons => assets/src/svg/svgs}/totp.icon.ts (98%) rename libs/{auth/src/angular/icons/two-factor-auth => assets/src/svg/svgs}/two-factor-auth-authenticator.icon.ts (96%) rename libs/{auth/src/angular/icons/two-factor-auth => assets/src/svg/svgs}/two-factor-auth-duo.icon.ts (81%) rename libs/{auth/src/angular/icons/two-factor-auth => assets/src/svg/svgs}/two-factor-auth-email.icon.ts (90%) rename libs/{auth/src/angular/icons/two-factor-auth => assets/src/svg/svgs}/two-factor-auth-security-key.icon.ts (96%) rename libs/{auth/src/angular/icons/two-factor-auth => assets/src/svg/svgs}/two-factor-auth-webauthn.icon.ts (96%) rename libs/{auth/src/angular/icons/two-factor-auth => assets/src/svg/svgs}/two-factor-auth-yubico.icon.ts (93%) rename libs/{auth/src/angular/icons => assets/src/svg/svgs}/two-factor-timeout.icon.ts (88%) rename libs/{auth/src/angular/icons => assets/src/svg/svgs}/user-lock.icon.ts (95%) rename libs/{auth/src/angular/icons => assets/src/svg/svgs}/user-verification-biometrics-fingerprint.icon.ts (92%) rename libs/{vault/src/icons/vault.ts => assets/src/svg/svgs/vault-open.ts} (98%) rename libs/{auth/src/angular/icons => assets/src/svg/svgs}/vault.icon.ts (92%) rename libs/{components/src/icon/icons => assets/src/svg/svgs}/vault.ts (99%) rename libs/{auth/src/angular/icons => assets/src/svg/svgs}/wave.icon.ts (90%) rename libs/{angular/src/auth/icons => assets/src/svg/svgs}/webauthn.icon.ts (96%) create mode 100644 libs/assets/tsconfig.eslint.json create mode 100644 libs/assets/tsconfig.json create mode 100644 libs/assets/tsconfig.lib.json create mode 100644 libs/assets/tsconfig.spec.json delete mode 100644 libs/auth/src/angular/icons/index.ts delete mode 100644 libs/auth/src/angular/icons/two-factor-auth/index.ts delete mode 100644 libs/components/src/anon-layout/illustrations/index.ts delete mode 100644 libs/components/src/icon/icons/index.ts delete mode 100644 libs/components/src/icon/logos/bitwarden/index.ts delete mode 100644 libs/components/src/icon/logos/index.ts delete mode 100644 libs/tools/send/send-ui/src/icons/index.ts delete mode 100644 libs/vault/src/icons/index.ts diff --git a/.github/CODEOWNERS b/.github/CODEOWNERS index 4b956fd577a..df71b6545fb 100644 --- a/.github/CODEOWNERS +++ b/.github/CODEOWNERS @@ -156,6 +156,7 @@ apps/desktop/desktop_native/core/src/ssh_agent @bitwarden/team-autofill-dev @bit ## UI Foundation ## .storybook @bitwarden/team-ui-foundation libs/components @bitwarden/team-ui-foundation +libs/assets @bitwarden/team-ui-foundation libs/ui @bitwarden/team-ui-foundation apps/browser/src/platform/popup/layout @bitwarden/team-ui-foundation apps/browser/src/popup/app-routing.animations.ts @bitwarden/team-ui-foundation diff --git a/apps/browser/src/autofill/popup/fido2/fido2.component.ts b/apps/browser/src/autofill/popup/fido2/fido2.component.ts index ac38fe2f894..11e00749bdf 100644 --- a/apps/browser/src/autofill/popup/fido2/fido2.component.ts +++ b/apps/browser/src/autofill/popup/fido2/fido2.component.ts @@ -18,6 +18,7 @@ import { } from "rxjs"; import { JslibModule } from "@bitwarden/angular/jslib.module"; +import { NoResults } from "@bitwarden/assets/svg"; import { AccountService } from "@bitwarden/common/auth/abstractions/account.service"; import { getUserId } from "@bitwarden/common/auth/services/account.service"; import { DomainSettingsService } from "@bitwarden/common/autofill/services/domain-settings.service"; @@ -36,7 +37,6 @@ import { SecureNoteView } from "@bitwarden/common/vault/models/view/secure-note. import { ButtonModule, DialogService, - Icons, ItemModule, NoItemsModule, SearchModule, @@ -102,7 +102,7 @@ export class Fido2Component implements OnInit, OnDestroy { protected equivalentDomainsURL: string; protected hostname: string; protected loading = false; - protected noResultsIcon = Icons.NoResults; + protected noResultsIcon = NoResults; protected passkeyAction: PasskeyActionValue = PasskeyActions.Register; protected PasskeyActions = PasskeyActions; protected hasSearched = false; diff --git a/apps/browser/src/platform/popup/layout/popup-layout.stories.ts b/apps/browser/src/platform/popup/layout/popup-layout.stories.ts index 7455921b08b..a7103fdfd3c 100644 --- a/apps/browser/src/platform/popup/layout/popup-layout.stories.ts +++ b/apps/browser/src/platform/popup/layout/popup-layout.stories.ts @@ -4,6 +4,16 @@ import { Component, importProvidersFrom } from "@angular/core"; import { RouterModule } from "@angular/router"; import { Meta, StoryObj, applicationConfig, moduleMetadata } from "@storybook/angular"; +import { + GeneratorActive, + GeneratorInactive, + SendActive, + SendInactive, + SettingsActive, + SettingsInactive, + VaultActive, + VaultInactive, +} from "@bitwarden/assets/svg"; import { PolicyService } from "@bitwarden/common/admin-console/abstractions/policy/policy.service.abstraction"; import { I18nService } from "@bitwarden/common/platform/abstractions/i18n.service"; import { SendService } from "@bitwarden/common/tools/send/services/send.service.abstraction"; @@ -13,7 +23,6 @@ import { BannerModule, ButtonModule, I18nMockService, - Icons, IconButtonModule, ItemModule, NoItemsModule, @@ -404,26 +413,26 @@ const navButtons = (showBerry = false) => [ { label: "vault", page: "/tabs/vault", - icon: Icons.VaultInactive, - iconActive: Icons.VaultActive, + icon: VaultInactive, + iconActive: VaultActive, }, { label: "generator", page: "/tabs/generator", - icon: Icons.GeneratorInactive, - iconActive: Icons.GeneratorActive, + icon: GeneratorInactive, + iconActive: GeneratorActive, }, { label: "send", page: "/tabs/send", - icon: Icons.SendInactive, - iconActive: Icons.SendActive, + icon: SendInactive, + iconActive: SendActive, }, { label: "settings", page: "/tabs/settings", - icon: Icons.SettingsInactive, - iconActive: Icons.SettingsActive, + icon: SettingsInactive, + iconActive: SettingsActive, showBerry: showBerry, }, ]; diff --git a/apps/browser/src/platform/popup/layout/popup-tab-navigation.component.ts b/apps/browser/src/platform/popup/layout/popup-tab-navigation.component.ts index 8a897e2e21b..742b12bb7ad 100644 --- a/apps/browser/src/platform/popup/layout/popup-tab-navigation.component.ts +++ b/apps/browser/src/platform/popup/layout/popup-tab-navigation.component.ts @@ -3,8 +3,9 @@ import { Component, Input } from "@angular/core"; import { RouterModule } from "@angular/router"; import { JslibModule } from "@bitwarden/angular/jslib.module"; +import { Icon } from "@bitwarden/assets/svg"; import { I18nService } from "@bitwarden/common/platform/abstractions/i18n.service"; -import { Icon, IconModule, LinkModule } from "@bitwarden/components"; +import { IconModule, LinkModule } from "@bitwarden/components"; export type NavButton = { label: string; diff --git a/apps/browser/src/popup/app-routing.module.ts b/apps/browser/src/popup/app-routing.module.ts index e2f4561e86c..34a37da425e 100644 --- a/apps/browser/src/popup/app-routing.module.ts +++ b/apps/browser/src/popup/app-routing.module.ts @@ -17,28 +17,31 @@ import { SetInitialPasswordComponent } from "@bitwarden/angular/auth/password-ma import { canAccessFeature } from "@bitwarden/angular/platform/guard/feature-flag.guard"; import { DevicesIcon, + RegistrationLockAltIcon, + RegistrationUserAddIcon, + TwoFactorTimeoutIcon, + DeviceVerificationIcon, + UserLockIcon, + VaultIcon, + LockIcon, +} from "@bitwarden/assets/svg"; +import { LoginComponent, LoginDecryptionOptionsComponent, LoginSecondaryContentComponent, LoginViaAuthRequestComponent, PasswordHintComponent, RegistrationFinishComponent, - RegistrationLockAltIcon, RegistrationStartComponent, RegistrationStartSecondaryComponent, RegistrationStartSecondaryComponentData, - RegistrationUserAddIcon, SsoComponent, - TwoFactorTimeoutIcon, TwoFactorAuthComponent, TwoFactorAuthGuard, NewDeviceVerificationComponent, - DeviceVerificationIcon, - UserLockIcon, - VaultIcon, } from "@bitwarden/auth/angular"; import { FeatureFlag } from "@bitwarden/common/enums/feature-flag.enum"; -import { AnonLayoutWrapperData, Icons } from "@bitwarden/components"; +import { AnonLayoutWrapperData } from "@bitwarden/components"; import { LockComponent } from "@bitwarden/key-management-ui"; import { AccountSwitcherComponent } from "../auth/popup/account-switching/account-switcher.component"; @@ -497,7 +500,7 @@ const routes: Routes = [ path: "lock", canActivate: [lockGuard()], data: { - pageIcon: Icons.LockIcon, + pageIcon: LockIcon, pageTitle: { key: "yourVaultIsLockedV2", }, diff --git a/apps/browser/src/popup/components/extension-anon-layout-wrapper/extension-anon-layout-wrapper.component.ts b/apps/browser/src/popup/components/extension-anon-layout-wrapper/extension-anon-layout-wrapper.component.ts index 7a98f570fda..3b84eac2217 100644 --- a/apps/browser/src/popup/components/extension-anon-layout-wrapper/extension-anon-layout-wrapper.component.ts +++ b/apps/browser/src/popup/components/extension-anon-layout-wrapper/extension-anon-layout-wrapper.component.ts @@ -5,10 +5,9 @@ import { Component, OnDestroy, OnInit } from "@angular/core"; import { ActivatedRoute, Data, NavigationEnd, Router, RouterModule } from "@angular/router"; import { Subject, filter, switchMap, takeUntil, tap } from "rxjs"; +import { ExtensionBitwardenLogo, Icon } from "@bitwarden/assets/svg"; import { I18nService } from "@bitwarden/common/platform/abstractions/i18n.service"; import { - Icon, - Icons, IconModule, Translation, AnonLayoutComponent, @@ -63,7 +62,7 @@ export class ExtensionAnonLayoutWrapperComponent implements OnInit, OnDestroy { protected hideCardWrapper: boolean = false; protected theme: string; - protected logo = Icons.ExtensionBitwardenLogo; + protected logo = ExtensionBitwardenLogo; constructor( private router: Router, diff --git a/apps/browser/src/popup/components/extension-anon-layout-wrapper/extension-anon-layout-wrapper.stories.ts b/apps/browser/src/popup/components/extension-anon-layout-wrapper/extension-anon-layout-wrapper.stories.ts index 2c3d09b79fb..4e6f2fb452d 100644 --- a/apps/browser/src/popup/components/extension-anon-layout-wrapper/extension-anon-layout-wrapper.stories.ts +++ b/apps/browser/src/popup/components/extension-anon-layout-wrapper/extension-anon-layout-wrapper.stories.ts @@ -9,6 +9,7 @@ import { } from "@storybook/angular"; import { of } from "rxjs"; +import { LockIcon, RegistrationCheckEmailIcon } from "@bitwarden/assets/svg"; import { AccountService } from "@bitwarden/common/auth/abstractions/account.service"; import { AuthService } from "@bitwarden/common/auth/abstractions/auth.service"; import { AvatarService } from "@bitwarden/common/auth/abstractions/avatar.service"; @@ -22,12 +23,7 @@ import { import { I18nService } from "@bitwarden/common/platform/abstractions/i18n.service"; import { PlatformUtilsService } from "@bitwarden/common/platform/abstractions/platform-utils.service"; import { UserId } from "@bitwarden/common/types/guid"; -import { - AnonLayoutWrapperDataService, - ButtonModule, - Icons, - I18nMockService, -} from "@bitwarden/components"; +import { AnonLayoutWrapperDataService, ButtonModule, I18nMockService } from "@bitwarden/components"; import { AccountSwitcherService } from "../../../auth/popup/account-switching/services/account-switcher.service"; import { PopupRouterCacheService } from "../../../platform/popup/view-cache/popup-router-cache.service"; @@ -244,7 +240,7 @@ const initialData: ExtensionAnonLayoutWrapperData = { pageSubtitle: { key: "finishCreatingYourAccountBySettingAPassword", }, - pageIcon: Icons.LockIcon, + pageIcon: LockIcon, showAcctSwitcher: true, showBackButton: true, showLogo: true, @@ -258,7 +254,7 @@ const changedData: ExtensionAnonLayoutWrapperData = { pageSubtitle: { key: "checkYourEmail", }, - pageIcon: Icons.RegistrationCheckEmailIcon, + pageIcon: RegistrationCheckEmailIcon, showAcctSwitcher: false, showBackButton: false, showLogo: false, diff --git a/apps/browser/src/popup/tabs-v2.component.ts b/apps/browser/src/popup/tabs-v2.component.ts index 860b71794ff..f1e42799b35 100644 --- a/apps/browser/src/popup/tabs-v2.component.ts +++ b/apps/browser/src/popup/tabs-v2.component.ts @@ -2,9 +2,18 @@ import { Component } from "@angular/core"; import { map, Observable, startWith, switchMap } from "rxjs"; import { NudgesService } from "@bitwarden/angular/vault"; +import { + VaultInactive, + VaultActive, + GeneratorInactive, + GeneratorActive, + SendInactive, + SendActive, + SettingsInactive, + SettingsActive, +} from "@bitwarden/assets/svg"; import { AccountService } from "@bitwarden/common/auth/abstractions/account.service"; import { getUserId } from "@bitwarden/common/auth/services/account.service"; -import { Icons } from "@bitwarden/components"; import { NavButton } from "../platform/popup/layout/popup-tab-navigation.component"; @@ -24,26 +33,26 @@ export class TabsV2Component { { label: "vault", page: "/tabs/vault", - icon: Icons.VaultInactive, - iconActive: Icons.VaultActive, + icon: VaultInactive, + iconActive: VaultActive, }, { label: "generator", page: "/tabs/generator", - icon: Icons.GeneratorInactive, - iconActive: Icons.GeneratorActive, + icon: GeneratorInactive, + iconActive: GeneratorActive, }, { label: "send", page: "/tabs/send", - icon: Icons.SendInactive, - iconActive: Icons.SendActive, + icon: SendInactive, + iconActive: SendActive, }, { label: "settings", page: "/tabs/settings", - icon: Icons.SettingsInactive, - iconActive: Icons.SettingsActive, + icon: SettingsInactive, + iconActive: SettingsActive, showBerry: hasBadges, }, ]; diff --git a/apps/browser/src/tools/popup/send-v2/send-created/send-created.component.ts b/apps/browser/src/tools/popup/send-v2/send-created/send-created.component.ts index dd9e95b64a1..30359e98fa0 100644 --- a/apps/browser/src/tools/popup/send-v2/send-created/send-created.component.ts +++ b/apps/browser/src/tools/popup/send-v2/send-created/send-created.component.ts @@ -7,13 +7,13 @@ import { ActivatedRoute, Router, RouterModule } from "@angular/router"; import { firstValueFrom } from "rxjs"; import { JslibModule } from "@bitwarden/angular/jslib.module"; +import { ActiveSendIcon } from "@bitwarden/assets/svg"; import { EnvironmentService } from "@bitwarden/common/platform/abstractions/environment.service"; import { I18nService } from "@bitwarden/common/platform/abstractions/i18n.service"; import { PlatformUtilsService } from "@bitwarden/common/platform/abstractions/platform-utils.service"; import { SendView } from "@bitwarden/common/tools/send/models/view/send.view"; import { SendService } from "@bitwarden/common/tools/send/services/send.service.abstraction"; import { ButtonModule, IconModule, ToastService } from "@bitwarden/components"; -import { ActiveSendIcon } from "@bitwarden/send-ui"; import { PopOutComponent } from "../../../../platform/popup/components/pop-out.component"; import { PopupFooterComponent } from "../../../../platform/popup/layout/popup-footer.component"; diff --git a/apps/browser/src/tools/popup/send-v2/send-v2.component.ts b/apps/browser/src/tools/popup/send-v2/send-v2.component.ts index 2fca3e41f88..5bd5386b1e0 100644 --- a/apps/browser/src/tools/popup/send-v2/send-v2.component.ts +++ b/apps/browser/src/tools/popup/send-v2/send-v2.component.ts @@ -4,15 +4,15 @@ import { takeUntilDestroyed } from "@angular/core/rxjs-interop"; import { combineLatest, switchMap } from "rxjs"; import { JslibModule } from "@bitwarden/angular/jslib.module"; +import { NoResults, NoSendsIcon } from "@bitwarden/assets/svg"; import { PolicyService } from "@bitwarden/common/admin-console/abstractions/policy/policy.service.abstraction"; import { PolicyType } from "@bitwarden/common/admin-console/enums"; import { AccountService } from "@bitwarden/common/auth/abstractions/account.service"; import { getUserId } from "@bitwarden/common/auth/services/account.service"; import { SendType } from "@bitwarden/common/tools/send/enums/send-type"; -import { ButtonModule, CalloutModule, Icons, NoItemsModule } from "@bitwarden/components"; +import { ButtonModule, CalloutModule, NoItemsModule } from "@bitwarden/components"; import { NewSendDropdownComponent, - NoSendsIcon, SendItemsService, SendListFiltersComponent, SendListFiltersService, @@ -59,7 +59,7 @@ export class SendV2Component implements OnDestroy { protected sendsLoading$ = this.sendItemsService.loading$; protected title: string = "allSends"; protected noItemIcon = NoSendsIcon; - protected noResultsIcon = Icons.NoResults; + protected noResultsIcon = NoResults; protected sendsDisabled = false; diff --git a/apps/browser/src/vault/popup/components/vault-v2/intro-carousel/intro-carousel.component.ts b/apps/browser/src/vault/popup/components/vault-v2/intro-carousel/intro-carousel.component.ts index 527f0f246af..22149f9dc86 100644 --- a/apps/browser/src/vault/popup/components/vault-v2/intro-carousel/intro-carousel.component.ts +++ b/apps/browser/src/vault/popup/components/vault-v2/intro-carousel/intro-carousel.component.ts @@ -2,9 +2,10 @@ import { Component } from "@angular/core"; import { Router } from "@angular/router"; import { JslibModule } from "@bitwarden/angular/jslib.module"; +import { SecurityHandshake, LoginCards, SecureUser, SecureDevices } from "@bitwarden/assets/svg"; import { ButtonModule, DialogModule, IconModule, TypographyModule } from "@bitwarden/components"; import { I18nPipe } from "@bitwarden/ui-common"; -import { VaultCarouselModule, VaultIcons } from "@bitwarden/vault"; +import { VaultCarouselModule } from "@bitwarden/vault"; import { IntroCarouselService } from "../../../services/intro-carousel.service"; @@ -22,10 +23,10 @@ import { IntroCarouselService } from "../../../services/intro-carousel.service"; ], }) export class IntroCarouselComponent { - protected securityHandshake = VaultIcons.SecurityHandshake; - protected loginCards = VaultIcons.LoginCards; - protected secureUser = VaultIcons.SecureUser; - protected secureDevices = VaultIcons.SecureDevices; + protected securityHandshake = SecurityHandshake; + protected loginCards = LoginCards; + protected secureUser = SecureUser; + protected secureDevices = SecureDevices; constructor( private router: Router, diff --git a/apps/browser/src/vault/popup/components/vault-v2/vault-v2.component.ts b/apps/browser/src/vault/popup/components/vault-v2/vault-v2.component.ts index 0340c82369d..604cc6b73ef 100644 --- a/apps/browser/src/vault/popup/components/vault-v2/vault-v2.component.ts +++ b/apps/browser/src/vault/popup/components/vault-v2/vault-v2.component.ts @@ -18,6 +18,7 @@ import { import { JslibModule } from "@bitwarden/angular/jslib.module"; import { NudgesService, NudgeType } from "@bitwarden/angular/vault"; import { SpotlightComponent } from "@bitwarden/angular/vault/components/spotlight/spotlight.component"; +import { DeactivatedOrg, NoResults, VaultOpen } from "@bitwarden/assets/svg"; import { AccountService } from "@bitwarden/common/auth/abstractions/account.service"; import { getUserId } from "@bitwarden/common/auth/services/account.service"; import { FeatureFlag } from "@bitwarden/common/enums/feature-flag.enum"; @@ -28,11 +29,10 @@ import { UnionOfValues } from "@bitwarden/common/vault/types/union-of-values"; import { ButtonModule, DialogService, - Icons, NoItemsModule, TypographyModule, } from "@bitwarden/components"; -import { DecryptionFailureDialogComponent, VaultIcons } from "@bitwarden/vault"; +import { DecryptionFailureDialogComponent } from "@bitwarden/vault"; import { CurrentAccountComponent } from "../../../../auth/popup/account-switching/current-account.component"; import { BrowserApi } from "../../../../platform/browser/browser-api"; @@ -136,9 +136,9 @@ export class VaultV2Component implements OnInit, AfterViewInit, OnDestroy { /** Visual state of the vault */ protected vaultState: VaultState | null = null; - protected vaultIcon = VaultIcons.Vault; - protected deactivatedIcon = VaultIcons.DeactivatedOrg; - protected noResultsIcon = Icons.NoResults; + protected vaultIcon = VaultOpen; + protected deactivatedIcon = DeactivatedOrg; + protected noResultsIcon = NoResults; protected VaultStateEnum = VaultState; diff --git a/apps/browser/src/vault/popup/settings/folders-v2.component.ts b/apps/browser/src/vault/popup/settings/folders-v2.component.ts index 2264415f4fa..b749f651d53 100644 --- a/apps/browser/src/vault/popup/settings/folders-v2.component.ts +++ b/apps/browser/src/vault/popup/settings/folders-v2.component.ts @@ -3,6 +3,7 @@ import { Component } from "@angular/core"; import { filter, map, Observable, switchMap } from "rxjs"; import { JslibModule } from "@bitwarden/angular/jslib.module"; +import { NoFolders } from "@bitwarden/assets/svg"; import { AccountService } from "@bitwarden/common/auth/abstractions/account.service"; import { UserId } from "@bitwarden/common/types/guid"; import { FolderService } from "@bitwarden/common/vault/abstractions/folder/folder.service.abstraction"; @@ -15,7 +16,7 @@ import { ItemModule, NoItemsModule, } from "@bitwarden/components"; -import { AddEditFolderDialogComponent, VaultIcons } from "@bitwarden/vault"; +import { AddEditFolderDialogComponent } from "@bitwarden/vault"; import { PopOutComponent } from "../../../platform/popup/components/pop-out.component"; import { PopupHeaderComponent } from "../../../platform/popup/layout/popup-header.component"; @@ -39,7 +40,7 @@ import { PopupPageComponent } from "../../../platform/popup/layout/popup-page.co export class FoldersV2Component { folders$: Observable; - NoFoldersIcon = VaultIcons.NoFolders; + NoFoldersIcon = NoFolders; private activeUserId$ = this.accountService.activeAccount$.pipe(map((a) => a?.id)); constructor( diff --git a/apps/browser/src/vault/popup/settings/trash.component.ts b/apps/browser/src/vault/popup/settings/trash.component.ts index d6e5f899bba..b9d6b621bba 100644 --- a/apps/browser/src/vault/popup/settings/trash.component.ts +++ b/apps/browser/src/vault/popup/settings/trash.component.ts @@ -2,8 +2,8 @@ import { CommonModule } from "@angular/common"; import { ChangeDetectionStrategy, Component } from "@angular/core"; import { JslibModule } from "@bitwarden/angular/jslib.module"; +import { EmptyTrash } from "@bitwarden/assets/svg"; import { CalloutModule, NoItemsModule } from "@bitwarden/components"; -import { VaultIcons } from "@bitwarden/vault"; import { PopOutComponent } from "../../../platform/popup/components/pop-out.component"; import { PopupHeaderComponent } from "../../../platform/popup/layout/popup-header.component"; @@ -29,7 +29,7 @@ import { TrashListItemsContainerComponent } from "./trash-list-items-container/t export class TrashComponent { protected deletedCiphers$ = this.vaultPopupItemsService.deletedCiphers$; - protected emptyTrashIcon = VaultIcons.EmptyTrash; + protected emptyTrashIcon = EmptyTrash; constructor(private vaultPopupItemsService: VaultPopupItemsService) {} } diff --git a/apps/browser/tailwind.config.js b/apps/browser/tailwind.config.js index 02e1d86f5ac..1ad56562bb3 100644 --- a/apps/browser/tailwind.config.js +++ b/apps/browser/tailwind.config.js @@ -4,6 +4,7 @@ const config = require("../../libs/components/tailwind.config.base"); config.content = [ "./src/**/*.{html,ts}", "../../libs/components/src/**/*.{html,ts}", + "../../libs/assets/src/**/*.{html,ts}", "../../libs/auth/src/**/*.{html,ts}", "../../libs/key-management-ui/src/**/*.{html,ts}", "../../libs/vault/src/**/*.{html,ts}", diff --git a/apps/desktop/src/app/app-routing.module.ts b/apps/desktop/src/app/app-routing.module.ts index db079cd60f9..1cfe8a85386 100644 --- a/apps/desktop/src/app/app-routing.module.ts +++ b/apps/desktop/src/app/app-routing.module.ts @@ -12,29 +12,32 @@ import { unauthGuardFn, } from "@bitwarden/angular/auth/guards"; import { ChangePasswordComponent } from "@bitwarden/angular/auth/password-management/change-password"; +import { + DevicesIcon, + RegistrationLockAltIcon, + RegistrationUserAddIcon, + TwoFactorTimeoutIcon, + DeviceVerificationIcon, + UserLockIcon, + VaultIcon, + LockIcon, +} from "@bitwarden/assets/svg"; import { LoginComponent, LoginSecondaryContentComponent, LoginViaAuthRequestComponent, PasswordHintComponent, RegistrationFinishComponent, - RegistrationLockAltIcon, RegistrationStartComponent, RegistrationStartSecondaryComponent, RegistrationStartSecondaryComponentData, - RegistrationUserAddIcon, - UserLockIcon, - VaultIcon, LoginDecryptionOptionsComponent, - DevicesIcon, SsoComponent, - TwoFactorTimeoutIcon, TwoFactorAuthComponent, TwoFactorAuthGuard, NewDeviceVerificationComponent, - DeviceVerificationIcon, } from "@bitwarden/auth/angular"; -import { AnonLayoutWrapperComponent, AnonLayoutWrapperData, Icons } from "@bitwarden/components"; +import { AnonLayoutWrapperComponent, AnonLayoutWrapperData } from "@bitwarden/components"; import { LockComponent } from "@bitwarden/key-management-ui"; import { maxAccountsGuardFn } from "../auth/guards/max-accounts.guard"; @@ -260,7 +263,7 @@ const routes: Routes = [ path: "lock", canActivate: [lockGuard()], data: { - pageIcon: Icons.LockIcon, + pageIcon: LockIcon, pageTitle: { key: "yourVaultIsLockedV2", }, diff --git a/apps/desktop/tailwind.config.js b/apps/desktop/tailwind.config.js index 5b4cab027ba..bf65ae8d7cb 100644 --- a/apps/desktop/tailwind.config.js +++ b/apps/desktop/tailwind.config.js @@ -4,6 +4,7 @@ const config = require("../../libs/components/tailwind.config.base"); config.content = [ "./src/**/*.{html,ts}", "../../libs/components/src/**/*.{html,ts}", + "../../libs/assets/src/**/*.{html,ts}", "../../libs/auth/src/**/*.{html,ts}", "../../libs/key-management-ui/src/**/*.{html,ts}", "../../libs/angular/src/**/*.{html,ts}", diff --git a/apps/web/src/app/admin-console/icons/index.ts b/apps/web/src/app/admin-console/icons/index.ts deleted file mode 100644 index e0c2c124af1..00000000000 --- a/apps/web/src/app/admin-console/icons/index.ts +++ /dev/null @@ -1 +0,0 @@ -export * from "./devices"; diff --git a/apps/web/src/app/admin-console/organizations/collections/collection-access-restricted.component.ts b/apps/web/src/app/admin-console/organizations/collections/collection-access-restricted.component.ts index 3f26e03e203..86b83d75ca4 100644 --- a/apps/web/src/app/admin-console/organizations/collections/collection-access-restricted.component.ts +++ b/apps/web/src/app/admin-console/organizations/collections/collection-access-restricted.component.ts @@ -1,15 +1,11 @@ import { Component, EventEmitter, Input, Output } from "@angular/core"; -import { ButtonModule, NoItemsModule, svgIcon } from "@bitwarden/components"; +import { RestrictedView } from "@bitwarden/assets/svg"; +import { ButtonModule, NoItemsModule } from "@bitwarden/components"; import { SharedModule } from "../../../shared"; import { CollectionDialogTabType } from "../shared/components/collection-dialog"; -const icon = svgIcon` - - -`; - @Component({ selector: "collection-access-restricted", imports: [SharedModule, ButtonModule, NoItemsModule], @@ -38,7 +34,7 @@ const icon = svgIcon``, }) export class CollectionAccessRestrictedComponent { - protected icon = icon; + protected icon = RestrictedView; protected collectionDialogTabType = CollectionDialogTabType; @Input() canEditCollection = false; diff --git a/apps/web/src/app/admin-console/organizations/collections/vault.component.ts b/apps/web/src/app/admin-console/organizations/collections/vault.component.ts index 87f309c6f66..8e4d844a871 100644 --- a/apps/web/src/app/admin-console/organizations/collections/vault.component.ts +++ b/apps/web/src/app/admin-console/organizations/collections/vault.component.ts @@ -34,6 +34,7 @@ import { Unassigned, } from "@bitwarden/admin-console/common"; import { SearchPipe } from "@bitwarden/angular/pipes/search.pipe"; +import { Search } from "@bitwarden/assets/svg"; import { ApiService } from "@bitwarden/common/abstractions/api.service"; import { EventCollectionService } from "@bitwarden/common/abstractions/event/event-collection.service"; import { OrganizationApiServiceAbstraction } from "@bitwarden/common/admin-console/abstractions/organization/organization-api.service.abstraction"; @@ -66,7 +67,6 @@ import { BannerModule, DialogRef, DialogService, - Icons, NoItemsModule, ToastService, } from "@bitwarden/components"; @@ -170,7 +170,7 @@ export class VaultComponent implements OnInit, OnDestroy { activeFilter: VaultFilter = new VaultFilter(); protected showAddAccessToggle = false; - protected noItemIcon = Icons.Search; + protected noItemIcon = Search; protected performingInitialLoad = true; protected refreshing = false; protected processingEvent = false; diff --git a/apps/web/src/app/admin-console/organizations/layouts/organization-layout.component.ts b/apps/web/src/app/admin-console/organizations/layouts/organization-layout.component.ts index 4b6e9a431b4..87b9d62f398 100644 --- a/apps/web/src/app/admin-console/organizations/layouts/organization-layout.component.ts +++ b/apps/web/src/app/admin-console/organizations/layouts/organization-layout.component.ts @@ -6,6 +6,7 @@ import { ActivatedRoute, RouterModule } from "@angular/router"; import { combineLatest, filter, map, Observable, switchMap, withLatestFrom } from "rxjs"; import { JslibModule } from "@bitwarden/angular/jslib.module"; +import { AdminConsoleLogo } from "@bitwarden/assets/svg"; import { canAccessBillingTab, canAccessGroupsTab, @@ -27,7 +28,7 @@ import { FeatureFlag } from "@bitwarden/common/enums/feature-flag.enum"; import { ConfigService } from "@bitwarden/common/platform/abstractions/config/config.service"; import { PlatformUtilsService } from "@bitwarden/common/platform/abstractions/platform-utils.service"; import { getById } from "@bitwarden/common/platform/misc"; -import { BannerModule, IconModule, AdminConsoleLogo } from "@bitwarden/components"; +import { BannerModule, IconModule } from "@bitwarden/components"; 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 { NonIndividualSubscriber } from "@bitwarden/web-vault/app/billing/types"; diff --git a/apps/web/src/app/admin-console/organizations/sponsorships/accept-family-sponsorship.component.ts b/apps/web/src/app/admin-console/organizations/sponsorships/accept-family-sponsorship.component.ts index 2ca566a0af2..c4fe0350006 100644 --- a/apps/web/src/app/admin-console/organizations/sponsorships/accept-family-sponsorship.component.ts +++ b/apps/web/src/app/admin-console/organizations/sponsorships/accept-family-sponsorship.component.ts @@ -4,10 +4,11 @@ import { CommonModule } from "@angular/common"; import { Component, inject } from "@angular/core"; import { Params } from "@angular/router"; +import { BitwardenLogo } from "@bitwarden/assets/svg"; import { PolicyApiServiceAbstraction } from "@bitwarden/common/admin-console/abstractions/policy/policy-api.service.abstraction"; import { OrganizationSponsorshipResponse } from "@bitwarden/common/admin-console/models/response/organization-sponsorship.response"; import { ConfigService } from "@bitwarden/common/platform/abstractions/config/config.service"; -import { IconModule, Icons, ToastService } from "@bitwarden/components"; +import { IconModule, ToastService } from "@bitwarden/components"; import { I18nPipe } from "@bitwarden/ui-common"; import { BaseAcceptComponent } from "../../../common/base.accept.component"; @@ -22,7 +23,7 @@ import { BaseAcceptComponent } from "../../../common/base.accept.component"; imports: [CommonModule, I18nPipe, IconModule], }) export class AcceptFamilySponsorshipComponent extends BaseAcceptComponent { - protected logo = Icons.BitwardenLogo; + protected logo = BitwardenLogo; failedShortMessage = "inviteAcceptFailedShort"; failedMessage = "inviteAcceptFailed"; diff --git a/apps/web/src/app/auth/login/login-via-webauthn/login-via-webauthn.component.ts b/apps/web/src/app/auth/login/login-via-webauthn/login-via-webauthn.component.ts index d4a381159ab..443005473c4 100644 --- a/apps/web/src/app/auth/login/login-via-webauthn/login-via-webauthn.component.ts +++ b/apps/web/src/app/auth/login/login-via-webauthn/login-via-webauthn.component.ts @@ -1,8 +1,7 @@ import { Component } from "@angular/core"; import { BaseLoginViaWebAuthnComponent } from "@bitwarden/angular/auth/components/base-login-via-webauthn.component"; -import { CreatePasskeyFailedIcon } from "@bitwarden/angular/auth/icons/create-passkey-failed.icon"; -import { CreatePasskeyIcon } from "@bitwarden/angular/auth/icons/create-passkey.icon"; +import { CreatePasskeyIcon, CreatePasskeyFailedIcon } from "@bitwarden/assets/svg"; @Component({ selector: "app-login-via-webauthn", @@ -10,5 +9,8 @@ import { CreatePasskeyIcon } from "@bitwarden/angular/auth/icons/create-passkey. standalone: false, }) export class LoginViaWebAuthnComponent extends BaseLoginViaWebAuthnComponent { - protected readonly Icons = { CreatePasskeyIcon, CreatePasskeyFailedIcon }; + protected readonly Icons = { + CreatePasskeyIcon, + CreatePasskeyFailedIcon, + }; } diff --git a/apps/web/src/app/auth/settings/webauthn-login-settings/create-credential-dialog/create-credential-dialog.component.ts b/apps/web/src/app/auth/settings/webauthn-login-settings/create-credential-dialog/create-credential-dialog.component.ts index 22c3b4376c5..35e5048b1af 100644 --- a/apps/web/src/app/auth/settings/webauthn-login-settings/create-credential-dialog/create-credential-dialog.component.ts +++ b/apps/web/src/app/auth/settings/webauthn-login-settings/create-credential-dialog/create-credential-dialog.component.ts @@ -4,6 +4,7 @@ import { Component, OnInit } from "@angular/core"; import { FormBuilder, Validators } from "@angular/forms"; import { firstValueFrom, map, Observable } from "rxjs"; +import { CreatePasskeyFailedIcon, CreatePasskeyIcon } from "@bitwarden/assets/svg"; import { PrfKeySet } from "@bitwarden/auth/common"; import { Verification } from "@bitwarden/common/auth/types/verification"; import { ErrorResponse } from "@bitwarden/common/models/response/error.response"; @@ -16,9 +17,6 @@ import { WebauthnLoginAdminService } from "../../../core"; import { CredentialCreateOptionsView } from "../../../core/views/credential-create-options.view"; import { PendingWebauthnLoginCredentialView } from "../../../core/views/pending-webauthn-login-credential.view"; -import { CreatePasskeyFailedIcon } from "./create-passkey-failed.icon"; -import { CreatePasskeyIcon } from "./create-passkey.icon"; - // FIXME: update to use a const object instead of a typescript enum // eslint-disable-next-line @bitwarden/platform/no-enums export enum CreateCredentialDialogResult { @@ -38,7 +36,10 @@ type Step = export class CreateCredentialDialogComponent implements OnInit { protected readonly NameMaxCharacters = 50; protected readonly CreateCredentialDialogResult = CreateCredentialDialogResult; - protected readonly Icons = { CreatePasskeyIcon, CreatePasskeyFailedIcon }; + protected readonly Icons = { + CreatePasskeyIcon, + CreatePasskeyFailedIcon, + }; protected currentStep: Step = "userVerification"; protected invalidSecret = false; diff --git a/apps/web/src/app/auth/settings/webauthn-login-settings/create-credential-dialog/create-passkey-failed.icon.ts b/apps/web/src/app/auth/settings/webauthn-login-settings/create-credential-dialog/create-passkey-failed.icon.ts deleted file mode 100644 index 65902a64c9f..00000000000 --- a/apps/web/src/app/auth/settings/webauthn-login-settings/create-credential-dialog/create-passkey-failed.icon.ts +++ /dev/null @@ -1,28 +0,0 @@ -import { svgIcon } from "@bitwarden/components"; - -export const CreatePasskeyFailedIcon = svgIcon` - - - - - - - - - - - -`; diff --git a/apps/web/src/app/billing/organizations/organization-subscription-cloud.component.ts b/apps/web/src/app/billing/organizations/organization-subscription-cloud.component.ts index 19c4ba04799..509fecb88fe 100644 --- a/apps/web/src/app/billing/organizations/organization-subscription-cloud.component.ts +++ b/apps/web/src/app/billing/organizations/organization-subscription-cloud.component.ts @@ -5,6 +5,7 @@ import { ActivatedRoute } from "@angular/router"; import { firstValueFrom, lastValueFrom, Subject } from "rxjs"; import { OrganizationUserApiService } from "@bitwarden/admin-console/common"; +import { SubscriptionHiddenIcon } from "@bitwarden/assets/svg"; import { ApiService } from "@bitwarden/common/abstractions/api.service"; import { OrganizationApiServiceAbstraction } from "@bitwarden/common/admin-console/abstractions/organization/organization-api.service.abstraction"; import { @@ -39,7 +40,6 @@ import { import { BillingSyncApiKeyComponent } from "./billing-sync-api-key.component"; import { ChangePlanDialogResultType, openChangePlanDialog } from "./change-plan-dialog.component"; import { DownloadLicenceDialogComponent } from "./download-license.component"; -import { SubscriptionHiddenIcon } from "./icons/subscription-hidden.icon"; import { SecretsManagerSubscriptionOptions } from "./sm-adjust-subscription.component"; @Component({ diff --git a/apps/web/src/app/billing/organizations/subscription-hidden.component.ts b/apps/web/src/app/billing/organizations/subscription-hidden.component.ts index 1455d76d67e..f68b20635ba 100644 --- a/apps/web/src/app/billing/organizations/subscription-hidden.component.ts +++ b/apps/web/src/app/billing/organizations/subscription-hidden.component.ts @@ -2,30 +2,7 @@ // @ts-strict-ignore import { Component, Input } from "@angular/core"; -import { svgIcon } from "@bitwarden/components"; - -const SubscriptionHiddenIcon = svgIcon` - - - - - - - - - - - - - - - - - - - - -`; +import { SubscriptionHiddenIcon } from "@bitwarden/assets/svg"; @Component({ selector: "app-org-subscription-hidden", diff --git a/apps/web/src/app/billing/shared/sm-subscribe.component.ts b/apps/web/src/app/billing/shared/sm-subscribe.component.ts index 1ecf3648bd2..d1e5566a235 100644 --- a/apps/web/src/app/billing/shared/sm-subscribe.component.ts +++ b/apps/web/src/app/billing/shared/sm-subscribe.component.ts @@ -5,13 +5,12 @@ import { FormBuilder, FormGroup, Validators } from "@angular/forms"; import { Subject, startWith, takeUntil } from "rxjs"; import { ControlsOf } from "@bitwarden/angular/types/controls-of"; +import { SecretsManagerAlt } from "@bitwarden/assets/svg"; import { ProductTierType } from "@bitwarden/common/billing/enums"; import { BillingCustomerDiscount } from "@bitwarden/common/billing/models/response/organization-subscription.response"; import { PlanResponse } from "@bitwarden/common/billing/models/response/plan.response"; import { I18nService } from "@bitwarden/common/platform/abstractions/i18n.service"; -import { SecretsManagerLogo } from "../../layouts/secrets-manager-logo"; - export interface SecretsManagerSubscription { enabled: boolean; userSeats: number; @@ -42,7 +41,7 @@ export class SecretsManagerSubscribeComponent implements OnInit, OnDestroy { @Input() selectedPlan: PlanResponse; @Input() customerDiscount: BillingCustomerDiscount; - logo = SecretsManagerLogo; + logo = SecretsManagerAlt; productTypes = ProductTierType; private destroy$ = new Subject(); diff --git a/apps/web/src/app/dirt/reports/reports.ts b/apps/web/src/app/dirt/reports/reports.ts index c47928af1e9..d7437382961 100644 --- a/apps/web/src/app/dirt/reports/reports.ts +++ b/apps/web/src/app/dirt/reports/reports.ts @@ -1,10 +1,13 @@ -import { ReportBreach } from "./icons/report-breach.icon"; -import { ReportExposedPasswords } from "./icons/report-exposed-passwords.icon"; -import { ReportInactiveTwoFactor } from "./icons/report-inactive-two-factor.icon"; -import { MemberAccess } from "./icons/report-member-access.icon"; -import { ReportReusedPasswords } from "./icons/report-reused-passwords.icon"; -import { ReportUnsecuredWebsites } from "./icons/report-unsecured-websites.icon"; -import { ReportWeakPasswords } from "./icons/report-weak-passwords.icon"; +import { + MemberAccess, + ReportBreach, + ReportExposedPasswords, + ReportInactiveTwoFactor, + ReportReusedPasswords, + ReportUnsecuredWebsites, + ReportWeakPasswords, +} from "@bitwarden/assets/svg"; + import { ReportEntry } from "./shared"; // FIXME: update to use a const object instead of a typescript enum diff --git a/apps/web/src/app/dirt/reports/shared/models/report-entry.ts b/apps/web/src/app/dirt/reports/shared/models/report-entry.ts index d4da4e36763..fd1e57991fb 100644 --- a/apps/web/src/app/dirt/reports/shared/models/report-entry.ts +++ b/apps/web/src/app/dirt/reports/shared/models/report-entry.ts @@ -1,4 +1,4 @@ -import { Icon } from "@bitwarden/components"; +import { Icon } from "@bitwarden/assets/svg"; import { ReportVariant } from "./report-variant"; diff --git a/apps/web/src/app/dirt/reports/shared/report-card/report-card.component.ts b/apps/web/src/app/dirt/reports/shared/report-card/report-card.component.ts index 92e6ddb0028..e8ffcd01068 100644 --- a/apps/web/src/app/dirt/reports/shared/report-card/report-card.component.ts +++ b/apps/web/src/app/dirt/reports/shared/report-card/report-card.component.ts @@ -2,7 +2,7 @@ // @ts-strict-ignore import { Component, Input } from "@angular/core"; -import { Icon } from "@bitwarden/components"; +import { Icon } from "@bitwarden/assets/svg"; import { ReportVariant } from "../models/report-variant"; diff --git a/apps/web/src/app/layouts/password-manager-logo.ts b/apps/web/src/app/layouts/password-manager-logo.ts deleted file mode 100644 index d93e2d5bb30..00000000000 --- a/apps/web/src/app/layouts/password-manager-logo.ts +++ /dev/null @@ -1,5 +0,0 @@ -import { svgIcon } from "@bitwarden/components"; - -export const PasswordManagerLogo = svgIcon` - -`; diff --git a/apps/web/src/app/layouts/user-layout.component.ts b/apps/web/src/app/layouts/user-layout.component.ts index db4c181cd0f..37b35ee41be 100644 --- a/apps/web/src/app/layouts/user-layout.component.ts +++ b/apps/web/src/app/layouts/user-layout.component.ts @@ -6,10 +6,11 @@ import { RouterModule } from "@angular/router"; import { Observable, switchMap } from "rxjs"; import { JslibModule } from "@bitwarden/angular/jslib.module"; +import { PasswordManagerLogo } from "@bitwarden/assets/svg"; import { AccountService } from "@bitwarden/common/auth/abstractions/account.service"; import { BillingAccountProfileStateService } from "@bitwarden/common/billing/abstractions/account/billing-account-profile-state.service"; import { SyncService } from "@bitwarden/common/platform/sync"; -import { IconModule, PasswordManagerLogo } from "@bitwarden/components"; +import { IconModule } from "@bitwarden/components"; import { BillingFreeFamiliesNavItemComponent } from "../billing/shared/billing-free-families-nav-item.component"; diff --git a/apps/web/src/app/oss-routing.module.ts b/apps/web/src/app/oss-routing.module.ts index 4c1ed1a7472..9536ba19cc8 100644 --- a/apps/web/src/app/oss-routing.module.ts +++ b/apps/web/src/app/oss-routing.module.ts @@ -12,6 +12,19 @@ import { } from "@bitwarden/angular/auth/guards"; import { ChangePasswordComponent } from "@bitwarden/angular/auth/password-management/change-password"; import { SetInitialPasswordComponent } from "@bitwarden/angular/auth/password-management/set-initial-password/set-initial-password.component"; +import { + DevicesIcon, + RegistrationLockAltIcon, + RegistrationUserAddIcon, + TwoFactorTimeoutIcon, + DeviceVerificationIcon, + UserLockIcon, + VaultIcon, + RegistrationExpiredLinkIcon, + SsoKeyIcon, + LockIcon, + BrowserExtensionIcon, +} from "@bitwarden/assets/svg"; import { PasswordHintComponent, RegistrationFinishComponent, @@ -21,25 +34,15 @@ import { RegistrationLinkExpiredComponent, LoginComponent, LoginSecondaryContentComponent, - TwoFactorTimeoutIcon, - UserLockIcon, - SsoKeyIcon, LoginViaAuthRequestComponent, - DevicesIcon, - RegistrationUserAddIcon, - RegistrationLockAltIcon, - RegistrationExpiredLinkIcon, SsoComponent, - VaultIcon, LoginDecryptionOptionsComponent, TwoFactorAuthComponent, TwoFactorAuthGuard, NewDeviceVerificationComponent, - DeviceVerificationIcon, } from "@bitwarden/auth/angular"; -import { AnonLayoutWrapperComponent, AnonLayoutWrapperData, Icons } from "@bitwarden/components"; +import { AnonLayoutWrapperComponent, AnonLayoutWrapperData } from "@bitwarden/components"; import { LockComponent } from "@bitwarden/key-management-ui"; -import { VaultIcons } from "@bitwarden/vault"; import { flagEnabled, Flags } from "../utils/flags"; @@ -374,7 +377,7 @@ const routes: Routes = [ pageTitle: { key: "yourVaultIsLockedV2", }, - pageIcon: Icons.LockIcon, + pageIcon: LockIcon, showReadonlyHostname: true, } satisfies AnonLayoutWrapperData, }, @@ -533,7 +536,7 @@ const routes: Routes = [ { path: "browser-extension-prompt", data: { - pageIcon: VaultIcons.BrowserExtensionIcon, + pageIcon: BrowserExtensionIcon, } satisfies AnonLayoutWrapperData, children: [ { diff --git a/apps/web/src/app/tools/send/send-access/access.component.ts b/apps/web/src/app/tools/send/send-access/access.component.ts index bc2851f0df7..1636ac37b87 100644 --- a/apps/web/src/app/tools/send/send-access/access.component.ts +++ b/apps/web/src/app/tools/send/send-access/access.component.ts @@ -4,6 +4,7 @@ import { Component, OnInit } from "@angular/core"; import { FormBuilder } from "@angular/forms"; import { ActivatedRoute } from "@angular/router"; +import { ExpiredSendIcon } from "@bitwarden/assets/svg"; import { CryptoFunctionService } from "@bitwarden/common/key-management/crypto/abstractions/crypto-function.service"; import { ErrorResponse } from "@bitwarden/common/models/response/error.response"; import { I18nService } from "@bitwarden/common/platform/abstractions/i18n.service"; @@ -18,7 +19,6 @@ import { SEND_KDF_ITERATIONS } from "@bitwarden/common/tools/send/send-kdf"; import { SendApiService } from "@bitwarden/common/tools/send/services/send-api.service.abstraction"; import { AnonLayoutWrapperDataService, NoItemsModule, ToastService } from "@bitwarden/components"; import { KeyService } from "@bitwarden/key-management"; -import { ExpiredSendIcon } from "@bitwarden/send-ui"; import { SharedModule } from "../../../shared"; diff --git a/apps/web/src/app/tools/send/send-access/routes.ts b/apps/web/src/app/tools/send/send-access/routes.ts index 4f794aecd23..e94453c9351 100644 --- a/apps/web/src/app/tools/send/send-access/routes.ts +++ b/apps/web/src/app/tools/send/send-access/routes.ts @@ -1,7 +1,7 @@ import { Routes } from "@angular/router"; +import { ActiveSendIcon } from "@bitwarden/assets/svg"; import { AnonLayoutWrapperData } from "@bitwarden/components"; -import { ActiveSendIcon } from "@bitwarden/send-ui"; import { RouteDataProperties } from "../../../core"; diff --git a/apps/web/src/app/tools/send/send.component.ts b/apps/web/src/app/tools/send/send.component.ts index b74a3b80ee3..20b93a10975 100644 --- a/apps/web/src/app/tools/send/send.component.ts +++ b/apps/web/src/app/tools/send/send.component.ts @@ -4,6 +4,7 @@ import { Component, NgZone, OnInit, OnDestroy } from "@angular/core"; import { lastValueFrom } from "rxjs"; import { SendComponent as BaseSendComponent } from "@bitwarden/angular/tools/send/send.component"; +import { NoSendsIcon } from "@bitwarden/assets/svg"; import { PolicyService } from "@bitwarden/common/admin-console/abstractions/policy/policy.service.abstraction"; import { AccountService } from "@bitwarden/common/auth/abstractions/account.service"; import { BroadcasterService } from "@bitwarden/common/platform/abstractions/broadcaster.service"; @@ -26,7 +27,6 @@ import { } from "@bitwarden/components"; import { DefaultSendFormConfigService, - NoSendsIcon, SendFormConfig, SendAddEditDialogComponent, SendItemDialogResult, diff --git a/apps/web/src/app/vault/components/manually-open-extension/manually-open-extension.component.ts b/apps/web/src/app/vault/components/manually-open-extension/manually-open-extension.component.ts index 22041b61198..646ff76311e 100644 --- a/apps/web/src/app/vault/components/manually-open-extension/manually-open-extension.component.ts +++ b/apps/web/src/app/vault/components/manually-open-extension/manually-open-extension.component.ts @@ -1,8 +1,8 @@ import { Component } from "@angular/core"; +import { BitwardenIcon } from "@bitwarden/assets/svg"; import { IconModule } from "@bitwarden/components"; import { I18nPipe } from "@bitwarden/ui-common"; -import { VaultIcons } from "@bitwarden/vault"; @Component({ selector: "vault-manually-open-extension", @@ -10,5 +10,5 @@ import { VaultIcons } from "@bitwarden/vault"; imports: [I18nPipe, IconModule], }) export class ManuallyOpenExtensionComponent { - protected BitwardenIcon = VaultIcons.BitwardenIcon; + protected BitwardenIcon = BitwardenIcon; } diff --git a/apps/web/src/app/vault/components/setup-extension/setup-extension.component.spec.ts b/apps/web/src/app/vault/components/setup-extension/setup-extension.component.spec.ts index 8bb80e6fb44..cd4d421a7b9 100644 --- a/apps/web/src/app/vault/components/setup-extension/setup-extension.component.spec.ts +++ b/apps/web/src/app/vault/components/setup-extension/setup-extension.component.spec.ts @@ -3,6 +3,7 @@ import { By } from "@angular/platform-browser"; import { Router, RouterModule } from "@angular/router"; import { BehaviorSubject } from "rxjs"; +import { BrowserExtensionIcon } from "@bitwarden/assets/svg"; import { AccountService } from "@bitwarden/common/auth/abstractions/account.service"; import { DeviceType } from "@bitwarden/common/enums"; import { FeatureFlag } from "@bitwarden/common/enums/feature-flag.enum"; @@ -12,7 +13,6 @@ import { PlatformUtilsService } from "@bitwarden/common/platform/abstractions/pl import { Utils } from "@bitwarden/common/platform/misc/utils"; import { StateProvider } from "@bitwarden/common/platform/state"; import { AnonLayoutWrapperDataService } from "@bitwarden/components"; -import { VaultIcons } from "@bitwarden/vault"; import { WebBrowserInteractionService } from "../../services/web-browser-interaction.service"; @@ -156,7 +156,7 @@ describe("SetupExtensionComponent", () => { pageTitle: { key: "somethingWentWrong", }, - pageIcon: VaultIcons.BrowserExtensionIcon, + pageIcon: BrowserExtensionIcon, hideIcon: false, hideCardWrapper: false, maxWidth: "md", diff --git a/apps/web/src/app/vault/components/setup-extension/setup-extension.component.ts b/apps/web/src/app/vault/components/setup-extension/setup-extension.component.ts index 67d13ef1e4f..a36627081f2 100644 --- a/apps/web/src/app/vault/components/setup-extension/setup-extension.component.ts +++ b/apps/web/src/app/vault/components/setup-extension/setup-extension.component.ts @@ -5,6 +5,7 @@ import { Router, RouterModule } from "@angular/router"; import { firstValueFrom, pairwise, startWith } from "rxjs"; import { JslibModule } from "@bitwarden/angular/jslib.module"; +import { BrowserExtensionIcon, Party } from "@bitwarden/assets/svg"; import { AccountService } from "@bitwarden/common/auth/abstractions/account.service"; import { getUserId } from "@bitwarden/common/auth/services/account.service"; import { FeatureFlag } from "@bitwarden/common/enums/feature-flag.enum"; @@ -22,7 +23,6 @@ import { IconModule, LinkModule, } from "@bitwarden/components"; -import { VaultIcons } from "@bitwarden/vault"; import { SETUP_EXTENSION_DISMISSED } from "../../guards/setup-extension-redirect.guard"; import { WebBrowserInteractionService } from "../../services/web-browser-interaction.service"; @@ -70,7 +70,7 @@ export class SetupExtensionComponent implements OnInit, OnDestroy { private anonLayoutWrapperDataService = inject(AnonLayoutWrapperDataService); protected SetupExtensionState = SetupExtensionState; - protected PartyIcon = VaultIcons.Party; + protected PartyIcon = Party; /** The current state of the setup extension component. */ protected state: SetupExtensionState = SetupExtensionState.Loading; @@ -167,7 +167,7 @@ export class SetupExtensionComponent implements OnInit, OnDestroy { pageTitle: { key: "somethingWentWrong", }, - pageIcon: VaultIcons.BrowserExtensionIcon, + pageIcon: BrowserExtensionIcon, hideIcon: false, hideCardWrapper: false, maxWidth: "md", diff --git a/apps/web/src/app/vault/individual-vault/vault.component.ts b/apps/web/src/app/vault/individual-vault/vault.component.ts index ca8b05c2701..7593e9c59bf 100644 --- a/apps/web/src/app/vault/individual-vault/vault.component.ts +++ b/apps/web/src/app/vault/individual-vault/vault.component.ts @@ -35,6 +35,7 @@ import { Unassigned, } from "@bitwarden/admin-console/common"; import { SearchPipe } from "@bitwarden/angular/pipes/search.pipe"; +import { Search } from "@bitwarden/assets/svg"; import { ApiService } from "@bitwarden/common/abstractions/api.service"; import { EventCollectionService } from "@bitwarden/common/abstractions/event/event-collection.service"; import { OrganizationApiServiceAbstraction } from "@bitwarden/common/admin-console/abstractions/organization/organization-api.service.abstraction"; @@ -72,7 +73,7 @@ import { CipherViewLikeUtils, } from "@bitwarden/common/vault/utils/cipher-view-like-utils"; import { filterOutNullish } from "@bitwarden/common/vault/utils/observable-utilities"; -import { DialogRef, DialogService, Icons, ToastService } from "@bitwarden/components"; +import { DialogRef, DialogService, ToastService } from "@bitwarden/components"; import { CipherListView } from "@bitwarden/sdk-internal"; import { AddEditFolderDialogComponent, @@ -163,7 +164,7 @@ export class VaultComponent implements OnInit, OnDestr kdfIterations: number; activeFilter: VaultFilter = new VaultFilter(); - protected noItemIcon = Icons.Search; + protected noItemIcon = Search; protected performingInitialLoad = true; protected refreshing = false; protected processingEvent = false; diff --git a/apps/web/tailwind.config.js b/apps/web/tailwind.config.js index d33f94e94a9..0e1ae28abd1 100644 --- a/apps/web/tailwind.config.js +++ b/apps/web/tailwind.config.js @@ -4,6 +4,7 @@ const config = require("../../libs/components/tailwind.config.base"); config.content = [ "./src/**/*.{html,ts}", "../../libs/components/src/**/*.{html,ts}", + "../../libs/assets/src/**/*.{html,ts}", "../../libs/auth/src/**/*.{html,ts}", "../../libs/key-management-ui/src/**/*.{html,ts}", "../../libs/vault/src/**/*.{html,ts}", diff --git a/bitwarden_license/bit-web/src/app/admin-console/organizations/manage/device-approvals/device-approvals.component.ts b/bitwarden_license/bit-web/src/app/admin-console/organizations/manage/device-approvals/device-approvals.component.ts index 3f698421e2d..f41b91261f7 100644 --- a/bitwarden_license/bit-web/src/app/admin-console/organizations/manage/device-approvals/device-approvals.component.ts +++ b/bitwarden_license/bit-web/src/app/admin-console/organizations/manage/device-approvals/device-approvals.component.ts @@ -6,6 +6,7 @@ import { BehaviorSubject, Subject, switchMap, takeUntil, tap } from "rxjs"; import { OrganizationUserApiService } from "@bitwarden/admin-console/common"; import { SafeProvider, safeProvider } from "@bitwarden/angular/platform/utils/safe-provider"; +import { Devices } from "@bitwarden/assets/svg"; import { OrganizationAuthRequestApiService } from "@bitwarden/bit-common/admin-console/auth-requests/organization-auth-request-api.service"; import { OrganizationAuthRequestService } from "@bitwarden/bit-common/admin-console/auth-requests/organization-auth-request.service"; import { PendingAuthRequestWithFingerprintView } from "@bitwarden/bit-common/admin-console/auth-requests/pending-auth-request-with-fingerprint.view"; @@ -20,7 +21,6 @@ import { PlatformUtilsService } from "@bitwarden/common/platform/abstractions/pl import { ValidationService } from "@bitwarden/common/platform/abstractions/validation.service"; import { TableDataSource, NoItemsModule, ToastService } from "@bitwarden/components"; import { KeyService } from "@bitwarden/key-management"; -import { Devices } from "@bitwarden/web-vault/app/admin-console/icons"; import { LooseComponentsModule } from "@bitwarden/web-vault/app/shared"; import { SharedModule } from "@bitwarden/web-vault/app/shared/shared.module"; diff --git a/bitwarden_license/bit-web/src/app/admin-console/providers/manage/accept-provider.component.ts b/bitwarden_license/bit-web/src/app/admin-console/providers/manage/accept-provider.component.ts index 7696742277a..9f28ba87186 100644 --- a/bitwarden_license/bit-web/src/app/admin-console/providers/manage/accept-provider.component.ts +++ b/bitwarden_license/bit-web/src/app/admin-console/providers/manage/accept-provider.component.ts @@ -3,12 +3,12 @@ import { Component } from "@angular/core"; import { ActivatedRoute, Params, Router } from "@angular/router"; +import { BitwardenLogo } from "@bitwarden/assets/svg"; import { ApiService } from "@bitwarden/common/abstractions/api.service"; import { ProviderUserAcceptRequest } from "@bitwarden/common/admin-console/models/request/provider/provider-user-accept.request"; import { AuthService } from "@bitwarden/common/auth/abstractions/auth.service"; import { I18nService } from "@bitwarden/common/platform/abstractions/i18n.service"; import { PlatformUtilsService } from "@bitwarden/common/platform/abstractions/platform-utils.service"; -import { Icons } from "@bitwarden/components"; import { BaseAcceptComponent } from "@bitwarden/web-vault/app/common/base.accept.component"; @Component({ @@ -17,7 +17,7 @@ import { BaseAcceptComponent } from "@bitwarden/web-vault/app/common/base.accept standalone: false, }) export class AcceptProviderComponent extends BaseAcceptComponent { - protected logo = Icons.BitwardenLogo; + protected logo = BitwardenLogo; providerName: string; providerId: string; providerUserId: string; diff --git a/bitwarden_license/bit-web/src/app/admin-console/providers/providers-layout.component.ts b/bitwarden_license/bit-web/src/app/admin-console/providers/providers-layout.component.ts index 5e2e9a14f2d..159a0105df9 100644 --- a/bitwarden_license/bit-web/src/app/admin-console/providers/providers-layout.component.ts +++ b/bitwarden_license/bit-web/src/app/admin-console/providers/providers-layout.component.ts @@ -7,17 +7,13 @@ import { combineLatest, map, Observable, Subject, switchMap } from "rxjs"; import { takeUntil } from "rxjs/operators"; import { JslibModule } from "@bitwarden/angular/jslib.module"; +import { BusinessUnitPortalLogo, Icon, ProviderPortalLogo } from "@bitwarden/assets/svg"; import { ProviderService } from "@bitwarden/common/admin-console/abstractions/provider.service"; import { ProviderStatusType, ProviderType } from "@bitwarden/common/admin-console/enums"; import { Provider } from "@bitwarden/common/admin-console/models/domain/provider"; import { FeatureFlag } from "@bitwarden/common/enums/feature-flag.enum"; import { ConfigService } from "@bitwarden/common/platform/abstractions/config/config.service"; -import { - Icon, - IconModule, - ProviderPortalLogo, - BusinessUnitPortalLogo, -} from "@bitwarden/components"; +import { IconModule } from "@bitwarden/components"; import { NonIndividualSubscriber } from "@bitwarden/web-vault/app/billing/types"; import { TaxIdWarningComponent } from "@bitwarden/web-vault/app/billing/warnings/components"; import { TaxIdWarningType } from "@bitwarden/web-vault/app/billing/warnings/types"; diff --git a/bitwarden_license/bit-web/src/app/admin-console/providers/setup/setup-provider.component.ts b/bitwarden_license/bit-web/src/app/admin-console/providers/setup/setup-provider.component.ts index 47c30490af3..02ca72fa9b8 100644 --- a/bitwarden_license/bit-web/src/app/admin-console/providers/setup/setup-provider.component.ts +++ b/bitwarden_license/bit-web/src/app/admin-console/providers/setup/setup-provider.component.ts @@ -1,7 +1,7 @@ import { Component } from "@angular/core"; import { Params } from "@angular/router"; -import { Icons } from "@bitwarden/components"; +import { BitwardenLogo } from "@bitwarden/assets/svg"; import { BaseAcceptComponent } from "@bitwarden/web-vault/app/common/base.accept.component"; @Component({ @@ -10,7 +10,7 @@ import { BaseAcceptComponent } from "@bitwarden/web-vault/app/common/base.accept standalone: false, }) export class SetupProviderComponent extends BaseAcceptComponent { - protected logo = Icons.BitwardenLogo; + protected logo = BitwardenLogo; failedShortMessage = "inviteAcceptFailedShort"; failedMessage = "inviteAcceptFailed"; diff --git a/bitwarden_license/bit-web/src/app/billing/providers/clients/no-clients.component.ts b/bitwarden_license/bit-web/src/app/billing/providers/clients/no-clients.component.ts index 039c42de302..8ff5d070241 100644 --- a/bitwarden_license/bit-web/src/app/billing/providers/clients/no-clients.component.ts +++ b/bitwarden_license/bit-web/src/app/billing/providers/clients/no-clients.component.ts @@ -1,27 +1,8 @@ import { Component, EventEmitter, Input, Output } from "@angular/core"; -import { svgIcon } from "@bitwarden/components"; +import { GearIcon } from "@bitwarden/assets/svg"; import { SharedOrganizationModule } from "@bitwarden/web-vault/app/admin-console/organizations/shared"; -const gearIcon = svgIcon` - - - - - - - - - - - - - - - - -`; - @Component({ selector: "app-no-clients", imports: [SharedOrganizationModule], @@ -42,7 +23,7 @@ const gearIcon = svgIcon`
`, }) export class NoClientsComponent { - icon = gearIcon; + icon = GearIcon; @Input() showAddOrganizationButton = true; @Input() disableAddOrganizationButton = false; @Output() addNewOrganizationClicked = new EventEmitter(); diff --git a/bitwarden_license/bit-web/src/app/billing/providers/setup/setup-business-unit.component.ts b/bitwarden_license/bit-web/src/app/billing/providers/setup/setup-business-unit.component.ts index 0634c891a05..c964108936a 100644 --- a/bitwarden_license/bit-web/src/app/billing/providers/setup/setup-business-unit.component.ts +++ b/bitwarden_license/bit-web/src/app/billing/providers/setup/setup-business-unit.component.ts @@ -3,6 +3,7 @@ import { ActivatedRoute, Params, Router } from "@angular/router"; import { firstValueFrom } from "rxjs"; import { filter, map, switchMap } from "rxjs/operators"; +import { BitwardenLogo } from "@bitwarden/assets/svg"; import { AuthService } from "@bitwarden/common/auth/abstractions/auth.service"; import { OrganizationBillingApiServiceAbstraction } from "@bitwarden/common/billing/abstractions/organizations/organization-billing-api.service.abstraction"; import { EncryptService } from "@bitwarden/common/key-management/crypto/abstractions/encrypt.service"; @@ -12,7 +13,6 @@ import { StateProvider } from "@bitwarden/common/platform/state"; import { SyncService } from "@bitwarden/common/platform/sync"; import { OrganizationId } from "@bitwarden/common/types/guid"; import { ProviderKey } from "@bitwarden/common/types/key"; -import { Icons } from "@bitwarden/components"; import { KeyService } from "@bitwarden/key-management"; import { BillingNotificationService } from "@bitwarden/web-vault/app/billing/services/billing-notification.service"; import { BaseAcceptComponent } from "@bitwarden/web-vault/app/common/base.accept.component"; @@ -22,7 +22,7 @@ import { BaseAcceptComponent } from "@bitwarden/web-vault/app/common/base.accept standalone: false, }) export class SetupBusinessUnitComponent extends BaseAcceptComponent { - protected bitwardenLogo = Icons.BitwardenLogo; + protected bitwardenLogo = BitwardenLogo; failedMessage = "emergencyInviteAcceptFailed"; failedShortMessage = "emergencyInviteAcceptFailedShort"; diff --git a/bitwarden_license/bit-web/src/app/dirt/access-intelligence/all-applications.component.ts b/bitwarden_license/bit-web/src/app/dirt/access-intelligence/all-applications.component.ts index ee08ec6661e..1ce9ab9a2e6 100644 --- a/bitwarden_license/bit-web/src/app/dirt/access-intelligence/all-applications.component.ts +++ b/bitwarden_license/bit-web/src/app/dirt/access-intelligence/all-applications.component.ts @@ -4,6 +4,7 @@ import { FormControl } from "@angular/forms"; import { ActivatedRoute } from "@angular/router"; import { combineLatest, debounceTime, firstValueFrom, map, Observable, of, switchMap } from "rxjs"; +import { Security } from "@bitwarden/assets/svg"; import { CriticalAppsService, RiskInsightsDataService, @@ -27,7 +28,6 @@ import { I18nService } from "@bitwarden/common/platform/abstractions/i18n.servic import { CipherService } from "@bitwarden/common/vault/abstractions/cipher.service"; import { IconButtonModule, - Icons, NoItemsModule, SearchModule, TableDataSource, @@ -63,7 +63,7 @@ export class AllApplicationsComponent implements OnInit { protected searchControl = new FormControl("", { nonNullable: true }); protected loading = true; protected organization = new Organization(); - noItemsIcon = Icons.Security; + noItemsIcon = Security; protected markingAsCritical = false; protected applicationSummary: ApplicationHealthReportSummary = { totalMemberCount: 0, diff --git a/bitwarden_license/bit-web/src/app/dirt/access-intelligence/critical-applications.component.ts b/bitwarden_license/bit-web/src/app/dirt/access-intelligence/critical-applications.component.ts index 4f9a9930f1c..531adc003c7 100644 --- a/bitwarden_license/bit-web/src/app/dirt/access-intelligence/critical-applications.component.ts +++ b/bitwarden_license/bit-web/src/app/dirt/access-intelligence/critical-applications.component.ts @@ -6,6 +6,7 @@ import { FormControl } from "@angular/forms"; import { ActivatedRoute, Router } from "@angular/router"; import { combineLatest, debounceTime, map, switchMap } from "rxjs"; +import { Security } from "@bitwarden/assets/svg"; import { CriticalAppsService, RiskInsightsDataService, @@ -20,13 +21,7 @@ import { ConfigService } from "@bitwarden/common/platform/abstractions/config/co import { I18nService } from "@bitwarden/common/platform/abstractions/i18n.service"; import { CipherId, OrganizationId } from "@bitwarden/common/types/guid"; import { SecurityTaskType } from "@bitwarden/common/vault/tasks"; -import { - Icons, - NoItemsModule, - SearchModule, - TableDataSource, - ToastService, -} from "@bitwarden/components"; +import { NoItemsModule, SearchModule, TableDataSource, ToastService } from "@bitwarden/components"; import { CardComponent } from "@bitwarden/dirt-card"; import { HeaderModule } from "@bitwarden/web-vault/app/layouts/header/header.module"; import { SharedModule } from "@bitwarden/web-vault/app/shared"; @@ -61,7 +56,7 @@ export class CriticalApplicationsComponent implements OnInit { protected loading = false; protected organizationId: string; protected applicationSummary = {} as ApplicationHealthReportSummary; - noItemsIcon = Icons.Security; + noItemsIcon = Security; enableRequestPasswordChange = false; async ngOnInit() { diff --git a/bitwarden_license/bit-web/src/app/secrets-manager/layout/navigation.component.ts b/bitwarden_license/bit-web/src/app/secrets-manager/layout/navigation.component.ts index 24da000f213..a714bc0d543 100644 --- a/bitwarden_license/bit-web/src/app/secrets-manager/layout/navigation.component.ts +++ b/bitwarden_license/bit-web/src/app/secrets-manager/layout/navigation.component.ts @@ -15,6 +15,7 @@ import { takeUntil, } from "rxjs"; +import { SecretsManagerLogo } from "@bitwarden/assets/svg"; import { getOrganizationById, OrganizationService, @@ -22,7 +23,6 @@ import { import { Organization } from "@bitwarden/common/admin-console/models/domain/organization"; import { AccountService } from "@bitwarden/common/auth/abstractions/account.service"; import { getUserId } from "@bitwarden/common/auth/services/account.service"; -import { SecretsManagerLogo } from "@bitwarden/components"; import { OrganizationCounts } from "../models/view/counts.view"; import { ProjectService } from "../projects/project.service"; diff --git a/bitwarden_license/bit-web/src/app/secrets-manager/shared/org-suspended.component.ts b/bitwarden_license/bit-web/src/app/secrets-manager/shared/org-suspended.component.ts index 89baf969c34..0a7d6befde2 100644 --- a/bitwarden_license/bit-web/src/app/secrets-manager/shared/org-suspended.component.ts +++ b/bitwarden_license/bit-web/src/app/secrets-manager/shared/org-suspended.component.ts @@ -2,13 +2,13 @@ import { Component } from "@angular/core"; import { ActivatedRoute } from "@angular/router"; import { map, concatMap, firstValueFrom } from "rxjs"; +import { Icon, NoAccess } from "@bitwarden/assets/svg"; import { getOrganizationById, OrganizationService, } from "@bitwarden/common/admin-console/abstractions/organization/organization.service.abstraction"; import { AccountService } from "@bitwarden/common/auth/abstractions/account.service"; import { getUserId } from "@bitwarden/common/auth/services/account.service"; -import { Icon, Icons } from "@bitwarden/components"; @Component({ templateUrl: "./org-suspended.component.html", @@ -21,7 +21,7 @@ export class OrgSuspendedComponent { private route: ActivatedRoute, ) {} - protected NoAccess: Icon = Icons.NoAccess; + protected NoAccess: Icon = NoAccess; protected organizationName$ = this.route.params.pipe( concatMap(async (params) => { const userId = await firstValueFrom(getUserId(this.accountService.activeAccount$)); diff --git a/libs/angular/src/auth/components/two-factor-icon.component.ts b/libs/angular/src/auth/components/two-factor-icon.component.ts index 0e811595bea..8c650b6b04c 100644 --- a/libs/angular/src/auth/components/two-factor-icon.component.ts +++ b/libs/angular/src/auth/components/two-factor-icon.component.ts @@ -2,10 +2,7 @@ // @ts-strict-ignore import { Component, Input } from "@angular/core"; -import { EmailIcon } from "../icons/email.icon"; -import { RecoveryCodeIcon } from "../icons/recovery.icon"; -import { TOTPIcon } from "../icons/totp.icon"; -import { WebAuthnIcon } from "../icons/webauthn.icon"; +import { EmailIcon, RecoveryCodeIcon, TOTPIcon, WebAuthnIcon } from "@bitwarden/assets/svg"; @Component({ selector: "auth-two-factor-icon", diff --git a/libs/angular/src/auth/icons/create-passkey.icon.ts b/libs/angular/src/auth/icons/create-passkey.icon.ts deleted file mode 100644 index 79ba4021b58..00000000000 --- a/libs/angular/src/auth/icons/create-passkey.icon.ts +++ /dev/null @@ -1,26 +0,0 @@ -import { svgIcon } from "@bitwarden/components"; - -export const CreatePasskeyIcon = svgIcon` - - - - - - - - - - -`; diff --git a/libs/angular/src/auth/password-management/change-password/change-password.component.ts b/libs/angular/src/auth/password-management/change-password/change-password.component.ts index 7bb9584e934..1512f348133 100644 --- a/libs/angular/src/auth/password-management/change-password/change-password.component.ts +++ b/libs/angular/src/auth/password-management/change-password/change-password.component.ts @@ -2,6 +2,7 @@ import { CommonModule } from "@angular/common"; import { Component, Input, OnInit } from "@angular/core"; import { firstValueFrom } from "rxjs"; +import { LockIcon } from "@bitwarden/assets/svg"; // This import has been flagged as unallowed for this class. It may be involved in a circular dependency loop. // eslint-disable-next-line no-restricted-imports import { @@ -24,7 +25,6 @@ import { AnonLayoutWrapperDataService, DialogService, ToastService, - Icons, CalloutComponent, } from "@bitwarden/components"; import { I18nPipe } from "@bitwarden/ui-common"; @@ -97,13 +97,13 @@ export class ChangePasswordComponent implements OnInit { if (this.forceSetPasswordReason === ForceSetPasswordReason.AdminForcePasswordReset) { this.anonLayoutWrapperDataService.setAnonLayoutWrapperData({ - pageIcon: Icons.LockIcon, + pageIcon: LockIcon, pageTitle: { key: "updateMasterPassword" }, pageSubtitle: { key: "accountRecoveryUpdateMasterPasswordSubtitle" }, }); } else if (this.forceSetPasswordReason === ForceSetPasswordReason.WeakMasterPassword) { this.anonLayoutWrapperDataService.setAnonLayoutWrapperData({ - pageIcon: Icons.LockIcon, + pageIcon: LockIcon, pageTitle: { key: "updateMasterPassword" }, pageSubtitle: { key: "updateMasterPasswordSubtitle" }, maxWidth: "lg", diff --git a/libs/angular/src/auth/password-management/set-initial-password/set-initial-password.component.ts b/libs/angular/src/auth/password-management/set-initial-password/set-initial-password.component.ts index 27d4c11f692..c31495b60fb 100644 --- a/libs/angular/src/auth/password-management/set-initial-password/set-initial-password.component.ts +++ b/libs/angular/src/auth/password-management/set-initial-password/set-initial-password.component.ts @@ -1,9 +1,9 @@ import { CommonModule } from "@angular/common"; import { Component, OnInit } from "@angular/core"; import { ActivatedRoute, Router } from "@angular/router"; -// import { NoAccess } from "libs/components/src/icon/icons"; import { firstValueFrom } from "rxjs"; +import { NoAccess } from "@bitwarden/assets/svg"; // This import has been flagged as unallowed for this class. It may be involved in a circular dependency loop. // eslint-disable-next-line no-restricted-imports import { @@ -35,7 +35,6 @@ import { CalloutComponent, DialogService, ToastService, - Icons, } from "@bitwarden/components"; import { I18nPipe } from "@bitwarden/ui-common"; @@ -113,7 +112,7 @@ export class SetInitialPasswordComponent implements OnInit { this.userType = SetInitialPasswordUserType.OFFBOARDED_TDE_ORG_USER_UNTRUSTED_DEVICE; this.anonLayoutWrapperDataService.setAnonLayoutWrapperData({ pageTitle: { key: "unableToCompleteLogin" }, - pageIcon: Icons.NoAccess, + pageIcon: NoAccess, }); } diff --git a/libs/angular/src/billing/components/invoices/no-invoices.component.ts b/libs/angular/src/billing/components/invoices/no-invoices.component.ts index 987650d1c83..5251fc0133b 100644 --- a/libs/angular/src/billing/components/invoices/no-invoices.component.ts +++ b/libs/angular/src/billing/components/invoices/no-invoices.component.ts @@ -1,28 +1,6 @@ import { Component } from "@angular/core"; -import { svgIcon } from "@bitwarden/components"; - -const partnerTrustIcon = svgIcon` - - - - - - - - - - - - - - - - - - - -`; +import { PartnerTrustIcon } from "@bitwarden/assets/svg"; @Component({ selector: "app-no-invoices", @@ -33,5 +11,5 @@ const partnerTrustIcon = svgIcon` standalone: false, }) export class NoInvoicesComponent { - icon = partnerTrustIcon; + icon = PartnerTrustIcon; } diff --git a/libs/assets/README.md b/libs/assets/README.md new file mode 100644 index 00000000000..60df3f8992a --- /dev/null +++ b/libs/assets/README.md @@ -0,0 +1,16 @@ +# Assets + +Owned by: ui-foundation + +This lib contains assets used by the Bitwarden clients. Unused assets are tree-shaken from client bundles. This means that all exports from this library must not have any [side effects](https://webpack.js.org/guides/tree-shaking/#mark-the-file-as-side-effect-free). + +## Usage + +### SVGs + +SVGs intended to be used with the `bit-icon` component live in `src/svgs`. These SVGs are built with the `icon-service` for security reasons. These SVGs can be viewed in our Component Library [Icon Story](https://components.bitwarden.com/?path=/story/component-library-icon--default). + +When adding a new SVG, follow the instructions in our Component Library: [SVG Icon Docs](https://components.bitwarden.com/?path=/docs/component-library-icon--docs) + +When importing an SVG in one of the clients: +`import { ExampleSvg } from "@bitwarden/assets/svg";` diff --git a/libs/assets/eslint.config.mjs b/libs/assets/eslint.config.mjs new file mode 100644 index 00000000000..9c37d10e3ff --- /dev/null +++ b/libs/assets/eslint.config.mjs @@ -0,0 +1,3 @@ +import baseConfig from "../../eslint.config.mjs"; + +export default [...baseConfig]; diff --git a/libs/assets/jest.config.js b/libs/assets/jest.config.js new file mode 100644 index 00000000000..fae52410152 --- /dev/null +++ b/libs/assets/jest.config.js @@ -0,0 +1,10 @@ +module.exports = { + displayName: "assets", + preset: "../../jest.preset.js", + testEnvironment: "node", + transform: { + "^.+\\.[tj]s$": ["ts-jest", { tsconfig: "/tsconfig.spec.json" }], + }, + moduleFileExtensions: ["ts", "js", "html"], + coverageDirectory: "../../coverage/libs/assets", +}; diff --git a/libs/assets/package.json b/libs/assets/package.json new file mode 100644 index 00000000000..cc5935833bf --- /dev/null +++ b/libs/assets/package.json @@ -0,0 +1,15 @@ +{ + "name": "@bitwarden/assets", + "version": "0.0.1", + "description": "Assets used in Bitwarden clients", + "private": true, + "type": "commonjs", + "main": "dist/index.js", + "types": "dist/index.d.ts", + "license": "GPL-3.0", + "author": "ui-foundation", + "scripts": { + "test": "jest" + }, + "sideEffects": false +} diff --git a/libs/assets/project.json b/libs/assets/project.json new file mode 100644 index 00000000000..97e32a24b33 --- /dev/null +++ b/libs/assets/project.json @@ -0,0 +1,33 @@ +{ + "name": "assets", + "$schema": "../../node_modules/nx/schemas/project-schema.json", + "sourceRoot": "libs/assets/src", + "projectType": "library", + "tags": [], + "targets": { + "build": { + "executor": "@nx/js:tsc", + "outputs": ["{options.outputPath}"], + "options": { + "outputPath": "dist/libs/assets", + "main": "libs/assets/src/index.ts", + "tsConfig": "libs/assets/tsconfig.lib.json", + "assets": ["libs/assets/*.md"] + } + }, + "lint": { + "executor": "@nx/eslint:lint", + "outputs": ["{options.outputFile}"], + "options": { + "lintFilePatterns": ["libs/assets/**/*.ts"] + } + }, + "test": { + "executor": "@nx/jest:jest", + "outputs": ["{workspaceRoot}/coverage/{projectRoot}"], + "options": { + "jestConfig": "libs/assets/jest.config.js" + } + } + } +} diff --git a/libs/components/src/icon/icon.spec.ts b/libs/assets/src/svg/icon-service.spec.ts similarity index 94% rename from libs/components/src/icon/icon.spec.ts rename to libs/assets/src/svg/icon-service.spec.ts index 3e7c011be93..2561c85aefa 100644 --- a/libs/components/src/icon/icon.spec.ts +++ b/libs/assets/src/svg/icon-service.spec.ts @@ -1,5 +1,5 @@ -import * as IconExports from "./icon"; -import { DynamicContentNotAllowedError, isIcon, svgIcon } from "./icon"; +import * as IconExports from "./icon-service"; +import { DynamicContentNotAllowedError, isIcon, svgIcon } from "./icon-service"; describe("Icon", () => { it("exports should not expose Icon class", () => { diff --git a/libs/components/src/icon/icon.ts b/libs/assets/src/svg/icon-service.ts similarity index 100% rename from libs/components/src/icon/icon.ts rename to libs/assets/src/svg/icon-service.ts diff --git a/libs/assets/src/svg/index.ts b/libs/assets/src/svg/index.ts new file mode 100644 index 00000000000..9f86a14f772 --- /dev/null +++ b/libs/assets/src/svg/index.ts @@ -0,0 +1,2 @@ +export * from "./svgs"; +export * from "./icon-service"; diff --git a/libs/tools/send/send-ui/src/icons/active-send.icon.ts b/libs/assets/src/svg/svgs/active-send.icon.ts similarity index 98% rename from libs/tools/send/send-ui/src/icons/active-send.icon.ts rename to libs/assets/src/svg/svgs/active-send.icon.ts index da5932bf95c..be5cb4540f7 100644 --- a/libs/tools/send/send-ui/src/icons/active-send.icon.ts +++ b/libs/assets/src/svg/svgs/active-send.icon.ts @@ -1,4 +1,4 @@ -import { svgIcon } from "@bitwarden/components"; +import { svgIcon } from "../icon-service"; export const ActiveSendIcon = svgIcon` diff --git a/libs/components/src/icon/logos/bitwarden/admin-console.ts b/libs/assets/src/svg/svgs/admin-console.ts similarity index 99% rename from libs/components/src/icon/logos/bitwarden/admin-console.ts rename to libs/assets/src/svg/svgs/admin-console.ts index 5fa96d91dfe..aa59c3f7e86 100644 --- a/libs/components/src/icon/logos/bitwarden/admin-console.ts +++ b/libs/assets/src/svg/svgs/admin-console.ts @@ -1,4 +1,4 @@ -import { svgIcon } from "../../icon"; +import { svgIcon } from "../icon-service"; const AdminConsoleLogo = svgIcon` diff --git a/libs/components/src/anon-layout/illustrations/left-illustration.ts b/libs/assets/src/svg/svgs/background-left-illustration.ts similarity index 99% rename from libs/components/src/anon-layout/illustrations/left-illustration.ts rename to libs/assets/src/svg/svgs/background-left-illustration.ts index 26fe9f6076b..50d9e76fb53 100644 --- a/libs/components/src/anon-layout/illustrations/left-illustration.ts +++ b/libs/assets/src/svg/svgs/background-left-illustration.ts @@ -1,5 +1,5 @@ -import { svgIcon } from "../../icon"; +import { svgIcon } from "../icon-service"; -export const LeftIllustration = svgIcon` +export const BackgroundLeftIllustration = svgIcon` `; diff --git a/libs/components/src/anon-layout/illustrations/right-illustration.ts b/libs/assets/src/svg/svgs/background-right-illustration.ts similarity index 99% rename from libs/components/src/anon-layout/illustrations/right-illustration.ts rename to libs/assets/src/svg/svgs/background-right-illustration.ts index ba3003ee01f..52be2213c3b 100644 --- a/libs/components/src/anon-layout/illustrations/right-illustration.ts +++ b/libs/assets/src/svg/svgs/background-right-illustration.ts @@ -1,5 +1,5 @@ -import { svgIcon } from "../../icon"; +import { svgIcon } from "../icon-service"; -export const RightIllustration = svgIcon` +export const BackgroundRightIllustration = svgIcon` `; diff --git a/libs/vault/src/icons/bitwarden-icon.ts b/libs/assets/src/svg/svgs/bitwarden-icon.ts similarity index 97% rename from libs/vault/src/icons/bitwarden-icon.ts rename to libs/assets/src/svg/svgs/bitwarden-icon.ts index 73e4304d5c7..710d20937bd 100644 --- a/libs/vault/src/icons/bitwarden-icon.ts +++ b/libs/assets/src/svg/svgs/bitwarden-icon.ts @@ -1,4 +1,4 @@ -import { svgIcon } from "@bitwarden/components"; +import { svgIcon } from "../icon-service"; export const BitwardenIcon = svgIcon` diff --git a/libs/components/src/icon/icons/bitwarden-logo.icon.ts b/libs/assets/src/svg/svgs/bitwarden-logo.icon.ts similarity index 99% rename from libs/components/src/icon/icons/bitwarden-logo.icon.ts rename to libs/assets/src/svg/svgs/bitwarden-logo.icon.ts index 27b8ece164d..9c1c7248ec6 100644 --- a/libs/components/src/icon/icons/bitwarden-logo.icon.ts +++ b/libs/assets/src/svg/svgs/bitwarden-logo.icon.ts @@ -1,4 +1,4 @@ -import { svgIcon } from "../icon"; +import { svgIcon } from "../icon-service"; export const BitwardenLogo = svgIcon` diff --git a/libs/vault/src/icons/browser-extension.ts b/libs/assets/src/svg/svgs/browser-extension.ts similarity index 97% rename from libs/vault/src/icons/browser-extension.ts rename to libs/assets/src/svg/svgs/browser-extension.ts index ac54322292f..4e3b54e77cd 100644 --- a/libs/vault/src/icons/browser-extension.ts +++ b/libs/assets/src/svg/svgs/browser-extension.ts @@ -1,4 +1,4 @@ -import { svgIcon } from "@bitwarden/components"; +import { svgIcon } from "../icon-service"; export const BrowserExtensionIcon = svgIcon` diff --git a/libs/components/src/icon/logos/bitwarden/business-unit-portal.ts b/libs/assets/src/svg/svgs/business-unit-portal.ts similarity index 99% rename from libs/components/src/icon/logos/bitwarden/business-unit-portal.ts rename to libs/assets/src/svg/svgs/business-unit-portal.ts index 6206256f88b..66b30ba06be 100644 --- a/libs/components/src/icon/logos/bitwarden/business-unit-portal.ts +++ b/libs/assets/src/svg/svgs/business-unit-portal.ts @@ -1,4 +1,4 @@ -import { svgIcon } from "../../icon"; +import { svgIcon } from "../icon-service"; const BusinessUnitPortalLogo = svgIcon` diff --git a/libs/vault/src/components/carousel/carousel-icons/carousel-icon.ts b/libs/assets/src/svg/svgs/carousel-icon.ts similarity index 85% rename from libs/vault/src/components/carousel/carousel-icons/carousel-icon.ts rename to libs/assets/src/svg/svgs/carousel-icon.ts index 64052e6fa6c..802f6ff1435 100644 --- a/libs/vault/src/components/carousel/carousel-icons/carousel-icon.ts +++ b/libs/assets/src/svg/svgs/carousel-icon.ts @@ -1,4 +1,4 @@ -import { svgIcon } from "@bitwarden/components"; +import { svgIcon } from "../icon-service"; export const CarouselIcon = svgIcon` diff --git a/libs/angular/src/auth/icons/create-passkey-failed.icon.ts b/libs/assets/src/svg/svgs/create-passkey-failed.icon.ts similarity index 98% rename from libs/angular/src/auth/icons/create-passkey-failed.icon.ts rename to libs/assets/src/svg/svgs/create-passkey-failed.icon.ts index 65902a64c9f..37e679b9b5e 100644 --- a/libs/angular/src/auth/icons/create-passkey-failed.icon.ts +++ b/libs/assets/src/svg/svgs/create-passkey-failed.icon.ts @@ -1,4 +1,4 @@ -import { svgIcon } from "@bitwarden/components"; +import { svgIcon } from "../icon-service"; export const CreatePasskeyFailedIcon = svgIcon` diff --git a/apps/web/src/app/auth/settings/webauthn-login-settings/create-credential-dialog/create-passkey.icon.ts b/libs/assets/src/svg/svgs/create-passkey.icon.ts similarity index 98% rename from apps/web/src/app/auth/settings/webauthn-login-settings/create-credential-dialog/create-passkey.icon.ts rename to libs/assets/src/svg/svgs/create-passkey.icon.ts index 79ba4021b58..efe180e1e2f 100644 --- a/apps/web/src/app/auth/settings/webauthn-login-settings/create-credential-dialog/create-passkey.icon.ts +++ b/libs/assets/src/svg/svgs/create-passkey.icon.ts @@ -1,4 +1,4 @@ -import { svgIcon } from "@bitwarden/components"; +import { svgIcon } from "../icon-service"; export const CreatePasskeyIcon = svgIcon` diff --git a/libs/vault/src/icons/deactivated-org.ts b/libs/assets/src/svg/svgs/deactivated-org.ts similarity index 98% rename from libs/vault/src/icons/deactivated-org.ts rename to libs/assets/src/svg/svgs/deactivated-org.ts index 5f7c910aec8..92a1064e31e 100644 --- a/libs/vault/src/icons/deactivated-org.ts +++ b/libs/assets/src/svg/svgs/deactivated-org.ts @@ -1,4 +1,4 @@ -import { svgIcon } from "@bitwarden/components"; +import { svgIcon } from "../icon-service"; export const DeactivatedOrg = svgIcon` diff --git a/libs/auth/src/angular/icons/device-verification.icon.ts b/libs/assets/src/svg/svgs/device-verification.icon.ts similarity index 89% rename from libs/auth/src/angular/icons/device-verification.icon.ts rename to libs/assets/src/svg/svgs/device-verification.icon.ts index 6c5313a8705..c8fccbf7eca 100644 --- a/libs/auth/src/angular/icons/device-verification.icon.ts +++ b/libs/assets/src/svg/svgs/device-verification.icon.ts @@ -1,6 +1,4 @@ -// This import has been flagged as unallowed for this class. It may be involved in a circular dependency loop. -// eslint-disable-next-line no-restricted-imports -import { svgIcon } from "@bitwarden/components"; +import { svgIcon } from "../icon-service"; export const DeviceVerificationIcon = svgIcon` diff --git a/libs/auth/src/angular/icons/devices.icon.ts b/libs/assets/src/svg/svgs/devices.icon.ts similarity index 91% rename from libs/auth/src/angular/icons/devices.icon.ts rename to libs/assets/src/svg/svgs/devices.icon.ts index dd268f0e6e2..471b44017b1 100644 --- a/libs/auth/src/angular/icons/devices.icon.ts +++ b/libs/assets/src/svg/svgs/devices.icon.ts @@ -1,6 +1,4 @@ -// This import has been flagged as unallowed for this class. It may be involved in a circular dependency loop. -// eslint-disable-next-line no-restricted-imports -import { svgIcon } from "@bitwarden/components"; +import { svgIcon } from "../icon-service"; export const DevicesIcon = svgIcon` diff --git a/apps/web/src/app/admin-console/icons/devices.ts b/libs/assets/src/svg/svgs/devices.ts similarity index 98% rename from apps/web/src/app/admin-console/icons/devices.ts rename to libs/assets/src/svg/svgs/devices.ts index 9faddb0b2ee..517256ec591 100644 --- a/apps/web/src/app/admin-console/icons/devices.ts +++ b/libs/assets/src/svg/svgs/devices.ts @@ -1,4 +1,4 @@ -import { svgIcon } from "@bitwarden/components"; +import { svgIcon } from "../icon-service"; export const Devices = svgIcon` diff --git a/libs/angular/src/auth/icons/email.icon.ts b/libs/assets/src/svg/svgs/email.icon.ts similarity index 92% rename from libs/angular/src/auth/icons/email.icon.ts rename to libs/assets/src/svg/svgs/email.icon.ts index 7b5163898fd..c6341707880 100644 --- a/libs/angular/src/auth/icons/email.icon.ts +++ b/libs/assets/src/svg/svgs/email.icon.ts @@ -1,4 +1,4 @@ -import { svgIcon } from "@bitwarden/components"; +import { svgIcon } from "../icon-service"; export const EmailIcon = svgIcon` - diff --git a/libs/vault/src/icons/empty-trash.ts b/libs/assets/src/svg/svgs/empty-trash.ts similarity index 99% rename from libs/vault/src/icons/empty-trash.ts rename to libs/assets/src/svg/svgs/empty-trash.ts index df74602e6d1..61df8933d44 100644 --- a/libs/vault/src/icons/empty-trash.ts +++ b/libs/assets/src/svg/svgs/empty-trash.ts @@ -1,4 +1,4 @@ -import { svgIcon } from "@bitwarden/components"; +import { svgIcon } from "../icon-service"; export const EmptyTrash = svgIcon` diff --git a/libs/tools/send/send-ui/src/icons/expired-send.icon.ts b/libs/assets/src/svg/svgs/expired-send.icon.ts similarity index 98% rename from libs/tools/send/send-ui/src/icons/expired-send.icon.ts rename to libs/assets/src/svg/svgs/expired-send.icon.ts index c699a544e7c..19283525b4c 100644 --- a/libs/tools/send/send-ui/src/icons/expired-send.icon.ts +++ b/libs/assets/src/svg/svgs/expired-send.icon.ts @@ -1,4 +1,4 @@ -import { svgIcon } from "@bitwarden/components"; +import { svgIcon } from "../icon-service"; export const ExpiredSendIcon = svgIcon` diff --git a/libs/components/src/icon/icons/extension-bitwarden-logo.icon.ts b/libs/assets/src/svg/svgs/extension-bitwarden-logo.icon.ts similarity index 99% rename from libs/components/src/icon/icons/extension-bitwarden-logo.icon.ts rename to libs/assets/src/svg/svgs/extension-bitwarden-logo.icon.ts index a8a07d5d1ef..42a74e006bc 100644 --- a/libs/components/src/icon/icons/extension-bitwarden-logo.icon.ts +++ b/libs/assets/src/svg/svgs/extension-bitwarden-logo.icon.ts @@ -1,4 +1,4 @@ -import { svgIcon } from "../icon"; +import { svgIcon } from "../icon-service"; export const ExtensionBitwardenLogo = svgIcon` + + + + + + + + + + + + + + + +`; diff --git a/libs/components/src/icon/icons/generator.ts b/libs/assets/src/svg/svgs/generator.ts similarity index 98% rename from libs/components/src/icon/icons/generator.ts rename to libs/assets/src/svg/svgs/generator.ts index 6d1e25abc27..52368ddc204 100644 --- a/libs/components/src/icon/icons/generator.ts +++ b/libs/assets/src/svg/svgs/generator.ts @@ -1,4 +1,4 @@ -import { svgIcon } from "../icon"; +import { svgIcon } from "../icon-service"; export const GeneratorInactive = svgIcon` diff --git a/libs/assets/src/svg/svgs/index.ts b/libs/assets/src/svg/svgs/index.ts new file mode 100644 index 00000000000..a5a4c215a29 --- /dev/null +++ b/libs/assets/src/svg/svgs/index.ts @@ -0,0 +1,72 @@ +export * from "./active-send.icon"; +export { default as AdminConsoleLogo } from "./admin-console"; +export * from "./background-left-illustration"; +export * from "./background-right-illustration"; +export * from "./bitwarden-icon"; +export * from "./bitwarden-logo.icon"; +export * from "./browser-extension"; +export { default as BusinessUnitPortalLogo } from "./business-unit-portal"; +export * from "./carousel-icon"; +export * from "./create-passkey-failed.icon"; +export * from "./create-passkey.icon"; +export * from "./deactivated-org"; +export * from "./device-verification.icon"; +export * from "./devices.icon"; +export * from "./devices"; +export * from "./email.icon"; +export * from "./empty-trash"; +export * from "./expired-send.icon"; +export * from "./extension-bitwarden-logo.icon"; +export * from "./gear"; +export * from "./generator"; +export * from "./lock.icon"; +export * from "./login-cards"; +export * from "./no-access"; +export * from "./no-credentials.icon"; +export * from "./no-folders"; +export * from "./no-results"; +export * from "./no-send.icon"; +export * from "./partner-trust"; +export * from "./party"; +export { default as PasswordManagerLogo } from "./password-manager"; +export { default as ProviderPortalLogo } from "./provider-portal"; +export * from "./recovery.icon"; +export * from "./registration-check-email.icon"; +export * from "./registration-expired-link.icon"; +export * from "./registration-lock-alt.icon"; +export * from "./registration-user-add.icon"; +export * from "./report-breach.icon"; +export * from "./report-exposed-passwords.icon"; +export * from "./report-inactive-two-factor.icon"; +export * from "./report-member-access.icon"; +export * from "./report-reused-passwords.icon"; +export * from "./report-unsecured-websites.icon"; +export * from "./report-weak-passwords.icon"; +export * from "./restricted-view"; +export * from "./search"; +export * from "./secrets-manager-alt"; +export { default as SecretsManagerLogo } from "./secrets-manager"; +export * from "./secure-devices"; +export * from "./secure-user"; +export * from "./security-handshake"; +export * from "./security"; +export * from "./send"; +export * from "./settings"; +export * from "./shield"; +export * from "./sso-key.icon"; +export * from "./subscription-hidden"; +export * from "./totp.icon"; +export * from "./two-factor-auth-authenticator.icon"; +export * from "./two-factor-auth-duo.icon"; +export * from "./two-factor-auth-email.icon"; +export * from "./two-factor-auth-security-key.icon"; +export * from "./two-factor-auth-webauthn.icon"; +export * from "./two-factor-auth-yubico.icon"; +export * from "./two-factor-timeout.icon"; +export * from "./user-lock.icon"; +export * from "./user-verification-biometrics-fingerprint.icon"; +export * from "./vault-open"; +export * from "./vault.icon"; +export * from "./vault"; +export * from "./wave.icon"; +export * from "./webauthn.icon"; diff --git a/libs/components/src/icon/icons/lock.icon.ts b/libs/assets/src/svg/svgs/lock.icon.ts similarity index 98% rename from libs/components/src/icon/icons/lock.icon.ts rename to libs/assets/src/svg/svgs/lock.icon.ts index d7a7e4abb1b..5d5d23bcdd1 100644 --- a/libs/components/src/icon/icons/lock.icon.ts +++ b/libs/assets/src/svg/svgs/lock.icon.ts @@ -1,4 +1,4 @@ -import { svgIcon } from "../icon"; +import { svgIcon } from "../icon-service"; export const LockIcon = svgIcon` diff --git a/libs/vault/src/icons/login-cards.ts b/libs/assets/src/svg/svgs/login-cards.ts similarity index 98% rename from libs/vault/src/icons/login-cards.ts rename to libs/assets/src/svg/svgs/login-cards.ts index 6e066a0d924..0eea164a512 100644 --- a/libs/vault/src/icons/login-cards.ts +++ b/libs/assets/src/svg/svgs/login-cards.ts @@ -1,4 +1,4 @@ -import { svgIcon } from "@bitwarden/components"; +import { svgIcon } from "../icon-service"; export const LoginCards = svgIcon` diff --git a/libs/components/src/icon/icons/no-access.ts b/libs/assets/src/svg/svgs/no-access.ts similarity index 96% rename from libs/components/src/icon/icons/no-access.ts rename to libs/assets/src/svg/svgs/no-access.ts index 1011b3089cf..6c9dfae939e 100644 --- a/libs/components/src/icon/icons/no-access.ts +++ b/libs/assets/src/svg/svgs/no-access.ts @@ -1,4 +1,4 @@ -import { svgIcon } from "../icon"; +import { svgIcon } from "../icon-service"; export const NoAccess = svgIcon` diff --git a/libs/tools/generator/components/src/icons/no-credentials.icon.ts b/libs/assets/src/svg/svgs/no-credentials.icon.ts similarity index 99% rename from libs/tools/generator/components/src/icons/no-credentials.icon.ts rename to libs/assets/src/svg/svgs/no-credentials.icon.ts index 7bb289600b8..a825de2f95b 100644 --- a/libs/tools/generator/components/src/icons/no-credentials.icon.ts +++ b/libs/assets/src/svg/svgs/no-credentials.icon.ts @@ -1,4 +1,4 @@ -import { svgIcon } from "@bitwarden/components"; +import { svgIcon } from "../icon-service"; export const NoCredentialsIcon = svgIcon` diff --git a/libs/vault/src/icons/no-folders.ts b/libs/assets/src/svg/svgs/no-folders.ts similarity index 98% rename from libs/vault/src/icons/no-folders.ts rename to libs/assets/src/svg/svgs/no-folders.ts index 666bfc86c4c..ea06a9827e9 100644 --- a/libs/vault/src/icons/no-folders.ts +++ b/libs/assets/src/svg/svgs/no-folders.ts @@ -1,4 +1,4 @@ -import { svgIcon } from "@bitwarden/components"; +import { svgIcon } from "../icon-service"; export const NoFolders = svgIcon` diff --git a/libs/components/src/icon/icons/no-results.ts b/libs/assets/src/svg/svgs/no-results.ts similarity index 98% rename from libs/components/src/icon/icons/no-results.ts rename to libs/assets/src/svg/svgs/no-results.ts index 7ed886a06e9..ce45fce7f3c 100644 --- a/libs/components/src/icon/icons/no-results.ts +++ b/libs/assets/src/svg/svgs/no-results.ts @@ -1,4 +1,4 @@ -import { svgIcon } from "../icon"; +import { svgIcon } from "../icon-service"; export const NoResults = svgIcon` diff --git a/libs/tools/send/send-ui/src/icons/no-send.icon.ts b/libs/assets/src/svg/svgs/no-send.icon.ts similarity index 97% rename from libs/tools/send/send-ui/src/icons/no-send.icon.ts rename to libs/assets/src/svg/svgs/no-send.icon.ts index 555d8024601..85106930961 100644 --- a/libs/tools/send/send-ui/src/icons/no-send.icon.ts +++ b/libs/assets/src/svg/svgs/no-send.icon.ts @@ -1,4 +1,4 @@ -import { svgIcon } from "@bitwarden/components"; +import { svgIcon } from "../icon-service"; export const NoSendsIcon = svgIcon` diff --git a/libs/assets/src/svg/svgs/partner-trust.ts b/libs/assets/src/svg/svgs/partner-trust.ts new file mode 100644 index 00000000000..22249874118 --- /dev/null +++ b/libs/assets/src/svg/svgs/partner-trust.ts @@ -0,0 +1,23 @@ +import { svgIcon } from "../icon-service"; + +export const PartnerTrustIcon = svgIcon` + + + + + + + + + + + + + + + + + + + +`; diff --git a/libs/vault/src/icons/party.ts b/libs/assets/src/svg/svgs/party.ts similarity index 99% rename from libs/vault/src/icons/party.ts rename to libs/assets/src/svg/svgs/party.ts index 2e506c5d705..6fb587a7c14 100644 --- a/libs/vault/src/icons/party.ts +++ b/libs/assets/src/svg/svgs/party.ts @@ -1,4 +1,4 @@ -import { svgIcon } from "@bitwarden/components"; +import { svgIcon } from "../icon-service"; export const Party = svgIcon` diff --git a/libs/components/src/icon/logos/bitwarden/password-manager.ts b/libs/assets/src/svg/svgs/password-manager.ts similarity index 99% rename from libs/components/src/icon/logos/bitwarden/password-manager.ts rename to libs/assets/src/svg/svgs/password-manager.ts index 7586e28bfae..42b3df1a0ed 100644 --- a/libs/components/src/icon/logos/bitwarden/password-manager.ts +++ b/libs/assets/src/svg/svgs/password-manager.ts @@ -1,4 +1,4 @@ -import { svgIcon } from "../../icon"; +import { svgIcon } from "../icon-service"; const PasswordManagerLogo = svgIcon` diff --git a/libs/components/src/icon/logos/bitwarden/provider-portal.ts b/libs/assets/src/svg/svgs/provider-portal.ts similarity index 99% rename from libs/components/src/icon/logos/bitwarden/provider-portal.ts rename to libs/assets/src/svg/svgs/provider-portal.ts index b9c4d76b0e3..9626cc30c57 100644 --- a/libs/components/src/icon/logos/bitwarden/provider-portal.ts +++ b/libs/assets/src/svg/svgs/provider-portal.ts @@ -1,4 +1,4 @@ -import { svgIcon } from "../../icon"; +import { svgIcon } from "../icon-service"; const ProviderPortalLogo = svgIcon` diff --git a/libs/angular/src/auth/icons/recovery.icon.ts b/libs/assets/src/svg/svgs/recovery.icon.ts similarity index 98% rename from libs/angular/src/auth/icons/recovery.icon.ts rename to libs/assets/src/svg/svgs/recovery.icon.ts index e23b46bebe1..95de89cad03 100644 --- a/libs/angular/src/auth/icons/recovery.icon.ts +++ b/libs/assets/src/svg/svgs/recovery.icon.ts @@ -1,4 +1,4 @@ -import { svgIcon } from "@bitwarden/components"; +import { svgIcon } from "../icon-service"; export const RecoveryCodeIcon = svgIcon` diff --git a/libs/auth/src/angular/icons/registration-expired-link.icon.ts b/libs/assets/src/svg/svgs/registration-expired-link.icon.ts similarity index 83% rename from libs/auth/src/angular/icons/registration-expired-link.icon.ts rename to libs/assets/src/svg/svgs/registration-expired-link.icon.ts index 099cf16d1d8..fbeda6c25ad 100644 --- a/libs/auth/src/angular/icons/registration-expired-link.icon.ts +++ b/libs/assets/src/svg/svgs/registration-expired-link.icon.ts @@ -1,6 +1,4 @@ -// This import has been flagged as unallowed for this class. It may be involved in a circular dependency loop. -// eslint-disable-next-line no-restricted-imports -import { svgIcon } from "@bitwarden/components"; +import { svgIcon } from "../icon-service"; export const RegistrationExpiredLinkIcon = svgIcon` diff --git a/libs/auth/src/angular/icons/registration-lock-alt.icon.ts b/libs/assets/src/svg/svgs/registration-lock-alt.icon.ts similarity index 94% rename from libs/auth/src/angular/icons/registration-lock-alt.icon.ts rename to libs/assets/src/svg/svgs/registration-lock-alt.icon.ts index d312e909413..2e81989c304 100644 --- a/libs/auth/src/angular/icons/registration-lock-alt.icon.ts +++ b/libs/assets/src/svg/svgs/registration-lock-alt.icon.ts @@ -1,6 +1,4 @@ -// This import has been flagged as unallowed for this class. It may be involved in a circular dependency loop. -// eslint-disable-next-line no-restricted-imports -import { svgIcon } from "@bitwarden/components"; +import { svgIcon } from "../icon-service"; export const RegistrationLockAltIcon = svgIcon` diff --git a/libs/auth/src/angular/icons/registration-user-add.icon.ts b/libs/assets/src/svg/svgs/registration-user-add.icon.ts similarity index 93% rename from libs/auth/src/angular/icons/registration-user-add.icon.ts rename to libs/assets/src/svg/svgs/registration-user-add.icon.ts index 4f68453639d..2aa5bcc81b5 100644 --- a/libs/auth/src/angular/icons/registration-user-add.icon.ts +++ b/libs/assets/src/svg/svgs/registration-user-add.icon.ts @@ -1,6 +1,4 @@ -// This import has been flagged as unallowed for this class. It may be involved in a circular dependency loop. -// eslint-disable-next-line no-restricted-imports -import { svgIcon } from "@bitwarden/components"; +import { svgIcon } from "../icon-service"; export const RegistrationUserAddIcon = svgIcon` diff --git a/apps/web/src/app/dirt/reports/icons/report-breach.icon.ts b/libs/assets/src/svg/svgs/report-breach.icon.ts similarity index 96% rename from apps/web/src/app/dirt/reports/icons/report-breach.icon.ts rename to libs/assets/src/svg/svgs/report-breach.icon.ts index 749779a87bc..6e7fde74cbc 100644 --- a/apps/web/src/app/dirt/reports/icons/report-breach.icon.ts +++ b/libs/assets/src/svg/svgs/report-breach.icon.ts @@ -1,4 +1,4 @@ -import { svgIcon } from "@bitwarden/components"; +import { svgIcon } from "../icon-service"; export const ReportBreach = svgIcon` diff --git a/apps/web/src/app/dirt/reports/icons/report-exposed-passwords.icon.ts b/libs/assets/src/svg/svgs/report-exposed-passwords.icon.ts similarity index 97% rename from apps/web/src/app/dirt/reports/icons/report-exposed-passwords.icon.ts rename to libs/assets/src/svg/svgs/report-exposed-passwords.icon.ts index df532fe1582..0a019885805 100644 --- a/apps/web/src/app/dirt/reports/icons/report-exposed-passwords.icon.ts +++ b/libs/assets/src/svg/svgs/report-exposed-passwords.icon.ts @@ -1,4 +1,4 @@ -import { svgIcon } from "@bitwarden/components"; +import { svgIcon } from "../icon-service"; export const ReportExposedPasswords = svgIcon` diff --git a/apps/web/src/app/dirt/reports/icons/report-inactive-two-factor.icon.ts b/libs/assets/src/svg/svgs/report-inactive-two-factor.icon.ts similarity index 94% rename from apps/web/src/app/dirt/reports/icons/report-inactive-two-factor.icon.ts rename to libs/assets/src/svg/svgs/report-inactive-two-factor.icon.ts index 65ca4469648..d7ad3c9084c 100644 --- a/apps/web/src/app/dirt/reports/icons/report-inactive-two-factor.icon.ts +++ b/libs/assets/src/svg/svgs/report-inactive-two-factor.icon.ts @@ -1,4 +1,4 @@ -import { svgIcon } from "@bitwarden/components"; +import { svgIcon } from "../icon-service"; export const ReportInactiveTwoFactor = svgIcon` diff --git a/apps/web/src/app/dirt/reports/icons/report-member-access.icon.ts b/libs/assets/src/svg/svgs/report-member-access.icon.ts similarity index 96% rename from apps/web/src/app/dirt/reports/icons/report-member-access.icon.ts rename to libs/assets/src/svg/svgs/report-member-access.icon.ts index 825968cd0c0..c47fed9cd2a 100644 --- a/apps/web/src/app/dirt/reports/icons/report-member-access.icon.ts +++ b/libs/assets/src/svg/svgs/report-member-access.icon.ts @@ -1,4 +1,4 @@ -import { svgIcon } from "@bitwarden/components"; +import { svgIcon } from "../icon-service"; export const MemberAccess = svgIcon` diff --git a/apps/web/src/app/dirt/reports/icons/report-reused-passwords.icon.ts b/libs/assets/src/svg/svgs/report-reused-passwords.icon.ts similarity index 96% rename from apps/web/src/app/dirt/reports/icons/report-reused-passwords.icon.ts rename to libs/assets/src/svg/svgs/report-reused-passwords.icon.ts index d28790ba051..30aaeee80fa 100644 --- a/apps/web/src/app/dirt/reports/icons/report-reused-passwords.icon.ts +++ b/libs/assets/src/svg/svgs/report-reused-passwords.icon.ts @@ -1,4 +1,4 @@ -import { svgIcon } from "@bitwarden/components"; +import { svgIcon } from "../icon-service"; export const ReportReusedPasswords = svgIcon` diff --git a/apps/web/src/app/dirt/reports/icons/report-unsecured-websites.icon.ts b/libs/assets/src/svg/svgs/report-unsecured-websites.icon.ts similarity index 94% rename from apps/web/src/app/dirt/reports/icons/report-unsecured-websites.icon.ts rename to libs/assets/src/svg/svgs/report-unsecured-websites.icon.ts index 083ddb40db7..d55c06987ca 100644 --- a/apps/web/src/app/dirt/reports/icons/report-unsecured-websites.icon.ts +++ b/libs/assets/src/svg/svgs/report-unsecured-websites.icon.ts @@ -1,4 +1,4 @@ -import { svgIcon } from "@bitwarden/components"; +import { svgIcon } from "../icon-service"; export const ReportUnsecuredWebsites = svgIcon` diff --git a/apps/web/src/app/dirt/reports/icons/report-weak-passwords.icon.ts b/libs/assets/src/svg/svgs/report-weak-passwords.icon.ts similarity index 95% rename from apps/web/src/app/dirt/reports/icons/report-weak-passwords.icon.ts rename to libs/assets/src/svg/svgs/report-weak-passwords.icon.ts index 8a0ef324c73..9709255169b 100644 --- a/apps/web/src/app/dirt/reports/icons/report-weak-passwords.icon.ts +++ b/libs/assets/src/svg/svgs/report-weak-passwords.icon.ts @@ -1,4 +1,4 @@ -import { svgIcon } from "@bitwarden/components"; +import { svgIcon } from "../icon-service"; export const ReportWeakPasswords = svgIcon` diff --git a/libs/assets/src/svg/svgs/restricted-view.ts b/libs/assets/src/svg/svgs/restricted-view.ts new file mode 100644 index 00000000000..afe6c752870 --- /dev/null +++ b/libs/assets/src/svg/svgs/restricted-view.ts @@ -0,0 +1,6 @@ +import { svgIcon } from "../icon-service"; + +export const RestrictedView = svgIcon` + + +`; diff --git a/libs/components/src/icon/icons/search.ts b/libs/assets/src/svg/svgs/search.ts similarity index 98% rename from libs/components/src/icon/icons/search.ts rename to libs/assets/src/svg/svgs/search.ts index 914fa0e9813..40f323acf3e 100644 --- a/libs/components/src/icon/icons/search.ts +++ b/libs/assets/src/svg/svgs/search.ts @@ -1,4 +1,4 @@ -import { svgIcon } from "../icon"; +import { svgIcon } from "../icon-service"; export const Search = svgIcon` diff --git a/apps/web/src/app/layouts/secrets-manager-logo.ts b/libs/assets/src/svg/svgs/secrets-manager-alt.ts similarity index 99% rename from apps/web/src/app/layouts/secrets-manager-logo.ts rename to libs/assets/src/svg/svgs/secrets-manager-alt.ts index 70f0f46540e..293bd99cbf3 100644 --- a/apps/web/src/app/layouts/secrets-manager-logo.ts +++ b/libs/assets/src/svg/svgs/secrets-manager-alt.ts @@ -1,5 +1,5 @@ -import { svgIcon } from "@bitwarden/components"; +import { svgIcon } from "../icon-service"; -export const SecretsManagerLogo = svgIcon` +export const SecretsManagerAlt = svgIcon` `; diff --git a/libs/components/src/icon/logos/bitwarden/secrets-manager.ts b/libs/assets/src/svg/svgs/secrets-manager.ts similarity index 99% rename from libs/components/src/icon/logos/bitwarden/secrets-manager.ts rename to libs/assets/src/svg/svgs/secrets-manager.ts index 45f3418b1e8..b2657f8fb67 100644 --- a/libs/components/src/icon/logos/bitwarden/secrets-manager.ts +++ b/libs/assets/src/svg/svgs/secrets-manager.ts @@ -1,4 +1,4 @@ -import { svgIcon } from "../../icon"; +import { svgIcon } from "../icon-service"; const SecretsManagerLogo = svgIcon` diff --git a/libs/vault/src/icons/secure-devices.ts b/libs/assets/src/svg/svgs/secure-devices.ts similarity index 97% rename from libs/vault/src/icons/secure-devices.ts rename to libs/assets/src/svg/svgs/secure-devices.ts index 4e123afad40..ed216f1bc87 100644 --- a/libs/vault/src/icons/secure-devices.ts +++ b/libs/assets/src/svg/svgs/secure-devices.ts @@ -1,4 +1,4 @@ -import { svgIcon } from "@bitwarden/components"; +import { svgIcon } from "../icon-service"; export const SecureDevices = svgIcon` diff --git a/libs/vault/src/icons/secure-user.ts b/libs/assets/src/svg/svgs/secure-user.ts similarity index 98% rename from libs/vault/src/icons/secure-user.ts rename to libs/assets/src/svg/svgs/secure-user.ts index 39d9957030c..8684549a815 100644 --- a/libs/vault/src/icons/secure-user.ts +++ b/libs/assets/src/svg/svgs/secure-user.ts @@ -1,4 +1,4 @@ -import { svgIcon } from "@bitwarden/components"; +import { svgIcon } from "../icon-service"; export const SecureUser = svgIcon` diff --git a/libs/vault/src/icons/security-handshake.ts b/libs/assets/src/svg/svgs/security-handshake.ts similarity index 99% rename from libs/vault/src/icons/security-handshake.ts rename to libs/assets/src/svg/svgs/security-handshake.ts index d68f8a948d3..f6309bc4c54 100644 --- a/libs/vault/src/icons/security-handshake.ts +++ b/libs/assets/src/svg/svgs/security-handshake.ts @@ -1,4 +1,4 @@ -import { svgIcon } from "@bitwarden/components"; +import { svgIcon } from "../icon-service"; export const SecurityHandshake = svgIcon` diff --git a/libs/components/src/icon/icons/security.ts b/libs/assets/src/svg/svgs/security.ts similarity index 99% rename from libs/components/src/icon/icons/security.ts rename to libs/assets/src/svg/svgs/security.ts index 5732b8066c6..0edf0aec14f 100644 --- a/libs/components/src/icon/icons/security.ts +++ b/libs/assets/src/svg/svgs/security.ts @@ -1,4 +1,4 @@ -import { svgIcon } from "../icon"; +import { svgIcon } from "../icon-service"; export const Security = svgIcon` diff --git a/libs/components/src/icon/icons/send.ts b/libs/assets/src/svg/svgs/send.ts similarity index 97% rename from libs/components/src/icon/icons/send.ts rename to libs/assets/src/svg/svgs/send.ts index 19026fc74cc..f09f59a5388 100644 --- a/libs/components/src/icon/icons/send.ts +++ b/libs/assets/src/svg/svgs/send.ts @@ -1,4 +1,4 @@ -import { svgIcon } from "../icon"; +import { svgIcon } from "../icon-service"; export const SendInactive = svgIcon` diff --git a/libs/components/src/icon/icons/settings.ts b/libs/assets/src/svg/svgs/settings.ts similarity index 99% rename from libs/components/src/icon/icons/settings.ts rename to libs/assets/src/svg/svgs/settings.ts index 361999bc244..3b54bbbd88c 100644 --- a/libs/components/src/icon/icons/settings.ts +++ b/libs/assets/src/svg/svgs/settings.ts @@ -1,4 +1,4 @@ -import { svgIcon } from "../icon"; +import { svgIcon } from "../icon-service"; export const SettingsInactive = svgIcon` diff --git a/libs/components/src/icon/logos/bitwarden/shield.ts b/libs/assets/src/svg/svgs/shield.ts similarity index 98% rename from libs/components/src/icon/logos/bitwarden/shield.ts rename to libs/assets/src/svg/svgs/shield.ts index d736a44ba3e..57a92e66e82 100644 --- a/libs/components/src/icon/logos/bitwarden/shield.ts +++ b/libs/assets/src/svg/svgs/shield.ts @@ -1,4 +1,4 @@ -import { svgIcon } from "../../icon"; +import { svgIcon } from "../icon-service"; /** * Shield logo with extra space in the viewbox. diff --git a/libs/auth/src/angular/icons/sso-key.icon.ts b/libs/assets/src/svg/svgs/sso-key.icon.ts similarity index 92% rename from libs/auth/src/angular/icons/sso-key.icon.ts rename to libs/assets/src/svg/svgs/sso-key.icon.ts index e00c3555906..533c033feac 100644 --- a/libs/auth/src/angular/icons/sso-key.icon.ts +++ b/libs/assets/src/svg/svgs/sso-key.icon.ts @@ -1,6 +1,4 @@ -// This import has been flagged as unallowed for this class. It may be involved in a circular dependency loop. -// eslint-disable-next-line no-restricted-imports -import { svgIcon } from "@bitwarden/components"; +import { svgIcon } from "../icon-service"; export const SsoKeyIcon = svgIcon` diff --git a/apps/web/src/app/billing/organizations/icons/subscription-hidden.icon.ts b/libs/assets/src/svg/svgs/subscription-hidden.ts similarity index 99% rename from apps/web/src/app/billing/organizations/icons/subscription-hidden.icon.ts rename to libs/assets/src/svg/svgs/subscription-hidden.ts index 82490e82a1d..38840580f86 100644 --- a/apps/web/src/app/billing/organizations/icons/subscription-hidden.icon.ts +++ b/libs/assets/src/svg/svgs/subscription-hidden.ts @@ -1,6 +1,6 @@ -import { Icon, svgIcon } from "@bitwarden/components"; +import { svgIcon } from "../icon-service"; -export const SubscriptionHiddenIcon: Icon = svgIcon` +export const SubscriptionHiddenIcon = svgIcon` diff --git a/libs/angular/src/auth/icons/totp.icon.ts b/libs/assets/src/svg/svgs/totp.icon.ts similarity index 98% rename from libs/angular/src/auth/icons/totp.icon.ts rename to libs/assets/src/svg/svgs/totp.icon.ts index 1754e77b308..00e96c93b6f 100644 --- a/libs/angular/src/auth/icons/totp.icon.ts +++ b/libs/assets/src/svg/svgs/totp.icon.ts @@ -1,4 +1,4 @@ -import { svgIcon } from "@bitwarden/components"; +import { svgIcon } from "../icon-service"; export const TOTPIcon = svgIcon` diff --git a/libs/auth/src/angular/icons/two-factor-auth/two-factor-auth-duo.icon.ts b/libs/assets/src/svg/svgs/two-factor-auth-duo.icon.ts similarity index 81% rename from libs/auth/src/angular/icons/two-factor-auth/two-factor-auth-duo.icon.ts rename to libs/assets/src/svg/svgs/two-factor-auth-duo.icon.ts index a64027c5fba..d56e3b325d1 100644 --- a/libs/auth/src/angular/icons/two-factor-auth/two-factor-auth-duo.icon.ts +++ b/libs/assets/src/svg/svgs/two-factor-auth-duo.icon.ts @@ -1,6 +1,4 @@ -// This import has been flagged as unallowed for this class. It may be involved in a circular dependency loop. -// eslint-disable-next-line no-restricted-imports -import { svgIcon } from "@bitwarden/components"; +import { svgIcon } from "../icon-service"; export const TwoFactorAuthDuoIcon = svgIcon` diff --git a/libs/auth/src/angular/icons/two-factor-auth/two-factor-auth-email.icon.ts b/libs/assets/src/svg/svgs/two-factor-auth-email.icon.ts similarity index 90% rename from libs/auth/src/angular/icons/two-factor-auth/two-factor-auth-email.icon.ts rename to libs/assets/src/svg/svgs/two-factor-auth-email.icon.ts index 380bc16a738..71ffc099e58 100644 --- a/libs/auth/src/angular/icons/two-factor-auth/two-factor-auth-email.icon.ts +++ b/libs/assets/src/svg/svgs/two-factor-auth-email.icon.ts @@ -1,6 +1,4 @@ -// This import has been flagged as unallowed for this class. It may be involved in a circular dependency loop. -// eslint-disable-next-line no-restricted-imports -import { svgIcon } from "@bitwarden/components"; +import { svgIcon } from "../icon-service"; export const TwoFactorAuthEmailIcon = svgIcon` diff --git a/libs/auth/src/angular/icons/two-factor-auth/two-factor-auth-security-key.icon.ts b/libs/assets/src/svg/svgs/two-factor-auth-security-key.icon.ts similarity index 96% rename from libs/auth/src/angular/icons/two-factor-auth/two-factor-auth-security-key.icon.ts rename to libs/assets/src/svg/svgs/two-factor-auth-security-key.icon.ts index 573dc890428..644f98a0cbd 100644 --- a/libs/auth/src/angular/icons/two-factor-auth/two-factor-auth-security-key.icon.ts +++ b/libs/assets/src/svg/svgs/two-factor-auth-security-key.icon.ts @@ -1,6 +1,4 @@ -// This import has been flagged as unallowed for this class. It may be involved in a circular dependency loop. -// eslint-disable-next-line no-restricted-imports -import { svgIcon } from "@bitwarden/components"; +import { svgIcon } from "../icon-service"; export const TwoFactorAuthSecurityKeyIcon = svgIcon` diff --git a/libs/auth/src/angular/icons/two-factor-auth/two-factor-auth-webauthn.icon.ts b/libs/assets/src/svg/svgs/two-factor-auth-webauthn.icon.ts similarity index 96% rename from libs/auth/src/angular/icons/two-factor-auth/two-factor-auth-webauthn.icon.ts rename to libs/assets/src/svg/svgs/two-factor-auth-webauthn.icon.ts index ff73bf2e255..f5e7519e024 100644 --- a/libs/auth/src/angular/icons/two-factor-auth/two-factor-auth-webauthn.icon.ts +++ b/libs/assets/src/svg/svgs/two-factor-auth-webauthn.icon.ts @@ -1,6 +1,4 @@ -// This import has been flagged as unallowed for this class. It may be involved in a circular dependency loop. -// eslint-disable-next-line no-restricted-imports -import { svgIcon } from "@bitwarden/components"; +import { svgIcon } from "../icon-service"; export const TwoFactorAuthWebAuthnIcon = svgIcon` diff --git a/libs/auth/src/angular/icons/two-factor-auth/two-factor-auth-yubico.icon.ts b/libs/assets/src/svg/svgs/two-factor-auth-yubico.icon.ts similarity index 93% rename from libs/auth/src/angular/icons/two-factor-auth/two-factor-auth-yubico.icon.ts rename to libs/assets/src/svg/svgs/two-factor-auth-yubico.icon.ts index 8f6dca837ad..231b3c3f5b1 100644 --- a/libs/auth/src/angular/icons/two-factor-auth/two-factor-auth-yubico.icon.ts +++ b/libs/assets/src/svg/svgs/two-factor-auth-yubico.icon.ts @@ -1,6 +1,4 @@ -// This import has been flagged as unallowed for this class. It may be involved in a circular dependency loop. -// eslint-disable-next-line no-restricted-imports -import { svgIcon } from "@bitwarden/components"; +import { svgIcon } from "../icon-service"; export const TwoFactorAuthYubicoIcon = svgIcon` diff --git a/libs/auth/src/angular/icons/two-factor-timeout.icon.ts b/libs/assets/src/svg/svgs/two-factor-timeout.icon.ts similarity index 88% rename from libs/auth/src/angular/icons/two-factor-timeout.icon.ts rename to libs/assets/src/svg/svgs/two-factor-timeout.icon.ts index 3681670c124..7a5e04c07a3 100644 --- a/libs/auth/src/angular/icons/two-factor-timeout.icon.ts +++ b/libs/assets/src/svg/svgs/two-factor-timeout.icon.ts @@ -1,6 +1,4 @@ -// This import has been flagged as unallowed for this class. It may be involved in a circular dependency loop. -// eslint-disable-next-line no-restricted-imports -import { svgIcon } from "@bitwarden/components"; +import { svgIcon } from "../icon-service"; export const TwoFactorTimeoutIcon = svgIcon` diff --git a/libs/auth/src/angular/icons/user-lock.icon.ts b/libs/assets/src/svg/svgs/user-lock.icon.ts similarity index 95% rename from libs/auth/src/angular/icons/user-lock.icon.ts rename to libs/assets/src/svg/svgs/user-lock.icon.ts index bc4fdd9e268..ad56d612268 100644 --- a/libs/auth/src/angular/icons/user-lock.icon.ts +++ b/libs/assets/src/svg/svgs/user-lock.icon.ts @@ -1,6 +1,4 @@ -// This import has been flagged as unallowed for this class. It may be involved in a circular dependency loop. -// eslint-disable-next-line no-restricted-imports -import { svgIcon } from "@bitwarden/components"; +import { svgIcon } from "../icon-service"; export const UserLockIcon = svgIcon` diff --git a/libs/auth/src/angular/icons/user-verification-biometrics-fingerprint.icon.ts b/libs/assets/src/svg/svgs/user-verification-biometrics-fingerprint.icon.ts similarity index 92% rename from libs/auth/src/angular/icons/user-verification-biometrics-fingerprint.icon.ts rename to libs/assets/src/svg/svgs/user-verification-biometrics-fingerprint.icon.ts index e329d889574..b3ace19a93d 100644 --- a/libs/auth/src/angular/icons/user-verification-biometrics-fingerprint.icon.ts +++ b/libs/assets/src/svg/svgs/user-verification-biometrics-fingerprint.icon.ts @@ -1,6 +1,4 @@ -// This import has been flagged as unallowed for this class. It may be involved in a circular dependency loop. -// eslint-disable-next-line no-restricted-imports -import { svgIcon } from "@bitwarden/components"; +import { svgIcon } from "../icon-service"; export const UserVerificationBiometricsIcon = svgIcon` diff --git a/libs/vault/src/icons/vault.ts b/libs/assets/src/svg/svgs/vault-open.ts similarity index 98% rename from libs/vault/src/icons/vault.ts rename to libs/assets/src/svg/svgs/vault-open.ts index 577080b0f37..e644e316c05 100644 --- a/libs/vault/src/icons/vault.ts +++ b/libs/assets/src/svg/svgs/vault-open.ts @@ -1,6 +1,6 @@ -import { svgIcon } from "@bitwarden/components"; +import { svgIcon } from "../icon-service"; -export const Vault = svgIcon` +export const VaultOpen = svgIcon` diff --git a/libs/auth/src/angular/icons/vault.icon.ts b/libs/assets/src/svg/svgs/vault.icon.ts similarity index 92% rename from libs/auth/src/angular/icons/vault.icon.ts rename to libs/assets/src/svg/svgs/vault.icon.ts index a341bcd99f5..21fcac24e7e 100644 --- a/libs/auth/src/angular/icons/vault.icon.ts +++ b/libs/assets/src/svg/svgs/vault.icon.ts @@ -1,6 +1,4 @@ -// This import has been flagged as unallowed for this class. It may be involved in a circular dependency loop. -// eslint-disable-next-line no-restricted-imports -import { svgIcon } from "@bitwarden/components"; +import { svgIcon } from "../icon-service"; export const VaultIcon = svgIcon` diff --git a/libs/components/src/icon/icons/vault.ts b/libs/assets/src/svg/svgs/vault.ts similarity index 99% rename from libs/components/src/icon/icons/vault.ts rename to libs/assets/src/svg/svgs/vault.ts index eda2e3d6b60..1c699f2ba8e 100644 --- a/libs/components/src/icon/icons/vault.ts +++ b/libs/assets/src/svg/svgs/vault.ts @@ -1,4 +1,4 @@ -import { svgIcon } from "../icon"; +import { svgIcon } from "../icon-service"; export const VaultInactive = svgIcon` diff --git a/libs/auth/src/angular/icons/wave.icon.ts b/libs/assets/src/svg/svgs/wave.icon.ts similarity index 90% rename from libs/auth/src/angular/icons/wave.icon.ts rename to libs/assets/src/svg/svgs/wave.icon.ts index 5629c43fc8d..b7e16213d0f 100644 --- a/libs/auth/src/angular/icons/wave.icon.ts +++ b/libs/assets/src/svg/svgs/wave.icon.ts @@ -1,6 +1,4 @@ -// This import has been flagged as unallowed for this class. It may be involved in a circular dependency loop. -// eslint-disable-next-line no-restricted-imports -import { svgIcon } from "@bitwarden/components"; +import { svgIcon } from "../icon-service"; export const WaveIcon = svgIcon` diff --git a/libs/angular/src/auth/icons/webauthn.icon.ts b/libs/assets/src/svg/svgs/webauthn.icon.ts similarity index 96% rename from libs/angular/src/auth/icons/webauthn.icon.ts rename to libs/assets/src/svg/svgs/webauthn.icon.ts index a72692233d8..c679438106c 100644 --- a/libs/angular/src/auth/icons/webauthn.icon.ts +++ b/libs/assets/src/svg/svgs/webauthn.icon.ts @@ -1,4 +1,4 @@ -import { svgIcon } from "@bitwarden/components"; +import { svgIcon } from "../icon-service"; export const WebAuthnIcon = svgIcon` (); readonly subtitle = input(); diff --git a/libs/components/src/anon-layout/anon-layout.mdx b/libs/components/src/anon-layout/anon-layout.mdx index 9d40d617b0d..3c6faeccfb0 100644 --- a/libs/components/src/anon-layout/anon-layout.mdx +++ b/libs/components/src/anon-layout/anon-layout.mdx @@ -65,7 +65,8 @@ example) to construct the page via routable composition: ```typescript // File: oss-routing.module.ts -import { AnonLayoutWrapperComponent, AnonLayoutWrapperData, LockIcon } from "@bitwarden/auth/angular"; +import { AnonLayoutWrapperComponent, AnonLayoutWrapperData } from "@bitwarden/auth/angular"; +import { LockIcon } from "@bitwarden/assets/svg"; { path: "", @@ -116,7 +117,8 @@ in the `AnonLayoutWrapperData` interface: All of these properties are optional. ```typescript -import { AnonLayoutWrapperComponent, AnonLayoutWrapperData, LockIcon } from "@bitwarden/auth/angular"; +import { AnonLayoutWrapperComponent, AnonLayoutWrapperData } from "@bitwarden/auth/angular"; +import { LockIcon } from "@bitwarden/assets/svg"; { // ... @@ -137,7 +139,8 @@ on your client) as a component with `outlet: "environment-selector"`. ```javascript // File: oss-routing.module.ts -import { AnonLayoutWrapperComponent, AnonLayoutWrapperData, LockIcon } from "@bitwarden/auth/angular"; +import { AnonLayoutWrapperComponent, AnonLayoutWrapperData } from "@bitwarden/auth/angular"; + import { EnvironmentSelectorComponent } from "./components/environment-selector/environment-selector.component"; { diff --git a/libs/components/src/anon-layout/anon-layout.stories.ts b/libs/components/src/anon-layout/anon-layout.stories.ts index 339f76ec06b..15cce39d8b7 100644 --- a/libs/components/src/anon-layout/anon-layout.stories.ts +++ b/libs/components/src/anon-layout/anon-layout.stories.ts @@ -2,14 +2,13 @@ import { ActivatedRoute, RouterModule } from "@angular/router"; import { Meta, StoryObj, moduleMetadata } from "@storybook/angular"; import { BehaviorSubject, of } from "rxjs"; +import { Icon, LockIcon } from "@bitwarden/assets/svg"; import { ClientType } from "@bitwarden/common/enums"; import { EnvironmentService } from "@bitwarden/common/platform/abstractions/environment.service"; import { I18nService } from "@bitwarden/common/platform/abstractions/i18n.service"; import { PlatformUtilsService } from "@bitwarden/common/platform/abstractions/platform-utils.service"; import { ButtonModule } from "../button"; -import { Icon } from "../icon"; -import { LockIcon } from "../icon/icons"; import { I18nMockService } from "../utils/i18n-mock.service"; import { AnonLayoutComponent } from "./anon-layout.component"; diff --git a/libs/components/src/anon-layout/illustrations/index.ts b/libs/components/src/anon-layout/illustrations/index.ts deleted file mode 100644 index a107eb7cd15..00000000000 --- a/libs/components/src/anon-layout/illustrations/index.ts +++ /dev/null @@ -1,2 +0,0 @@ -export * from "./left-illustration"; -export * from "./right-illustration"; diff --git a/libs/components/src/icon/icon.component.ts b/libs/components/src/icon/icon.component.ts index ec25ad30d56..49f284b947c 100644 --- a/libs/components/src/icon/icon.component.ts +++ b/libs/components/src/icon/icon.component.ts @@ -1,7 +1,7 @@ import { Component, effect, input } from "@angular/core"; import { DomSanitizer, SafeHtml } from "@angular/platform-browser"; -import { Icon, isIcon } from "./icon"; +import { Icon, isIcon } from "@bitwarden/assets/svg"; @Component({ selector: "bit-icon", diff --git a/libs/components/src/icon/icon.components.spec.ts b/libs/components/src/icon/icon.components.spec.ts index 76e86971587..3ae37ff5423 100644 --- a/libs/components/src/icon/icon.components.spec.ts +++ b/libs/components/src/icon/icon.components.spec.ts @@ -1,6 +1,7 @@ import { ComponentFixture, TestBed } from "@angular/core/testing"; -import { Icon, svgIcon } from "./icon"; +import { Icon, svgIcon } from "@bitwarden/assets/svg"; + import { BitIconComponent } from "./icon.component"; describe("IconComponent", () => { diff --git a/libs/components/src/icon/icon.mdx b/libs/components/src/icon/icon.mdx index e4186b5e4a9..9d48a2f3c45 100644 --- a/libs/components/src/icon/icon.mdx +++ b/libs/components/src/icon/icon.mdx @@ -23,9 +23,10 @@ import { IconModule } from "@bitwarden/components"; [SVG Formatter Beautifier](https://codebeautify.org/svg-formatter-beautifier) to make applying classes easier. -2. **Rename the file** as a `.icon.ts` TypeScript file. +2. **Rename the file** as a `.icon.ts` TypeScript file and place it in the `libs/assets/svg` + lib. -3. **Import** `svgIcon` from `@bitwarden/components`. +3. **Import** `svgIcon` from `./icon-service`. 4. **Define and export** a `const` to represent your `svgIcon`. @@ -74,7 +75,7 @@ import { IconModule } from "@bitwarden/components"; [viewBox](https://developer.mozilla.org/en-US/docs/Web/SVG/Attribute/viewBox) attribute in order to allow the SVG to scale to fit its container. - **Note:** Scaling is required for any SVG used as an - [AnonLayout](?path=/docs/auth-anon-layout--docs) `pageIcon`. + [AnonLayout](?path=/docs/component-library-anon-layout--docs) `pageIcon`. 7. **Import your SVG const** anywhere you want to use the SVG. - **Angular Component Example:** @@ -82,8 +83,8 @@ import { IconModule } from "@bitwarden/components"; ```typescript import { Component } from "@angular/core"; - import { ExampleIcon } from "your/path/here"; import { IconModule } from '@bitwarden/components'; + import { ExampleIcon, Example2Icon } from "@bitwarden/assets/svg"; @Component({ selector: "app-example", diff --git a/libs/components/src/icon/icon.stories.ts b/libs/components/src/icon/icon.stories.ts index 7892bdd3ec1..e71a7597913 100644 --- a/libs/components/src/icon/icon.stories.ts +++ b/libs/components/src/icon/icon.stories.ts @@ -1,7 +1,8 @@ import { Meta, StoryObj } from "@storybook/angular"; +import * as SvgIcons from "@bitwarden/assets/svg"; + import { BitIconComponent } from "./icon.component"; -import * as GenericIcons from "./icons"; export default { title: "Component Library/Icon", @@ -16,14 +17,18 @@ export default { type Story = StoryObj; +// Filtering out the few non-icons in the libs/assets/svg import +// eslint-disable-next-line @typescript-eslint/no-unused-vars +const { DynamicContentNotAllowedError, isIcon, svgIcon, ...Icons } = SvgIcons; + export const Default: Story = { args: { - icon: GenericIcons.NoAccess, + icon: Icons.NoAccess, }, argTypes: { icon: { - options: Object.keys(GenericIcons), - mapping: GenericIcons, + options: Object.keys(Icons), + mapping: Icons, control: { type: "select" }, }, ariaLabel: { diff --git a/libs/components/src/icon/icons/index.ts b/libs/components/src/icon/icons/index.ts deleted file mode 100644 index 69fac7d644e..00000000000 --- a/libs/components/src/icon/icons/index.ts +++ /dev/null @@ -1,12 +0,0 @@ -export * from "./bitwarden-logo.icon"; -export * from "./extension-bitwarden-logo.icon"; -export * from "./lock.icon"; -export * from "./generator"; -export * from "./no-access"; -export * from "./no-results"; -export * from "./registration-check-email.icon"; -export * from "./search"; -export * from "./security"; -export * from "./send"; -export * from "./settings"; -export * from "./vault"; diff --git a/libs/components/src/icon/index.ts b/libs/components/src/icon/index.ts index 01819a3678e..1ee66e59837 100644 --- a/libs/components/src/icon/index.ts +++ b/libs/components/src/icon/index.ts @@ -1,10 +1 @@ export * from "./icon.module"; -export * from "./icon"; -export * as Icons from "./icons"; -export { - AdminConsoleLogo, - BusinessUnitPortalLogo, - PasswordManagerLogo, - ProviderPortalLogo, - SecretsManagerLogo, -} from "./logos"; diff --git a/libs/components/src/icon/logos/bitwarden/index.ts b/libs/components/src/icon/logos/bitwarden/index.ts deleted file mode 100644 index d74c6fe453a..00000000000 --- a/libs/components/src/icon/logos/bitwarden/index.ts +++ /dev/null @@ -1,6 +0,0 @@ -export { default as AdminConsoleLogo } from "./admin-console"; -export { default as BusinessUnitPortalLogo } from "./business-unit-portal"; -export * from "./shield"; -export { default as PasswordManagerLogo } from "./password-manager"; -export { default as ProviderPortalLogo } from "./provider-portal"; -export { default as SecretsManagerLogo } from "./secrets-manager"; diff --git a/libs/components/src/icon/logos/index.ts b/libs/components/src/icon/logos/index.ts deleted file mode 100644 index 07a8a739289..00000000000 --- a/libs/components/src/icon/logos/index.ts +++ /dev/null @@ -1 +0,0 @@ -export * from "./bitwarden"; diff --git a/libs/components/src/navigation/nav-logo.component.ts b/libs/components/src/navigation/nav-logo.component.ts index 52d67446f2f..96258740d74 100644 --- a/libs/components/src/navigation/nav-logo.component.ts +++ b/libs/components/src/navigation/nav-logo.component.ts @@ -2,9 +2,9 @@ import { CommonModule } from "@angular/common"; import { Component, input } from "@angular/core"; import { RouterLinkActive, RouterLink } from "@angular/router"; -import { Icon } from "../icon"; +import { BitwardenShield, Icon } from "@bitwarden/assets/svg"; + import { BitIconComponent } from "../icon/icon.component"; -import { BitwardenShield } from "../icon/logos"; import { SideNavService } from "./side-nav.service"; diff --git a/libs/components/src/no-items/no-items.component.ts b/libs/components/src/no-items/no-items.component.ts index 7c00999f59f..3d7394a16ae 100644 --- a/libs/components/src/no-items/no-items.component.ts +++ b/libs/components/src/no-items/no-items.component.ts @@ -1,6 +1,7 @@ import { Component, input } from "@angular/core"; -import { Icons } from ".."; +import { Search } from "@bitwarden/assets/svg"; + import { BitIconComponent } from "../icon/icon.component"; /** @@ -12,5 +13,5 @@ import { BitIconComponent } from "../icon/icon.component"; imports: [BitIconComponent], }) export class NoItemsComponent { - readonly icon = input(Icons.Search); + readonly icon = input(Search); } diff --git a/libs/components/src/stories/kitchen-sink/kitchen-sink.stories.ts b/libs/components/src/stories/kitchen-sink/kitchen-sink.stories.ts index cb8a72e1b3f..2cacab5af75 100644 --- a/libs/components/src/stories/kitchen-sink/kitchen-sink.stories.ts +++ b/libs/components/src/stories/kitchen-sink/kitchen-sink.stories.ts @@ -11,9 +11,9 @@ import { getAllByLabelText, } from "@storybook/test"; +import { PasswordManagerLogo } from "@bitwarden/assets/svg"; import { I18nService } from "@bitwarden/common/platform/abstractions/i18n.service"; -import { PasswordManagerLogo } from "../../icon"; import { LayoutComponent } from "../../layout"; import { I18nMockService } from "../../utils/i18n-mock.service"; import { positionFixedWrapperDecorator } from "../storybook-decorators"; diff --git a/libs/components/tailwind.config.base.js b/libs/components/tailwind.config.base.js index fe33e592609..95b239537ff 100644 --- a/libs/components/tailwind.config.base.js +++ b/libs/components/tailwind.config.base.js @@ -10,6 +10,7 @@ module.exports = { prefix: "tw-", content: [ "./src/**/*.{html,ts}", + "../../libs/assets/src/**/*.{html,ts}", "../../libs/components/src/**/*.{html,ts}", "../../libs/key-management-ui/src/**/*.{html,ts}", "../../libs/auth/src/**/*.{html,ts}", diff --git a/libs/components/tailwind.config.js b/libs/components/tailwind.config.js index d256214a4ff..d8cef6596dc 100644 --- a/libs/components/tailwind.config.js +++ b/libs/components/tailwind.config.js @@ -3,6 +3,7 @@ const config = require("./tailwind.config.base"); config.content = [ "libs/components/src/**/*.{html,ts,mdx}", + "libs/assets/src/**/*.{html,ts,mdx}", "libs/auth/src/**/*.{html,ts,mdx}", "libs/vault/src/**/*.{html,ts,mdx}", "apps/web/src/**/*.{html,ts,mdx}", diff --git a/libs/tools/generator/components/src/empty-credential-history.component.ts b/libs/tools/generator/components/src/empty-credential-history.component.ts index 29c9fc277fc..6ae55d33d2c 100644 --- a/libs/tools/generator/components/src/empty-credential-history.component.ts +++ b/libs/tools/generator/components/src/empty-credential-history.component.ts @@ -1,10 +1,9 @@ import { Component } from "@angular/core"; import { JslibModule } from "@bitwarden/angular/jslib.module"; +import { NoCredentialsIcon } from "@bitwarden/assets/svg"; import { IconModule, TypographyModule } from "@bitwarden/components"; -import { NoCredentialsIcon } from "./icons/no-credentials.icon"; - @Component({ selector: "bit-empty-credential-history", templateUrl: "empty-credential-history.component.html", diff --git a/libs/tools/send/send-ui/src/icons/index.ts b/libs/tools/send/send-ui/src/icons/index.ts deleted file mode 100644 index 57636daadcf..00000000000 --- a/libs/tools/send/send-ui/src/icons/index.ts +++ /dev/null @@ -1,3 +0,0 @@ -export { ExpiredSendIcon } from "./expired-send.icon"; -export { NoSendsIcon } from "./no-send.icon"; -export { ActiveSendIcon } from "./active-send.icon"; diff --git a/libs/tools/send/send-ui/src/index.ts b/libs/tools/send/send-ui/src/index.ts index db4416a13f0..2803e91c418 100644 --- a/libs/tools/send/send-ui/src/index.ts +++ b/libs/tools/send/send-ui/src/index.ts @@ -1,4 +1,3 @@ -export * from "./icons"; export * from "./send-form"; export { NewSendDropdownComponent } from "./new-send-dropdown/new-send-dropdown.component"; export * from "./add-edit/send-add-edit-dialog.component"; diff --git a/libs/vault/src/components/carousel/carousel-button/carousel-button.component.ts b/libs/vault/src/components/carousel/carousel-button/carousel-button.component.ts index 7b5f7d3b164..ae2ce12cba8 100644 --- a/libs/vault/src/components/carousel/carousel-button/carousel-button.component.ts +++ b/libs/vault/src/components/carousel/carousel-button/carousel-button.component.ts @@ -2,9 +2,9 @@ import { FocusableOption } from "@angular/cdk/a11y"; import { CommonModule } from "@angular/common"; import { Component, ElementRef, EventEmitter, Input, Output, ViewChild } from "@angular/core"; +import { CarouselIcon } from "@bitwarden/assets/svg"; import { IconModule } from "@bitwarden/components"; -import { CarouselIcon } from "../carousel-icons/carousel-icon"; import { VaultCarouselSlideComponent } from "../carousel-slide/carousel-slide.component"; @Component({ diff --git a/libs/vault/src/icons/index.ts b/libs/vault/src/icons/index.ts deleted file mode 100644 index 904399da4b3..00000000000 --- a/libs/vault/src/icons/index.ts +++ /dev/null @@ -1,11 +0,0 @@ -export * from "./deactivated-org"; -export * from "./no-folders"; -export * from "./vault"; -export * from "./empty-trash"; -export * from "./browser-extension"; -export * from "./bitwarden-icon"; -export * from "./security-handshake"; -export * from "./login-cards"; -export * from "./secure-user"; -export * from "./secure-devices"; -export * from "./party"; diff --git a/libs/vault/src/index.ts b/libs/vault/src/index.ts index 9d037d8fe5e..f3925ac3379 100644 --- a/libs/vault/src/index.ts +++ b/libs/vault/src/index.ts @@ -21,8 +21,6 @@ export * from "./components/add-edit-folder-dialog/add-edit-folder-dialog.compon export * from "./components/carousel"; export * from "./components/new-cipher-menu/new-cipher-menu.component"; -export * as VaultIcons from "./icons"; - export { DefaultSshImportPromptService } from "./services/default-ssh-import-prompt.service"; export { SshImportPromptService } from "./services/ssh-import-prompt.service"; diff --git a/package-lock.json b/package-lock.json index d2d497d10b0..c0958eab200 100644 --- a/package-lock.json +++ b/package-lock.json @@ -303,6 +303,11 @@ "version": "0.0.0", "license": "GPL-3.0" }, + "libs/assets": { + "name": "@bitwarden/assets", + "version": "0.0.1", + "license": "GPL-3.0" + }, "libs/auth": { "name": "@bitwarden/auth", "version": "0.0.0", @@ -4563,6 +4568,10 @@ "resolved": "libs/angular", "link": true }, + "node_modules/@bitwarden/assets": { + "resolved": "libs/assets", + "link": true + }, "node_modules/@bitwarden/auth": { "resolved": "libs/auth", "link": true diff --git a/tailwind.config.js b/tailwind.config.js index 637c28a54ea..dff04c897c3 100644 --- a/tailwind.config.js +++ b/tailwind.config.js @@ -6,6 +6,7 @@ config.content = [ "./libs/admin-console/src/**/*.{html,ts,mdx}", "./libs/auth/src/**/*.{html,ts,mdx}", "./libs/billing/src/**/*.{html,ts,mdx}", + "./libs/assets/src/**/*.{html,ts}", "./libs/platform/src/**/*.{html,ts,mdx}", "./libs/tools/send/send-ui/src/*.{html,ts,mdx}", "./libs/vault/src/**/*.{html,ts,mdx}", diff --git a/tsconfig.base.json b/tsconfig.base.json index c1256383915..8053bfe6c63 100644 --- a/tsconfig.base.json +++ b/tsconfig.base.json @@ -20,6 +20,8 @@ "paths": { "@bitwarden/admin-console/common": ["./libs/admin-console/src/common"], "@bitwarden/angular/*": ["./libs/angular/src/*"], + "@bitwarden/assets": ["libs/assets/src/index.ts"], + "@bitwarden/assets/svg": ["libs/assets/src/svg/index.ts"], "@bitwarden/auth/angular": ["./libs/auth/src/angular"], "@bitwarden/auth/common": ["./libs/auth/src/common"], "@bitwarden/billing": ["./libs/billing/src"], From a6e7efddeb5a6263053118b5f211e7d2b0c13a91 Mon Sep 17 00:00:00 2001 From: Thomas Avery <43214426+Thomas-Avery@users.noreply.github.com> Date: Thu, 21 Aug 2025 15:49:19 -0500 Subject: [PATCH 07/44] [PM-23627] Require publicKey for keyService getFingerprint (#15933) * require public key on keyService getFingerprint * Update consumers and add error handling & logging --- .../account-security.component.spec.ts | 2 - .../settings/account-security.component.ts | 16 ++++-- apps/cli/src/commands/get.command.ts | 3 + apps/desktop/src/app/app.component.ts | 18 ++++-- .../settings/account/profile.component.html | 13 +++-- .../settings/account/profile.component.ts | 24 ++++++-- .../src/abstractions/key.service.ts | 10 ++-- libs/key-management/src/key.service.spec.ts | 57 +++++++++++++++++++ libs/key-management/src/key.service.ts | 12 +--- 9 files changed, 119 insertions(+), 36 deletions(-) diff --git a/apps/browser/src/auth/popup/settings/account-security.component.spec.ts b/apps/browser/src/auth/popup/settings/account-security.component.spec.ts index 014f2a7638b..63666440a76 100644 --- a/apps/browser/src/auth/popup/settings/account-security.component.spec.ts +++ b/apps/browser/src/auth/popup/settings/account-security.component.spec.ts @@ -24,7 +24,6 @@ import { EnvironmentService } from "@bitwarden/common/platform/abstractions/envi import { I18nService } from "@bitwarden/common/platform/abstractions/i18n.service"; import { LogService } from "@bitwarden/common/platform/abstractions/log.service"; import { PlatformUtilsService } from "@bitwarden/common/platform/abstractions/platform-utils.service"; -import { StateService } from "@bitwarden/common/platform/abstractions/state.service"; import { ValidationService } from "@bitwarden/common/platform/abstractions/validation.service"; import { MessageSender } from "@bitwarden/common/platform/messaging"; import { Utils } from "@bitwarden/common/platform/misc/utils"; @@ -79,7 +78,6 @@ describe("AccountSecurityComponent", () => { { provide: PlatformUtilsService, useValue: platformUtilsService }, { provide: PolicyService, useValue: policyService }, { provide: PopupRouterCacheService, useValue: mock() }, - { provide: StateService, useValue: mock() }, { provide: ToastService, useValue: mock() }, { provide: UserVerificationService, useValue: mock() }, { provide: VaultTimeoutService, useValue: mock() }, diff --git a/apps/browser/src/auth/popup/settings/account-security.component.ts b/apps/browser/src/auth/popup/settings/account-security.component.ts index b41cfe14c4f..72a389ecf71 100644 --- a/apps/browser/src/auth/popup/settings/account-security.component.ts +++ b/apps/browser/src/auth/popup/settings/account-security.component.ts @@ -44,9 +44,9 @@ import { import { ConfigService } from "@bitwarden/common/platform/abstractions/config/config.service"; import { EnvironmentService } from "@bitwarden/common/platform/abstractions/environment.service"; import { I18nService } from "@bitwarden/common/platform/abstractions/i18n.service"; +import { LogService } from "@bitwarden/common/platform/abstractions/log.service"; import { MessagingService } from "@bitwarden/common/platform/abstractions/messaging.service"; import { PlatformUtilsService } from "@bitwarden/common/platform/abstractions/platform-utils.service"; -import { StateService } from "@bitwarden/common/platform/abstractions/state.service"; import { ValidationService } from "@bitwarden/common/platform/abstractions/validation.service"; import { DialogRef, @@ -149,7 +149,6 @@ export class AccountSecurityComponent implements OnInit, OnDestroy { public messagingService: MessagingService, private environmentService: EnvironmentService, private keyService: KeyService, - private stateService: StateService, private userVerificationService: UserVerificationService, private dialogService: DialogService, private changeDetectorRef: ChangeDetectorRef, @@ -159,6 +158,7 @@ export class AccountSecurityComponent implements OnInit, OnDestroy { private vaultNudgesService: NudgesService, private validationService: ValidationService, private configService: ConfigService, + private logService: LogService, ) {} async ngOnInit() { @@ -683,10 +683,16 @@ export class AccountSecurityComponent implements OnInit, OnDestroy { } async openAcctFingerprintDialog() { - const activeUserId = await firstValueFrom( - this.accountService.activeAccount$.pipe(map((a) => a?.id)), - ); + const activeUserId = await firstValueFrom(getUserId(this.accountService.activeAccount$)); const publicKey = await firstValueFrom(this.keyService.userPublicKey$(activeUserId)); + if (publicKey == null) { + this.logService.error( + "[AccountSecurityComponent] No public key available for the user: " + + activeUserId + + " fingerprint can't be displayed.", + ); + return; + } const fingerprint = await this.keyService.getFingerprint(activeUserId, publicKey); const dialogRef = FingerprintDialogComponent.open(this.dialogService, { diff --git a/apps/cli/src/commands/get.command.ts b/apps/cli/src/commands/get.command.ts index 58181cff6ce..a994ad3117c 100644 --- a/apps/cli/src/commands/get.command.ts +++ b/apps/cli/src/commands/get.command.ts @@ -606,6 +606,9 @@ export class GetCommand extends DownloadCommand { if (id === "me") { const activeUserId = await firstValueFrom(this.accountService.activeAccount$.pipe(getUserId)); const publicKey = await firstValueFrom(this.keyService.userPublicKey$(activeUserId)); + if (publicKey == null) { + return Response.error("No public key available for the active user."); + } fingerprint = await this.keyService.getFingerprint(activeUserId, publicKey); } else if (Utils.isGuid(id)) { try { diff --git a/apps/desktop/src/app/app.component.ts b/apps/desktop/src/app/app.component.ts index 197290cf690..c4e60e4ff93 100644 --- a/apps/desktop/src/app/app.component.ts +++ b/apps/desktop/src/app/app.component.ts @@ -299,12 +299,22 @@ export class AppComponent implements OnInit, OnDestroy { break; case "showFingerprintPhrase": { const activeUserId = await firstValueFrom( - this.accountService.activeAccount$.pipe(map((a) => a?.id)), + getUserId(this.accountService.activeAccount$), ); const publicKey = await firstValueFrom(this.keyService.userPublicKey$(activeUserId)); - const fingerprint = await this.keyService.getFingerprint(activeUserId, publicKey); - const dialogRef = FingerprintDialogComponent.open(this.dialogService, { fingerprint }); - await firstValueFrom(dialogRef.closed); + if (publicKey == null) { + this.logService.error( + "[AppComponent] No public key available for the user: " + + activeUserId + + " fingerprint can't be displayed.", + ); + } else { + const fingerprint = await this.keyService.getFingerprint(activeUserId, publicKey); + const dialogRef = FingerprintDialogComponent.open(this.dialogService, { + fingerprint, + }); + await firstValueFrom(dialogRef.closed); + } break; } case "deleteAccount": diff --git a/apps/web/src/app/auth/settings/account/profile.component.html b/apps/web/src/app/auth/settings/account/profile.component.html index 74e9cf08f89..a49e6c31d2e 100644 --- a/apps/web/src/app/auth/settings/account/profile.component.html +++ b/apps/web/src/app/auth/settings/account/profile.component.html @@ -46,11 +46,14 @@
- - + @if (fingerprintMaterial && userPublicKey) { + + + } diff --git a/apps/web/src/app/auth/settings/account/profile.component.ts b/apps/web/src/app/auth/settings/account/profile.component.ts index a0572b846db..54f9ac58291 100644 --- a/apps/web/src/app/auth/settings/account/profile.component.ts +++ b/apps/web/src/app/auth/settings/account/profile.component.ts @@ -12,7 +12,10 @@ import { UpdateProfileRequest } from "@bitwarden/common/auth/models/request/upda import { getUserId } from "@bitwarden/common/auth/services/account.service"; import { ProfileResponse } from "@bitwarden/common/models/response/profile.response"; import { I18nService } from "@bitwarden/common/platform/abstractions/i18n.service"; +import { LogService } from "@bitwarden/common/platform/abstractions/log.service"; +import { UserPublicKey } from "@bitwarden/common/types/key"; import { DialogService, ToastService } from "@bitwarden/components"; +import { KeyService } from "@bitwarden/key-management"; import { DynamicAvatarComponent } from "../../../components/dynamic-avatar.component"; import { SharedModule } from "../../../shared"; @@ -29,6 +32,7 @@ export class ProfileComponent implements OnInit, OnDestroy { loading = true; profile: ProfileResponse; fingerprintMaterial: string; + userPublicKey: UserPublicKey; managingOrganization$: Observable; private destroy$ = new Subject(); @@ -44,16 +48,24 @@ export class ProfileComponent implements OnInit, OnDestroy { private dialogService: DialogService, private toastService: ToastService, private organizationService: OrganizationService, + private keyService: KeyService, + private logService: LogService, ) {} async ngOnInit() { this.profile = await this.apiService.getProfile(); - this.loading = false; - this.fingerprintMaterial = await firstValueFrom( - this.accountService.activeAccount$.pipe(map((a) => a?.id)), - ); - const userId = await firstValueFrom(getUserId(this.accountService.activeAccount$)); + this.fingerprintMaterial = userId; + const publicKey = await firstValueFrom(this.keyService.userPublicKey$(userId)); + if (publicKey == null) { + this.logService.error( + "[ProfileComponent] No public key available for the user: " + + userId + + " fingerprint can't be displayed.", + ); + } else { + this.userPublicKey = publicKey; + } this.managingOrganization$ = this.organizationService .organizations$(userId) @@ -70,6 +82,8 @@ export class ProfileComponent implements OnInit, OnDestroy { .subscribe((name) => { this.profile.name = name; }); + + this.loading = false; } openChangeAvatar = async () => { diff --git a/libs/key-management/src/abstractions/key.service.ts b/libs/key-management/src/abstractions/key.service.ts index 4f14f5523b9..1685938de3d 100644 --- a/libs/key-management/src/abstractions/key.service.ts +++ b/libs/key-management/src/abstractions/key.service.ts @@ -318,14 +318,14 @@ export abstract class KeyService { ): Observable<{ privateKey: UserPrivateKey; publicKey: UserPublicKey } | null>; /** - * Generates a fingerprint phrase for the user based on their public key + * Generates a fingerprint phrase for the public key provided. * - * @throws Error when publicKey is null and there is no active user, or the active user does not have a public key + * @throws Error when publicKey is null or undefined. * @param fingerprintMaterial Fingerprint material - * @param publicKey The user's public key - * @returns The user's fingerprint phrase + * @param publicKey The public key to generate the fingerprint phrase for. + * @returns The fingerprint phrase */ - abstract getFingerprint(fingerprintMaterial: string, publicKey?: Uint8Array): Promise; + abstract getFingerprint(fingerprintMaterial: string, publicKey: Uint8Array): Promise; /** * Generates a new keypair * @param key A key to encrypt the private key with. If not provided, diff --git a/libs/key-management/src/key.service.spec.ts b/libs/key-management/src/key.service.spec.ts index 4d872e2cd5c..6e1ee5d6506 100644 --- a/libs/key-management/src/key.service.spec.ts +++ b/libs/key-management/src/key.service.spec.ts @@ -1227,6 +1227,63 @@ describe("keyService", () => { }); }); + describe("getFingerprint", () => { + const mockFingerprintMaterial = "test@example.com"; + const mockPublicKey = new Uint8Array(256); + const mockKeyFingerprint = Utils.fromB64ToArray("nfG2jTrJilBEsSrg7ffe9exE9PlClem4P2bxlQ6rNbs="); + const mockUserFingerprint = Utils.fromB64ToArray( + "V5AQSk83YXd6kZqCncC6d9J72R7UZ60Xl1eIoDoWgTc=", + ); + const expectedFingerprint = ["predefine", "hunting", "pastime", "enrich", "unhearing"]; + + beforeEach(() => { + cryptoFunctionService.hash.mockResolvedValue(mockKeyFingerprint); + cryptoFunctionService.hkdfExpand.mockResolvedValue(mockUserFingerprint); + }); + + test.each([null as unknown as Uint8Array, undefined as unknown as Uint8Array])( + "throws when publicKey is %s", + async (publicKey) => { + await expect(keyService.getFingerprint(mockFingerprintMaterial, publicKey)).rejects.toThrow( + "Public key is required to generate a fingerprint.", + ); + expect(cryptoFunctionService.hash).not.toHaveBeenCalled(); + expect(cryptoFunctionService.hkdfExpand).not.toHaveBeenCalled(); + }, + ); + + it("generates fingerprint successfully", async () => { + const result = await keyService.getFingerprint(mockFingerprintMaterial, mockPublicKey); + + expect(result).toEqual(expectedFingerprint); + expect(cryptoFunctionService.hash).toHaveBeenCalledWith(mockPublicKey, "sha256"); + expect(cryptoFunctionService.hkdfExpand).toHaveBeenCalledWith( + mockKeyFingerprint, + mockFingerprintMaterial, + 32, + "sha256", + ); + }); + + it("throws when entropy of hash function is too small", async () => { + const keyFingerprint = new Uint8Array(3); + cryptoFunctionService.hash.mockResolvedValue(keyFingerprint); + cryptoFunctionService.hkdfExpand.mockResolvedValue(new Uint8Array(3)); + + await expect( + keyService.getFingerprint(mockFingerprintMaterial, mockPublicKey), + ).rejects.toThrow("Output entropy of hash function is too small"); + + expect(cryptoFunctionService.hash).toHaveBeenCalledWith(mockPublicKey, "sha256"); + expect(cryptoFunctionService.hkdfExpand).toHaveBeenCalledWith( + keyFingerprint, + mockFingerprintMaterial, + 32, + "sha256", + ); + }); + }); + describe("makeKeyPair", () => { test.each([null as unknown as SymmetricCryptoKey, undefined as unknown as SymmetricCryptoKey])( "throws when the provided key is %s", diff --git a/libs/key-management/src/key.service.ts b/libs/key-management/src/key.service.ts index 92bee383a0b..ed0b844a2a4 100644 --- a/libs/key-management/src/key.service.ts +++ b/libs/key-management/src/key.service.ts @@ -473,19 +473,11 @@ export class DefaultKeyService implements KeyServiceAbstraction { .update(() => encPrivateKey); } - // TODO: Make public key required - async getFingerprint(fingerprintMaterial: string, publicKey?: Uint8Array): Promise { + async getFingerprint(fingerprintMaterial: string, publicKey: Uint8Array): Promise { if (publicKey == null) { - const activeUserId = await firstValueFrom(this.stateProvider.activeUserId$); - if (activeUserId == null) { - throw new Error("No active user found."); - } - publicKey = (await firstValueFrom(this.userPublicKey$(activeUserId))) as Uint8Array; + throw new Error("Public key is required to generate a fingerprint."); } - if (publicKey === null) { - throw new Error("No public key available."); - } const keyFingerprint = await this.cryptoFunctionService.hash(publicKey, "sha256"); const userFingerprint = await this.cryptoFunctionService.hkdfExpand( keyFingerprint, From 7aca0cdbd7345a0e10bbd24cb86daf0f4c75938b Mon Sep 17 00:00:00 2001 From: Justin Baur <19896123+justindbaur@users.noreply.github.com> Date: Thu, 21 Aug 2025 17:28:03 -0400 Subject: [PATCH 08/44] Fix `AppComponent.ngOnInit` throwing an error (#16115) --- apps/browser/src/popup/app.component.ts | 3 +++ 1 file changed, 3 insertions(+) diff --git a/apps/browser/src/popup/app.component.ts b/apps/browser/src/popup/app.component.ts index fa1e6c237c9..bd7b41b6e5f 100644 --- a/apps/browser/src/popup/app.component.ts +++ b/apps/browser/src/popup/app.component.ts @@ -321,6 +321,9 @@ export class AppComponent implements OnInit, OnDestroy { } private async clearComponentStates() { + if (this.activeUserId == null) { + return; + } if (!(await firstValueFrom(this.tokenService.hasAccessToken$(this.activeUserId)))) { return; } From 12df7def61cc5b90af972edb5638e94b5cd53744 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Daniel=20Garc=C3=ADa?= Date: Fri, 22 Aug 2025 14:21:52 +0200 Subject: [PATCH 09/44] [PM-19479] Client-Managed SDK state definition (#14839) * [PM-19479] Client-Managed SDK state definition * Remove test code * Update based on latest sdk * Add DB config * Remove uuid conversion step * Move mapper into separate file * Revert to client managed state * Move mapper to Cipher * Typo --------- Co-authored-by: Andreas Coroiu --- .../browser/src/background/main.background.ts | 1 + .../service-container/service-container.ts | 1 + .../src/services/jslib-services.module.ts | 1 + .../services/sdk/client-managed-state.ts | 64 +++++++++++++++++++ .../services/sdk/default-sdk.service.ts | 10 +++ .../vault/models/domain/cipher-sdk-mapper.ts | 22 +++++++ 6 files changed, 99 insertions(+) create mode 100644 libs/common/src/platform/services/sdk/client-managed-state.ts create mode 100644 libs/common/src/vault/models/domain/cipher-sdk-mapper.ts diff --git a/apps/browser/src/background/main.background.ts b/apps/browser/src/background/main.background.ts index a5fb9397125..cd045c9874e 100644 --- a/apps/browser/src/background/main.background.ts +++ b/apps/browser/src/background/main.background.ts @@ -779,6 +779,7 @@ export default class MainBackground { this.accountService, this.kdfConfigService, this.keyService, + this.stateProvider, ); this.passwordStrengthService = new PasswordStrengthService(); diff --git a/apps/cli/src/service-container/service-container.ts b/apps/cli/src/service-container/service-container.ts index e82ceb5a6e9..0268eed06ae 100644 --- a/apps/cli/src/service-container/service-container.ts +++ b/apps/cli/src/service-container/service-container.ts @@ -599,6 +599,7 @@ export class ServiceContainer { this.accountService, this.kdfConfigService, this.keyService, + this.stateProvider, customUserAgent, ); diff --git a/libs/angular/src/services/jslib-services.module.ts b/libs/angular/src/services/jslib-services.module.ts index 50d1c477c96..ab7c12ceffa 100644 --- a/libs/angular/src/services/jslib-services.module.ts +++ b/libs/angular/src/services/jslib-services.module.ts @@ -1467,6 +1467,7 @@ const safeProviders: SafeProvider[] = [ AccountServiceAbstraction, KdfConfigService, KeyService, + StateProvider, ], }), safeProvider({ diff --git a/libs/common/src/platform/services/sdk/client-managed-state.ts b/libs/common/src/platform/services/sdk/client-managed-state.ts new file mode 100644 index 00000000000..1e3273d0801 --- /dev/null +++ b/libs/common/src/platform/services/sdk/client-managed-state.ts @@ -0,0 +1,64 @@ +import { firstValueFrom, map } from "rxjs"; + +import { UserId } from "@bitwarden/common/types/guid"; +import { CipherRecordMapper } from "@bitwarden/common/vault/models/domain/cipher-sdk-mapper"; +import { StateClient, Repository } from "@bitwarden/sdk-internal"; + +import { StateProvider, UserKeyDefinition } from "../../state"; + +export async function initializeState( + userId: UserId, + stateClient: StateClient, + stateProvider: StateProvider, +): Promise { + await stateClient.register_cipher_repository( + new RepositoryRecord(userId, stateProvider, new CipherRecordMapper()), + ); +} + +export interface SdkRecordMapper { + userKeyDefinition(): UserKeyDefinition>; + toSdk(value: ClientType): SdkType; + fromSdk(value: SdkType): ClientType; +} + +class RepositoryRecord implements Repository { + constructor( + private userId: UserId, + private stateProvider: StateProvider, + private mapper: SdkRecordMapper, + ) {} + + async get(id: string): Promise { + const prov = this.stateProvider.getUser(this.userId, this.mapper.userKeyDefinition()); + const data = await firstValueFrom(prov.state$.pipe(map((data) => data ?? {}))); + const element = data[id]; + if (!element) { + return null; + } + return this.mapper.toSdk(element); + } + + async list(): Promise { + const prov = this.stateProvider.getUser(this.userId, this.mapper.userKeyDefinition()); + const elements = await firstValueFrom(prov.state$.pipe(map((data) => data ?? {}))); + return Object.values(elements).map((element) => this.mapper.toSdk(element)); + } + + async set(id: string, value: SdkType): Promise { + const prov = this.stateProvider.getUser(this.userId, this.mapper.userKeyDefinition()); + const elements = await firstValueFrom(prov.state$.pipe(map((data) => data ?? {}))); + elements[id] = this.mapper.fromSdk(value); + await prov.update(() => elements); + } + + async remove(id: string): Promise { + const prov = this.stateProvider.getUser(this.userId, this.mapper.userKeyDefinition()); + const elements = await firstValueFrom(prov.state$.pipe(map((data) => data ?? {}))); + if (!elements[id]) { + return; + } + delete elements[id]; + await prov.update(() => elements); + } +} diff --git a/libs/common/src/platform/services/sdk/default-sdk.service.ts b/libs/common/src/platform/services/sdk/default-sdk.service.ts index d8780b0f1f4..4359f03a17f 100644 --- a/libs/common/src/platform/services/sdk/default-sdk.service.ts +++ b/libs/common/src/platform/services/sdk/default-sdk.service.ts @@ -38,6 +38,9 @@ import { SdkLoadService } from "../../abstractions/sdk/sdk-load.service"; import { SdkService, UserNotLoggedInError } from "../../abstractions/sdk/sdk.service"; import { compareValues } from "../../misc/compare-values"; import { Rc } from "../../misc/reference-counting/rc"; +import { StateProvider } from "../../state"; + +import { initializeState } from "./client-managed-state"; // A symbol that represents an overriden client that is explicitly set to undefined, // blocking the creation of an internal client for that user. @@ -81,6 +84,7 @@ export class DefaultSdkService implements SdkService { private accountService: AccountService, private kdfConfigService: KdfConfigService, private keyService: KeyService, + private stateProvider?: StateProvider, private userAgent: string | null = null, ) {} @@ -241,6 +245,12 @@ export class DefaultSdkService implements SdkService { .map(([k, v]) => [k, v.key as UnsignedSharedKey]), ), }); + + // This is optional to avoid having to mock it on the tests + if (this.stateProvider) { + // Initialize the SDK managed database and the client managed repositories. + await initializeState(userId, client.platform().state(), this.stateProvider); + } } private toSettings(env: Environment): ClientSettings { diff --git a/libs/common/src/vault/models/domain/cipher-sdk-mapper.ts b/libs/common/src/vault/models/domain/cipher-sdk-mapper.ts new file mode 100644 index 00000000000..644a9ff7645 --- /dev/null +++ b/libs/common/src/vault/models/domain/cipher-sdk-mapper.ts @@ -0,0 +1,22 @@ +import { SdkRecordMapper } from "@bitwarden/common/platform/services/sdk/client-managed-state"; +import { UserKeyDefinition } from "@bitwarden/common/platform/state"; +import { Cipher as SdkCipher } from "@bitwarden/sdk-internal"; + +import { ENCRYPTED_CIPHERS } from "../../services/key-state/ciphers.state"; +import { CipherData } from "../data/cipher.data"; + +import { Cipher } from "./cipher"; + +export class CipherRecordMapper implements SdkRecordMapper { + userKeyDefinition(): UserKeyDefinition> { + return ENCRYPTED_CIPHERS; + } + + toSdk(value: CipherData): SdkCipher { + return new Cipher(value).toSdkCipher(); + } + + fromSdk(value: SdkCipher): CipherData { + throw new Error("Cipher.fromSdk is not implemented yet"); + } +} From 92c9aa7b3e37a7dcdcf48fca927a868abc7e44a4 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Daniel=20Garc=C3=ADa?= Date: Fri, 22 Aug 2025 15:19:18 +0200 Subject: [PATCH 10/44] Use FakeStateProvider in SdkService tests (#16126) --- .../services/sdk/default-sdk.service.spec.ts | 22 +++++++++++++++---- .../services/sdk/default-sdk.service.ts | 9 +++----- 2 files changed, 21 insertions(+), 10 deletions(-) diff --git a/libs/common/src/platform/services/sdk/default-sdk.service.spec.ts b/libs/common/src/platform/services/sdk/default-sdk.service.spec.ts index 17d98159c41..30b43bfe00a 100644 --- a/libs/common/src/platform/services/sdk/default-sdk.service.spec.ts +++ b/libs/common/src/platform/services/sdk/default-sdk.service.spec.ts @@ -6,8 +6,13 @@ import { BehaviorSubject, firstValueFrom, of } from "rxjs"; import { KdfConfigService, KeyService, PBKDF2KdfConfig } from "@bitwarden/key-management"; import { BitwardenClient } from "@bitwarden/sdk-internal"; -import { ObservableTracker } from "../../../../spec"; -import { AccountInfo, AccountService } from "../../../auth/abstractions/account.service"; +import { + FakeAccountService, + FakeStateProvider, + mockAccountServiceWith, + ObservableTracker, +} from "../../../../spec"; +import { AccountInfo } from "../../../auth/abstractions/account.service"; import { EncryptedString } from "../../../key-management/crypto/models/enc-string"; import { UserId } from "../../../types/guid"; import { UserKey } from "../../../types/key"; @@ -17,6 +22,7 @@ import { SdkClientFactory } from "../../abstractions/sdk/sdk-client-factory"; import { SdkLoadService } from "../../abstractions/sdk/sdk-load.service"; import { UserNotLoggedInError } from "../../abstractions/sdk/sdk.service"; import { Rc } from "../../misc/reference-counting/rc"; +import { Utils } from "../../misc/utils"; import { SymmetricCryptoKey } from "../../models/domain/symmetric-crypto-key"; import { DefaultSdkService } from "./default-sdk.service"; @@ -33,10 +39,11 @@ describe("DefaultSdkService", () => { let sdkClientFactory!: MockProxy; let environmentService!: MockProxy; let platformUtilsService!: MockProxy; - let accountService!: MockProxy; let kdfConfigService!: MockProxy; let keyService!: MockProxy; let service!: DefaultSdkService; + let accountService!: FakeAccountService; + let fakeStateProvider!: FakeStateProvider; beforeEach(async () => { await new TestSdkLoadService().loadAndInit(); @@ -44,9 +51,11 @@ describe("DefaultSdkService", () => { sdkClientFactory = mock(); environmentService = mock(); platformUtilsService = mock(); - accountService = mock(); kdfConfigService = mock(); keyService = mock(); + const mockUserId = Utils.newGuid() as UserId; + accountService = mockAccountServiceWith(mockUserId); + fakeStateProvider = new FakeStateProvider(accountService); // Can't use `of(mock())` for some reason environmentService.environment$ = new BehaviorSubject(mock()); @@ -58,6 +67,7 @@ describe("DefaultSdkService", () => { accountService, kdfConfigService, keyService, + fakeStateProvider, ); }); @@ -219,5 +229,9 @@ describe("DefaultSdkService", () => { function createMockClient(): MockProxy { const client = mock(); client.crypto.mockReturnValue(mock()); + client.platform.mockReturnValue({ + state: jest.fn().mockReturnValue(mock()), + free: mock(), + }); return client; } diff --git a/libs/common/src/platform/services/sdk/default-sdk.service.ts b/libs/common/src/platform/services/sdk/default-sdk.service.ts index 4359f03a17f..629d7dafed5 100644 --- a/libs/common/src/platform/services/sdk/default-sdk.service.ts +++ b/libs/common/src/platform/services/sdk/default-sdk.service.ts @@ -84,7 +84,7 @@ export class DefaultSdkService implements SdkService { private accountService: AccountService, private kdfConfigService: KdfConfigService, private keyService: KeyService, - private stateProvider?: StateProvider, + private stateProvider: StateProvider, private userAgent: string | null = null, ) {} @@ -246,11 +246,8 @@ export class DefaultSdkService implements SdkService { ), }); - // This is optional to avoid having to mock it on the tests - if (this.stateProvider) { - // Initialize the SDK managed database and the client managed repositories. - await initializeState(userId, client.platform().state(), this.stateProvider); - } + // Initialize the SDK managed database and the client managed repositories. + await initializeState(userId, client.platform().state(), this.stateProvider); } private toSettings(env: Environment): ClientSettings { From eb84faaf9907e67e3ff23f6968ffcbcba542952b Mon Sep 17 00:00:00 2001 From: Bryan Cunningham Date: Fri, 22 Aug 2025 10:01:23 -0400 Subject: [PATCH 11/44] [CL-825] Provide dimensions to checkbox to fix ios rendering bug (#16109) * absolutely position checkbox to fix ios rendering bug * remove absolute positioning. Dimensions fix it --- libs/components/src/checkbox/checkbox.component.ts | 3 +++ libs/components/src/form-control/form-control.component.html | 2 +- 2 files changed, 4 insertions(+), 1 deletion(-) diff --git a/libs/components/src/checkbox/checkbox.component.ts b/libs/components/src/checkbox/checkbox.component.ts index f93861c877a..b5d53c41fd6 100644 --- a/libs/components/src/checkbox/checkbox.component.ts +++ b/libs/components/src/checkbox/checkbox.component.ts @@ -21,6 +21,9 @@ export class CheckboxComponent implements BitFormControlAbstraction { "tw-align-sub", "tw-flex-none", // Flexbox fix for bit-form-control "!tw-p-1", + // Give checkbox explicit height and width to fix iOS rendering bug + "tw-h-[calc(1.12rem_+_theme(spacing.2))]", + "tw-w-[calc(1.12rem_+_theme(spacing.2))]", "after:tw-inset-1", // negative margin to negate the positioning added by the padding "!-tw-mt-1", diff --git a/libs/components/src/form-control/form-control.component.html b/libs/components/src/form-control/form-control.component.html index 3dc3f90c9b0..4fbb8e6342e 100644 --- a/libs/components/src/form-control/form-control.component.html +++ b/libs/components/src/form-control/form-control.component.html @@ -1,5 +1,5 @@