import * as i0 from '@angular/core';
import { inject, ElementRef, Renderer2, HostListener, Input, HostBinding, Component } from '@angular/core';
import { NgControl } from '@angular/forms';
import { InputDirective } from '@eui/components/shared';
import { coerceBooleanProperty } from '@angular/cdk/coercion';

/**
 * @description
 * Radio input component for selecting a single value from a set of mutually exclusive options.
 * Integrates with Angular forms (both reactive and template-driven) and provides custom EUI styling.
 * Implements ControlValueAccessor for seamless form integration with validation states and error handling.
 * Automatically manages checked state, value binding, and form control synchronization.
 * Must be applied as an attribute directive to native HTML radio input elements.
 *
 * @usageNotes
 * ### Basic Usage
 * ```html
 * <!-- Template-driven forms -->
 * <div>
 *   <input euiInputRadio type="radio" name="size" value="small" [(ngModel)]="selectedSize" id="size-small" />
 *   <label for="size-small">Small</label>
 * </div>
 * <div>
 *   <input euiInputRadio type="radio" name="size" value="medium" [(ngModel)]="selectedSize" id="size-medium" />
 *   <label for="size-medium">Medium</label>
 * </div>
 * <div>
 *   <input euiInputRadio type="radio" name="size" value="large" [(ngModel)]="selectedSize" id="size-large" />
 *   <label for="size-large">Large</label>
 * </div>
 * ```
 *
 * ### Reactive Forms
 * ```html
 * <form [formGroup]="myForm">
 *   <div>
 *     <input euiInputRadio type="radio" formControlName="plan" value="basic" id="plan-basic" />
 *     <label for="plan-basic">Basic Plan</label>
 *   </div>
 *   <div>
 *     <input euiInputRadio type="radio" formControlName="plan" value="premium" id="plan-premium" />
 *     <label for="plan-premium">Premium Plan</label>
 *   </div>
 * </form>
 * ```
 *
 * ```typescript
 * myForm = this.fb.group({
 *   plan: ['basic', Validators.required]
 * });
 * ```
 *
 * ### With Validation
 * ```html
 * <form [formGroup]="form">
 *   <div>
 *     <input euiInputRadio type="radio" formControlName="option" value="yes" id="opt-yes" />
 *     <label for="opt-yes">Yes</label>
 *   </div>
 *   <div>
 *     <input euiInputRadio type="radio" formControlName="option" value="no" id="opt-no" />
 *     <label for="opt-no">No</label>
 *   </div>
 *   <div *ngIf="form.get('option')?.invalid && form.get('option')?.touched" class="error">
 *     Please select an option
 *   </div>
 * </form>
 * ```
 *
 * ### Disabled State
 * ```html
 * <input euiInputRadio type="radio" name="status" value="active" [disabled]="true" id="status-active" />
 * <label for="status-active">Active (disabled)</label>
 * ```
 *
 * ### Accessibility
 * - Always associate radio inputs with labels using for/id attributes
 * - Group related radio buttons with the same name attribute
 * - Use fieldset and legend for radio button groups
 * - Provide clear, descriptive labels for each option
 * - Invalid state automatically applies aria-invalid
 * - Keyboard navigation: Tab to focus, Space to select
 *
 * ### Notes
 * - Radio buttons with the same name are mutually exclusive
 * - Automatically generates unique IDs if not provided
 * - Invalid state styling applied when form control is invalid
 * - Supports readonly mode to prevent changes
 * - Value can be string, number, or boolean
 * - Integrates with Angular form validation
 * - Use with eui-label components for consistent styling
 *
 * @example
 * <input euiInputRadio type="radio" name="option" value="1" [(ngModel)]="selected" id="opt-1" />
 * <label for="opt-1">Option 1</label>
 */
