import * as i0 from '@angular/core';
import { input, numberAttribute, booleanAttribute, computed, output, viewChild, signal, inject, ChangeDetectorRef, ChangeDetectionStrategy, Component, NgModule } from '@angular/core';
import { Validators, NG_VALUE_ACCESSOR, NG_VALIDATORS } from '@angular/forms';
import { elementPlus, elementMinus } from '@siemens/element-icons';
import { SI_FORM_ITEM_CONTROL } from '@siemens/element-ng/form';
import { addIcons, SiIconComponent } from '@siemens/element-ng/icon';
import { SiTranslatePipe } from '@siemens/element-translate-ng/translate';
import { timer } from 'rxjs';

/**
 * Copyright (c) Siemens 2016 - 2026
 * SPDX-License-Identifier: MIT
 */
class SiNumberInputComponent {
    static idCounter = 0;
    static formatValidator = control => {
        if (control.value != null && isNaN(control.value)) {
            return { numberFormat: true };
        }
        return null;
    };
    /**
     * The min. value for HTML input
     *
     * @defaultValue undefined
     */
    minInput = input(undefined, { ...(ngDevMode ? { debugName: "minInput" } : {}), 
        // eslint-disable-next-line @angular-eslint/no-input-rename
        alias: 'min',
        transform: numberAttribute });
    /**
     * The max. value for HTML input
     *
     * @defaultValue undefined
     */
    maxInput = input(undefined, { ...(ngDevMode ? { debugName: "maxInput" } : {}), 
        // eslint-disable-next-line @angular-eslint/no-input-rename
        alias: 'max',
        transform: numberAttribute });
    /**
     * The step size for HTML input
     *
     * @defaultValue 1
     */
    step = input(1, ...(ngDevMode ? [{ debugName: "step" }] : []));
    /** The value */
    // eslint-disable-next-line @angular-eslint/prefer-signal-model
    value = input(...(ngDevMode ? [undefined, { debugName: "value" }] : []));
    /** Optional unit label */
    unit = input(...(ngDevMode ? [undefined, { debugName: "unit" }] : []));
    /**
     * Show increment/decrement buttons?
     *
     * @defaultValue true
     */
    showButtons = input(true, { ...(ngDevMode ? { debugName: "showButtons" } : {}), transform: booleanAttribute });
    /**
     * The aria-label passed to the input
     *
     * @defaultValue undefined
     */
    ariaLabel = input(undefined, { ...(ngDevMode ? { debugName: "ariaLabel" } : {}), alias: 'aria-label' });
    /**
     * ID that is set on the input, e.g. for `<label for="...">`
     *
     * @defaultValue
     * ```
     * `__si-number-input-${SiNumberInputComponent.idCounter++}`
     * ```
     */
    inputId = input(`__si-number-input-${SiNumberInputComponent.idCounter++}`, ...(ngDevMode ? [{ debugName: "inputId" }] : []));
    id = computed(() => this.inputId(), ...(ngDevMode ? [{ debugName: "id" }] : []));
    /** @defaultValue false */
    // eslint-disable-next-line @angular-eslint/no-input-rename
    disabledInput = input(false, { ...(ngDevMode ? { debugName: "disabledInput" } : {}), alias: 'disabled', transform: booleanAttribute });
    /** @defaultValue false */
    readonly = input(false, { ...(ngDevMode ? { debugName: "readonly" } : {}), transform: booleanAttribute });
    /**
     * The placeholder for input field.
     */
    placeholder = input(...(ngDevMode ? [undefined, { debugName: "placeholder" }] : []));
    valueChange = output();
    inputElement = viewChild.required('inputElement');
    /**
     * This ID will be bound to the `aria-describedby` attribute of the number-input.
     * Use this to reference the element containing the error message(s) for the number-input.
     * It will be picked by the {@link SiFormItemComponent} if the number-input is used inside a form item.
     *
     * @defaultValue
     * ```
     * `${this.id()}-errormessage`
     * ```
     */
    errormessageId = input(`${this.id()}-errormessage`, ...(ngDevMode ? [{ debugName: "errormessageId" }] : []));
    canInc = true;
    canDec = true;
    disabled = computed(() => this.disabledInput() || this.disabledNgControl(), ...(ngDevMode ? [{ debugName: "disabled" }] : []));
    disabledNgControl = signal(false, ...(ngDevMode ? [{ debugName: "disabledNgControl" }] : []));
    onTouched = () => { };
    onChange = () => { };
    validator = SiNumberInputComponent.formatValidator;
    onValidatorChanged = () => { };
    min = computed(() => {
        const minVal = this.minInput();
        return minVal === undefined || isNaN(minVal) ? undefined : minVal;
    }, ...(ngDevMode ? [{ debugName: "min" }] : []));
    max = computed(() => {
        const maxVal = this.maxInput();
        return maxVal === undefined || isNaN(maxVal) ? undefined : maxVal;
    }, ...(ngDevMode ? [{ debugName: "max" }] : []));
    icons = addIcons({ elementMinus, elementPlus });
    internalValue;
    autoUpdate$ = timer(400, 80);
    autoUpdateSubs;
    changeDetectorRef = inject(ChangeDetectorRef);
    ngOnChanges(changes) {
        if (changes.value) {
            this.writeValueToInput(this.value());
        }
        if (changes.minInput || changes.maxInput) {
            const minValue = this.min();
            const maxValue = this.max();
            this.validator = Validators.compose([
                minValue != null ? Validators.min(minValue) : null,
                maxValue != null ? Validators.max(maxValue) : null,
                SiNumberInputComponent.formatValidator
            ]);
            this.onValidatorChanged();
        }
        this.updateStepButtons();
    }
    /** @internal */
    registerOnChange(fn) {
        this.onChange = fn;
    }
    /** @internal */
    registerOnTouched(fn) {
        this.onTouched = fn;
    }
    /** @internal */
    setDisabledState(isDisabled) {
        this.disabledNgControl.set(isDisabled);
    }
    /** @internal */
    writeValue(value) {
        this.writeValueToInput(value);
        this.updateStepButtons();
        this.changeDetectorRef.markForCheck();
    }
    /** @internal */
    validate(control) {
        return this.validator ? this.validator(control) : null;
    }
    /** @internal */
    registerOnValidatorChange(fn) {
        this.onValidatorChanged = fn;
    }
    modelChanged() {
        const value = this.inputElement().nativeElement.value
            ? this.inputElement().nativeElement.valueAsNumber
            : undefined;
        this.internalValue = value;
        this.updateStepButtons();
        this.onChange(value);
        this.valueChange.emit(value);
    }
    autoUpdateStart(event, isIncrement) {
        const mouseButton = event.button;
        if (mouseButton) {
            return;
        }
        this.onTouched();
        event.preventDefault();
        const trigger = isIncrement ? () => this.increment() : () => this.decrement();
        this.autoUpdateSubs?.unsubscribe();
        this.autoUpdateSubs = this.autoUpdate$.subscribe(trigger);
        trigger();
    }
    autoUpdateStop() {
        this.autoUpdateSubs?.unsubscribe();
        this.autoUpdateSubs = undefined;
    }
    updateStepButtons() {
        const stepValue = this.step();
        const step = typeof stepValue === 'number' ? stepValue : 1;
        const max = this.max();
        this.canInc = max == null || this.internalValue == null || this.internalValue + step <= max;
        const min = this.min();
        this.canDec = min == null || this.internalValue == null || this.internalValue - step >= min;
        if (!this.canInc || !this.canDec) {
            this.autoUpdateStop();
        }
    }
    decrement() {
        this.inputElement().nativeElement.stepDown();
        this.modelChanged();
    }
    increment() {
        this.inputElement().nativeElement.stepUp();
        this.modelChanged();
    }
    writeValueToInput(value) {
        this.inputElement().nativeElement.value = value == null ? '' : value.toString();
        this.internalValue = value;
    }
    static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "21.0.8", ngImport: i0, type: SiNumberInputComponent, deps: [], target: i0.ɵɵFactoryTarget.Component });
    static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "21.0.8", type: SiNumberInputComponent, isStandalone: true, selector: "si-number-input", inputs: { minInput: { classPropertyName: "minInput", publicName: "min", isSignal: true, isRequired: false, transformFunction: null }, maxInput: { classPropertyName: "maxInput", publicName: "max", isSignal: true, isRequired: false, transformFunction: null }, step: { classPropertyName: "step", publicName: "step", isSignal: true, isRequired: false, transformFunction: null }, value: { classPropertyName: "value", publicName: "value", isSignal: true, isRequired: false, transformFunction: null }, unit: { classPropertyName: "unit", publicName: "unit", isSignal: true, isRequired: false, transformFunction: null }, showButtons: { classPropertyName: "showButtons", publicName: "showButtons", isSignal: true, isRequired: false, transformFunction: null }, ariaLabel: { classPropertyName: "ariaLabel", publicName: "aria-label", isSignal: true, isRequired: false, transformFunction: null }, inputId: { classPropertyName: "inputId", publicName: "inputId", isSignal: true, isRequired: false, transformFunction: null }, disabledInput: { classPropertyName: "disabledInput", publicName: "disabled", isSignal: true, isRequired: false, transformFunction: null }, readonly: { classPropertyName: "readonly", publicName: "readonly", isSignal: true, isRequired: false, transformFunction: null }, placeholder: { classPropertyName: "placeholder", publicName: "placeholder", isSignal: true, isRequired: false, transformFunction: null }, errormessageId: { classPropertyName: "errormessageId", publicName: "errormessageId", isSignal: true, isRequired: false, transformFunction: null } }, outputs: { valueChange: "valueChange" }, host: { properties: { "class.show-step-buttons": "showButtons()", "class.disabled": "disabled()", "class.readonly": "readonly()" } }, providers: [
            {
                provide: NG_VALUE_ACCESSOR,
                useExisting: SiNumberInputComponent,
                multi: true
            },
            {
                provide: NG_VALIDATORS,
                useExisting: SiNumberInputComponent,
                multi: true
            },
            {
                provide: SI_FORM_ITEM_CONTROL,
                useExisting: SiNumberInputComponent
            }
        ], viewQueries: [{ propertyName: "inputElement", first: true, predicate: ["inputElement"], descendants: true, isSignal: true }], usesOnChanges: true, ngImport: i0, template: "<input\n  #inputElement\n  type=\"number\"\n  class=\"focus-none\"\n  [attr.id]=\"inputId()\"\n  [step]=\"step()\"\n  [readonly]=\"readonly()\"\n  [disabled]=\"disabled()\"\n  [attr.aria-label]=\"ariaLabel() | translate\"\n  [attr.aria-describedby]=\"errormessageId()\"\n  [attr.placeholder]=\"placeholder() | translate\"\n  [attr.min]=\"min()\"\n  [attr.max]=\"max()\"\n  (blur)=\"onTouched()\"\n  (input)=\"modelChanged()\"\n/>\n@if (unit()) {\n  <span class=\"unit ms-2\" [class.text-secondary]=\"!disabled()\" [class.text-disabled]=\"disabled()\">{{\n    unit()\n  }}</span>\n} @else {\n  <!-- To reserve space for feedback icon -->\n  <span class=\"unit\"></span>\n}\n@if (showButtons()) {\n  <button\n    type=\"button\"\n    tabindex=\"-1\"\n    aria-hidden=\"true\"\n    class=\"dec btn btn-icon btn-tertiary btn-sm my-n3 ms-2\"\n    [disabled]=\"disabled() || readonly() || !canDec\"\n    (mousedown)=\"autoUpdateStart($event, false)\"\n    (touchstart)=\"autoUpdateStart($event, false)\"\n    (touchend)=\"autoUpdateStop()\"\n    (mouseup)=\"autoUpdateStop()\"\n    (mouseleave)=\"autoUpdateStop()\"\n  >\n    <si-icon [icon]=\"icons.elementMinus\" />\n  </button>\n  <button\n    type=\"button\"\n    tabindex=\"-1\"\n    aria-hidden=\"true\"\n    class=\"inc btn btn-icon btn-tertiary btn-sm my-n3 me-n2\"\n    [disabled]=\"disabled() || readonly() || !canInc\"\n    (mousedown)=\"autoUpdateStart($event, true)\"\n    (touchstart)=\"autoUpdateStart($event, true)\"\n    (touchend)=\"autoUpdateStop()\"\n    (mouseup)=\"autoUpdateStop()\"\n    (mouseleave)=\"autoUpdateStop()\"\n  >\n    <si-icon [icon]=\"icons.elementPlus\" />\n  </button>\n}\n", styles: [":host{display:flex;align-items:center;padding-inline-end:7px}:host.show-step-buttons{--si-action-icon-offset: 48px}:host:focus-within{outline:var(--element-button-focus-width) solid var(--element-focus-default);outline-offset:var(--element-button-focus-overlay-width)}:host.disabled ::placeholder{color:transparent}input{-moz-appearance:textfield;border:0;margin:0;padding-block:0;background:transparent;color:inherit;text-align:inherit;flex:1 0 0;min-inline-size:0}input::-webkit-outer-spin-button,input::-webkit-inner-spin-button{-webkit-appearance:none;margin:0}.unit{padding-inline-end:var(--si-feedback-icon-offset, 0)}\n"], dependencies: [{ kind: "component", type: SiIconComponent, selector: "si-icon", inputs: ["icon"] }, { kind: "pipe", type: SiTranslatePipe, name: "translate" }], changeDetection: i0.ChangeDetectionStrategy.OnPush });
}
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.0.8", ngImport: i0, type: SiNumberInputComponent, decorators: [{
            type: Component,
            args: [{ selector: 'si-number-input', imports: [SiIconComponent, SiTranslatePipe], providers: [
                        {
                            provide: NG_VALUE_ACCESSOR,
                            useExisting: SiNumberInputComponent,
                            multi: true
                        },
                        {
                            provide: NG_VALIDATORS,
                            useExisting: SiNumberInputComponent,
                            multi: true
                        },
                        {
                            provide: SI_FORM_ITEM_CONTROL,
                            useExisting: SiNumberInputComponent
                        }
                    ], changeDetection: ChangeDetectionStrategy.OnPush, host: {
                        '[class.show-step-buttons]': 'showButtons()',
                        '[class.disabled]': 'disabled()',
                        '[class.readonly]': 'readonly()'
                    }, template: "<input\n  #inputElement\n  type=\"number\"\n  class=\"focus-none\"\n  [attr.id]=\"inputId()\"\n  [step]=\"step()\"\n  [readonly]=\"readonly()\"\n  [disabled]=\"disabled()\"\n  [attr.aria-label]=\"ariaLabel() | translate\"\n  [attr.aria-describedby]=\"errormessageId()\"\n  [attr.placeholder]=\"placeholder() | translate\"\n  [attr.min]=\"min()\"\n  [attr.max]=\"max()\"\n  (blur)=\"onTouched()\"\n  (input)=\"modelChanged()\"\n/>\n@if (unit()) {\n  <span class=\"unit ms-2\" [class.text-secondary]=\"!disabled()\" [class.text-disabled]=\"disabled()\">{{\n    unit()\n  }}</span>\n} @else {\n  <!-- To reserve space for feedback icon -->\n  <span class=\"unit\"></span>\n}\n@if (showButtons()) {\n  <button\n    type=\"button\"\n    tabindex=\"-1\"\n    aria-hidden=\"true\"\n    class=\"dec btn btn-icon btn-tertiary btn-sm my-n3 ms-2\"\n    [disabled]=\"disabled() || readonly() || !canDec\"\n    (mousedown)=\"autoUpdateStart($event, false)\"\n    (touchstart)=\"autoUpdateStart($event, false)\"\n    (touchend)=\"autoUpdateStop()\"\n    (mouseup)=\"autoUpdateStop()\"\n    (mouseleave)=\"autoUpdateStop()\"\n  >\n    <si-icon [icon]=\"icons.elementMinus\" />\n  </button>\n  <button\n    type=\"button\"\n    tabindex=\"-1\"\n    aria-hidden=\"true\"\n    class=\"inc btn btn-icon btn-tertiary btn-sm my-n3 me-n2\"\n    [disabled]=\"disabled() || readonly() || !canInc\"\n    (mousedown)=\"autoUpdateStart($event, true)\"\n    (touchstart)=\"autoUpdateStart($event, true)\"\n    (touchend)=\"autoUpdateStop()\"\n    (mouseup)=\"autoUpdateStop()\"\n    (mouseleave)=\"autoUpdateStop()\"\n  >\n    <si-icon [icon]=\"icons.elementPlus\" />\n  </button>\n}\n", styles: [":host{display:flex;align-items:center;padding-inline-end:7px}:host.show-step-buttons{--si-action-icon-offset: 48px}:host:focus-within{outline:var(--element-button-focus-width) solid var(--element-focus-default);outline-offset:var(--element-button-focus-overlay-width)}:host.disabled ::placeholder{color:transparent}input{-moz-appearance:textfield;border:0;margin:0;padding-block:0;background:transparent;color:inherit;text-align:inherit;flex:1 0 0;min-inline-size:0}input::-webkit-outer-spin-button,input::-webkit-inner-spin-button{-webkit-appearance:none;margin:0}.unit{padding-inline-end:var(--si-feedback-icon-offset, 0)}\n"] }]
        }], propDecorators: { minInput: [{ type: i0.Input, args: [{ isSignal: true, alias: "min", required: false }] }], maxInput: [{ type: i0.Input, args: [{ isSignal: true, alias: "max", required: false }] }], step: [{ type: i0.Input, args: [{ isSignal: true, alias: "step", required: false }] }], value: [{ type: i0.Input, args: [{ isSignal: true, alias: "value", required: false }] }], unit: [{ type: i0.Input, args: [{ isSignal: true, alias: "unit", required: false }] }], showButtons: [{ type: i0.Input, args: [{ isSignal: true, alias: "showButtons", required: false }] }], ariaLabel: [{ type: i0.Input, args: [{ isSignal: true, alias: "aria-label", required: false }] }], inputId: [{ type: i0.Input, args: [{ isSignal: true, alias: "inputId", required: false }] }], disabledInput: [{ type: i0.Input, args: [{ isSignal: true, alias: "disabled", required: false }] }], readonly: [{ type: i0.Input, args: [{ isSignal: true, alias: "readonly", required: false }] }], placeholder: [{ type: i0.Input, args: [{ isSignal: true, alias: "placeholder", required: false }] }], valueChange: [{ type: i0.Output, args: ["valueChange"] }], inputElement: [{ type: i0.ViewChild, args: ['inputElement', { isSignal: true }] }], errormessageId: [{ type: i0.Input, args: [{ isSignal: true, alias: "errormessageId", required: false }] }] } });

