import { AXEvent, MXValueComponent, AXComponent, MXBaseComponent, AXValuableComponent } from '@acorex/cdk/common';
import { AXLabelComponent } from '@acorex/components/label';
import { AXSelectBoxComponent } from '@acorex/components/select-box';
import { AXUnsubscriber } from '@acorex/core/utils';
import * as i0 from '@angular/core';
import { input, contentChildren, effect, afterNextRender, EventEmitter, Input, Output, ChangeDetectionStrategy, ViewEncapsulation, Component, signal, inject, ViewContainerRef, HostBinding, ContentChild, InjectionToken, Directive, NgModule } from '@angular/core';
import { AXAlertComponent, AXAlertModule } from '@acorex/components/alert';
import { AXButtonComponent, AXButtonModule } from '@acorex/components/button';
import { AXDecoratorIconComponent, AXDecoratorGenericComponent, AXDecoratorModule } from '@acorex/components/decorators';
import { AXTranslationService, AXTranslatorPipe, AXTranslationModule } from '@acorex/core/translation';
import { AXValidationModule } from '@acorex/core/validation';
import { AsyncPipe, CommonModule } from '@angular/common';
import { AXToastService } from '@acorex/components/toast';

/**
 *  Contains native event
 * @category Events
 */
class AXFormValidationEvent extends AXEvent {
}
/**
 * The AXForm is a component which detects user interaction and triggers a corresponding event
 *
 * @category Components
 */