class EuiInputRadioComponent extends InputDirective {
    /**
     * Gets or sets whether the radio input is in an invalid state.
     * This can be set manually or will be automatically set when used with form validation.
     *
     * @property {boolean} isInvalid - The invalid state of the radio input
     */
    get isInvalid() {
        return this._isInvalid || null;
    }
    set isInvalid(state) {
        this.setInvalid(state);
    }
    /**
     * Gets the CSS classes for the radio input component.
     * Combines base classes with invalid state modifier if applicable.
     *
     * @returns {string} Space-separated list of CSS classes
     */
    get class() {
        return [super.getCssClasses('eui-input-radio'), this._isInvalid ? 'eui-input-radio--invalid' : ''].join(' ').trim();
    }
    /**
     * Gets or sets the default checked state of the radio input.
     * This is different from the current checked state and represents the initial value.
     *
     * @property {any} defaultChecked - The default checked state
     */
    get defaultChecked() {
        return this._defaultChecked ? '' : null;
    }
    set defaultChecked(value) {
        this._defaultChecked = coerceBooleanProperty(value);
        this._renderer.setProperty(this._elementRef.nativeElement, 'checked', this._defaultChecked);
    }
    /**
     * Gets whether the radio input is currently selected.
     *
     * @returns {boolean} True if the radio input is selected, false otherwise
     */
    get selected() {
        return this._elementRef?.nativeElement.checked;
    }
    /**
     * Gets or sets the value of the radio input.
     * The value can be of any type and will be used when the radio is selected in a form group.
     *
     * @property {any} value - The value associated with this radio input
     */
    get value() {
        return this._value;
    }
    set value(value) {
        this._value = value;
        if (typeof value === 'number' || typeof value === 'boolean' || !!value) {
            this._elementRef.nativeElement.value = this._value;
        }
    }
    constructor() {
        super();
        this.type = 'radio';
        this.ngControl = inject(NgControl, { optional: true, self: true });
        this._elementRef = inject(ElementRef);
        this._renderer = inject(Renderer2);
        // eslint-disable-next-line @typescript-eslint/no-unused-vars
        this.onChange = (_) => {
            /* Nothing to be Done so far */
        };
        // eslint-disable-next-line @typescript-eslint/no-unused-vars
        this.onTouched = (_) => {
            /* Nothing to be Done so far */
        };
        // Firefox fix: set type to radio before first ngDoCheck runs
        this._elementRef.nativeElement.type = 'radio';
        // if there's no id attribute set one
        if (!this._elementRef.nativeElement.id) {
            this.setIdAttribute();
        }
        // register control valueAccessor
        if (this.ngControl) {
            this.ngControl.valueAccessor = this;
        }
    }
    /**
     * Initializes the component.
     * Sets up form control validation status subscription and handles initial state.
     */
    ngOnInit() {
        super.ngOnInit();
        // in case control value is null set the default one (isChecked) and sync Control State
        // if (this.ngControl?.control?.value === null) {
        // this.ngControl.control.setValue('', { emitModelToViewChange: false });
        // changing Model Expression after view checked, so detect changes
        // TODO: check why although it's checked .checked returns false
        // this.ngControl.viewToModelUpdate(this._checked);
        // this._cd.detectChanges();
        // }
        if (this.ngControl) {
            this.ngControl.statusChanges.subscribe((status) => {
                this.isInvalid = status === 'INVALID';
                this.euiDanger = this.isInvalid;
            });
        }
    }
    /**
     * Performs change detection and updates invalid state based on form control status.
     */
    ngDoCheck() {
        if (this.ngControl) {
            this.isInvalid = this.ngControl.invalid && this.ngControl.touched;
        }
    }
    /**
     * Handles changes to component inputs. Specifically, handles changes to
     * readonly and invalid states.
     *
     * @param {SimpleChanges} changes - Object containing changed properties
     */
    ngOnChanges(changes) {
        // when readonly changes hide other radio (input+label)
        if (changes['readonly']) {
            const readonly = coerceBooleanProperty(changes['readonly']?.currentValue);
            if (readonly) {
                this._renderer.setAttribute(this._elementRef.nativeElement, 'readonly', null);
            }
            else {
                this._renderer.removeAttribute(this._elementRef.nativeElement, 'readonly');
            }
        }
        if (changes['isInvalid']) {
            if (changes['isInvalid'].currentValue) {
                this._renderer.addClass(this._elementRef.nativeElement, 'eui-input-radio--invalid');
            }
            else {
                this._renderer.removeClass(this._elementRef.nativeElement, 'eui-input-radio--invalid');
            }
        }
    }
    /**
     * Implements ControlValueAccessor.writeValue.
     * Updates the checked state based on the form control value.
     *
     * @param {string} obj - The value to write
     */
    writeValue(obj) {
        // set checked state based if the radio value matches the control's one
        this._elementRef.nativeElement.checked = this._value === obj;
    }
    /**
     * Registers a callback function that is called when the control's value changes.
     *
     * @param {Function} fn - The callback function
     */
    // TODO: find the correct type or turn into a generic, https://www.typescriptlang.org/docs/handbook/2/generics.html
    // eslint-disable-next-line @typescript-eslint/no-explicit-any
    registerOnChange(fn) {
        this.onChange = fn;
    }
    /**
     * Registers a callback function that is called when the control is touched.
     *
     * @param {Function} fn - The callback function
     */
    // TODO: find the correct type or turn into a generic, https://www.typescriptlang.org/docs/handbook/2/generics.html
    // eslint-disable-next-line @typescript-eslint/no-explicit-any
    registerOnTouched(fn) {
        this.onTouched = fn;
    }
    /**
     * Sets the disabled state of the radio input.
     *
     * @param {boolean} isDisabled - Whether the radio input should be disabled
     */
    setDisabledState(isDisabled) {
        this.disabled = isDisabled;
    }
    /**
     * Handles change events on the radio input.
     * Updates the model value when the radio selection changes.
     *
     * @param {Event} event - The change event
     */
    onCheckedChanged(event) {
        const target = event.target;
        this._defaultChecked = target.checked;
        const emitValue = this._value !== undefined ? this._value : (target.value === 'on' ? null : target.value);
        this.onChange(emitValue);
        this.onTouched(emitValue);
    }
    /**
     * Handles space key press events. Prevents selection changes when the input
     * is readonly.
     *
     * @param {KeyboardEvent} event - The keyboard event
     */
    onSpacePressed(event) {
        if (this.readonly) {
            event.preventDefault();
            event.stopPropagation();
        }
    }
    /**
     * Sets the invalid state of the radio input.
     * Updates both the internal state and the visual appearance.
     *
     * @param {boolean} state - The invalid state to set
     */
    setInvalid(state) {
        // in case it's controlled by NgControl override
        this._isInvalid = this.control ? this.control.invalid && this.control.touched : coerceBooleanProperty(state);
        // set BaseDirective Attribute
        this.euiDanger = this._isInvalid;
    }
    static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "21.2.16", ngImport: i0, type: EuiInputRadioComponent, deps: [], target: i0.ɵɵFactoryTarget.Component }); }
    static { this.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "14.0.0", version: "21.2.16", type: EuiInputRadioComponent, isStandalone: true, selector: "input[euiInputRadio]", inputs: { isInvalid: "isInvalid", defaultChecked: ["checked", "defaultChecked"], value: "value" }, host: { listeners: { "change": "onCheckedChanged($any($event))", "keydown.space": "onSpacePressed($any($event))" }, properties: { "class": "this.class", "attr.type": "this.type", "attr.checked": "this.defaultChecked" } }, usesInheritance: true, usesOnChanges: true, ngImport: i0, template: '', isInline: true, styles: [".eui-21 :host.eui-input-radio:not(.cdk-visually-hidden){appearance:inherit;align-items:center;border-radius:var(--eui-br-max);cursor:pointer;display:inline-flex;flex-shrink:0;height:var(--eui-s-xl);justify-content:center;margin-right:var(--eui-s-s);position:relative;vertical-align:middle;width:var(--eui-s-xl);accent-color:var(--eui-c-white);background:var(--eui-c-surface-container);border:var(--eui-bw-xs) solid var(--eui-c-secondary-border)}.eui-21 :host.eui-input-radio:not(.cdk-visually-hidden) ::ng-deep~.eui-label,.eui-21 :host.eui-input-radio:not(.cdk-visually-hidden) ::ng-deep~label{display:inline-flex;cursor:pointer;font:var(--eui-f-m);margin-right:var(--eui-s-m);white-space:inherit}.eui-21 :host.eui-input-radio:not(.cdk-visually-hidden):checked{background:var(--eui-c-surface-container);border:var(--eui-bw-xs) solid var(--eui-c-primary-base)}.eui-21 :host.eui-input-radio:not(.cdk-visually-hidden):checked:before{height:1rem;width:1rem;content:\"\";-webkit-mask-repeat:no-repeat;mask-repeat:no-repeat;-webkit-mask-position:50% 50%;mask-position:50% 50%;-webkit-mask-size:cover;mask-size:cover;-webkit-mask-image:var(--eui-internal-icon-ellipse-path);mask-image:var(--eui-internal-icon-ellipse-path);background-color:var(--eui-c-primary-surface);height:var(--eui-s-m);width:var(--eui-s-m)}.eui-21 :host.eui-input-radio:not(.cdk-visually-hidden):disabled:not([readonly]){background:var(--eui-c-disabled-bg);opacity:var(--eui-o-50);pointer-events:none;-webkit-user-select:none;user-select:none}.eui-21 :host.eui-input-radio:not(.cdk-visually-hidden):disabled:not([readonly]):checked:before{height:1rem;width:1rem;content:\"\";-webkit-mask-repeat:no-repeat;mask-repeat:no-repeat;-webkit-mask-position:50% 50%;mask-position:50% 50%;-webkit-mask-size:cover;mask-size:cover;-webkit-mask-image:var(--eui-internal-icon-ellipse-path);mask-image:var(--eui-internal-icon-ellipse-path);background-color:var(--eui-c-primary-surface);height:var(--eui-s-m);width:var(--eui-s-m)}.eui-21 :host.eui-input-radio:not(.cdk-visually-hidden):disabled:not([readonly])+::ng-deep label{pointer-events:none}.eui-21 :host.eui-input-radio:not(.cdk-visually-hidden)[readonly]{display:none;pointer-events:none;-webkit-user-select:none;user-select:none}.eui-21 :host.eui-input-radio:not(.cdk-visually-hidden)[readonly]+::ng-deep label,.eui-21 :host.eui-input-radio:not(.cdk-visually-hidden)[readonly]+::ng-deep .eui-label{display:none}.eui-21 :host.eui-input-radio:not(.cdk-visually-hidden)[readonly]:checked{display:none}.eui-21 :host.eui-input-radio:not(.cdk-visually-hidden)[readonly]:checked+::ng-deep label,.eui-21 :host.eui-input-radio:not(.cdk-visually-hidden)[readonly]:checked+::ng-deep .eui-label{align-items:center;display:inline-flex;pointer-events:none;position:initial}.eui-21 :host.eui-input-radio:not(.cdk-visually-hidden).eui-input-radio--invalid,.eui-21 :host.eui-input-radio:not(.cdk-visually-hidden).eui-input-radio--danger{border:var(--eui-bw-xs) solid var(--eui-c-danger)!important}.eui-21 :host.eui-input-radio:not(.cdk-visually-hidden).eui-input-radio--invalid:checked:before,.eui-21 :host.eui-input-radio:not(.cdk-visually-hidden).eui-input-radio--danger:checked:before{height:1rem;width:1rem;content:\"\";-webkit-mask-repeat:no-repeat;mask-repeat:no-repeat;-webkit-mask-position:50% 50%;mask-position:50% 50%;-webkit-mask-size:cover;mask-size:cover;-webkit-mask-image:var(--eui-internal-icon-ellipse-path);mask-image:var(--eui-internal-icon-ellipse-path);background-color:var(--eui-c-danger-surface);height:var(--eui-s-m);width:var(--eui-s-m)}.eui-21 :host.eui-input-radio:not(.cdk-visually-hidden):focus:not([readonly]){outline:var(--eui-bw-s) solid var(--eui-c-primary-border-light)!important;outline-offset:1px!important;border-radius:var(--eui-br-max)!important}.eui-21 :host.eui-input-radio:not(.cdk-visually-hidden).eui-input-radio--invalid:not([readonly]),.eui-21 :host.eui-input-radio:not(.cdk-visually-hidden).eui-input-radio--danger:not([readonly]){outline-color:var(--eui-c-danger-border-light)!important}\n"] }); }
}
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.16", ngImport: i0, type: EuiInputRadioComponent, decorators: [{
            type: Component,
            args: [{ selector: 'input[euiInputRadio]', template: '', styles: [".eui-21 :host.eui-input-radio:not(.cdk-visually-hidden){appearance:inherit;align-items:center;border-radius:var(--eui-br-max);cursor:pointer;display:inline-flex;flex-shrink:0;height:var(--eui-s-xl);justify-content:center;margin-right:var(--eui-s-s);position:relative;vertical-align:middle;width:var(--eui-s-xl);accent-color:var(--eui-c-white);background:var(--eui-c-surface-container);border:var(--eui-bw-xs) solid var(--eui-c-secondary-border)}.eui-21 :host.eui-input-radio:not(.cdk-visually-hidden) ::ng-deep~.eui-label,.eui-21 :host.eui-input-radio:not(.cdk-visually-hidden) ::ng-deep~label{display:inline-flex;cursor:pointer;font:var(--eui-f-m);margin-right:var(--eui-s-m);white-space:inherit}.eui-21 :host.eui-input-radio:not(.cdk-visually-hidden):checked{background:var(--eui-c-surface-container);border:var(--eui-bw-xs) solid var(--eui-c-primary-base)}.eui-21 :host.eui-input-radio:not(.cdk-visually-hidden):checked:before{height:1rem;width:1rem;content:\"\";-webkit-mask-repeat:no-repeat;mask-repeat:no-repeat;-webkit-mask-position:50% 50%;mask-position:50% 50%;-webkit-mask-size:cover;mask-size:cover;-webkit-mask-image:var(--eui-internal-icon-ellipse-path);mask-image:var(--eui-internal-icon-ellipse-path);background-color:var(--eui-c-primary-surface);height:var(--eui-s-m);width:var(--eui-s-m)}.eui-21 :host.eui-input-radio:not(.cdk-visually-hidden):disabled:not([readonly]){background:var(--eui-c-disabled-bg);opacity:var(--eui-o-50);pointer-events:none;-webkit-user-select:none;user-select:none}.eui-21 :host.eui-input-radio:not(.cdk-visually-hidden):disabled:not([readonly]):checked:before{height:1rem;width:1rem;content:\"\";-webkit-mask-repeat:no-repeat;mask-repeat:no-repeat;-webkit-mask-position:50% 50%;mask-position:50% 50%;-webkit-mask-size:cover;mask-size:cover;-webkit-mask-image:var(--eui-internal-icon-ellipse-path);mask-image:var(--eui-internal-icon-ellipse-path);background-color:var(--eui-c-primary-surface);height:var(--eui-s-m);width:var(--eui-s-m)}.eui-21 :host.eui-input-radio:not(.cdk-visually-hidden):disabled:not([readonly])+::ng-deep label{pointer-events:none}.eui-21 :host.eui-input-radio:not(.cdk-visually-hidden)[readonly]{display:none;pointer-events:none;-webkit-user-select:none;user-select:none}.eui-21 :host.eui-input-radio:not(.cdk-visually-hidden)[readonly]+::ng-deep label,.eui-21 :host.eui-input-radio:not(.cdk-visually-hidden)[readonly]+::ng-deep .eui-label{display:none}.eui-21 :host.eui-input-radio:not(.cdk-visually-hidden)[readonly]:checked{display:none}.eui-21 :host.eui-input-radio:not(.cdk-visually-hidden)[readonly]:checked+::ng-deep label,.eui-21 :host.eui-input-radio:not(.cdk-visually-hidden)[readonly]:checked+::ng-deep .eui-label{align-items:center;display:inline-flex;pointer-events:none;position:initial}.eui-21 :host.eui-input-radio:not(.cdk-visually-hidden).eui-input-radio--invalid,.eui-21 :host.eui-input-radio:not(.cdk-visually-hidden).eui-input-radio--danger{border:var(--eui-bw-xs) solid var(--eui-c-danger)!important}.eui-21 :host.eui-input-radio:not(.cdk-visually-hidden).eui-input-radio--invalid:checked:before,.eui-21 :host.eui-input-radio:not(.cdk-visually-hidden).eui-input-radio--danger:checked:before{height:1rem;width:1rem;content:\"\";-webkit-mask-repeat:no-repeat;mask-repeat:no-repeat;-webkit-mask-position:50% 50%;mask-position:50% 50%;-webkit-mask-size:cover;mask-size:cover;-webkit-mask-image:var(--eui-internal-icon-ellipse-path);mask-image:var(--eui-internal-icon-ellipse-path);background-color:var(--eui-c-danger-surface);height:var(--eui-s-m);width:var(--eui-s-m)}.eui-21 :host.eui-input-radio:not(.cdk-visually-hidden):focus:not([readonly]){outline:var(--eui-bw-s) solid var(--eui-c-primary-border-light)!important;outline-offset:1px!important;border-radius:var(--eui-br-max)!important}.eui-21 :host.eui-input-radio:not(.cdk-visually-hidden).eui-input-radio--invalid:not([readonly]),.eui-21 :host.eui-input-radio:not(.cdk-visually-hidden).eui-input-radio--danger:not([readonly]){outline-color:var(--eui-c-danger-border-light)!important}\n"] }]
        }], ctorParameters: () => [], propDecorators: { isInvalid: [{
                type: Input
            }], class: [{
                type: HostBinding,
                args: ['class']
            }], type: [{
                type: HostBinding,
                args: ['attr.type']
            }], defaultChecked: [{
                type: HostBinding,
                args: ['attr.checked']
            }, {
                type: Input,
                args: ['checked']
            }], value: [{
                type: Input
            }], onCheckedChanged: [{
                type: HostListener,
                args: ['change', ['$any($event)']]
            }], onSpacePressed: [{
                type: HostListener,
                args: ['keydown.space', ['$any($event)']]
            }] } });

const EUI_INPUT_RADIO = [
    EuiInputRadioComponent,
];
// export { EuiInputRadioComponent as EuiInputRadio } from './eui-input-radio.component';

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

export { EUI_INPUT_RADIO, EuiInputRadioComponent };
//# sourceMappingURL=eui-components-eui-input-radio.mjs.map