/**
 * Copyright (c) Siemens 2016 - 2026
 * SPDX-License-Identifier: MIT
 */
class SiNumberInputModule {
    static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "21.0.8", ngImport: i0, type: SiNumberInputModule, deps: [], target: i0.ɵɵFactoryTarget.NgModule });
    static ɵmod = i0.ɵɵngDeclareNgModule({ minVersion: "14.0.0", version: "21.0.8", ngImport: i0, type: SiNumberInputModule, imports: [SiNumberInputComponent], exports: [SiNumberInputComponent] });
    static ɵinj = i0.ɵɵngDeclareInjector({ minVersion: "12.0.0", version: "21.0.8", ngImport: i0, type: SiNumberInputModule, imports: [SiNumberInputComponent] });
}
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.0.8", ngImport: i0, type: SiNumberInputModule, decorators: [{
            type: NgModule,
            args: [{
                    imports: [SiNumberInputComponent],
                    exports: [SiNumberInputComponent]
                }]
        }] });

/**
 * Copyright (c) Siemens 2016 - 2026
 * SPDX-License-Identifier: MIT
 */

/**
 * Generated bundle index. Do not edit.
 */

export { SiNumberInputComponent, SiNumberInputModule };
//# sourceMappingURL=siemens-element-ng-number-input.mjs.map
