// #region Imports
import { DomServiceLocator } from '../../../../../../Dom/Dom';
import { on } from '@breadstone/mosaik-elements';
import { InputBaseElement } from '../../../../Inputs/Abstracts/InputBase';
// #endregion
/**
 * UpDown Base Element - The foundational base class for all numeric and value spinner components.
 *
 * @description
 * UpDownBaseElement provides the core infrastructure for input controls that allow users to
 * incrementally adjust values within a defined range using up/down buttons or keyboard navigation.
 * It extends InputBaseElement with range constraints (min/max) and manages the connection between
 * the visual input element and change event handling. This abstract class establishes the common
 * API surface for numeric spinners, time pickers, quantity selectors, and other bounded value
 * controls. Subclasses must implement the abstract min/max properties and the onInputChanged()
 * method to handle value type-specific logic (numbers, dates, times, etc.).
 *
 * @remarks
 * The class manages the lifecycle of the internal input element subscription, automatically
 * attaching event listeners in onApplyTemplate() and cleaning them up in disconnectedCallback().
 * The generic type parameter `T` allows type-safe implementations for different value types
 * (number, Date, string, etc.).
 *
 * @name UpDownBaseElement
 * @category Abstract Elements
 *
 * @slot [dynamic] - Slots are defined by concrete updown implementations
 *
 * @csspart [dynamic] - Parts are defined by concrete updown implementations
 *
 * @fires connected {ConnectedEvent} - Emitted when the element is connected to the DOM
 * @fires disconnected {DisconnectedEvent} - Emitted when the element is disconnected from the DOM
 * @fires changed {PropertyChangedEvent} - Emitted when any attribute changes before update
 * @fires input {Event} - Emitted when the input value changes
 *
 * @example
 * Extending UpDownBaseElement for a numeric spinner:
 * ```typescript
 * export class NumericUpDownElement extends UpDownBaseElement<number> {
 *   private _min: number = 0;
 *   private _max: number = 100;
 *
 *   public get min(): number { return this._min; }
 *   public set min(value: number) { this._min = value; }
 *
 *   public get max(): number { return this._max; }
 *   public set max(value: number) { this._max = value; }
 *
 *   protected onInputChanged(event: Event): void {
 *     const value = parseFloat(this.input?.value ?? '0');
 *     this.value = Math.max(this.min, Math.min(this.max, value));
 *   }
 * }
 * ```
 *
 * @example
 * Using updown controls in HTML:
 * ```html
 * <numeric-updown min="0" max="100" value="50"></numeric-updown>
 * <time-updown min="00:00" max="23:59" value="12:00"></time-updown>
 * ```
 *
 * @example
 * Programmatically setting values with range enforcement:
 * ```typescript
 * const updown = document.querySelector('numeric-updown');
 * updown.min = 10;
 * updown.max = 90;
 * updown.value = 50; // Within range
 * updown.setInputValue('75'); // Triggers input event and validation
 * ```
 *
 * @example
 * Accessing the internal input element:
 * ```typescript
 * protected override onApplyTemplate(): void {
 *   super.onApplyTemplate();
 *   if (this.input) {
 *     this.input.setAttribute('inputmode', 'numeric');
 *   }
 * }
 * ```
 *
 * @abstract
 * @public
 */
export class UpDownBaseElement extends InputBaseElement {
    // #region Fields
    _inputSubscription;
    // #endregion
    // #region Ctor
    /**
     * Constructs a new instance of the `UpDownBaseElement` class.
     *
     * @protected
     */
    constructor() {
        super();
        this._inputSubscription = null;
    }
    /**
     * Returns the `input` property.
     *
     * @protected
     * @readonly
     */
    get input() {
        const input = this.shadowRoot
            ? DomServiceLocator.current.findDescendant(this.shadowRoot, 'input')
            : null;
        return input;
    }
    // #endregion
    // #region Methods
    disconnectedCallback() {
        super.disconnectedCallback();
        this._inputSubscription?.dispose();
    }
    onApplyTemplate() {
        super.onApplyTemplate();
        if (this.input) {
            this._inputSubscription = on(this.input, 'input', (x) => this.onInputChanged(x));
        }
    }
    /**
     * @protected
     */
    setInputValue(value) {
        if (this.input) {
            this.input.value = value;
            // it muss be dispatched; otherwise the value will not be updated
            this.input.dispatchEvent(new Event('input', { bubbles: true }));
        }
    }
}
//# sourceMappingURL=UpDownBaseElement.js.map