import * as i0 from '@angular/core';
import { inject, TemplateRef, Directive, ElementRef, viewChild, contentChild, input, numberAttribute, booleanAttribute, signal, output, computed, effect, forwardRef, Optional, Self, ChangeDetectionStrategy, Component } from '@angular/core';
import * as i1 from '@angular/forms';
import { NgForm, FormGroupDirective } from '@angular/forms';
import { coerceBooleanProperty } from '@angular/cdk/coercion';
import { FormFieldControl } from '@ngstarter-ui/components/form-field';
import { Subject } from 'rxjs';
import { Ripple } from '@ngstarter-ui/components/core';
import { NgTemplateOutlet } from '@angular/common';

class DecreaseControlDirective {
    templateRef = inject(TemplateRef);
    static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "21.2.4", ngImport: i0, type: DecreaseControlDirective, deps: [], target: i0.ɵɵFactoryTarget.Directive });
    static ɵdir = i0.ɵɵngDeclareDirective({ minVersion: "14.0.0", version: "21.2.4", type: DecreaseControlDirective, isStandalone: true, selector: "[ngsDecreaseControl]", exportAs: ["ngsDecreaseControl"], ngImport: i0 });
}
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.4", ngImport: i0, type: DecreaseControlDirective, decorators: [{
            type: Directive,
            args: [{
                    selector: '[ngsDecreaseControl]',
                    exportAs: 'ngsDecreaseControl'
                }]
        }] });

class IncreaseControlDirective {
    templateRef = inject(TemplateRef);
    static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "21.2.4", ngImport: i0, type: IncreaseControlDirective, deps: [], target: i0.ɵɵFactoryTarget.Directive });
    static ɵdir = i0.ɵɵngDeclareDirective({ minVersion: "14.0.0", version: "21.2.4", type: IncreaseControlDirective, isStandalone: true, selector: "[ngsIncreaseControl]", exportAs: ["ngsIncreaseControl"], ngImport: i0 });
}
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.4", ngImport: i0, type: IncreaseControlDirective, decorators: [{
            type: Directive,
            args: [{
                    selector: '[ngsIncreaseControl]',
                    exportAs: 'ngsIncreaseControl'
                }]
        }] });

