1
0
mirror of https://github.com/bitwarden/browser synced 2026-02-17 09:59:41 +00:00
Files
browser/libs/components/src/form-field/password-input-toggle.directive.ts
Will Martin 827c4c0301 [PM-15847] libs/components strict migration (#15738)
This PR migrates `libs/components` to use strict TypeScript.

- Remove `@ts-strict-ignore` from each file in `libs/components` and resolved any new compilation errors
- Converted ViewChild and ContentChild decorators to use the new signal-based queries using the [Angular signal queries migration](https://angular.dev/reference/migrations/signal-queries)
  - Made view/content children `required` where appropriate, eliminating the need for additional null checking. This helped simplify the strict migration.

---

Co-authored-by: Vicki League <vleague@bitwarden.com>
2025-08-18 15:36:45 -04:00

76 lines
1.8 KiB
TypeScript

import {
AfterContentInit,
Directive,
EventEmitter,
Host,
HostBinding,
HostListener,
model,
OnChanges,
Output,
} from "@angular/core";
import { I18nService } from "@bitwarden/common/platform/abstractions/i18n.service";
import { BitIconButtonComponent } from "../icon-button/icon-button.component";
import { BitFormFieldComponent } from "./form-field.component";
@Directive({
selector: "[bitPasswordInputToggle]",
host: {
"[attr.aria-pressed]": "toggled()",
},
})
export class BitPasswordInputToggleDirective implements AfterContentInit, OnChanges {
/**
* Whether the input is toggled to show the password.
*/
readonly toggled = model(false);
@Output() toggledChange = new EventEmitter<boolean>();
@HostBinding("attr.title") title = this.i18nService.t("toggleVisibility");
@HostBinding("attr.aria-label") label = this.i18nService.t("toggleVisibility");
/**
* Click handler to toggle the state of the input type.
*/
@HostListener("click") onClick() {
this.toggled.update((toggled) => !toggled);
this.toggledChange.emit(this.toggled());
this.update();
}
constructor(
@Host() private button: BitIconButtonComponent,
private formField: BitFormFieldComponent,
private i18nService: I18nService,
) {}
get icon() {
return this.toggled() ? "bwi-eye-slash" : "bwi-eye";
}
ngOnChanges(): void {
this.update();
}
ngAfterContentInit(): void {
const input = this.formField.input();
if (input?.type) {
this.toggled.set(input.type() !== "password");
}
this.button.icon.set(this.icon);
}
private update() {
this.button.icon.set(this.icon);
const input = this.formField.input();
if (input?.type != null) {
input.type.set(this.toggled() ? "text" : "password");
input?.spellcheck?.set(this.toggled() ? false : undefined);
}
}
}