import * as i0 from '@angular/core';
import { input, booleanAttribute, linkedSignal, inject, ElementRef, Renderer2, effect, Component, output, ViewContainerRef, computed, HostBinding, Directive } from '@angular/core';
import { NgControl } from '@angular/forms';
import { InputDirective } from '@eui/components/shared';
import * as i1 from '@eui/components/directives';
import { EuiClearableDirective, EuiLoadingDirective } from '@eui/components/directives';
import { EuiIconSvgComponent } from '@eui/components/eui-icon';

/**
 * @description
 * A custom input text component that extends InputDirective and provides additional functionality
 * such as validation states, clearable input, and loading states.
 *
 * @usageNotes
 * ### Basic Usage
 * ```html
 * <input euiInputText [(ngModel)]="username" placeholder="Enter username" />
 * ```
 *
 * ### With Clearable Button
 * ```html
 * <input euiInputText [euiClearable]="true" [(ngModel)]="searchTerm" />
 * ```
 *
 * ### With Loading State
 * ```html
 * <input euiInputText [euiLoading]="isSearching" [(ngModel)]="query" />
 * ```
 *
 * ### Accessibility
 * - Use associated `<label>` with `for` attribute
 * - Invalid state is communicated via visual styling and `aria-invalid`
 * - Clearable button has appropriate ARIA label
 *
 * ### Notes
 * - Supports all standard HTML input attributes
 * - Works with Angular Forms (template-driven and reactive)
 * - Validation state automatically syncs with form control
 */
