import { CommonModule } from '@angular/common';
import { Component, inject, Input, Output, EventEmitter } from '@angular/core';
import { ReactiveFormsModule } from '@angular/forms';
import { IonButton, IonIcon, IonInput } from '@ionic/angular/standalone';
import { addIcons } from 'ionicons';
import { addOutline, removeOutline } from 'ionicons/icons';
import { I18nService } from '../../../services/i18n';
import { ComponentStates } from '../../types';
import * as i0 from "@angular/core";
import * as i1 from "@angular/forms";
addIcons({ addOutline, removeOutline });
/**
 * val-number-stepper
 *
 * A number input with increment/decrement buttons, ideal for quantity selection.
 *
 * @example Basic usage
 * ```html
 * <val-number-stepper
 *   [props]="{
 *     control: quantityControl,
 *     min: 1,
 *     max: 100
 *   }"
 * ></val-number-stepper>
 * ```
 *
 * @example With pricing
 * ```html
 * <val-number-stepper
 *   [props]="{
 *     control: ticketControl,
 *     min: 1,
 *     max: 50,
 *     unitPrice: 10,
 *     currency: 'MXN',
 *     currencySymbol: '$',
 *     showTotal: true,
 *     unitLabel: 'boletos',
 *     unitLabelSingular: 'boleto'
 *   }"
 *   (valueChange)="onQuantityChange($event)"
 * ></val-number-stepper>
 * ```
 *
 * @example With presets
 * ```html
 * <val-number-stepper
 *   [props]="{
 *     control: ticketControl,
 *     min: 1,
 *     max: 100,
 *     showPresets: true,
 *     presets: [
 *       { value: 1 },
 *       { value: 5, popular: true },
 *       { value: 10 },
 *       { value: 25 }
 *     ]
 *   }"
 * ></val-number-stepper>
 * ```
 */