class AXFormComponent extends MXValueComponent {
    #applyLooks;
    #init;
    /**
     * Determines when the form should be updated.
     */
    get updateOn() {
        return this._updateOn;
    }
    /**
     * Sets the criteria for when the form should be updated.
     * @param v The criteria to set (e.g., 'change', 'blur').
     */
    set updateOn(v) {
        this.setOption({
            name: 'updateOn',
            value: v,
            afterCallback: () => {
                this._bindEvents();
            },
        });
    }
    /**
     *  @ignore
     */
    async _handleSubmit(e) {
        e.preventDefault();
        await this.validate();
    }
    /**
     *  @ignore
     */
    _handleReset() {
        this.reset();
    }
    /**
     *  @ignore
     */
    constructor() {
        super();
        /**
         * Specifies the mode of the label in the form field.
         *  @defaultValue 'static'
         */
        this.labelMode = input('static', ...(ngDevMode ? [{ debugName: "labelMode" }] : []));
        this.look = input(null, ...(ngDevMode ? [{ debugName: "look" }] : []));
        this.content = contentChildren(AXFormFieldComponent, ...(ngDevMode ? [{ debugName: "content", descendants: true }] : [{ descendants: true }]));
        this.#applyLooks = effect(() => {
            const currentLook = this.look();
            if (!currentLook)
                return;
            this.content().forEach((item) => {
                if (item.input) {
                    item.input.look = currentLook;
                }
            });
        }, ...(ngDevMode ? [{ debugName: "#applyLooks" }] : []));
        this.#init = afterNextRender(() => {
            this.content().forEach((item) => {
                if (item.input?.readonly === null) {
                    item.input.readonly = this.readonly;
                }
                if (item.input?.disabled === null) {
                    item.input.disabled = this.disabled;
                }
            });
            this.disabledChange.subscribe((disabled) => {
                this.content().forEach((item) => {
                    item.input.disabled = disabled;
                });
            });
            this.readonlyChange.subscribe((readonly) => {
                this.content().forEach((item) => {
                    item.input.readonly = readonly;
                });
            });
        });
        /**
         * Determines the style of the message in the form field.
         * @defaultValue 'bottom'
         */
        this.messageStyle = input('bottom', ...(ngDevMode ? [{ debugName: "messageStyle" }] : []));
        /**
         * Emitted when the form is validated.
         *
         * @event
         */
        this.onValidate = new EventEmitter();
        /**
         * Emitted when the form's update mode changes.
         *
         * @event
         */
        this.updateOnChange = new EventEmitter();
        /**
         *  @ignore
         */
        this._updateOn = 'blur';
        this.inUserInteractionActive = input(true, ...(ngDevMode ? [{ debugName: "inUserInteractionActive" }] : []));
        /**
         *  @ignore
         */
        this._subs = [];
    }
    ngAfterViewInit() {
        this._bindEvents();
    }
    _bindEvents() {
        this._clearSubs();
        const widgets = this.content();
        widgets.forEach((w) => {
            const input = w?.input;
            if (!input)
                return;
            const shouldValidate = () => this.updateOn === 'change';
            const applyUpdate = () => (shouldValidate() ? input.validate() : input.resetErrors());
            if (this.updateOn === 'blur') {
                this._subs.push(input.onBlur?.subscribe(() => input.validate()));
                return;
            }
            this._subs.push(input.onValueChanged?.subscribe((e) => {
                // Only gate on user interaction when that mode is active
                if (this.inUserInteractionActive() && !e.isUserInteraction)
                    return;
                applyUpdate();
            }));
        });
    }
    /**
     *  @ignore
     */
    _clearSubs() {
        this._subs.forEach((c) => c?.unsubscribe());
        this._subs = [];
    }
    /**
     *  @ignore
     */
    get fields() {
        return Array.from(this.getHostElement().querySelectorAll('[ax-form-item="true"]'))
            .map((c) => c.__axContext__)
            .filter((c) => c != null);
    }
    /**
     * Validates the form fields.
     *
     * @param names - Optional array of field names to validate.
     * @returns Promise<AXValidationSummary> - Promise that resolves with validation results.
     */
    async validate(...names) {
        const results = await Promise.all(this.fields
            .filter((c) => names == null || names.length == 0 || names.includes(c.name))
            .map((field) => field.validate()));
        // Merge all validation summaries into one
        const mergedSummary = {
            result: results.every((res) => res.result),
            rules: results.flatMap((res) => res.rules),
        };
        this._emitOnValidateEvent(mergedSummary);
        return mergedSummary;
    }
    /**
     *  @ignore
     */
    _emitOnValidateEvent(e) {
        this.onValidate.emit({
            component: this,
            result: e,
            htmlElement: this.getHostElement(),
        });
    }
    /**
     * Resets all form fields without clearing errors.
     *
     * @returns void - No return value. Form fields are reset to their initial values.
     */
    reset() {
        this.fields.forEach((c) => c.reset(false));
        this.fields.forEach((c) => c.resetErrors());
    }
    /**
     * Resets validation errors for all form fields.
     *
     * @returns void - No return value. All validation errors are cleared.
     */
    resetErrors() {
        this.fields.forEach((c) => c.resetErrors());
    }
    /**
     *  @ignore
     */
    ngOnDestroy() {
        this._clearSubs();
    }
    static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "20.3.3", ngImport: i0, type: AXFormComponent, deps: [], target: i0.ɵɵFactoryTarget.Component }); }
    static { this.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.2.0", version: "20.3.3", type: AXFormComponent, isStandalone: true, selector: "ax-form", inputs: { disabled: { classPropertyName: "disabled", publicName: "disabled", isSignal: false, isRequired: false, transformFunction: null }, readonly: { classPropertyName: "readonly", publicName: "readonly", isSignal: false, isRequired: false, transformFunction: null }, labelMode: { classPropertyName: "labelMode", publicName: "labelMode", isSignal: true, isRequired: false, transformFunction: null }, look: { classPropertyName: "look", publicName: "look", isSignal: true, isRequired: false, transformFunction: null }, messageStyle: { classPropertyName: "messageStyle", publicName: "messageStyle", isSignal: true, isRequired: false, transformFunction: null }, updateOn: { classPropertyName: "updateOn", publicName: "updateOn", isSignal: false, isRequired: false, transformFunction: null }, inUserInteractionActive: { classPropertyName: "inUserInteractionActive", publicName: "inUserInteractionActive", isSignal: true, isRequired: false, transformFunction: null } }, outputs: { onValidate: "onValidate", updateOnChange: "updateOnChange" }, providers: [{ provide: AXComponent, useExisting: AXFormComponent }], queries: [{ propertyName: "content", predicate: AXFormFieldComponent, descendants: true, isSignal: true }], usesInheritance: true, ngImport: i0, template: `<form (submit)="_handleSubmit($event)" (reset)="_handleReset()" class="ax-{{ messageStyle() }}-error">
    <ng-content></ng-content>
  </form>`, isInline: true, styles: ["form{height:inherit}\n"], changeDetection: i0.ChangeDetectionStrategy.OnPush, encapsulation: i0.ViewEncapsulation.None }); }
}
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.3.3", ngImport: i0, type: AXFormComponent, decorators: [{
            type: Component,
            args: [{ selector: 'ax-form', template: `<form (submit)="_handleSubmit($event)" (reset)="_handleReset()" class="ax-{{ messageStyle() }}-error">
    <ng-content></ng-content>
  </form>`, inputs: ['disabled', 'readonly'], encapsulation: ViewEncapsulation.None, changeDetection: ChangeDetectionStrategy.OnPush, providers: [{ provide: AXComponent, useExisting: AXFormComponent }], styles: ["form{height:inherit}\n"] }]
        }], ctorParameters: () => [], propDecorators: { onValidate: [{
                type: Output
            }], updateOnChange: [{
                type: Output
            }], updateOn: [{
                type: Input
            }] } });

/**
 * A container component for form fields that provides styling and structure.
 *
 * @category Components
 */
class AXFormFieldComponent extends MXBaseComponent {
    /**
     *  @ignore
     */
    constructor() {
        super();
        /**
         * Specifies the mode of the label in the form field.
         *  @defaultValue 'static'
         */
        this.labelMode = input('static', ...(ngDevMode ? [{ debugName: "labelMode" }] : []));
        /**
         *  @ignore
         */
        this._labelMode = signal(this.labelMode(), ...(ngDevMode ? [{ debugName: "_labelMode" }] : []));
        this.unsubscriber = inject(AXUnsubscriber);
        this.form = inject(AXFormComponent, { optional: true });
        this.host = inject(ViewContainerRef);
        afterNextRender(() => {
            this.setRequired();
            this.setLabelMode();
            this.listeningEvent();
            this.calcIndentSize();
            this.autoSetLabelAssociation();
        });
        effect(() => {
            this.setLabelMode();
        });
    }
    ngAfterContentChecked() {
        this.calcIndentSize();
    }
    /**
     * Calculates and sets the indentation size for the label based on the width of the prefix element.
     * @ignore
     */
    calcIndentSize() {
        const prefix = this.input?.getHostElement()?.querySelector('ax-prefix');
        if (prefix && this.label) {
            this.label.getHostElement().style.insetInlineStart = `calc(${prefix?.clientWidth}px + var(--ax-comp-editor-gap))`;
            this.label.getHostElement().style.paddingInline = '0px';
        }
    }
    /**
     * Sets the required attribute for the input field based on validation rules.
     * Automatically updates if validation rules change.
     * @ignore
     */
    setRequired() {
        this.autoSetRequired();
        this.input?.validationRulesChange.pipe(this.unsubscriber.takeUntilDestroy).subscribe(() => {
            this.autoSetRequired();
        });
    }
    /**
     * Sets the label mode based on the form's label mode configuration.
     * @ignore
     */
    setLabelMode() {
        this._labelMode.set(this.form?.labelMode());
    }
    /**
     * Subscribes to focus and blur events on the input element.
     * Adds or removes the 'ax-state-focused' class to/from the host element based on the focus state.
     * @ignone
     */
    listeningEvent() {
        const focusEvent = this.input?.['onFocus'];
        focusEvent?.subscribe((e) => {
            // this.handleFloating('focus');
            this.host.element.nativeElement.classList.add('ax-state-focused');
        });
        //
        const blurEvent = this.input?.['onBlur'];
        blurEvent?.subscribe((e) => {
            // this.handleFloating('blur');
            this.host.element.nativeElement.classList.remove('ax-state-focused');
        });
    }
    // protected handleFloating(mode: 'focus' | 'blur') {
    //   const _host = this.host.element.nativeElement as HTMLElement;
    //   const placeholder = this.input;
    //   switch (mode) {
    //     case 'focus':
    //       _host.classList.add('ax-state-floating');
    //       this.label.getHostElement().style.insetInlineStart = 'inherit';
    //       break;
    //     case 'blur':
    //       _host.classList.remove('ax-state-floating');
    //       break;
    //   }
    // }
    /**
     *  @ignore
     */
    autoSetRequired() {
        if (this.label && this.input) {
            if (this.label.required == null || this.label['autoSetRequired']) {
                this.label.required = this.input.isRequired;
                this.label['autoSetRequired'] = true;
            }
        }
    }
    /**
     *  @ignore
     */
    autoSetLabelAssociation() {
        if (this.label && this.input) {
            this.label.for = this.input;
        }
    }
    /**
     *  @ignore
     */
    get __hostClass() {
        let hasValue;
        if (this.input) {
            if (this.input instanceof AXSelectBoxComponent && this.input.multiple) {
                hasValue = this.input.value?.length;
            }
            else {
                hasValue = this.input.value;
            }
        }
        return [`ax-state-${this._labelMode()}-label`, `${hasValue && 'ax-state-has-value'}`];
    }
    static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "20.3.3", ngImport: i0, type: AXFormFieldComponent, deps: [], target: i0.ɵɵFactoryTarget.Component }); }
    static { this.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.1.0", version: "20.3.3", type: AXFormFieldComponent, isStandalone: true, selector: "ax-form-field", inputs: { labelMode: { classPropertyName: "labelMode", publicName: "labelMode", isSignal: true, isRequired: false, transformFunction: null } }, host: { properties: { "class": "this.__hostClass" } }, providers: [AXUnsubscriber, { provide: AXComponent, useExisting: AXFormFieldComponent }], queries: [{ propertyName: "input", first: true, predicate: AXValuableComponent, descendants: true }, { propertyName: "label", first: true, predicate: AXLabelComponent, descendants: true }], usesInheritance: true, ngImport: i0, template: `<ng-content></ng-content>`, isInline: true, styles: ["ax-form-field{position:relative;display:block;width:100%}ax-form-field.ax-state-floating-label{--ax-sys-size-base: 3.5rem}ax-form-field.ax-state-floating-label>ax-label{position:absolute;top:calc(var(--ax-sys-size-base, 3.5rem) / 2);transform:translateY(-50%);inset-inline-start:1rem;pointer-events:none;z-index:10;display:inline-grid;transition-property:transform,top;transition-duration:var(--ax-sys-transition-duration);transition-timing-function:var(--ax-sys-transition-timing-function)}ax-form-field.ax-state-floating-label>ax-label label{margin:0;overflow:hidden;text-overflow:ellipsis;white-space:nowrap}ax-form-field.ax-state-floating-label .ax-input::placeholder,ax-form-field.ax-state-floating-label .ax-input .ax-placeholder{opacity:0}ax-form-field.ax-state-floating-label.ax-state-focused>ax-label,ax-form-field.ax-state-floating-label.ax-state-has-value>ax-label{transform:translateY(-115%) translate(-2.5%) scale(.95);inset-inline-start:.5rem}ax-form-field.ax-state-floating-label.ax-state-focused>ax-label label,ax-form-field.ax-state-floating-label.ax-state-has-value>ax-label label{font-size:.75rem;color:rgba(var(--ax-sys-body-text-color),.5)}ax-form-field.ax-state-floating-label.ax-state-focused .ax-input,ax-form-field.ax-state-floating-label.ax-state-focused .ax-content,ax-form-field.ax-state-floating-label.ax-state-focused ax-text-area,ax-form-field.ax-state-floating-label.ax-state-has-value .ax-input,ax-form-field.ax-state-floating-label.ax-state-has-value .ax-content,ax-form-field.ax-state-floating-label.ax-state-has-value ax-text-area{padding-top:.875rem}ax-form-field.ax-state-floating-label.ax-state-focused .ax-input::placeholder,ax-form-field.ax-state-floating-label.ax-state-focused .ax-content::placeholder,ax-form-field.ax-state-floating-label.ax-state-focused ax-text-area::placeholder,ax-form-field.ax-state-floating-label.ax-state-has-value .ax-input::placeholder,ax-form-field.ax-state-floating-label.ax-state-has-value .ax-content::placeholder,ax-form-field.ax-state-floating-label.ax-state-has-value ax-text-area::placeholder{opacity:1}ax-form-field.ax-state-floating-label.ax-state-focused .ax-chips-container,ax-form-field.ax-state-floating-label.ax-state-has-value .ax-chips-container{padding:0}ax-form-field.ax-state-floating-label.ax-state-focused ax-text-area .ax-editor-container,ax-form-field.ax-state-floating-label.ax-state-has-value ax-text-area .ax-editor-container{padding-top:1.5rem}ax-form-field.ax-state-floating-label.ax-state-focused ax-text-area textarea,ax-form-field.ax-state-floating-label.ax-state-has-value ax-text-area textarea{padding-top:0!important}ax-form-field.ax-state-over-label{--ax-sys-size-base: 3.5rem}ax-form-field.ax-state-over-label>ax-label{position:absolute;pointer-events:none;z-index:10;display:inline-grid;top:10%;transform:translateY(-10%);inset-inline-start:.5rem;transition-property:transform,top;transition-duration:var(--ax-sys-transition-duration);transition-timing-function:var(--ax-sys-transition-timing-function)}ax-form-field.ax-state-over-label>ax-label label{margin:0;overflow:hidden;text-overflow:ellipsis;font-size:.75rem;white-space:nowrap}ax-form-field.ax-state-over-label .ax-input,ax-form-field.ax-state-over-label .ax-content,ax-form-field.ax-state-over-label ax-text-area{padding-top:1rem}ax-form-field.ax-state-over-label.ax-state-focused ax-text-area .ax-editor-container,ax-form-field.ax-state-over-label.ax-state-has-value ax-text-area .ax-editor-container{padding-top:1.5rem}ax-form-field.ax-state-over-label.ax-state-focused ax-text-area textarea,ax-form-field.ax-state-over-label.ax-state-has-value ax-text-area textarea{padding-top:0!important}ax-form-field.ax-state-floating-label .ax-chips-container.ax-multiple,ax-form-field.ax-state-over-label .ax-chips-container.ax-multiple{padding-top:1.5rem!important;padding-inline-start:.75rem}ax-form-field .ax-error-message{margin-top:.25rem;margin-bottom:.25rem;display:block;font-size:.75rem;line-height:1rem}ax-form{width:100%}ax-form form.ax-bottom-error .ax-error-message{color:rgba(var(--ax-sys-color-danger-surface))}ax-form form.ax-float-error .ax-error-message{position:absolute;bottom:-2.5rem;z-index:20;display:block;width:fit-content;border-radius:.375rem;border-width:1px;border-color:rgba(var(--ax-sys-color-border-danger-surface));background-color:rgba(var(--ax-sys-color-danger-surface));color:rgba(var(--ax-sys-color-on-danger-surface));padding:.25rem .5rem;font-weight:400}ax-form form.ax-float-error .ax-error-message:before,ax-form form.ax-float-error .ax-error-message:after{pointer-events:none;position:absolute;bottom:100%;inset-inline-start:.75rem;z-index:20;height:0px;width:0px;border-bottom-color:rgba(var(--ax-sys-color-danger-surface));border-inline-end-color:transparent;border-inline-start-color:transparent;border-top-color:transparent;content:\"\"}ax-form form.ax-float-error .ax-error-message:before{margin-inline-start:-1px;border-width:4px;border-bottom-color:rgba(var(--ax-sys-color-danger-surface))}ax-form form.ax-float-error .ax-error-message:after{border-width:4px}\n"], changeDetection: i0.ChangeDetectionStrategy.OnPush, encapsulation: i0.ViewEncapsulation.None }); }
}
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.3.3", ngImport: i0, type: AXFormFieldComponent, decorators: [{
            type: Component,
            args: [{ selector: 'ax-form-field', template: `<ng-content></ng-content>`, encapsulation: ViewEncapsulation.None, changeDetection: ChangeDetectionStrategy.OnPush, providers: [AXUnsubscriber, { provide: AXComponent, useExisting: AXFormFieldComponent }], styles: ["ax-form-field{position:relative;display:block;width:100%}ax-form-field.ax-state-floating-label{--ax-sys-size-base: 3.5rem}ax-form-field.ax-state-floating-label>ax-label{position:absolute;top:calc(var(--ax-sys-size-base, 3.5rem) / 2);transform:translateY(-50%);inset-inline-start:1rem;pointer-events:none;z-index:10;display:inline-grid;transition-property:transform,top;transition-duration:var(--ax-sys-transition-duration);transition-timing-function:var(--ax-sys-transition-timing-function)}ax-form-field.ax-state-floating-label>ax-label label{margin:0;overflow:hidden;text-overflow:ellipsis;white-space:nowrap}ax-form-field.ax-state-floating-label .ax-input::placeholder,ax-form-field.ax-state-floating-label .ax-input .ax-placeholder{opacity:0}ax-form-field.ax-state-floating-label.ax-state-focused>ax-label,ax-form-field.ax-state-floating-label.ax-state-has-value>ax-label{transform:translateY(-115%) translate(-2.5%) scale(.95);inset-inline-start:.5rem}ax-form-field.ax-state-floating-label.ax-state-focused>ax-label label,ax-form-field.ax-state-floating-label.ax-state-has-value>ax-label label{font-size:.75rem;color:rgba(var(--ax-sys-body-text-color),.5)}ax-form-field.ax-state-floating-label.ax-state-focused .ax-input,ax-form-field.ax-state-floating-label.ax-state-focused .ax-content,ax-form-field.ax-state-floating-label.ax-state-focused ax-text-area,ax-form-field.ax-state-floating-label.ax-state-has-value .ax-input,ax-form-field.ax-state-floating-label.ax-state-has-value .ax-content,ax-form-field.ax-state-floating-label.ax-state-has-value ax-text-area{padding-top:.875rem}ax-form-field.ax-state-floating-label.ax-state-focused .ax-input::placeholder,ax-form-field.ax-state-floating-label.ax-state-focused .ax-content::placeholder,ax-form-field.ax-state-floating-label.ax-state-focused ax-text-area::placeholder,ax-form-field.ax-state-floating-label.ax-state-has-value .ax-input::placeholder,ax-form-field.ax-state-floating-label.ax-state-has-value .ax-content::placeholder,ax-form-field.ax-state-floating-label.ax-state-has-value ax-text-area::placeholder{opacity:1}ax-form-field.ax-state-floating-label.ax-state-focused .ax-chips-container,ax-form-field.ax-state-floating-label.ax-state-has-value .ax-chips-container{padding:0}ax-form-field.ax-state-floating-label.ax-state-focused ax-text-area .ax-editor-container,ax-form-field.ax-state-floating-label.ax-state-has-value ax-text-area .ax-editor-container{padding-top:1.5rem}ax-form-field.ax-state-floating-label.ax-state-focused ax-text-area textarea,ax-form-field.ax-state-floating-label.ax-state-has-value ax-text-area textarea{padding-top:0!important}ax-form-field.ax-state-over-label{--ax-sys-size-base: 3.5rem}ax-form-field.ax-state-over-label>ax-label{position:absolute;pointer-events:none;z-index:10;display:inline-grid;top:10%;transform:translateY(-10%);inset-inline-start:.5rem;transition-property:transform,top;transition-duration:var(--ax-sys-transition-duration);transition-timing-function:var(--ax-sys-transition-timing-function)}ax-form-field.ax-state-over-label>ax-label label{margin:0;overflow:hidden;text-overflow:ellipsis;font-size:.75rem;white-space:nowrap}ax-form-field.ax-state-over-label .ax-input,ax-form-field.ax-state-over-label .ax-content,ax-form-field.ax-state-over-label ax-text-area{padding-top:1rem}ax-form-field.ax-state-over-label.ax-state-focused ax-text-area .ax-editor-container,ax-form-field.ax-state-over-label.ax-state-has-value ax-text-area .ax-editor-container{padding-top:1.5rem}ax-form-field.ax-state-over-label.ax-state-focused ax-text-area textarea,ax-form-field.ax-state-over-label.ax-state-has-value ax-text-area textarea{padding-top:0!important}ax-form-field.ax-state-floating-label .ax-chips-container.ax-multiple,ax-form-field.ax-state-over-label .ax-chips-container.ax-multiple{padding-top:1.5rem!important;padding-inline-start:.75rem}ax-form-field .ax-error-message{margin-top:.25rem;margin-bottom:.25rem;display:block;font-size:.75rem;line-height:1rem}ax-form{width:100%}ax-form form.ax-bottom-error .ax-error-message{color:rgba(var(--ax-sys-color-danger-surface))}ax-form form.ax-float-error .ax-error-message{position:absolute;bottom:-2.5rem;z-index:20;display:block;width:fit-content;border-radius:.375rem;border-width:1px;border-color:rgba(var(--ax-sys-color-border-danger-surface));background-color:rgba(var(--ax-sys-color-danger-surface));color:rgba(var(--ax-sys-color-on-danger-surface));padding:.25rem .5rem;font-weight:400}ax-form form.ax-float-error .ax-error-message:before,ax-form form.ax-float-error .ax-error-message:after{pointer-events:none;position:absolute;bottom:100%;inset-inline-start:.75rem;z-index:20;height:0px;width:0px;border-bottom-color:rgba(var(--ax-sys-color-danger-surface));border-inline-end-color:transparent;border-inline-start-color:transparent;border-top-color:transparent;content:\"\"}ax-form form.ax-float-error .ax-error-message:before{margin-inline-start:-1px;border-width:4px;border-bottom-color:rgba(var(--ax-sys-color-danger-surface))}ax-form form.ax-float-error .ax-error-message:after{border-width:4px}\n"] }]
        }], ctorParameters: () => [], propDecorators: { input: [{
                type: ContentChild,
                args: [AXValuableComponent]
            }], label: [{
                type: ContentChild,
                args: [AXLabelComponent]
            }], __hostClass: [{
                type: HostBinding,
                args: ['class']
            }] } });

const AX_FORM_CONFIG = new InjectionToken('AX_FORM_CONFIG', {
    providedIn: 'root',
    factory: () => {
        return AXFormDefaultConfig;
    },
});
const AXFormDefaultConfig = {};
function formConfig(config = {}) {
    const result = {
        ...AXFormDefaultConfig,
        ...config,
    };
    return result;
}

class AXValidationRuleDirective {
    constructor() {
        this.host = inject(AXValuableComponent);
        this.rule = input(...(ngDevMode ? [undefined, { debugName: "rule" }] : []));
        this.options = input(...(ngDevMode ? [undefined, { debugName: "options" }] : []));
        this.message = input(...(ngDevMode ? [undefined, { debugName: "message" }] : []));
        this.disabled = input(false, ...(ngDevMode ? [{ debugName: "disabled" }] : []));
        this.#disabledChanged = effect(() => {
            if (this.disabled()) {
                this.removeValidation();
            }
            else {
                this.addValidation();
            }
        }, ...(ngDevMode ? [{ debugName: "#disabledChanged" }] : []));
    }
    #disabledChanged;
    ngOnDestroy() {
        this.removeValidation();
    }
    addValidation() {
        this.host.addValidationRule({ rule: this.rule(), disabled: this.disabled(), options: this.ruleOptions });
    }
    removeValidation() {
        this.host.removeValidationRule({
            rule: this.rule(),
            disabled: this.disabled(),
            options: this.ruleOptions,
        });
    }
    get ruleOptions() {
        return Object.assign({ message: this.message(), name: this.host.name }, this.options());
    }
    static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "20.3.3", ngImport: i0, type: AXValidationRuleDirective, deps: [], target: i0.ɵɵFactoryTarget.Directive }); }
    static { this.ɵdir = i0.ɵɵngDeclareDirective({ minVersion: "17.1.0", version: "20.3.3", type: AXValidationRuleDirective, isStandalone: true, selector: "ax-validation-rule", inputs: { rule: { classPropertyName: "rule", publicName: "rule", isSignal: true, isRequired: false, transformFunction: null }, options: { classPropertyName: "options", publicName: "options", isSignal: true, isRequired: false, transformFunction: null }, message: { classPropertyName: "message", publicName: "message", isSignal: true, isRequired: false, transformFunction: null }, disabled: { classPropertyName: "disabled", publicName: "disabled", isSignal: true, isRequired: false, transformFunction: null } }, ngImport: i0 }); }
}
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.3.3", ngImport: i0, type: AXValidationRuleDirective, decorators: [{
            type: Directive,
            args: [{ selector: 'ax-validation-rule' }]
        }] });

/**
 * Displays validation summaries in the form of an alert.
 *
 * @category Components
 */
class AXValidationSummaryComponent extends MXBaseComponent {
    /**
     * The title of the validation summary alert.
     */
    get title() {
        return this._title;
    }
    /**
     * Sets the title of the validation summary alert.
     *
     * @param v The title to be set.
     */
    set title(v) {
        this._title = v;
    }
    /**
     *  @ignore
     */
    constructor() {
        super();
        this._tosatService = inject(AXToastService);
        this.host = inject(AXFormComponent, { optional: true });
        this.translateService = inject(AXTranslationService);
        /**
         *  @ignore
         */
        this._content = null;
        /**
         *  @ignore
         */
        this._title = '@acorex:validation.messages.title';
        /**
         * Specifies the display mode for the validation summary.
         *
         *  @defaultValue 'toast'
         */
        this.displayMode = 'toast';
        /**
         * Determines whether the validation summary should automatically hide after a specified time.
         * @defaultValue false
         */
        this.autoHide = false;
        const host = this.host;
        //
        this.sub = host.onValidate.subscribe(async (e) => {
            if (e.result.result) {
                this._content = null;
            }
            else {
                const failedRules = e.result.rules.filter((c) => !c.result && c.message);
                this._content = `<ul>${failedRules.map((c) => this.formatRule({ title: c['title'], message: c.message })).join('')}</ul>`;
                this._timeOut = this.autoHide ? (this.timeOut ?? Math.max(failedRules.length * 1000, 2000)) : 0;
                if (this.displayMode == 'toast') {
                    this._tosatService.show({
                        color: 'danger',
                        closeButton: true,
                        timeOut: this._timeOut,
                        timeOutProgress: true,
                        content: this._content,
                        title: await this.translateService.translateAsync(this.title),
                        location: 'bottom-center',
                    });
                }
            }
            this.cdr.markForCheck();
        });
    }
    /**
     *  @ignore
     */
    formatRule(rule) {
        return rule.title ? `<li><b>${rule.title}:</b> ${rule.message}</li>` : `<li>${rule.message}</li>`;
    }
    /**
     *  @ignore
     */
    _handleOnDismissed() {
        this._content = null;
    }
    /**
     *  @ignore
     */
    ngOnDestroy() {
        this.sub?.unsubscribe();
    }
    static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "20.3.3", ngImport: i0, type: AXValidationSummaryComponent, deps: [], target: i0.ɵɵFactoryTarget.Component }); }
    static { this.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "20.3.3", type: AXValidationSummaryComponent, isStandalone: true, selector: "ax-validation-summary", inputs: { title: "title", displayMode: "displayMode", timeOut: "timeOut", autoHide: "autoHide" }, providers: [{ provide: AXComponent, useExisting: AXValidationSummaryComponent }], usesInheritance: true, ngImport: i0, template: `
    @if (displayMode === 'alert' && _content) {
      <ax-alert color="danger" [timeOut]="_timeOut" #a (onClosed)="_handleOnDismissed()">
        <ax-icon></ax-icon>
        <ax-title>{{ title | translate | async }}</ax-title>
        <ax-content>
          <div [innerHTML]="_content"></div>
        </ax-content>
        <ax-footer>
          <ax-suffix>
            <ax-button text="Dismiss" (onClick)="a.close()"></ax-button>
          </ax-suffix>
        </ax-footer>
      </ax-alert>
    }
  `, isInline: true, dependencies: [{ kind: "component", type: AXAlertComponent, selector: "ax-alert", inputs: ["color", "timeOut"], outputs: ["colorChange", "onClosed", "timeOutChange"] }, { kind: "component", type: AXDecoratorIconComponent, selector: "ax-icon", inputs: ["icon"] }, { kind: "component", type: AXDecoratorGenericComponent, selector: "ax-footer, ax-header, ax-content, ax-divider, ax-form-hint, ax-prefix, ax-suffix, ax-text, ax-title, ax-subtitle, ax-placeholder, ax-overlay" }, { kind: "component", type: AXButtonComponent, selector: "ax-button", inputs: ["disabled", "size", "tabIndex", "color", "look", "text", "toggleable", "selected", "iconOnly", "type", "loadingText"], outputs: ["onBlur", "onFocus", "onClick", "selectedChange", "toggleableChange", "lookChange", "colorChange", "disabledChange", "loadingTextChange"] }, { kind: "pipe", type: AsyncPipe, name: "async" }, { kind: "pipe", type: AXTranslatorPipe, name: "translate" }], changeDetection: i0.ChangeDetectionStrategy.OnPush, encapsulation: i0.ViewEncapsulation.None }); }
}
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.3.3", ngImport: i0, type: AXValidationSummaryComponent, decorators: [{
            type: Component,
            args: [{
                    selector: 'ax-validation-summary',
                    template: `
    @if (displayMode === 'alert' && _content) {
      <ax-alert color="danger" [timeOut]="_timeOut" #a (onClosed)="_handleOnDismissed()">
        <ax-icon></ax-icon>
        <ax-title>{{ title | translate | async }}</ax-title>
        <ax-content>
          <div [innerHTML]="_content"></div>
        </ax-content>
        <ax-footer>
          <ax-suffix>
            <ax-button text="Dismiss" (onClick)="a.close()"></ax-button>
          </ax-suffix>
        </ax-footer>
      </ax-alert>
    }
  `,
                    changeDetection: ChangeDetectionStrategy.OnPush,
                    encapsulation: ViewEncapsulation.None,
                    imports: [
                        AXAlertComponent,
                        AXDecoratorIconComponent,
                        AXDecoratorGenericComponent,
                        AXButtonComponent,
                        AsyncPipe,
                        AXTranslatorPipe,
                    ],
                    providers: [{ provide: AXComponent, useExisting: AXValidationSummaryComponent }],
                }]
        }], ctorParameters: () => [], propDecorators: { title: [{
                type: Input
            }], displayMode: [{
                type: Input
            }], timeOut: [{
                type: Input
            }], autoHide: [{
                type: Input
            }] } });

class AXFormModule {
    static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "20.3.3", ngImport: i0, type: AXFormModule, deps: [], target: i0.ɵɵFactoryTarget.NgModule }); }
    static { this.ɵmod = i0.ɵɵngDeclareNgModule({ minVersion: "14.0.0", version: "20.3.3", ngImport: i0, type: AXFormModule, imports: [CommonModule,
            AXDecoratorModule,
            AXAlertModule,
            AXButtonModule,
            AXValidationModule,
            AXTranslationModule,
            AXFormFieldComponent,
            AXFormComponent,
            AXValidationRuleDirective,
            AXValidationSummaryComponent], exports: [AXFormFieldComponent, AXFormComponent, AXValidationRuleDirective, AXValidationSummaryComponent] }); }
    static { this.ɵinj = i0.ɵɵngDeclareInjector({ minVersion: "12.0.0", version: "20.3.3", ngImport: i0, type: AXFormModule, imports: [CommonModule,
            AXDecoratorModule,
            AXAlertModule,
            AXButtonModule,
            AXValidationModule,
            AXTranslationModule,
            AXValidationSummaryComponent] }); }
}
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.3.3", ngImport: i0, type: AXFormModule, decorators: [{
            type: NgModule,
            args: [{
                    imports: [
                        CommonModule,
                        AXDecoratorModule,
                        AXAlertModule,
                        AXButtonModule,
                        AXValidationModule,
                        AXTranslationModule,
                        AXFormFieldComponent,
                        AXFormComponent,
                        AXValidationRuleDirective,
                        AXValidationSummaryComponent,
                    ],
                    exports: [AXFormFieldComponent, AXFormComponent, AXValidationRuleDirective, AXValidationSummaryComponent],
                    providers: [],
                }]
        }] });

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

export { AXFormComponent, AXFormDefaultConfig, AXFormFieldComponent, AXFormModule, AXFormValidationEvent, AXValidationRuleDirective, AXValidationSummaryComponent, AX_FORM_CONFIG, formConfig };
//# sourceMappingURL=acorex-components-form.mjs.map