class EuiInputTextComponent extends InputDirective {
    /**
     * @description
     * Gets the CSS classes for the component, including validation state classes
     *
     * @returns {string} Space-separated string of CSS class names
     */
    get class() {
        return [super.getCssClasses('eui-input-text'), this._isInvalid() ? 'eui-input-text--invalid' : ''].join(' ').trim();
    }
    constructor() {
        super();
        /**
         * @description
         * Gets or sets the invalid state of the input
         * When used with NgControl, this state is automatically managed based on control state
         *
         * @returns {boolean} Current invalid state
         */
        this.isInvalid = input(null, { ...(ngDevMode ? { debugName: "isInvalid" } : {}), transform: booleanAttribute });
        /** @internal */
        this._isInvalid = linkedSignal({ ...(ngDevMode ? { debugName: "_isInvalid" } : {}), source: this.isInvalid,
            computation: () => this.isInvalid() });
        this.control = inject(NgControl, { optional: true, self: true });
        this._elementRef = inject(ElementRef);
        this._renderer = inject(Renderer2);
        effect(() => {
            this.setInvalid(this.isInvalid());
        });
    }
    /**
     * @description
     * Initializes the component and sets the root class name
     */
    ngOnInit() {
        super.ngOnInit();
        this._renderer.setProperty(this._elementRef.nativeElement, 'rootClassName', 'eui-input-text');
    }
    /**
     * @description
     * Cleans up component resources
     */
    ngOnDestroy() {
        super.ngOnDestroy();
    }
    /**
     * @description
     * Checks and updates the invalid state when using NgControl
     */
    ngDoCheck() {
        if (this.control) {
            this._isInvalid.set(this.control.invalid && this.control.touched);
        }
    }
    /**
     * @description
     * Sets the invalid state of the input and updates related properties
     *
     * @param {boolean} state - The invalid state to set
     * @private
     */
    setInvalid(state) {
        // in case it's controlled by NgControl override
        this._isInvalid.set(this.control ? this.control.invalid && this.control.touched : state);
        // set BaseDirective Attribute
        this.euiDanger = this._isInvalid();
    }
    static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "21.2.1", ngImport: i0, type: EuiInputTextComponent, deps: [], target: i0.ɵɵFactoryTarget.Component }); }
    static { this.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.1.0", version: "21.2.1", type: EuiInputTextComponent, isStandalone: true, selector: "input[euiInputText]", inputs: { isInvalid: { classPropertyName: "isInvalid", publicName: "isInvalid", isSignal: true, isRequired: false, transformFunction: null } }, host: { properties: { "class": "class" } }, usesInheritance: true, hostDirectives: [{ directive: i1.EuiClearableDirective, inputs: ["euiClearable", "euiClearable", "readonly", "readonly", "disabled", "disabled"] }, { directive: i1.EuiLoadingDirective, inputs: ["euiLoading", "euiLoading", "readonly", "readonly"] }], ngImport: i0, template: '', isInline: true, styles: [".eui-21 :host.eui-input-text{overflow:hidden;text-overflow:ellipsis;white-space:nowrap;font:var(--eui-f);appearance:none;background-color:var(--eui-c-surface-container);border:1px solid var(--eui-c-secondary-border);border-radius:var(--eui-br-s);box-shadow:none;color:var(--eui-c-text);min-height:var(--eui-s-5xl);padding:calc(var(--eui-s-xs) - 1px) calc(var(--eui-s-m) - 1px);width:100%}.eui-21 :host.eui-input-text:focus:not([readonly]){outline:2px solid var(--eui-c-focus)!important;outline-offset:-2px!important;transition:none}.eui-21 :host.eui-input-text:focus-visible:not([readonly]){outline:2px solid var(--eui-c-focus-visible)!important;outline-offset:-2px!important;transition:none}.eui-21 :host.eui-input-text [tabindex=\"0\"]:focus:not([readonly]){outline:2px solid var(--eui-c-focus-visible)!important;outline-offset:-2px!important;transition:none}.eui-21 :host.eui-input-text:not([hidden]){display:block}.eui-21 :host.eui-input-text::placeholder{color:var(--eui-c-text-lighter)!important;opacity:1}.eui-21 :host.eui-input-text[readonly]{background-color:transparent;border-color:transparent;box-shadow:none;height:inherit;padding-left:0;padding-right:0;pointer-events:none}.eui-21 :host.eui-input-text[readonly]+.eui-feedback-message,.eui-21 :host.eui-input-text[readonly]+.eui-input-maxlength{appearance:none;display:none}.eui-21 :host.eui-input-text[disabled]:not([readonly]),.eui-21 :host.eui-input-text--disabled:not([readonly]){background-color:var(--eui-c-disabled-bg)!important;border:1px solid var(--eui-c-secondary-border-lighter);color:var(--eui-c-text-light);pointer-events:none}.eui-21 :host.eui-input-text--invalid,.eui-21 :host.eui-input-text--danger{border:1px solid var(--eui-c-danger-border)}.eui-21 :host.eui-input-text--loading{padding-right:var(--eui-s-7xl)}.eui-21 :host.eui-input-text--loading-icon{align-items:center;display:flex}.eui-21 :host.eui-input-text--loading-icon:after,.eui-21 :host.eui-input-text--loading-icon:before{content:\"\";height:var(--eui-s-l);position:absolute;right:var(--eui-s-s);width:var(--eui-s-l)}.eui-21 :host.eui-input-text--loading-icon:before{border:var(--eui-s-3xs) solid rgba(0,0,0,.35);border-radius:100%}.eui-21 :host.eui-input-text--loading-icon:after{animation:loading .6s linear;animation-iteration-count:infinite;border-color:var(--eui-c-white) transparent transparent;border-radius:100%;border-style:solid;border-width:var(--eui-s-3xs);box-shadow:0 0 0 1px transparent}.eui-21 :host.eui-input-text--loading-icon--sm:after,.eui-21 :host.eui-input-text--loading-icon--sm:before{height:var(--eui-s-m);width:var(--eui-s-m)}@keyframes loading{to{transform:rotate(360deg)}}.eui-21 :host.eui-input-text--clearable{padding-right:var(--eui-s-7xl)}.eui-21 :host.eui-input-text[readonly]{pointer-events:auto}.eui-21 :host.eui-input-text[type=search]::-webkit-search-cancel-button{display:none}\n"] }); }
}
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.1", ngImport: i0, type: EuiInputTextComponent, decorators: [{
            type: Component,
            args: [{ selector: 'input[euiInputText]', template: '', hostDirectives: [
                        {
                            directive: EuiClearableDirective,
                            inputs: ['euiClearable', 'readonly', 'disabled'],
                        },
                        {
                            directive: EuiLoadingDirective,
                            inputs: ['euiLoading', 'readonly'],
                        },
                    ], host: {
                        '[class]': 'class',
                    }, styles: [".eui-21 :host.eui-input-text{overflow:hidden;text-overflow:ellipsis;white-space:nowrap;font:var(--eui-f);appearance:none;background-color:var(--eui-c-surface-container);border:1px solid var(--eui-c-secondary-border);border-radius:var(--eui-br-s);box-shadow:none;color:var(--eui-c-text);min-height:var(--eui-s-5xl);padding:calc(var(--eui-s-xs) - 1px) calc(var(--eui-s-m) - 1px);width:100%}.eui-21 :host.eui-input-text:focus:not([readonly]){outline:2px solid var(--eui-c-focus)!important;outline-offset:-2px!important;transition:none}.eui-21 :host.eui-input-text:focus-visible:not([readonly]){outline:2px solid var(--eui-c-focus-visible)!important;outline-offset:-2px!important;transition:none}.eui-21 :host.eui-input-text [tabindex=\"0\"]:focus:not([readonly]){outline:2px solid var(--eui-c-focus-visible)!important;outline-offset:-2px!important;transition:none}.eui-21 :host.eui-input-text:not([hidden]){display:block}.eui-21 :host.eui-input-text::placeholder{color:var(--eui-c-text-lighter)!important;opacity:1}.eui-21 :host.eui-input-text[readonly]{background-color:transparent;border-color:transparent;box-shadow:none;height:inherit;padding-left:0;padding-right:0;pointer-events:none}.eui-21 :host.eui-input-text[readonly]+.eui-feedback-message,.eui-21 :host.eui-input-text[readonly]+.eui-input-maxlength{appearance:none;display:none}.eui-21 :host.eui-input-text[disabled]:not([readonly]),.eui-21 :host.eui-input-text--disabled:not([readonly]){background-color:var(--eui-c-disabled-bg)!important;border:1px solid var(--eui-c-secondary-border-lighter);color:var(--eui-c-text-light);pointer-events:none}.eui-21 :host.eui-input-text--invalid,.eui-21 :host.eui-input-text--danger{border:1px solid var(--eui-c-danger-border)}.eui-21 :host.eui-input-text--loading{padding-right:var(--eui-s-7xl)}.eui-21 :host.eui-input-text--loading-icon{align-items:center;display:flex}.eui-21 :host.eui-input-text--loading-icon:after,.eui-21 :host.eui-input-text--loading-icon:before{content:\"\";height:var(--eui-s-l);position:absolute;right:var(--eui-s-s);width:var(--eui-s-l)}.eui-21 :host.eui-input-text--loading-icon:before{border:var(--eui-s-3xs) solid rgba(0,0,0,.35);border-radius:100%}.eui-21 :host.eui-input-text--loading-icon:after{animation:loading .6s linear;animation-iteration-count:infinite;border-color:var(--eui-c-white) transparent transparent;border-radius:100%;border-style:solid;border-width:var(--eui-s-3xs);box-shadow:0 0 0 1px transparent}.eui-21 :host.eui-input-text--loading-icon--sm:after,.eui-21 :host.eui-input-text--loading-icon--sm:before{height:var(--eui-s-m);width:var(--eui-s-m)}@keyframes loading{to{transform:rotate(360deg)}}.eui-21 :host.eui-input-text--clearable{padding-right:var(--eui-s-7xl)}.eui-21 :host.eui-input-text[readonly]{pointer-events:auto}.eui-21 :host.eui-input-text[type=search]::-webkit-search-cancel-button{display:none}\n"] }]
        }], ctorParameters: () => [], propDecorators: { isInvalid: [{ type: i0.Input, args: [{ isSignal: true, alias: "isInvalid", required: false }] }] } });