class NumberInput {
    ngControl;
    _parentForm = inject(NgForm, {
        optional: true,
    });
    _parentFormGroup = inject(FormGroupDirective, {
        optional: true,
    });
    _elementRef = inject(ElementRef);
    disableAutomaticLabeling = false;
    _input = viewChild.required('input');
    _decreaseControlRef = contentChild(DecreaseControlDirective, ...(ngDevMode ? [{ debugName: "_decreaseControlRef" }] : /* istanbul ignore next */ []));
    _increaseControlRef = contentChild(IncreaseControlDirective, ...(ngDevMode ? [{ debugName: "_increaseControlRef" }] : /* istanbul ignore next */ []));
    min = input(undefined, { ...(ngDevMode ? { debugName: "min" } : /* istanbul ignore next */ {}), transform: numberAttribute });
    max = input(undefined, { ...(ngDevMode ? { debugName: "max" } : /* istanbul ignore next */ {}), transform: numberAttribute });
    step = input(1, { ...(ngDevMode ? { debugName: "step" } : /* istanbul ignore next */ {}), transform: numberAttribute });
    readonly = input(false, { ...(ngDevMode ? { debugName: "readonly" } : /* istanbul ignore next */ {}), transform: booleanAttribute });
    disabledInput = input(false, { ...(ngDevMode ? { debugName: "disabledInput" } : /* istanbul ignore next */ {}), transform: booleanAttribute,
        alias: 'disabled' });
    get disabled() {
        return this.disabledInput() || this._disabled();
    }
    _disabled = signal(false, ...(ngDevMode ? [{ debugName: "_disabled" }] : /* istanbul ignore next */ []));
    requiredInput = input(false, { ...(ngDevMode ? { debugName: "requiredInput" } : /* istanbul ignore next */ {}), transform: booleanAttribute,
        alias: 'required' });
    get required() {
        return this.requiredInput() || this._required();
    }
    _required = signal(false, ...(ngDevMode ? [{ debugName: "_required" }] : /* istanbul ignore next */ []));
    valueChange = output();
    static nextId = 0;
    _value = signal(undefined, ...(ngDevMode ? [{ debugName: "_value" }] : /* istanbul ignore next */ []));
    controlType;
    autofilled;
    userAriaDescribedBy;
    stateChanges = new Subject();
    focused = false;
    _focused = signal(false, ...(ngDevMode ? [{ debugName: "_focused" }] : /* istanbul ignore next */ []));
    touched = false;
    errorState = false;
    _errorState = signal(false, ...(ngDevMode ? [{ debugName: "_errorState" }] : /* istanbul ignore next */ []));
    id = '';
    _id = signal(`ngs-number-input${NumberInput.nextId++}`, ...(ngDevMode ? [{ debugName: "_id" }] : /* istanbul ignore next */ []));
    shouldLabelFloat = false;
    _shouldLabelFloat = computed(() => {
        return this._focused() || !this._empty();
    }, ...(ngDevMode ? [{ debugName: "_shouldLabelFloat" }] : /* istanbul ignore next */ []));
    empty = true;
    _empty = computed(() => {
        const value = this._value();
        return value === undefined || value === null || value === '';
    }, ...(ngDevMode ? [{ debugName: "_empty" }] : /* istanbul ignore next */ []));
    _placeholder = input('', { ...(ngDevMode ? { debugName: "_placeholder" } : /* istanbul ignore next */ {}), alias: 'placeholder' });
    get placeholder() {
        return this._placeholder();
    }
    constructor(ngControl) {
        this.ngControl = ngControl;
        // Replace the provider from above with this.
        if (this.ngControl != null) {
            // Setting the value accessor directly (instead of using
            // the providers) to avoid running into a circular import.
            this.ngControl.valueAccessor = this;
        }
        effect(() => {
            this.id = this._id();
            this.focused = this._focused();
            this.errorState = this._errorState();
            this.empty = this._empty();
            this.shouldLabelFloat = this._shouldLabelFloat();
            this.stateChanges.next();
        });
        effect(() => {
            const value = this._value();
            if (this._input()) {
                this._input().nativeElement.value = (value === undefined || value === null) ? '' : value;
            }
        });
    }
    setDescribedByIds(ids) {
        const controlElement = this._elementRef.nativeElement;
        controlElement.setAttribute('aria-describedby', ids.join(' '));
    }
    onFocusIn(event) {
        if (!this._focused()) {
            this._focused.set(true);
            this.stateChanges.next();
        }
    }
    onFocusOut(event) {
        if (!this._elementRef.nativeElement.contains(event.relatedTarget)) {
            this.touched = true;
            this._focused.set(false);
            this.onTouched();
            this.stateChanges.next();
        }
    }
    set value(value) {
        if (value !== this._value()) {
            this._value.set(value);
            this.stateChanges.next();
        }
    }
    get value() {
        return this._value();
    }
    ngOnDestroy() {
        this.stateChanges.complete();
    }
    get _decreaseControlTemplateRef() {
        return this._decreaseControlRef()?.templateRef;
    }
    get _increaseControlTemplateRef() {
        return this._increaseControlRef()?.templateRef;
    }
    onChange = () => { };
    onTouched = () => { };
    registerOnChange(fn) {
        this.onChange = fn;
    }
    registerOnTouched(fn) {
        this.onTouched = fn;
    }
    setDisabledState(isDisabled) {
        this._disabled.set(coerceBooleanProperty(isDisabled));
    }
    writeValue(value) {
        this.value = value;
    }
    decrease(event, input) {
        event.preventDefault();
        event.stopPropagation();
        let value = this._value() ?? 0;
        value -= this.step();
        this._value.set(value);
        this._emitEvent();
    }
    increase(event, input) {
        event.preventDefault();
        event.stopPropagation();
        let value = this._value() ?? 0;
        value += this.step();
        this._value.set(value);
        this._emitEvent();
    }
    isDecreaseDisabled() {
        const value = this._value();
        if (this.min() === undefined) {
            return false;
        }
        return (value !== undefined && value <= this.min()) || this.readonly() || this.disabled;
    }
    isIncreaseDisabled() {
        const value = this._value();
        if (this.max() === undefined) {
            return false;
        }
        return (value !== undefined && value >= this.max()) || this.readonly() || this.disabled;
    }
    inputChange(event) {
        const inputValue = event.target.value;
        const value = inputValue === '' ? undefined : +inputValue;
        this._value.set(value);
        this._emitEvent();
    }
    _emitEvent() {
        const value = this._value();
        this.onChange(value);
        this.valueChange.emit(value);
        this.updateErrorState();
    }
    ngDoCheck() {
        if (this.ngControl) {
            this.updateErrorState();
        }
    }
    focus() {
        this._input().nativeElement.focus();
    }
    onContainerClick(event) {
        if (event.target.tagName.toLowerCase() != 'input') {
            this.focus();
        }
    }
    updateErrorState() {
        const parent = this._parentFormGroup || this._parentForm;
        let oldState = this._errorState();
        let newState = !!(this.ngControl?.invalid) && this.touched;
        if (parent) {
            newState = !!(this.ngControl?.invalid) && (this.touched || parent.submitted);
        }
        if (oldState !== newState) {
            this._errorState.set(newState);
            this.stateChanges.next();
        }
    }
    static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "21.2.4", ngImport: i0, type: NumberInput, deps: [{ token: i1.NgControl, optional: true, self: true }], target: i0.ɵɵFactoryTarget.Component });
    static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "21.2.4", type: NumberInput, isStandalone: true, selector: "ngs-number-input", inputs: { min: { classPropertyName: "min", publicName: "min", isSignal: true, isRequired: false, transformFunction: null }, max: { classPropertyName: "max", publicName: "max", isSignal: true, isRequired: false, transformFunction: null }, step: { classPropertyName: "step", publicName: "step", isSignal: true, isRequired: false, transformFunction: null }, readonly: { classPropertyName: "readonly", publicName: "readonly", isSignal: true, isRequired: false, transformFunction: null }, disabledInput: { classPropertyName: "disabledInput", publicName: "disabled", isSignal: true, isRequired: false, transformFunction: null }, requiredInput: { classPropertyName: "requiredInput", publicName: "required", isSignal: true, isRequired: false, transformFunction: null }, _placeholder: { classPropertyName: "_placeholder", publicName: "placeholder", isSignal: true, isRequired: false, transformFunction: null } }, outputs: { valueChange: "valueChange" }, host: { attributes: { "id": "id" }, properties: { "class.floating": "shouldLabelFloat" }, classAttribute: "ngs-number-input" }, providers: [
            {
                provide: FormFieldControl,
                useExisting: forwardRef(() => NumberInput),
            }
        ], queries: [{ propertyName: "_decreaseControlRef", first: true, predicate: DecreaseControlDirective, descendants: true, isSignal: true }, { propertyName: "_increaseControlRef", first: true, predicate: IncreaseControlDirective, descendants: true, isSignal: true }], viewQueries: [{ propertyName: "_input", first: true, predicate: ["input"], descendants: true, isSignal: true }], exportAs: ["ngsNumberInput"], ngImport: i0, template: "<input #input type=\"number\" class=\"input\"\n       (focusin)=\"onFocusIn($event)\"\n       (focusout)=\"onFocusOut($event)\"\n       [attr.min]=\"min()\"\n       [attr.max]=\"max()\"\n       [step]=\"step()\"\n       (input)=\"inputChange($event)\">\n<div class=\"controls\">\n  <button class=\"control control-decrease\" ngsRipple [disabled]=\"isDecreaseDisabled()\" (click)=\"decrease($event, input)\">\n    @if (_decreaseControlRef()) {\n      <ng-template [ngTemplateOutlet]=\"_decreaseControlTemplateRef\"/>\n    } @else {\n      <span>&minus;</span>\n    }\n  </button>\n  <button class=\"control control-increase\" ngsRipple [disabled]=\"isIncreaseDisabled()\" (click)=\"increase($event, input)\">\n    @if (_increaseControlRef()) {\n      <ng-template [ngTemplateOutlet]=\"_increaseControlTemplateRef\"/>\n    } @else {\n      <span>&plus;</span>\n    }\n  </button>\n</div>\n", styles: [":host{--ngs-number-input-gap: calc(var(--spacing, .25rem) * 2);--ngs-number-input-control-bg: none;--ngs-number-input-control-color: var(--ngs-color-neutral-500);--ngs-number-input-control-hover-color: var(--ngs-color-neutral-600);--ngs-number-input-control-active-color: var(--ngs-color-neutral-700);--ngs-number-input-control-hover-bg: var(--ngs-color-surface-container);--ngs-number-input-control-active-bg: var(--ngs-color-surface-container-high);--ngs-number-input-control-font-size: 1.5rem;--ngs-number-input-control-border-radius: var(--ngs-radius-md);--ngs-number-input-suffix-gap: calc(var(--spacing, .25rem) * 3);--ngs-number-input-control-size: calc(var(--spacing, .25rem) * 7);--ngs-number-input-control-border: none;display:flex!important;gap:var(--ngs-number-input-gap)}:host .input{width:auto;max-width:none;flex-grow:1;min-width:0}:host .input{background:none;outline:none;color:currentColor;font:inherit;border:none}:host .input::-webkit-outer-spin-button,:host .input::-webkit-inner-spin-button{appearance:none;margin:0}:host .controls{display:flex;height:100%;gap:.375rem;-webkit-user-select:none;user-select:none}:host .control{cursor:pointer;flex:none;display:flex;align-items:center;justify-content:center;width:var(--ngs-number-input-control-size);height:var(--ngs-number-input-control-size);background:var(--ngs-number-input-control-bg);color:var(--ngs-number-input-control-color);font-size:var(--ngs-number-input-control-font-size);line-height:var(--ngs-number-input-control-font-size);border-radius:var(--ngs-number-input-control-border-radius);position:relative;border:var(--ngs-number-input-control-border);top:1px}:host .control span{position:relative;top:-1px}:host .control ::ng-deep .mat-icon{line-height:24px}:host .control:hover{background:var(--ngs-number-input-control-hover-bg);color:var(--ngs-number-input-control-hover-color)}:host .control[disabled]{pointer-events:none;opacity:.65}:host-context(html.dark){--ngs-number-input-control-color: var(--ngs-color-neutral-300);--ngs-number-input-control-hover-color: var(--ngs-color-neutral-200);--ngs-number-input-control-hover-bg: var(--ngs-color-neutral-500)}\n/*! tailwindcss v4.2.2 | MIT License | https://tailwindcss.com */\n"], dependencies: [{ kind: "directive", type: Ripple, selector: "[ngsRipple]", inputs: ["ngsRippleColor", "ngsRippleUnbounded", "ngsRippleCentered", "ngsRippleRadius", "ngsRippleAnimation", "ngsRippleDisabled", "ngsRippleTrigger"], outputs: ["ngsRippleCenteredChange", "ngsRippleDisabledChange", "ngsRippleTriggerChange"], exportAs: ["ngsRipple"] }, { kind: "directive", type: NgTemplateOutlet, selector: "[ngTemplateOutlet]", inputs: ["ngTemplateOutletContext", "ngTemplateOutlet", "ngTemplateOutletInjector"] }], changeDetection: i0.ChangeDetectionStrategy.OnPush });
}
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.4", ngImport: i0, type: NumberInput, decorators: [{
            type: Component,
            args: [{ selector: 'ngs-number-input', exportAs: 'ngsNumberInput', imports: [
                        Ripple,
                        NgTemplateOutlet
                    ], providers: [
                        {
                            provide: FormFieldControl,
                            useExisting: forwardRef(() => NumberInput),
                        }
                    ], changeDetection: ChangeDetectionStrategy.OnPush, host: {
                        'class': 'ngs-number-input',
                        '[class.floating]': 'shouldLabelFloat',
                        'id': 'id'
                    }, template: "<input #input type=\"number\" class=\"input\"\n       (focusin)=\"onFocusIn($event)\"\n       (focusout)=\"onFocusOut($event)\"\n       [attr.min]=\"min()\"\n       [attr.max]=\"max()\"\n       [step]=\"step()\"\n       (input)=\"inputChange($event)\">\n<div class=\"controls\">\n  <button class=\"control control-decrease\" ngsRipple [disabled]=\"isDecreaseDisabled()\" (click)=\"decrease($event, input)\">\n    @if (_decreaseControlRef()) {\n      <ng-template [ngTemplateOutlet]=\"_decreaseControlTemplateRef\"/>\n    } @else {\n      <span>&minus;</span>\n    }\n  </button>\n  <button class=\"control control-increase\" ngsRipple [disabled]=\"isIncreaseDisabled()\" (click)=\"increase($event, input)\">\n    @if (_increaseControlRef()) {\n      <ng-template [ngTemplateOutlet]=\"_increaseControlTemplateRef\"/>\n    } @else {\n      <span>&plus;</span>\n    }\n  </button>\n</div>\n", styles: [":host{--ngs-number-input-gap: calc(var(--spacing, .25rem) * 2);--ngs-number-input-control-bg: none;--ngs-number-input-control-color: var(--ngs-color-neutral-500);--ngs-number-input-control-hover-color: var(--ngs-color-neutral-600);--ngs-number-input-control-active-color: var(--ngs-color-neutral-700);--ngs-number-input-control-hover-bg: var(--ngs-color-surface-container);--ngs-number-input-control-active-bg: var(--ngs-color-surface-container-high);--ngs-number-input-control-font-size: 1.5rem;--ngs-number-input-control-border-radius: var(--ngs-radius-md);--ngs-number-input-suffix-gap: calc(var(--spacing, .25rem) * 3);--ngs-number-input-control-size: calc(var(--spacing, .25rem) * 7);--ngs-number-input-control-border: none;display:flex!important;gap:var(--ngs-number-input-gap)}:host .input{width:auto;max-width:none;flex-grow:1;min-width:0}:host .input{background:none;outline:none;color:currentColor;font:inherit;border:none}:host .input::-webkit-outer-spin-button,:host .input::-webkit-inner-spin-button{appearance:none;margin:0}:host .controls{display:flex;height:100%;gap:.375rem;-webkit-user-select:none;user-select:none}:host .control{cursor:pointer;flex:none;display:flex;align-items:center;justify-content:center;width:var(--ngs-number-input-control-size);height:var(--ngs-number-input-control-size);background:var(--ngs-number-input-control-bg);color:var(--ngs-number-input-control-color);font-size:var(--ngs-number-input-control-font-size);line-height:var(--ngs-number-input-control-font-size);border-radius:var(--ngs-number-input-control-border-radius);position:relative;border:var(--ngs-number-input-control-border);top:1px}:host .control span{position:relative;top:-1px}:host .control ::ng-deep .mat-icon{line-height:24px}:host .control:hover{background:var(--ngs-number-input-control-hover-bg);color:var(--ngs-number-input-control-hover-color)}:host .control[disabled]{pointer-events:none;opacity:.65}:host-context(html.dark){--ngs-number-input-control-color: var(--ngs-color-neutral-300);--ngs-number-input-control-hover-color: var(--ngs-color-neutral-200);--ngs-number-input-control-hover-bg: var(--ngs-color-neutral-500)}\n/*! tailwindcss v4.2.2 | MIT License | https://tailwindcss.com */\n"] }]
        }], ctorParameters: () => [{ type: i1.NgControl, decorators: [{
                    type: Optional
                }, {
                    type: Self
                }] }], propDecorators: { _input: [{ type: i0.ViewChild, args: ['input', { isSignal: true }] }], _decreaseControlRef: [{ type: i0.ContentChild, args: [i0.forwardRef(() => DecreaseControlDirective), { isSignal: true }] }], _increaseControlRef: [{ type: i0.ContentChild, args: [i0.forwardRef(() => IncreaseControlDirective), { isSignal: true }] }], min: [{ type: i0.Input, args: [{ isSignal: true, alias: "min", required: false }] }], max: [{ type: i0.Input, args: [{ isSignal: true, alias: "max", required: false }] }], step: [{ type: i0.Input, args: [{ isSignal: true, alias: "step", required: false }] }], readonly: [{ type: i0.Input, args: [{ isSignal: true, alias: "readonly", required: false }] }], disabledInput: [{ type: i0.Input, args: [{ isSignal: true, alias: "disabled", required: false }] }], requiredInput: [{ type: i0.Input, args: [{ isSignal: true, alias: "required", required: false }] }], valueChange: [{ type: i0.Output, args: ["valueChange"] }], _placeholder: [{ type: i0.Input, args: [{ isSignal: true, alias: "placeholder", required: false }] }] } });

