1
0
mirror of https://github.com/bitwarden/browser synced 2026-02-06 19:53:59 +00:00
This commit is contained in:
Bryan Cunningham
2025-06-30 08:57:20 -04:00
parent 13aaec6c39
commit 0ce3064838
5 changed files with 81 additions and 23 deletions

View File

@@ -1,6 +1,6 @@
// FIXME: Update this file to be type safe and remove this and next line
// @ts-strict-ignore
import { Component, HostBinding, Input, Optional, Self } from "@angular/core";
import { Component, ElementRef, HostBinding, Input, Optional, Self } from "@angular/core";
import { NgControl, Validators } from "@angular/forms";
import { BitFormControlAbstraction } from "../form-control";
@@ -10,7 +10,7 @@ import { BitFormControlAbstraction } from "../form-control";
template: "",
providers: [{ provide: BitFormControlAbstraction, useExisting: CheckboxComponent }],
})
export class CheckboxComponent implements BitFormControlAbstraction {
export class CheckboxComponent extends BitFormControlAbstraction {
@HostBinding("class")
protected inputClasses = [
"tw-appearance-none",
@@ -80,7 +80,12 @@ export class CheckboxComponent implements BitFormControlAbstraction {
"indeterminate:disabled:before:tw-bg-text-muted",
];
constructor(@Optional() @Self() private ngControl?: NgControl) {}
constructor(
elementRef: ElementRef,
@Optional() @Self() private ngControl?: NgControl,
) {
super(elementRef);
}
@HostBinding("style.--mask-image")
protected maskImage =
@@ -98,7 +103,7 @@ export class CheckboxComponent implements BitFormControlAbstraction {
set disabled(value: any) {
this._disabled = value != null && value !== false;
}
private _disabled: boolean;
// private _disabled: boolean;
@Input()
get required() {
@@ -109,7 +114,7 @@ export class CheckboxComponent implements BitFormControlAbstraction {
set required(value: any) {
this._required = value != null && value !== false;
}
private _required: boolean;
// private _required: boolean;
get hasError() {
return this.ngControl?.status === "INVALID" && this.ngControl?.touched;

View File

@@ -1,8 +1,41 @@
// FIXME: Update this file to be type safe and remove this and next line
import { ElementRef } from "@angular/core";
// import { NgControl } from "@angular/forms";
// @ts-strict-ignore
export abstract class BitFormControlAbstraction {
disabled: boolean;
required: boolean;
hasError: boolean;
error: [string, any];
_disabled: boolean;
get disabled(): boolean {
return this._disabled;
}
set disabled(value: boolean) {
this._disabled = value;
}
_required: boolean;
get required(): boolean {
return this._required;
}
set required(value: boolean) {
this._required = value;
}
_hasError: boolean;
get hasError(): boolean {
return this._hasError;
}
set hasError(value: boolean) {
this._hasError = value;
}
_error: [string, any];
get error(): [string, any] {
return this._error;
}
set error(value: [string, any]) {
this._error = value;
}
_elementRef: ElementRef<HTMLElement>;
constructor(elementRef: ElementRef<HTMLElement>) {
this._elementRef = elementRef;
}
}

View File

@@ -1,11 +1,11 @@
<label
class="tw-transition tw-select-none tw-mb-0 tw-inline-flex tw-rounded tw-p-0.5 has-[:focus-visible]:tw-ring has-[:focus-visible]:tw-ring-primary-600"
[ngClass]="[formControl.disabled ? 'tw-cursor-auto' : 'tw-cursor-pointer']"
[ngClass]="[formControl().disabled ? 'tw-cursor-auto' : 'tw-cursor-pointer']"
>
<ng-content></ng-content>
<span
class="tw-inline-flex tw-flex-col"
[ngClass]="formControl.disabled ? 'tw-text-muted' : 'tw-text-main'"
[ngClass]="formControl().disabled ? 'tw-text-muted' : 'tw-text-main'"
>
<span bitTypography="body2">
<ng-content select="bit-label"></ng-content>

View File

@@ -2,7 +2,7 @@
// @ts-strict-ignore
import { coerceBooleanProperty } from "@angular/cdk/coercion";
import { NgClass } from "@angular/common";
import { Component, ContentChild, HostBinding, Input } from "@angular/core";
import { Component, HostBinding, Input, AfterContentInit, contentChild } from "@angular/core";
import { I18nService } from "@bitwarden/common/platform/abstractions/i18n.service";
import { I18nPipe } from "@bitwarden/ui-common";
@@ -11,12 +11,14 @@ import { TypographyDirective } from "../typography/typography.directive";
import { BitFormControlAbstraction } from "./form-control.abstraction";
// Increments for each instance of this component
let nextId = 0;
@Component({
selector: "bit-form-control",
templateUrl: "form-control.component.html",
imports: [NgClass, TypographyDirective, I18nPipe],
})
export class FormControlComponent {
export class FormControlComponent implements AfterContentInit {
@Input() label: string;
private _inline = false;
@@ -35,8 +37,8 @@ export class FormControlComponent {
return this._disableMargin;
}
@ContentChild(BitFormControlAbstraction) protected formControl: BitFormControlAbstraction;
formControl = contentChild(BitFormControlAbstraction);
inputId = "";
@HostBinding("class") get classes() {
return []
.concat(this.inline ? ["tw-inline-block", "tw-me-4"] : ["tw-block"])
@@ -46,15 +48,15 @@ export class FormControlComponent {
constructor(private i18nService: I18nService) {}
get required() {
return this.formControl.required;
return this.formControl().required;
}
get hasError() {
return this.formControl.hasError;
return this.formControl().hasError;
}
get error() {
return this.formControl.error;
return this.formControl().error;
}
get displayError() {
@@ -70,4 +72,17 @@ export class FormControlComponent {
return this.error;
}
}
inputElementId: string = "";
ngAfterContentInit() {
const nativeElement = this.formControl()._elementRef.nativeElement;
const currentElementId = nativeElement.id;
const nextElementId = `bit-control-id-${nextId++}`;
this.inputElementId = currentElementId || nextElementId;
if (!currentElementId) {
nativeElement.setAttribute("id", nextElementId);
}
}
}

View File

@@ -1,6 +1,6 @@
// FIXME: Update this file to be type safe and remove this and next line
// @ts-strict-ignore
import { Component, HostBinding, Input, Optional, Self } from "@angular/core";
import { Component, ElementRef, HostBinding, Input, Optional, Self } from "@angular/core";
import { NgControl, Validators } from "@angular/forms";
import { BitFormControlAbstraction } from "../form-control";
@@ -12,7 +12,7 @@ let nextId = 0;
template: "",
providers: [{ provide: BitFormControlAbstraction, useExisting: RadioInputComponent }],
})
export class RadioInputComponent implements BitFormControlAbstraction {
export class RadioInputComponent extends BitFormControlAbstraction {
@HostBinding("attr.id") @Input() id = `bit-radio-input-${nextId++}`;
@HostBinding("class")
@@ -72,7 +72,12 @@ export class RadioInputComponent implements BitFormControlAbstraction {
"checked:disabled:before:tw-bg-secondary-600",
];
constructor(@Optional() @Self() private ngControl?: NgControl) {}
constructor(
elementRef: ElementRef,
@Optional() @Self() private ngControl?: NgControl,
) {
super(elementRef);
}
@HostBinding()
@Input()
@@ -82,7 +87,7 @@ export class RadioInputComponent implements BitFormControlAbstraction {
set disabled(value: any) {
this._disabled = value != null && value !== false;
}
private _disabled: boolean;
// private _disabled: boolean;
@Input()
get required() {
@@ -93,7 +98,7 @@ export class RadioInputComponent implements BitFormControlAbstraction {
set required(value: any) {
this._required = value != null && value !== false;
}
private _required: boolean;
// private _required: boolean;
get hasError() {
return this.ngControl?.status === "INVALID" && this.ngControl?.touched;