/* eslint-disable @angular-eslint/directive-selector, @angular-eslint/no-host-metadata-property */ import { Directive, ElementRef, EventEmitter, HostListener, Input, Output } from "@angular/core" import { ControlValueAccessor, NG_VALUE_ACCESSOR } from "@angular/forms"; @Directive({ standalone: true, }) // eslint-disable-next-line @angular-eslint/directive-class-suffix export class ValueAccessor implements ControlValueAccessor { private onChange: (value: any) => void = () => {}; private onTouched: () => void = () => {}; protected lastValue: any; constructor(protected el: ElementRef) {} writeValue(value: any) { this.el.nativeElement.value = this.lastValue = value == null ? '' : value; } handleChangeEvent(value: any) { if (value !== this.lastValue) { this.lastValue = value; this.onChange(value); } } @HostListener('focusout') _handleBlurEvent() { this.onTouched(); } registerOnChange(fn: (value: any) => void) { this.onChange = fn; } registerOnTouched(fn: () => void) { this.onTouched = fn; } setDisabledState(disabled: boolean) { this.el.nativeElement.disabled = disabled; } } @Directive({ selector: "duet-input:not([type=number]), duet-textarea, duet-date-picker", host: { "(duetChange)": "handleChangeEvent($event.target.value)" }, standalone: true, providers: [ { provide: NG_VALUE_ACCESSOR, useExisting: TextValueAccessorDirective, multi: true } ] }) export class TextValueAccessorDirective extends ValueAccessor { constructor(el: ElementRef) { super(el); } } @Directive({ /* tslint:disable-next-line:directive-selector */ selector: "duet-range-slider, duet-select, duet-radio-group, duet-choice-group", host: { "(duetChange)": "handleChangeEvent($event.target.value)" }, standalone: true, providers: [ { provide: NG_VALUE_ACCESSOR, useExisting: SelectValueAccessorDirective, multi: true } ] }) export class SelectValueAccessorDirective extends ValueAccessor { constructor(el: ElementRef) { super(el); } } @Directive({ /* tslint:disable-next-line:directive-selector */ selector: 'duet-radio, duet-choice[type=radio]', host: { '(duetSelect)': 'handleChangeEvent($event.target.checked)' }, standalone: true, providers: [ { provide: NG_VALUE_ACCESSOR, useExisting: RadioValueAccessorDirective, multi: true } ] }) export class RadioValueAccessorDirective extends ValueAccessor { constructor(el: ElementRef) { super(el); } } @Directive({ /* tslint:disable-next-line:directive-selector */ selector: "duet-input[type=number], duet-number-input", host: { "(duetChange)": "handleChangeEvent($event.target.value)" }, standalone: true, providers: [ { provide: NG_VALUE_ACCESSOR, useExisting: NumericValueAccessorDirective, multi: true } ] }) export class NumericValueAccessorDirective extends ValueAccessor { constructor(el: ElementRef) { super(el); } registerOnChange(fn: (_: number | null) => void) { super.registerOnChange(value => { fn(value === '' ? null : parseFloat(value)); }); } } @Directive({ /* tslint:disable-next-line:directive-selector */ selector: "duet-checkbox, duet-toggle, duet-choice[type=checkbox]", host: { "(duetChange)": "handleChangeEvent($event.target.checked)" }, standalone: true, providers: [ { provide: NG_VALUE_ACCESSOR, useExisting: BooleanValueAccessorDirective, multi: true } ] }) export class BooleanValueAccessorDirective extends ValueAccessor { @Output() duetChange = new EventEmitter>() constructor(el: ElementRef) { super(el); } writeValue(value: any) { this.el.nativeElement.checked = this.lastValue = value == null ? false : value; } }