import * as i0 from '@angular/core';
import { forwardRef, Injectable, inject, Injector, ChangeDetectorRef, NgZone, EventEmitter, booleanAttribute, Output, Input, ViewChild, ViewEncapsulation, ChangeDetectionStrategy, Component } from '@angular/core';
import { NG_VALUE_ACCESSOR, NgControl } from '@angular/forms';
import { Subject, fromEvent, filter, takeUntil } from 'rxjs';

const RADIO_VALUE_ACCESSOR = {
    provide: NG_VALUE_ACCESSOR,
    useExisting: forwardRef(() => RadioComponent),
    multi: true,
};
class RadioControlRegistry {
    accessors = [];
    add(control, accessor) {
        this.accessors.push([control, accessor]);
    }
    remove(accessor) {
        this.accessors = this.accessors.filter(([, radioComponent]) => {
            return radioComponent !== accessor;
        });
    }
    select(accessor) {
        this.accessors.forEach(([ngControl, radioComponent]) => {
            if (this.isSameGroup(ngControl, radioComponent, accessor) && radioComponent !== accessor) {
                radioComponent.writeValue(accessor.value);
            }
        });
    }
    getIndex(accessor) {
        return this.accessors.findIndex(([, radioComponent]) => {
            return radioComponent === accessor;
        });
    }
    getNextRadio(accessor) {
        const index = this.getIndex(accessor);
        const nextIndex = index + 1;
        if (nextIndex >= this.accessors.length) {
            return this.accessors[0][1];
        }
        const nextRadio = this.accessors[nextIndex];
        return nextRadio ? nextRadio[1] : null;
    }
    getPreviousRadio(accessor) {
        const index = this.getIndex(accessor);
        if (index === 0) {
            return this.accessors[this.accessors.length - 1][1];
        }
        const previousIndex = index - 1;
        const previousRadio = this.accessors[previousIndex];
        return previousRadio ? previousRadio[1] : null;
    }
    blurAllGroup(accessor) {
        this.accessors.forEach(([, radioComponent]) => {
            if (this.isSameGroup(accessor.control, radioComponent, accessor)) {
                radioComponent.inputElement.nativeElement.blur();
            }
        });
    }
    setNegativeTabIndexToAllExcept(accessor) {
        this.accessors.forEach(([, radioComponent]) => {
            if (this.isSameGroup(accessor.control, radioComponent, accessor)) {
                if (accessor.radioId !== radioComponent.radioId) {
                    radioComponent.inputElement.nativeElement.tabIndex = -1;
                }
                else {
                    radioComponent.inputElement.nativeElement.tabIndex = 0;
                }
            }
        });
    }
    focusPrevious(accessor) {
        const previousRadio = this.getPreviousRadio(accessor);
        if (previousRadio) {
            previousRadio.inputElement.nativeElement.focus();
        }
    }
    focusNext(accessor) {
        const nextRadio = this.getNextRadio(accessor);
        if (nextRadio) {
            nextRadio.inputElement.nativeElement.focus();
        }
    }
    getFirstCheckedRadio() {
        const checkedRadio = this.accessors.find(([, radioComponent]) => {
            return radioComponent.checked;
        });
        return checkedRadio ? checkedRadio[1] : null;
    }
    isSameGroup(ngControl, radioComponent, accessor) {
        if (!ngControl.control) {
            return false;
        }
        return radioComponent.name === accessor.name;
    }
    static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "20.3.18", ngImport: i0, type: RadioControlRegistry, deps: [], target: i0.ɵɵFactoryTarget.Injectable });
    static ɵprov = i0.ɵɵngDeclareInjectable({ minVersion: "12.0.0", version: "20.3.18", ngImport: i0, type: RadioControlRegistry, providedIn: 'root' });
}
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.3.18", ngImport: i0, type: RadioControlRegistry, decorators: [{
            type: Injectable,
            args: [{
                    providedIn: 'root',
                }]
        }] });
