65 lines
1.8 KiB
TypeScript
65 lines
1.8 KiB
TypeScript
|
|
import { ChangeDetectionStrategy, Component, forwardRef, input } from '@angular/core';
|
||
|
|
import { ControlValueAccessor, NG_VALUE_ACCESSOR } from '@angular/forms';
|
||
|
|
|
||
|
|
export type InputSize = 'sm' | 'md' | 'lg';
|
||
|
|
export type InputState = 'default' | 'error' | 'success';
|
||
|
|
|
||
|
|
@Component({
|
||
|
|
selector: 'app-input',
|
||
|
|
standalone: true,
|
||
|
|
templateUrl: './input.component.html',
|
||
|
|
styleUrl: './input.component.scss',
|
||
|
|
changeDetection: ChangeDetectionStrategy.OnPush,
|
||
|
|
providers: [
|
||
|
|
{
|
||
|
|
provide: NG_VALUE_ACCESSOR,
|
||
|
|
useExisting: forwardRef(() => InputComponent),
|
||
|
|
multi: true
|
||
|
|
}
|
||
|
|
],
|
||
|
|
host: {
|
||
|
|
'[class.app-input-host--full-width]': 'fullWidth()'
|
||
|
|
}
|
||
|
|
})
|
||
|
|
export class InputComponent implements ControlValueAccessor {
|
||
|
|
readonly type = input<'text' | 'email' | 'password' | 'number' | 'search' | 'tel' | 'url'>('text');
|
||
|
|
readonly size = input<InputSize>('md');
|
||
|
|
readonly state = input<InputState>('default');
|
||
|
|
readonly placeholder = input('');
|
||
|
|
readonly disabled = input(false);
|
||
|
|
readonly fullWidth = input(false);
|
||
|
|
readonly ariaLabel = input<string | null>(null);
|
||
|
|
|
||
|
|
protected value: string | number = '';
|
||
|
|
protected isDisabled = false;
|
||
|
|
|
||
|
|
private onChange: (value: string | number) => void = () => {};
|
||
|
|
private onTouched: () => void = () => {};
|
||
|
|
|
||
|
|
writeValue(value: string | number): void {
|
||
|
|
this.value = value ?? '';
|
||
|
|
}
|
||
|
|
|
||
|
|
registerOnChange(fn: (value: string | number) => void): void {
|
||
|
|
this.onChange = fn;
|
||
|
|
}
|
||
|
|
|
||
|
|
registerOnTouched(fn: () => void): void {
|
||
|
|
this.onTouched = fn;
|
||
|
|
}
|
||
|
|
|
||
|
|
setDisabledState(isDisabled: boolean): void {
|
||
|
|
this.isDisabled = isDisabled;
|
||
|
|
}
|
||
|
|
|
||
|
|
protected handleInput(event: Event): void {
|
||
|
|
const target = event.target as HTMLInputElement;
|
||
|
|
this.value = target.value;
|
||
|
|
this.onChange(this.value);
|
||
|
|
}
|
||
|
|
|
||
|
|
protected handleBlur(): void {
|
||
|
|
this.onTouched();
|
||
|
|
}
|
||
|
|
}
|