export class NumberStepperComponent {
    constructor() {
        this.valueChange = new EventEmitter();
        this.states = ComponentStates;
        this.i18n = inject(I18nService);
        this.valueSubscription = null;
    }
    /** Get decrement button aria-label with i18n fallback */
    getDecrementLabel() {
        return this.props.decrementLabel || this.i18n.t('decrease');
    }
    /** Get increment button aria-label with i18n fallback */
    getIncrementLabel() {
        return this.props.incrementLabel || this.i18n.t('increase');
    }
    ngOnInit() {
        // Ensure initial value is within bounds
        this.clampValue();
        // Subscribe to value changes
        this.valueSubscription = this.props.control.valueChanges.subscribe(() => {
            this.clampValue();
        });
    }
    ngOnDestroy() {
        this.valueSubscription?.unsubscribe();
    }
    get currentValue() {
        return this.props.control.value ?? this.props.min ?? 0;
    }
    get isAtMin() {
        if (this.props.min === undefined)
            return false;
        return this.currentValue <= this.props.min;
    }
    get isAtMax() {
        if (this.props.max === undefined)
            return false;
        return this.currentValue >= this.props.max;
    }
    get totalPrice() {
        return this.currentValue * (this.props.unitPrice || 0);
    }
    increment() {
        const step = this.props.step || 1;
        const newValue = this.currentValue + step;
        this.setValue(newValue);
    }
    decrement() {
        const step = this.props.step || 1;
        const newValue = this.currentValue - step;
        this.setValue(newValue);
    }
    setValue(value) {
        const previousValue = this.currentValue;
        const clampedValue = this.clamp(value);
        if (clampedValue !== previousValue) {
            this.props.control.setValue(clampedValue);
            this.emitChange(clampedValue, previousValue);
        }
    }
    onInputBlur() {
        this.clampValue();
    }
    clampValue() {
        const currentVal = this.props.control.value;
        const clampedVal = this.clamp(currentVal);
        if (currentVal !== clampedVal) {
            this.props.control.setValue(clampedVal);
        }
    }
    clamp(value) {
        let result = value;
        if (this.props.min !== undefined && result < this.props.min) {
            result = this.props.min;
        }
        if (this.props.max !== undefined && result > this.props.max) {
            result = this.props.max;
        }
        return result;
    }
    emitChange(value, previousValue) {
        this.valueChange.emit({
            value,
            previousValue,
            totalPrice: this.props.unitPrice ? value * this.props.unitPrice : undefined,
            atMin: this.isAtMin,
            atMax: this.isAtMax,
        });
    }
    getLabel() {
        return this.props.label || '';
    }
    getUnitLabel() {
        if (this.currentValue === 1 && this.props.unitLabelSingular) {
            return this.props.unitLabelSingular;
        }
        return this.props.unitLabel || '';
    }
    formatPrice(amount) {
        const symbol = this.props.currencySymbol || '$';
        const formatted = amount.toLocaleString('es-MX', {
            minimumFractionDigits: 2,
            maximumFractionDigits: 2,
        });
        return `${symbol}${formatted}`;
    }
    getColor() {
        if (this.props.color) {
            return `var(--ion-color-${this.props.color})`;
        }
        return 'var(--ion-color-primary)';
    }
    static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "18.2.14", ngImport: i0, type: NumberStepperComponent, deps: [], target: i0.ɵɵFactoryTarget.Component }); }
    static { this.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "18.2.14", type: NumberStepperComponent, isStandalone: true, selector: "val-number-stepper", inputs: { props: "props" }, outputs: { valueChange: "valueChange" }, ngImport: i0, template: `
    <div
      class="number-stepper-container"
      [class]="props.cssClass"
      [class.size-small]="props.size === 'small'"
      [class.size-medium]="props.size === 'medium' || !props.size"
      [class.size-large]="props.size === 'large'"
      [class.layout-vertical]="props.layout === 'vertical'"
      [class.disabled]="props.state === states.DISABLED"
      [style.--stepper-color]="getColor()"
    >
      @if (props.label) {
        <label class="stepper-label">{{ getLabel() }}</label>
      }

      <!-- Preset buttons -->
      @if (props.showPresets && props.presets?.length) {
        <div class="preset-buttons">
          @for (preset of props.presets; track preset.value) {
            <button
              type="button"
              class="preset-button"
              [class.active]="currentValue === preset.value"
              [class.popular]="preset.popular"
              (click)="setValue(preset.value)"
              [disabled]="props.state === states.DISABLED"
            >
              {{ preset.label || preset.value }}
            </button>
          }
        </div>
      }

      <!-- Stepper controls -->
      <div class="stepper-controls">
        <ion-button
          class="stepper-button decrement"
          [color]="props.color || 'primary'"
          fill="outline"
          [shape]="props.buttonShape || 'round'"
          [disabled]="isAtMin || props.state === states.DISABLED"
          (click)="decrement()"
          [attr.aria-label]="getDecrementLabel()"
        >
          <ion-icon slot="icon-only" name="remove-outline"></ion-icon>
        </ion-button>

        <div class="value-display">
          @if (props.showInput !== false && props.editableInput) {
            <ion-input
              type="number"
              [formControl]="props.control"
              [min]="props.min"
              [max]="props.max"
              [step]="props.step || 1"
              [disabled]="props.state === states.DISABLED"
              class="value-input"
              (ionBlur)="onInputBlur()"
            ></ion-input>
          } @else {
            <span class="value-text">{{ currentValue }}</span>
          }

          @if (props.unitLabel) {
            <span class="unit-label">{{ getUnitLabel() }}</span>
          }
        </div>

        <ion-button
          class="stepper-button increment"
          [color]="props.color || 'primary'"
          fill="outline"
          [shape]="props.buttonShape || 'round'"
          [disabled]="isAtMax || props.state === states.DISABLED"
          (click)="increment()"
          [attr.aria-label]="getIncrementLabel()"
        >
          <ion-icon slot="icon-only" name="add-outline"></ion-icon>
        </ion-button>
      </div>

      <!-- Price display -->
      @if (props.showTotal && props.unitPrice) {
        <div class="price-display">
          <span class="price-calculation">
            {{ currentValue }} × {{ formatPrice(props.unitPrice) }}
          </span>
          <span class="price-equals">=</span>
          <span class="price-total">{{ formatPrice(totalPrice) }}</span>
        </div>
      }

      @if (props.hint) {
        <span class="stepper-hint">{{ props.hint }}</span>
      }
    </div>
  `, isInline: true, styles: ["@charset \"UTF-8\";:host{display:block}.number-stepper-container{--stepper-color: var(--ion-color-primary);display:flex;flex-direction:column;align-items:center;gap:12px}.number-stepper-container.disabled{opacity:.5;pointer-events:none}.stepper-label{font-size:.875rem;font-weight:500;color:var(--ion-color-dark);margin-bottom:4px}.preset-buttons{display:flex;gap:8px;flex-wrap:wrap;justify-content:center}.preset-button{padding:6px 16px;border:1px solid var(--ion-color-medium-shade);border-radius:20px;background:transparent;color:var(--ion-color-dark);font-size:.875rem;font-weight:500;cursor:pointer;transition:all .2s}.preset-button:hover:not(:disabled){border-color:var(--stepper-color);color:var(--stepper-color)}.preset-button.active{background:var(--stepper-color);border-color:var(--stepper-color);color:#fff}.preset-button.popular{position:relative}.preset-button.popular:after{content:\"\\2605\";position:absolute;top:-8px;right:-4px;font-size:.75rem;color:var(--ion-color-warning)}.preset-button:disabled{opacity:.5;cursor:not-allowed}.stepper-controls{display:flex;align-items:center;gap:16px}.stepper-button{--padding-start: 0;--padding-end: 0}.stepper-button::part(native){padding:8px}.stepper-button ion-icon{font-size:1.5rem}.value-display{display:flex;flex-direction:column;align-items:center;min-width:80px;text-align:center}.value-text{font-size:2rem;font-weight:700;color:var(--ion-color-dark);font-variant-numeric:tabular-nums}.value-input{text-align:center;font-size:2rem;font-weight:700;max-width:100px}.value-input::part(native){text-align:center}.unit-label{font-size:.75rem;color:var(--ion-color-medium);margin-top:2px}.price-display{display:flex;align-items:center;gap:8px;padding:8px 16px;background:var(--ion-color-light);border-radius:8px;font-size:.875rem}.price-calculation{color:var(--ion-color-medium-shade)}.price-equals{color:var(--ion-color-medium)}.price-total{font-size:1.125rem;font-weight:700;color:var(--stepper-color)}.stepper-hint{font-size:.75rem;color:var(--ion-color-medium)}.size-small,.size-small .stepper-controls{gap:8px}.size-small .stepper-button{--size: 32px}.size-small .stepper-button ion-icon{font-size:1.125rem}.size-small .value-display{min-width:50px}.size-small .value-text,.size-small .value-input{font-size:1.25rem}.size-small .preset-button,.size-small .price-display{padding:4px 12px;font-size:.75rem}.size-small .price-total{font-size:.875rem}.size-large{gap:16px}.size-large .stepper-controls{gap:24px}.size-large .stepper-button{--size: 56px}.size-large .stepper-button ion-icon{font-size:2rem}.size-large .value-display{min-width:120px}.size-large .value-text,.size-large .value-input{font-size:3rem}.size-large .preset-button{padding:8px 20px;font-size:1rem}.size-large .price-display{padding:12px 24px;font-size:1rem}.size-large .price-total{font-size:1.5rem}.layout-vertical .stepper-controls{flex-direction:column-reverse;gap:8px}.layout-vertical .stepper-button{width:100%;max-width:120px}\n"], dependencies: [{ kind: "ngmodule", type: CommonModule }, { kind: "ngmodule", type: ReactiveFormsModule }, { kind: "directive", type: i1.NgControlStatus, selector: "[formControlName],[ngModel],[formControl]" }, { kind: "directive", type: i1.FormControlDirective, selector: "[formControl]", inputs: ["formControl", "disabled", "ngModel"], outputs: ["ngModelChange"], exportAs: ["ngForm"] }, { kind: "component", type: IonButton, selector: "ion-button", inputs: ["buttonType", "color", "disabled", "download", "expand", "fill", "form", "href", "mode", "rel", "routerAnimation", "routerDirection", "shape", "size", "strong", "target", "type"] }, { kind: "component", type: IonIcon, selector: "ion-icon", inputs: ["color", "flipRtl", "icon", "ios", "lazy", "md", "mode", "name", "sanitize", "size", "src"] }, { kind: "component", type: IonInput, selector: "ion-input", inputs: ["accept", "autocapitalize", "autocomplete", "autocorrect", "autofocus", "clearInput", "clearOnEdit", "color", "counter", "counterFormatter", "debounce", "disabled", "enterkeyhint", "errorText", "fill", "helperText", "inputmode", "label", "labelPlacement", "max", "maxlength", "min", "minlength", "mode", "multiple", "name", "pattern", "placeholder", "readonly", "required", "shape", "size", "spellcheck", "step", "type", "value"] }] }); }
}
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "18.2.14", ngImport: i0, type: NumberStepperComponent, decorators: [{
            type: Component,
            args: [{ selector: 'val-number-stepper', standalone: true, imports: [CommonModule, ReactiveFormsModule, IonButton, IonIcon, IonInput], template: `
    <div
      class="number-stepper-container"
      [class]="props.cssClass"
      [class.size-small]="props.size === 'small'"
      [class.size-medium]="props.size === 'medium' || !props.size"
      [class.size-large]="props.size === 'large'"
      [class.layout-vertical]="props.layout === 'vertical'"
      [class.disabled]="props.state === states.DISABLED"
      [style.--stepper-color]="getColor()"
    >
      @if (props.label) {
        <label class="stepper-label">{{ getLabel() }}</label>
      }

      <!-- Preset buttons -->
      @if (props.showPresets && props.presets?.length) {
        <div class="preset-buttons">
          @for (preset of props.presets; track preset.value) {
            <button
              type="button"
              class="preset-button"
              [class.active]="currentValue === preset.value"
              [class.popular]="preset.popular"
              (click)="setValue(preset.value)"
              [disabled]="props.state === states.DISABLED"
            >
              {{ preset.label || preset.value }}
            </button>
          }
        </div>
      }

      <!-- Stepper controls -->
      <div class="stepper-controls">
        <ion-button
          class="stepper-button decrement"
          [color]="props.color || 'primary'"
          fill="outline"
          [shape]="props.buttonShape || 'round'"
          [disabled]="isAtMin || props.state === states.DISABLED"
          (click)="decrement()"
          [attr.aria-label]="getDecrementLabel()"
        >
          <ion-icon slot="icon-only" name="remove-outline"></ion-icon>
        </ion-button>

        <div class="value-display">
          @if (props.showInput !== false && props.editableInput) {
            <ion-input
              type="number"
              [formControl]="props.control"
              [min]="props.min"
              [max]="props.max"
              [step]="props.step || 1"
              [disabled]="props.state === states.DISABLED"
              class="value-input"
              (ionBlur)="onInputBlur()"
            ></ion-input>
          } @else {
            <span class="value-text">{{ currentValue }}</span>
          }

          @if (props.unitLabel) {
            <span class="unit-label">{{ getUnitLabel() }}</span>
          }
        </div>

        <ion-button
          class="stepper-button increment"
          [color]="props.color || 'primary'"
          fill="outline"
          [shape]="props.buttonShape || 'round'"
          [disabled]="isAtMax || props.state === states.DISABLED"
          (click)="increment()"
          [attr.aria-label]="getIncrementLabel()"
        >
          <ion-icon slot="icon-only" name="add-outline"></ion-icon>
        </ion-button>
      </div>

      <!-- Price display -->
      @if (props.showTotal && props.unitPrice) {
        <div class="price-display">
          <span class="price-calculation">
            {{ currentValue }} × {{ formatPrice(props.unitPrice) }}
          </span>
          <span class="price-equals">=</span>
          <span class="price-total">{{ formatPrice(totalPrice) }}</span>
        </div>
      }

      @if (props.hint) {
        <span class="stepper-hint">{{ props.hint }}</span>
      }
    </div>
  `, styles: ["@charset \"UTF-8\";:host{display:block}.number-stepper-container{--stepper-color: var(--ion-color-primary);display:flex;flex-direction:column;align-items:center;gap:12px}.number-stepper-container.disabled{opacity:.5;pointer-events:none}.stepper-label{font-size:.875rem;font-weight:500;color:var(--ion-color-dark);margin-bottom:4px}.preset-buttons{display:flex;gap:8px;flex-wrap:wrap;justify-content:center}.preset-button{padding:6px 16px;border:1px solid var(--ion-color-medium-shade);border-radius:20px;background:transparent;color:var(--ion-color-dark);font-size:.875rem;font-weight:500;cursor:pointer;transition:all .2s}.preset-button:hover:not(:disabled){border-color:var(--stepper-color);color:var(--stepper-color)}.preset-button.active{background:var(--stepper-color);border-color:var(--stepper-color);color:#fff}.preset-button.popular{position:relative}.preset-button.popular:after{content:\"\\2605\";position:absolute;top:-8px;right:-4px;font-size:.75rem;color:var(--ion-color-warning)}.preset-button:disabled{opacity:.5;cursor:not-allowed}.stepper-controls{display:flex;align-items:center;gap:16px}.stepper-button{--padding-start: 0;--padding-end: 0}.stepper-button::part(native){padding:8px}.stepper-button ion-icon{font-size:1.5rem}.value-display{display:flex;flex-direction:column;align-items:center;min-width:80px;text-align:center}.value-text{font-size:2rem;font-weight:700;color:var(--ion-color-dark);font-variant-numeric:tabular-nums}.value-input{text-align:center;font-size:2rem;font-weight:700;max-width:100px}.value-input::part(native){text-align:center}.unit-label{font-size:.75rem;color:var(--ion-color-medium);margin-top:2px}.price-display{display:flex;align-items:center;gap:8px;padding:8px 16px;background:var(--ion-color-light);border-radius:8px;font-size:.875rem}.price-calculation{color:var(--ion-color-medium-shade)}.price-equals{color:var(--ion-color-medium)}.price-total{font-size:1.125rem;font-weight:700;color:var(--stepper-color)}.stepper-hint{font-size:.75rem;color:var(--ion-color-medium)}.size-small,.size-small .stepper-controls{gap:8px}.size-small .stepper-button{--size: 32px}.size-small .stepper-button ion-icon{font-size:1.125rem}.size-small .value-display{min-width:50px}.size-small .value-text,.size-small .value-input{font-size:1.25rem}.size-small .preset-button,.size-small .price-display{padding:4px 12px;font-size:.75rem}.size-small .price-total{font-size:.875rem}.size-large{gap:16px}.size-large .stepper-controls{gap:24px}.size-large .stepper-button{--size: 56px}.size-large .stepper-button ion-icon{font-size:2rem}.size-large .value-display{min-width:120px}.size-large .value-text,.size-large .value-input{font-size:3rem}.size-large .preset-button{padding:8px 20px;font-size:1rem}.size-large .price-display{padding:12px 24px;font-size:1rem}.size-large .price-total{font-size:1.5rem}.layout-vertical .stepper-controls{flex-direction:column-reverse;gap:8px}.layout-vertical .stepper-button{width:100%;max-width:120px}\n"] }]
        }], propDecorators: { props: [{
                type: Input
            }], valueChange: [{
                type: Output
            }] } });
//# sourceMappingURL=data:application/json;base64, 