class RadioComponent {
    elementRef;
    injector = inject(Injector);
    changeDetectorRef = inject(ChangeDetectorRef);
    radioControlRegistry = inject(RadioControlRegistry);
    ngZone = inject(NgZone);
    inputElement;
    labelElement;
    ariaLabel = '';
    ariaLabelledby = null;
    ariaDescribedby = '';
    set disabled(disabled) {
        this._disabled = disabled;
    }
    get disabled() {
        return this._disabled;
    }
    labelPosition = 'right';
    radioId = '';
    formControlName;
    value;
    required = false;
    name = '';
    // eslint-disable-next-line @angular-eslint/no-output-on-prefix
    onClick = new EventEmitter();
    // eslint-disable-next-line @angular-eslint/no-output-on-prefix
    onFocus = new EventEmitter();
    // eslint-disable-next-line @angular-eslint/no-output-on-prefix
    onBlur = new EventEmitter();
    inputId = '';
    _disabled = false;
    hasLabel = false;
    hostDataTest;
    control;
    checked = false;
    focused = false;
    radioIndex = 0;
    destroy$ = new Subject();
    onModelChange = () => {
        // ignore
    };
    onModelTouched = () => {
        // ignore
    };
    constructor(elementRef) {
        this.elementRef = elementRef;
        this.hostDataTest = elementRef.nativeElement.getAttribute('data-test');
        this.ngZone.runOutsideAngular(() => {
            fromEvent(window, 'keydown')
                .pipe(filter((event) => 'key' in event), takeUntil(this.destroy$))
                .subscribe((event) => {
                // Handle keydown event
                switch (event.key) {
                    case 'ArrowDown':
                    case 'ArrowRight':
                        this.ngZone.run(() => {
                            if (this.focused) {
                                event.stopImmediatePropagation();
                                this.radioControlRegistry.blurAllGroup(this);
                                this.radioControlRegistry.focusNext(this);
                            }
                        });
                        break;
                    case 'ArrowUp':
                    case 'ArrowLeft':
                        this.ngZone.run(() => {
                            if (this.focused) {
                                event.stopImmediatePropagation();
                                this.radioControlRegistry.blurAllGroup(this);
                                this.radioControlRegistry.focusPrevious(this);
                            }
                        });
                        break;
                    default:
                        return;
                }
            });
        });
    }
    ngOnChanges() {
        if (this.labelElement) {
            this.hasLabel = !!this.labelElement.nativeElement.textContent?.trim();
        }
    }
    ngOnInit() {
        this.control = this.injector.get(NgControl);
        this.checkName();
        this.radioControlRegistry.add(this.control, this);
        this.radioIndex = this.radioControlRegistry.getIndex(this);
        this.inputId = `${this.radioId}-${this.radioIndex}`;
    }
    ngAfterContentInit() {
        if (this.labelElement) {
            this.hasLabel = !!this.labelElement.nativeElement.textContent?.trim();
        }
    }
    ngOnDestroy() {
        this.radioControlRegistry.remove(this);
        this.destroy$.next();
        this.destroy$.complete();
    }
    handleClick(event, radioButton) {
        event.preventDefault();
        if (this.disabled) {
            return;
        }
        this.select(event);
        radioButton.focus();
    }
    select(event) {
        if (!this.disabled && !this.checked) {
            this.inputElement.nativeElement.checked = true;
            this.checked = true;
            this.onModelChange(this.value);
            this.radioControlRegistry.select(this);
            this.onClick.emit({ originalEvent: event, value: this.value });
        }
    }
    writeValue(value) {
        this.checked = value == this.value;
        if (this.inputElement?.nativeElement) {
            this.inputElement.nativeElement.checked = this.checked;
        }
        this.changeDetectorRef.markForCheck();
    }
    registerOnChange(fn) {
        this.onModelChange = fn;
    }
    registerOnTouched(fn) {
        this.onModelTouched = fn;
    }
    onInputFocus(event) {
        this.focused = true;
        if (!this.disabled && !this.checked) {
            this.radioControlRegistry.setNegativeTabIndexToAllExcept(this);
            this.inputElement.nativeElement.checked = true;
            this.checked = true;
            this.onModelChange(this.value);
            this.onFocus.emit(event);
        }
    }
    onInputBlur(event) {
        this.focused = false;
        this.onModelTouched();
        this.onBlur.emit(event);
    }
    onChange(event) {
        this.select(event);
    }
    checkName() {
        if (this.name && this.formControlName && this.name !== this.formControlName) {
            this.throwNameError();
        }
        if (!this.name && this.formControlName) {
            this.name = this.formControlName;
        }
    }
    throwNameError() {
        throw new Error(`
          If you define both a name and a formControlName attribute on your radio button, their values
          must match. Ex: <p-radioButton formControlName="food" name="food"></p-radioButton>
        `);
    }
    static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "20.3.18", ngImport: i0, type: RadioComponent, deps: [{ token: i0.ElementRef }], target: i0.ɵɵFactoryTarget.Component });
    static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "16.1.0", version: "20.3.18", type: RadioComponent, isStandalone: true, selector: "ap-radio", inputs: { ariaLabel: ["aria-label", "ariaLabel"], ariaLabelledby: ["aria-labelledby", "ariaLabelledby"], ariaDescribedby: ["aria-describedby", "ariaDescribedby"], disabled: ["disabled", "disabled", booleanAttribute], labelPosition: "labelPosition", radioId: "radioId", formControlName: "formControlName", value: "value", required: ["required", "required", booleanAttribute], name: "name" }, outputs: { onClick: "onClick", onFocus: "onFocus", onBlur: "onBlur" }, providers: [RADIO_VALUE_ACCESSOR], viewQueries: [{ propertyName: "inputElement", first: true, predicate: ["input"], descendants: true, static: true }, { propertyName: "labelElement", first: true, predicate: ["label"], descendants: true, static: true }], usesOnChanges: true, ngImport: i0, template: "<div\n    class=\"radio-button-container\"\n    [class.required]=\"required\"\n    [class.label-left]=\"labelPosition === 'left'\">\n    <input\n        #input\n        type=\"radio\"\n        tabindex=\"0\"\n        [attr.id]=\"inputId\"\n        [attr.name]=\"name + '-radio-' + radioIndex\"\n        [attr.value]=\"value\"\n        [attr.aria-checked]=\"checked\"\n        [attr.aria-label]=\"ariaLabel || null\"\n        [attr.aria-labelledby]=\"ariaLabelledby\"\n        [attr.aria-describedby]=\"ariaDescribedby\"\n        [attr.data-test]=\"hostDataTest ?? name\"\n        [checked]=\"checked\"\n        [required]=\"required\"\n        [class.disabled]=\"disabled\"\n        (change)=\"onChange($event)\"\n        (blur)=\"onInputBlur($event)\"\n        (focus)=\"onInputFocus($event)\" />\n    <div\n        class=\"radio-button\"\n        [class.disabled]=\"disabled\"\n        (click)=\"select($event)\"></div>\n    <label\n        [for]=\"inputId\"\n        (click)=\"select($event)\">\n        <ng-content />\n    </label>\n</div>\n", styles: ["ap-radio .radio-button-container{display:flex;align-items:center;gap:var(--ref-spacing-xxs)}ap-radio .radio-button-container.label-left{flex-direction:row-reverse}ap-radio .radio-button-container input[type=radio]{transform:scale(0);position:absolute}ap-radio .radio-button-container input[type=radio]:checked~.radio-button{border-color:var(--ref-color-electric-blue-100);box-shadow:inset 0 0 0 3px var(--ref-color-white)}ap-radio .radio-button-container input[type=radio]:checked~.radio-button.disabled{background:var(--ref-color-grey-40);box-shadow:inset 0 0 0 3px var(--ref-color-grey-10)}ap-radio .radio-button-container input[type=radio]:checked:focus~.radio-button{border-color:var(--ref-color-electric-blue-100)}ap-radio .radio-button-container input[type=radio].disabled~.radio-button{pointer-events:none;cursor:default;box-shadow:inset 0 0 0 16px var(--ref-color-grey-10);border-color:var(--ref-color-grey-20)}ap-radio .radio-button-container input[type=radio].disabled~label{pointer-events:none;cursor:default;color:var(--ref-color-grey-60)}ap-radio .radio-button-container input[type=radio]:focus~.radio-button{outline:3px solid var(--ref-color-electric-blue-100);border-color:var(--ref-color-grey-80);outline-offset:1px}ap-radio .radio-button-container .radio-button{width:16px;height:16px;border-radius:100%;border:1px solid var(--ref-color-grey-60);background:var(--ref-color-electric-blue-100);box-shadow:inset 0 0 0 16px var(--ref-color-white);transition:box-shadow var(--comp-radio-transition-duration);flex-shrink:0}ap-radio .radio-button-container .radio-button:hover:not(.disabled){cursor:pointer;border-color:var(--ref-color-grey-80)}ap-radio .radio-button-container label{display:flex;align-items:center;font-family:var(--sys-text-style-body-font-family);font-size:var(--sys-text-style-body-size);font-weight:var(--sys-text-style-body-weight);line-height:var(--sys-text-style-body-line-height);color:var(--ref-color-grey-100)}ap-radio .radio-button-container label:empty{display:none}ap-radio .radio-button-container label.disabled{color:var(--ref-color-grey-60)}ap-radio .radio-button-container label:hover:not(.disabled){cursor:pointer}ap-radio.ng-invalid.ng-dirty .radio-button{border-color:var(--ref-color-red-100)}ap-radio.ng-invalid.ng-dirty .radio-button:hover{border-color:var(--ref-color-red-60)}ap-radio.ng-invalid.ng-dirty input[type=radio]:focus~.radio-button{border-color:var(--ref-color-red-60)}\n"], changeDetection: i0.ChangeDetectionStrategy.OnPush, encapsulation: i0.ViewEncapsulation.None });
}
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.3.18", ngImport: i0, type: RadioComponent, decorators: [{
            type: Component,
            args: [{ changeDetection: ChangeDetectionStrategy.OnPush, selector: 'ap-radio', standalone: true, providers: [RADIO_VALUE_ACCESSOR], encapsulation: ViewEncapsulation.None, template: "<div\n    class=\"radio-button-container\"\n    [class.required]=\"required\"\n    [class.label-left]=\"labelPosition === 'left'\">\n    <input\n        #input\n        type=\"radio\"\n        tabindex=\"0\"\n        [attr.id]=\"inputId\"\n        [attr.name]=\"name + '-radio-' + radioIndex\"\n        [attr.value]=\"value\"\n        [attr.aria-checked]=\"checked\"\n        [attr.aria-label]=\"ariaLabel || null\"\n        [attr.aria-labelledby]=\"ariaLabelledby\"\n        [attr.aria-describedby]=\"ariaDescribedby\"\n        [attr.data-test]=\"hostDataTest ?? name\"\n        [checked]=\"checked\"\n        [required]=\"required\"\n        [class.disabled]=\"disabled\"\n        (change)=\"onChange($event)\"\n        (blur)=\"onInputBlur($event)\"\n        (focus)=\"onInputFocus($event)\" />\n    <div\n        class=\"radio-button\"\n        [class.disabled]=\"disabled\"\n        (click)=\"select($event)\"></div>\n    <label\n        [for]=\"inputId\"\n        (click)=\"select($event)\">\n        <ng-content />\n    </label>\n</div>\n", styles: ["ap-radio .radio-button-container{display:flex;align-items:center;gap:var(--ref-spacing-xxs)}ap-radio .radio-button-container.label-left{flex-direction:row-reverse}ap-radio .radio-button-container input[type=radio]{transform:scale(0);position:absolute}ap-radio .radio-button-container input[type=radio]:checked~.radio-button{border-color:var(--ref-color-electric-blue-100);box-shadow:inset 0 0 0 3px var(--ref-color-white)}ap-radio .radio-button-container input[type=radio]:checked~.radio-button.disabled{background:var(--ref-color-grey-40);box-shadow:inset 0 0 0 3px var(--ref-color-grey-10)}ap-radio .radio-button-container input[type=radio]:checked:focus~.radio-button{border-color:var(--ref-color-electric-blue-100)}ap-radio .radio-button-container input[type=radio].disabled~.radio-button{pointer-events:none;cursor:default;box-shadow:inset 0 0 0 16px var(--ref-color-grey-10);border-color:var(--ref-color-grey-20)}ap-radio .radio-button-container input[type=radio].disabled~label{pointer-events:none;cursor:default;color:var(--ref-color-grey-60)}ap-radio .radio-button-container input[type=radio]:focus~.radio-button{outline:3px solid var(--ref-color-electric-blue-100);border-color:var(--ref-color-grey-80);outline-offset:1px}ap-radio .radio-button-container .radio-button{width:16px;height:16px;border-radius:100%;border:1px solid var(--ref-color-grey-60);background:var(--ref-color-electric-blue-100);box-shadow:inset 0 0 0 16px var(--ref-color-white);transition:box-shadow var(--comp-radio-transition-duration);flex-shrink:0}ap-radio .radio-button-container .radio-button:hover:not(.disabled){cursor:pointer;border-color:var(--ref-color-grey-80)}ap-radio .radio-button-container label{display:flex;align-items:center;font-family:var(--sys-text-style-body-font-family);font-size:var(--sys-text-style-body-size);font-weight:var(--sys-text-style-body-weight);line-height:var(--sys-text-style-body-line-height);color:var(--ref-color-grey-100)}ap-radio .radio-button-container label:empty{display:none}ap-radio .radio-button-container label.disabled{color:var(--ref-color-grey-60)}ap-radio .radio-button-container label:hover:not(.disabled){cursor:pointer}ap-radio.ng-invalid.ng-dirty .radio-button{border-color:var(--ref-color-red-100)}ap-radio.ng-invalid.ng-dirty .radio-button:hover{border-color:var(--ref-color-red-60)}ap-radio.ng-invalid.ng-dirty input[type=radio]:focus~.radio-button{border-color:var(--ref-color-red-60)}\n"] }]
        }], ctorParameters: () => [{ type: i0.ElementRef }], propDecorators: { inputElement: [{
                type: ViewChild,
                args: ['input', { static: true }]
            }], labelElement: [{
                type: ViewChild,
                args: ['label', { static: true }]
            }], ariaLabel: [{
                type: Input,
                args: ['aria-label']
            }], ariaLabelledby: [{
                type: Input,
                args: ['aria-labelledby']
            }], ariaDescribedby: [{
                type: Input,
                args: ['aria-describedby']
            }], disabled: [{
                type: Input,
                args: [{
                        transform: booleanAttribute,
                    }]
            }], labelPosition: [{
                type: Input
            }], radioId: [{
                type: Input,
                args: [{
                        required: true,
                    }]
            }], formControlName: [{
                type: Input
            }], value: [{
                type: Input,
                args: [{
                        required: true,
                    }]
            }], required: [{
                type: Input,
                args: [{
                        transform: booleanAttribute,
                    }]
            }], name: [{
                type: Input
            }], onClick: [{
                type: Output
            }], onFocus: [{
                type: Output
            }], onBlur: [{
                type: Output
            }] } });

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

export { RADIO_VALUE_ACCESSOR, RadioComponent, RadioControlRegistry };
//# sourceMappingURL=agorapulse-ui-components-radio.mjs.map