/**
 * @description
 * Directive to add an icon to an eui-input-text element, allowing for click events too.
 *
 * @usageNotes
 * ### Basic Usage
 * ```html
 * <input euiInputText [euiIcon]="{ icon: 'eui-search' }" />
 * ```
 *
 * ### Clickable Icon
 * ```html
 * <input euiInputText
 *   [euiIcon]="{ icon: 'eui-close', clickable: true, ariaLabel: 'Clear search' }"
 *   (iconClick)="clearSearch()" />
 * ```
 *
 * ### Accessibility
 * - Non-clickable icons should be decorative (`aria-hidden="true"`)
 * - Clickable icons must have `ariaLabel` for screen readers
 * - Clickable icons are keyboard accessible (Tab + Enter)
 *
 * ### Notes
 * - Icon is positioned at the end of the input
 * - Automatically creates flex wrapper for layout
 * - Supports custom icon colors via `colour` property
 */
class EuiIconDirective {
    get cssClasses() {
        return [this._cssClasses, this.euiIcon()?.icon ? `${this._elementRef.nativeElement.rootClassName}--loading` : ''].join(' ').trim();
    }
    set cssClasses(value) {
        this._cssClasses = value;
    }
    constructor() {
        this.euiIcon = input(...(ngDevMode ? [undefined, { debugName: "euiIcon" }] : []));
        this.readonly = input(null, { ...(ngDevMode ? { debugName: "readonly" } : {}), transform: booleanAttribute });
        this.iconClick = output();
        this._elementRef = inject(ElementRef);
        this._viewContainerRef = inject(ViewContainerRef);
        this._renderer = inject(Renderer2);
        this.listeners = [];
        this.clickable = computed(() => this.euiIcon()?.clickable ?? false, ...(ngDevMode ? [{ debugName: "clickable" }] : []));
        this.icon = computed(() => this.euiIcon()?.icon, ...(ngDevMode ? [{ debugName: "icon" }] : []));
        this.iconColour = computed(() => this.euiIcon()?.colour, ...(ngDevMode ? [{ debugName: "iconColour" }] : []));
        this.DEFAULT_ICON_COLOUR = 'secondary';
        effect(() => {
            this._readonly = this.readonly() ? '' : null;
            if (this.readonly()) {
                this.removeIcon();
                this.removeFlexWrapper();
            }
            else if (this.euiIcon()?.icon && this.readonly() === false) {
                // create wrapper
                this.createFlexWrapper();
                // dynamically create the icon
                this.createIcon();
                this._renderer.appendChild(this._euiUFlexWrapper, this._icon.location.nativeElement);
            }
        });
        effect(() => {
            const icon = this.icon();
            if (!icon) {
                this.removeIcon();
                this.removeFlexWrapper();
            }
            else if (!this._icon && !this.readonly()) {
                this.createFlexWrapper();
                this.createIcon();
            }
            else if (this._icon) {
                this._icon.setInput('icon', icon);
            }
        });
        effect(() => {
            const clickable = this.clickable();
            if (!clickable) {
                this._renderer.removeAttribute(this._icon.location.nativeElement, 'tabindex');
                this._renderer.setStyle(this._icon.location.nativeElement, 'pointer-events', 'none');
            }
            else {
                this._renderer.setAttribute(this._icon.location.nativeElement, 'tabindex', '0');
                this._icon.setInput('ariaHidden', false);
                this._icon.setInput('focusable', true);
                this._icon.setInput('ariaLabel', this.euiIcon()?.ariaLabel || 'Input icon');
                this._renderer.removeStyle(this._icon.location.nativeElement, 'pointer-events');
            }
        });
        effect(() => {
            const iconColour = this.iconColour();
            if (this._icon) {
                this._icon.setInput('fillColor', iconColour || this.DEFAULT_ICON_COLOUR);
            }
        });
    }
    ngOnDestroy() {
        // Clean up listeners
        this.listeners?.forEach(listener => listener());
        this.listeners = [];
    }
    /**
     * create a flex wrapper for the input to hold the icon
     *
     * @private
     */
    createFlexWrapper() {
        if (!this._euiUFlexWrapper && !this.doesParentHasAFlexWrapper()) {
            this._euiUFlexWrapper = this._renderer.createElement('div');
            this._renderer.addClass(this._euiUFlexWrapper, 'eui-u-flex');
            this._renderer.setAttribute(this._euiUFlexWrapper, 'flexWrapper', null);
            this._renderer.setStyle(this._euiUFlexWrapper, 'position', 'relative');
            this._renderer.insertBefore(this._elementRef.nativeElement.parentElement, this._euiUFlexWrapper, this._elementRef.nativeElement);
            this._renderer.appendChild(this._euiUFlexWrapper, this._elementRef.nativeElement);
        }
        if (!this._euiUFlexWrapper && this.doesParentHasAFlexWrapper()) {
            this._euiUFlexWrapper = this._elementRef.nativeElement.parentElement;
        }
    }
    /**
     * checks if the parent has a flexWrapper. This is used to avoid creating multiple flexWrappers
     *
     * @private
     */
    doesParentHasAFlexWrapper() {
        return this._elementRef.nativeElement.parentElement.hasAttribute('flexWrapper');
    }
    /**
     * removes the flexWrapper while keeping the input element intact
     *
     * @private
     */
    removeFlexWrapper() {
        if (this._euiUFlexWrapper) {
            this._renderer.insertBefore(this._euiUFlexWrapper.parentElement, this._elementRef.nativeElement, this._euiUFlexWrapper);
            this._renderer.removeChild(this._euiUFlexWrapper.parentElement, this._euiUFlexWrapper);
            this._euiUFlexWrapper.remove();
            this._euiUFlexWrapper = null;
        }
    }
    registerIconClickListener() {
        this.listeners.push(this._renderer.listen(this._icon.location.nativeElement, 'click', this.onIconClicked.bind(this)), this._renderer.listen(this._icon.location.nativeElement, 'keydown.enter', this.onIconClicked.bind(this)), this._renderer.listen(this._icon.location.nativeElement, 'focus', () => {
            if (!this.readonly() && this.euiIcon()?.clickable) {
                this._renderer.setStyle(this._icon.location.nativeElement, 'transition', 'none');
                this._renderer.setStyle(this._icon.location.nativeElement, 'outline-offset', '-2px !important');
                this._renderer.setStyle(this._icon.location.nativeElement, 'outline', '2px solid var(--eui-c-focus-visible) !important');
            }
        }), this._renderer.listen(this._icon.location.nativeElement, 'blur', () => {
            this._renderer.removeStyle(this._icon.location.nativeElement, 'outline');
            this._renderer.removeStyle(this._icon.location.nativeElement, 'outline-offset');
            this._renderer.removeStyle(this._icon.location.nativeElement, 'transition');
        }));
    }
    /**
     * creates the icon component
     *
     * @private
     */
    createIcon() {
        if (!this._icon) {
            this._icon = this._viewContainerRef.createComponent(EuiIconSvgComponent);
            this._icon.instance.isInputIcon = true;
            this._icon.instance.euiEnd = true;
            this._icon.instance.icon = this.euiIcon()?.icon;
            this._icon.instance.ariaLabel = this.euiIcon()?.ariaLabel;
            this._icon.instance.fillColor = this.euiIcon()?.colour || this.DEFAULT_ICON_COLOUR;
            this.registerIconClickListener();
            this._renderer.appendChild(this._euiUFlexWrapper, this._icon.location.nativeElement);
        }
    }
    /**
     * @description
     * Handles the click event on the icon.
     */
    onIconClicked() {
        this.iconClick.emit();
    }
    /**
     * removes the icon component
     *
     * @private
     */
    removeIcon() {
        if (this._icon) {
            const index = this._viewContainerRef.indexOf(this._icon.hostView);
            this._viewContainerRef.detach(index);
            this._icon = null;
            // Clean up listeners
            this.listeners.forEach(listener => listener());
            this.listeners = [];
        }
    }
    static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "21.2.1", ngImport: i0, type: EuiIconDirective, deps: [], target: i0.ɵɵFactoryTarget.Directive }); }
    static { this.ɵdir = i0.ɵɵngDeclareDirective({ minVersion: "17.1.0", version: "21.2.1", type: EuiIconDirective, isStandalone: true, selector: "input[euiInputText][euiIcon]", inputs: { euiIcon: { classPropertyName: "euiIcon", publicName: "euiIcon", isSignal: true, isRequired: false, transformFunction: null }, readonly: { classPropertyName: "readonly", publicName: "readonly", isSignal: true, isRequired: false, transformFunction: null } }, outputs: { iconClick: "iconClick" }, host: { properties: { "class": "cssClasses", "attr.readonly": "this._readonly" } }, ngImport: i0 }); }
}
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.1", ngImport: i0, type: EuiIconDirective, decorators: [{
            type: Directive,
            args: [{
                    selector: 'input[euiInputText][euiIcon]',
                    host: {
                        '[class]': 'cssClasses',
                    },
                }]
        }], ctorParameters: () => [], propDecorators: { euiIcon: [{ type: i0.Input, args: [{ isSignal: true, alias: "euiIcon", required: false }] }], readonly: [{ type: i0.Input, args: [{ isSignal: true, alias: "readonly", required: false }] }], iconClick: [{ type: i0.Output, args: ["iconClick"] }], _readonly: [{
                type: HostBinding,
                args: ['attr.readonly']
            }] } });

const EUI_INPUT_TEXT = [
    EuiInputTextComponent,
];
// export { EuiInputTextComponent as EuiInputText } from './eui-input-text.component';

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

export { EUI_INPUT_TEXT, EuiIconDirective, EuiInputTextComponent };
//# sourceMappingURL=eui-components-eui-input-text.mjs.map