class NumberInputPrefixDirective {
    templateRef = inject(TemplateRef);
    static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "21.2.4", ngImport: i0, type: NumberInputPrefixDirective, deps: [], target: i0.ɵɵFactoryTarget.Directive });
    static ɵdir = i0.ɵɵngDeclareDirective({ minVersion: "14.0.0", version: "21.2.4", type: NumberInputPrefixDirective, isStandalone: true, selector: "[ngsNumberInputPrefix]", exportAs: ["ngsNumberInputPrefix"], ngImport: i0 });
}
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.4", ngImport: i0, type: NumberInputPrefixDirective, decorators: [{
            type: Directive,
            args: [{
                    selector: '[ngsNumberInputPrefix]',
                    exportAs: 'ngsNumberInputPrefix'
                }]
        }] });

class NumberInputSuffixDirective {
    templateRef = inject(TemplateRef);
    static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "21.2.4", ngImport: i0, type: NumberInputSuffixDirective, deps: [], target: i0.ɵɵFactoryTarget.Directive });
    static ɵdir = i0.ɵɵngDeclareDirective({ minVersion: "14.0.0", version: "21.2.4", type: NumberInputSuffixDirective, isStandalone: true, selector: "[ngsNumberInputSuffix]", exportAs: ["ngsNumberInputSuffix"], ngImport: i0 });
}
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.4", ngImport: i0, type: NumberInputSuffixDirective, decorators: [{
            type: Directive,
            args: [{
                    selector: '[ngsNumberInputSuffix]',
                    exportAs: 'ngsNumberInputSuffix'
                }]
        }] });

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

export { DecreaseControlDirective, IncreaseControlDirective, NumberInput, NumberInputPrefixDirective, NumberInputSuffixDirective };
//# sourceMappingURL=ngstarter-ui-components-number-input.mjs.map
