import { SelectionModel } from '@angular/cdk/collections';
import { ScrollingModule } from '@angular/cdk/scrolling';
import { CommonModule } from '@angular/common';
import { ChangeDetectionStrategy, Component, ContentChild, ElementRef, Input, TemplateRef, booleanAttribute, computed, effect, forwardRef, input, signal } from '@angular/core';
import { takeUntilDestroyed, toSignal } from '@angular/core/rxjs-interop';
import { FormControl, FormsModule, NG_VALUE_ACCESSOR, ReactiveFormsModule } from '@angular/forms';
import { MatAutocompleteModule } from '@angular/material/autocomplete';
import { mixinColor, mixinDisableRipple, mixinDisabled } from '@angular/material/core';
import { MatIconModule } from '@angular/material/icon';
import { MatInputModule } from '@angular/material/input';
import { MatSelectModule } from '@angular/material/select';
import { OcapCoreModule } from '@metad/ocap-angular/core';
import { isNil, nonNullable } from '@metad/ocap-core';
import { distinctUntilChanged, filter } from 'rxjs/operators';
import { NgmDisplayBehaviourComponent } from '../../display-behaviour';
import { NgmOptionContent } from '../../input/option-content';
import * as i0 from "@angular/core";
import * as i1 from "@angular/common";
import * as i2 from "@angular/forms";
import * as i3 from "@angular/material/form-field";
import * as i4 from "@angular/material/select";
import * as i5 from "@angular/material/core";
import * as i6 from "@angular/material/autocomplete";
import * as i7 from "@angular/material/input";
import * as i8 from "@angular/material/icon";
import * as i9 from "@angular/cdk/scrolling";
export class NgmSelectComponent extends mixinColor(mixinDisabled(mixinDisableRipple(class {
    constructor(_elementRef) {
        this._elementRef = _elementRef;
    }
}))) {
    constructor(_elementRef) {
        super(_elementRef);
        /**
         * The name of key field of option
         */
        this.valueKey = input('value');
        this.searchable = input(false, {
            transform: booleanAttribute
        });
        this.virtualScroll = input(false, {
            transform: booleanAttribute
        });
        this.validators = input();
        this.multiple = input(false, {
            transform: booleanAttribute
        });
        this.selectOptions = input();
        this.panelWidth = input(null);
        this._explicitContent = undefined;
        this.formControl = new FormControl(null);
        this.value = toSignal(this.formControl.valueChanges, { initialValue: '' });
        this.selection = new SelectionModel(true);
        this.searchControl = new FormControl(null);
        this.highlight = toSignal(this.searchControl.valueChanges, { initialValue: '' });
        this.options$ = computed(() => {
            const text = this.highlight()?.trim().toLowerCase();
            if (text) {
                const terms = text.split(' ').filter((t) => !!t);
                return this.selectOptions()?.filter((option) => {
                    const str = `${option.caption || option.label || ''}${option[this.valueKey()]}`;
                    return terms.every((term) => str?.toLowerCase().includes(term));
                });
            }
            return this.selectOptions();
        });
        this.selectTrigger = computed(() => {
            return this.selectOptions()?.find((option) => option[this.valueKey()] === this.value());
        });
        this.autoInput = signal(null);
        this.valueSub = this.formControl.valueChanges
            .pipe(filter(() => !this.multiple()), distinctUntilChanged(), takeUntilDestroyed())
            .subscribe((value) => {
            this.onChange?.(value);
        });
        this.selectionSub = this.selection.changed
            .pipe(filter(() => this.multiple()), takeUntilDestroyed())
            .subscribe(() => {
            this.onChange?.(this.selection.selected);
        });
        effect(() => {
            if (!isNil(this.value())) {
                const selectedOption = this.selectOptions()?.find((item) => item[this.valueKey()] === this.value());
                if (nonNullable(selectedOption?.[this.valueKey()])) {
                    this.autoInput.set(selectedOption);
                }
                else {
                    this.autoInput.set(null);
                }
            }
            else {
                this.autoInput.set(null);
            }
        }, { allowSignalWrites: true });
    }
    writeValue(obj) {
        this.formControl.setValue(obj);
    }
    registerOnChange(fn) {
        this.onChange = fn;
    }
    registerOnTouched(fn) {
        this.onTouched = fn;
    }
    setDisabledState(isDisabled) {
        this.disabled = isDisabled;
        isDisabled ? this.formControl.disable() : this.formControl.enable();
    }
    trackByValue(index, item) {
        return item?.key;
    }
    displayWith(option) {
        return option?.caption || option?.label || option?.key;
    }
    onAutoInput(event) {
        if (typeof event === 'string') {
            this.searchControl.setValue(event);
        }
        else {
            this.formControl.setValue(event?.[this.valueKey()]);
            this.searchControl.setValue(null);
        }
    }
    onOptionSelected(event) {
        //
    }
    static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "17.3.10", ngImport: i0, type: NgmSelectComponent, deps: [{ token: i0.ElementRef }], target: i0.ɵɵFactoryTarget.Component }); }
    static { this.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "17.3.10", type: NgmSelectComponent, isStandalone: true, selector: "ngm-select", inputs: { displayBehaviour: { classPropertyName: "displayBehaviour", publicName: "displayBehaviour", isSignal: false, isRequired: false, transformFunction: null }, displayDensity: { classPropertyName: "displayDensity", publicName: "displayDensity", isSignal: false, isRequired: false, transformFunction: null }, valueKey: { classPropertyName: "valueKey", publicName: "valueKey", isSignal: true, isRequired: false, transformFunction: null }, label: { classPropertyName: "label", publicName: "label", isSignal: false, isRequired: false, transformFunction: null }, placeholder: { classPropertyName: "placeholder", publicName: "placeholder", isSignal: false, isRequired: false, transformFunction: null }, searchable: { classPropertyName: "searchable", publicName: "searchable", isSignal: true, isRequired: false, transformFunction: null }, virtualScroll: { classPropertyName: "virtualScroll", publicName: "virtualScroll", isSignal: true, isRequired: false, transformFunction: null }, validators: { classPropertyName: "validators", publicName: "validators", isSignal: true, isRequired: false, transformFunction: null }, multiple: { classPropertyName: "multiple", publicName: "multiple", isSignal: true, isRequired: false, transformFunction: null }, selectOptions: { classPropertyName: "selectOptions", publicName: "selectOptions", isSignal: true, isRequired: false, transformFunction: null }, panelWidth: { classPropertyName: "panelWidth", publicName: "panelWidth", isSignal: true, isRequired: false, transformFunction: null } }, host: { classAttribute: "ngm-select" }, providers: [
            {
                provide: NG_VALUE_ACCESSOR,
                multi: true,
                useExisting: forwardRef(() => NgmSelectComponent)
            }
        ], queries: [{ propertyName: "_explicitContent", first: true, predicate: NgmOptionContent, descendants: true, read: TemplateRef, static: true }], usesInheritance: true, ngImport: i0, template: "@if (label) {\n  <label class=\"ngm-select-label shrink-0\" [title]=\"label\">\n    {{label}}\n  </label>\n}\n\n@if (!searchable()) {\n  <div class=\"relative\">\n    <mat-select class=\"ngm-select-element relative\" [panelClass]=\"'ngm-select-panel ' + (displayDensity==='compact' ? 'ngm-density__compact' : '') + ' ' + (displayDensity==='cosy' ? 'ngm-density__cosy' : '')\"\n      [formControl]=\"formControl\"\n      [placeholder]=\"placeholder\"\n      [panelWidth]=\"panelWidth() || 'auto'\"\n    >\n      <mat-select-trigger *ngIf=\"selectTrigger()\" class=\"flex items-center overflow-hidden\">\n        <span class=\"flex-1\">\n          {{selectTrigger().caption || selectTrigger().label || selectTrigger()[valueKey()] || placeholder}}\n        </span>\n      </mat-select-trigger>\n      @for (option of selectOptions(); track option[valueKey()]) {\n        <mat-option [value]=\"option[valueKey()]\">\n          <ng-container *ngTemplateOutlet=\"optionTemplate; context: {$implicit: option}\"></ng-container>\n        </mat-option>\n      }\n    </mat-select>\n\n    <div class=\"absolute right-6 top-0 h-full flex items-center\">\n      <ng-container *ngTemplateOutlet=\"suffixTemplate\"></ng-container>\n    </div>\n  </div>\n} @else {\n  <div class=\"relative\">\n    <input class=\"ngm-input-element w-full relative\"\n      type=\"text\"\n      [placeholder]=\"placeholder\"\n      matInput\n      [ngModel]=\"autoInput()\"\n      (ngModelChange)=\"onAutoInput($event)\"\n      [matAutocomplete]=\"auto\"\n    />\n  \n    <div class=\"absolute right-0 top-0 h-full flex items-center\">\n      <ng-container *ngTemplateOutlet=\"suffixTemplate\"></ng-container>\n    </div>\n  </div>\n}\n\n<mat-autocomplete autoActiveFirstOption #auto=\"matAutocomplete\" class=\"ngm-density__compact ngm-select__autocomplete-panel ngm-autocomplete-panel\"\n  [panelWidth]=\"panelWidth() || null\"\n  [displayWith]=\"displayWith\"\n  (optionSelected)=\"onOptionSelected($event)\"\n>\n  @if (virtualScroll()) {\n    <cdk-virtual-scroll-viewport class=\"nx-formly__virtual-scroll-viewport\" minBufferPx=\"200\" maxBufferPx=\"400\"\n      [style.height.px]=\"240\" [itemSize]=\"30\"\n    >\n      <mat-option *cdkVirtualFor=\"let option of options$(); trackBy: trackByValue\" [value]=\"option\">\n        <ng-container *ngTemplateOutlet=\"optionTemplate; context: {$implicit: option}\"></ng-container>\n      </mat-option>\n    </cdk-virtual-scroll-viewport>\n  } @else {\n    @for (option of options$(); track option.key) {\n      <mat-option [value]=\"option\" class=\"text-sm\">\n        <ng-container *ngTemplateOutlet=\"optionTemplate; context: {$implicit: option}\"></ng-container>\n      </mat-option>\n    }\n  }\n</mat-autocomplete>\n\n<mat-error class=\"text-xs h-4\">\n  @if (formControl.invalid) {\n    <span>{{formControl.getError('error')}}</span>\n  }\n  <ng-content select=\"[ngmError]\"></ng-content>\n</mat-error>\n\n<ng-template #optionTemplate let-option>\n  <ng-template [ngIf]=\"_explicitContent\" [ngIfElse]=\"optionTextLabel\">\n    <ng-container *ngTemplateOutlet=\"_explicitContent; context: {$implicit: option, value: option.value, caption: option.caption, key: option.key, highlight: highlight()}\"></ng-container>\n  </ng-template>\n  <ng-template #optionTextLabel>\n    @if (option.icon) {\n      <mat-icon [fontSet]=\"option.fontSet\">{{option.icon}}</mat-icon>\n    }\n    <ngm-display-behaviour class=\"flex-1 overflow-hidden\" [displayBehaviour]=\"displayBehaviour\"\n      [option]=\"option\"\n      [highlight]=\"highlight()\">\n    </ngm-display-behaviour>\n  </ng-template>\n</ng-template>\n\n<ng-template #suffixTemplate>\n  <ng-content select=\"[ngmSuffix]\"></ng-content>\n</ng-template>\n", styles: [":host{position:relative;display:flex;min-width:100px;flex-direction:column;align-items:stretch}:host.ngm-select-error .mat-mdc-select.ngm-select-element{border-color:var(--mdc-theme-error)}:host.ngm-select-error .ngm-input-element{border-color:var(--mdc-theme-error)}.mat-mdc-form-field-error{display:inline-flex;color:var(--mat-form-field-error-text-color)}:host::ng-deep .mat-mdc-select-placeholder{font-style:italic;opacity:.5}\n"], dependencies: [{ kind: "ngmodule", type: CommonModule }, { kind: "directive", type: i1.NgIf, selector: "[ngIf]", inputs: ["ngIf", "ngIfThen", "ngIfElse"] }, { kind: "directive", type: i1.NgTemplateOutlet, selector: "[ngTemplateOutlet]", inputs: ["ngTemplateOutletContext", "ngTemplateOutlet", "ngTemplateOutletInjector"] }, { kind: "ngmodule", type: FormsModule }, { kind: "directive", type: i2.DefaultValueAccessor, selector: "input:not([type=checkbox])[formControlName],textarea[formControlName],input:not([type=checkbox])[formControl],textarea[formControl],input:not([type=checkbox])[ngModel],textarea[ngModel],[ngDefaultControl]" }, { kind: "directive", type: i2.NgControlStatus, selector: "[formControlName],[ngModel],[formControl]" }, { kind: "directive", type: i2.NgModel, selector: "[ngModel]:not([formControlName]):not([formControl])", inputs: ["name", "disabled", "ngModel", "ngModelOptions"], outputs: ["ngModelChange"], exportAs: ["ngModel"] }, { kind: "ngmodule", type: ReactiveFormsModule }, { kind: "directive", type: i2.FormControlDirective, selector: "[formControl]", inputs: ["formControl", "disabled", "ngModel"], outputs: ["ngModelChange"], exportAs: ["ngForm"] }, { kind: "ngmodule", type: MatSelectModule }, { kind: "directive", type: i3.MatError, selector: "mat-error, [matError]", inputs: ["id"] }, { kind: "component", type: i4.MatSelect, selector: "mat-select", inputs: ["aria-describedby", "panelClass", "disabled", "disableRipple", "tabIndex", "hideSingleSelectionIndicator", "placeholder", "required", "multiple", "disableOptionCentering", "compareWith", "value", "aria-label", "aria-labelledby", "errorStateMatcher", "typeaheadDebounceInterval", "sortComparator", "id", "panelWidth"], outputs: ["openedChange", "opened", "closed", "selectionChange", "valueChange"], exportAs: ["matSelect"] }, { kind: "directive", type: i4.MatSelectTrigger, selector: "mat-select-trigger" }, { kind: "component", type: i5.MatOption, selector: "mat-option", inputs: ["value", "id", "disabled"], outputs: ["onSelectionChange"], exportAs: ["matOption"] }, { kind: "ngmodule", type: MatAutocompleteModule }, { kind: "component", type: i6.MatAutocomplete, selector: "mat-autocomplete", inputs: ["aria-label", "aria-labelledby", "displayWith", "autoActiveFirstOption", "autoSelectActiveOption", "requireSelection", "panelWidth", "disableRipple", "class", "hideSingleSelectionIndicator"], outputs: ["optionSelected", "opened", "closed", "optionActivated"], exportAs: ["matAutocomplete"] }, { kind: "directive", type: i6.MatAutocompleteTrigger, selector: "input[matAutocomplete], textarea[matAutocomplete]", inputs: ["matAutocomplete", "matAutocompletePosition", "matAutocompleteConnectedTo", "autocomplete", "matAutocompleteDisabled"], exportAs: ["matAutocompleteTrigger"] }, { kind: "ngmodule", type: MatInputModule }, { kind: "directive", type: i7.MatInput, selector: "input[matInput], textarea[matInput], select[matNativeControl],      input[matNativeControl], textarea[matNativeControl]", inputs: ["disabled", "id", "placeholder", "name", "required", "type", "errorStateMatcher", "aria-describedby", "value", "readonly"], exportAs: ["matInput"] }, { kind: "ngmodule", type: MatIconModule }, { kind: "component", type: i8.MatIcon, selector: "mat-icon", inputs: ["color", "inline", "svgIcon", "fontSet", "fontIcon"], exportAs: ["matIcon"] }, { kind: "ngmodule", type: ScrollingModule }, { kind: "directive", type: i9.CdkFixedSizeVirtualScroll, selector: "cdk-virtual-scroll-viewport[itemSize]", inputs: ["itemSize", "minBufferPx", "maxBufferPx"] }, { kind: "directive", type: i9.CdkVirtualForOf, selector: "[cdkVirtualFor][cdkVirtualForOf]", inputs: ["cdkVirtualForOf", "cdkVirtualForTrackBy", "cdkVirtualForTemplate", "cdkVirtualForTemplateCacheSize"] }, { kind: "component", type: i9.CdkVirtualScrollViewport, selector: "cdk-virtual-scroll-viewport", inputs: ["orientation", "appendOnly"], outputs: ["scrolledIndexChange"] }, { kind: "ngmodule", type: OcapCoreModule }, { kind: "component", type: NgmDisplayBehaviourComponent, selector: "ngm-display-behaviour", inputs: ["displayBehaviour", "excludeSelected", "option", "highlight"] }], changeDetection: i0.ChangeDetectionStrategy.OnPush }); }
}
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "17.3.10", ngImport: i0, type: NgmSelectComponent, decorators: [{
            type: Component,
            args: [{ standalone: true, selector: 'ngm-select', changeDetection: ChangeDetectionStrategy.OnPush, host: {
                        class: 'ngm-select'
                    }, providers: [
                        {
                            provide: NG_VALUE_ACCESSOR,
                            multi: true,
                            useExisting: forwardRef(() => NgmSelectComponent)
                        }
                    ], imports: [
                        CommonModule,
                        FormsModule,
                        ReactiveFormsModule,
                        MatSelectModule,
                        MatAutocompleteModule,
                        MatInputModule,
                        MatIconModule,
                        ScrollingModule,
                        OcapCoreModule,
                        NgmDisplayBehaviourComponent,
                        NgmOptionContent
                    ], template: "@if (label) {\n  <label class=\"ngm-select-label shrink-0\" [title]=\"label\">\n    {{label}}\n  </label>\n}\n\n@if (!searchable()) {\n  <div class=\"relative\">\n    <mat-select class=\"ngm-select-element relative\" [panelClass]=\"'ngm-select-panel ' + (displayDensity==='compact' ? 'ngm-density__compact' : '') + ' ' + (displayDensity==='cosy' ? 'ngm-density__cosy' : '')\"\n      [formControl]=\"formControl\"\n      [placeholder]=\"placeholder\"\n      [panelWidth]=\"panelWidth() || 'auto'\"\n    >\n      <mat-select-trigger *ngIf=\"selectTrigger()\" class=\"flex items-center overflow-hidden\">\n        <span class=\"flex-1\">\n          {{selectTrigger().caption || selectTrigger().label || selectTrigger()[valueKey()] || placeholder}}\n        </span>\n      </mat-select-trigger>\n      @for (option of selectOptions(); track option[valueKey()]) {\n        <mat-option [value]=\"option[valueKey()]\">\n          <ng-container *ngTemplateOutlet=\"optionTemplate; context: {$implicit: option}\"></ng-container>\n        </mat-option>\n      }\n    </mat-select>\n\n    <div class=\"absolute right-6 top-0 h-full flex items-center\">\n      <ng-container *ngTemplateOutlet=\"suffixTemplate\"></ng-container>\n    </div>\n  </div>\n} @else {\n  <div class=\"relative\">\n    <input class=\"ngm-input-element w-full relative\"\n      type=\"text\"\n      [placeholder]=\"placeholder\"\n      matInput\n      [ngModel]=\"autoInput()\"\n      (ngModelChange)=\"onAutoInput($event)\"\n      [matAutocomplete]=\"auto\"\n    />\n  \n    <div class=\"absolute right-0 top-0 h-full flex items-center\">\n      <ng-container *ngTemplateOutlet=\"suffixTemplate\"></ng-container>\n    </div>\n  </div>\n}\n\n<mat-autocomplete autoActiveFirstOption #auto=\"matAutocomplete\" class=\"ngm-density__compact ngm-select__autocomplete-panel ngm-autocomplete-panel\"\n  [panelWidth]=\"panelWidth() || null\"\n  [displayWith]=\"displayWith\"\n  (optionSelected)=\"onOptionSelected($event)\"\n>\n  @if (virtualScroll()) {\n    <cdk-virtual-scroll-viewport class=\"nx-formly__virtual-scroll-viewport\" minBufferPx=\"200\" maxBufferPx=\"400\"\n      [style.height.px]=\"240\" [itemSize]=\"30\"\n    >\n      <mat-option *cdkVirtualFor=\"let option of options$(); trackBy: trackByValue\" [value]=\"option\">\n        <ng-container *ngTemplateOutlet=\"optionTemplate; context: {$implicit: option}\"></ng-container>\n      </mat-option>\n    </cdk-virtual-scroll-viewport>\n  } @else {\n    @for (option of options$(); track option.key) {\n      <mat-option [value]=\"option\" class=\"text-sm\">\n        <ng-container *ngTemplateOutlet=\"optionTemplate; context: {$implicit: option}\"></ng-container>\n      </mat-option>\n    }\n  }\n</mat-autocomplete>\n\n<mat-error class=\"text-xs h-4\">\n  @if (formControl.invalid) {\n    <span>{{formControl.getError('error')}}</span>\n  }\n  <ng-content select=\"[ngmError]\"></ng-content>\n</mat-error>\n\n<ng-template #optionTemplate let-option>\n  <ng-template [ngIf]=\"_explicitContent\" [ngIfElse]=\"optionTextLabel\">\n    <ng-container *ngTemplateOutlet=\"_explicitContent; context: {$implicit: option, value: option.value, caption: option.caption, key: option.key, highlight: highlight()}\"></ng-container>\n  </ng-template>\n  <ng-template #optionTextLabel>\n    @if (option.icon) {\n      <mat-icon [fontSet]=\"option.fontSet\">{{option.icon}}</mat-icon>\n    }\n    <ngm-display-behaviour class=\"flex-1 overflow-hidden\" [displayBehaviour]=\"displayBehaviour\"\n      [option]=\"option\"\n      [highlight]=\"highlight()\">\n    </ngm-display-behaviour>\n  </ng-template>\n</ng-template>\n\n<ng-template #suffixTemplate>\n  <ng-content select=\"[ngmSuffix]\"></ng-content>\n</ng-template>\n", styles: [":host{position:relative;display:flex;min-width:100px;flex-direction:column;align-items:stretch}:host.ngm-select-error .mat-mdc-select.ngm-select-element{border-color:var(--mdc-theme-error)}:host.ngm-select-error .ngm-input-element{border-color:var(--mdc-theme-error)}.mat-mdc-form-field-error{display:inline-flex;color:var(--mat-form-field-error-text-color)}:host::ng-deep .mat-mdc-select-placeholder{font-style:italic;opacity:.5}\n"] }]
        }], ctorParameters: () => [{ type: i0.ElementRef }], propDecorators: { displayBehaviour: [{
                type: Input
            }], displayDensity: [{
                type: Input
            }], label: [{
                type: Input
            }], placeholder: [{
                type: Input
            }], _explicitContent: [{
                type: ContentChild,
                args: [NgmOptionContent, { read: TemplateRef, static: true }]
            }] } });
//# sourceMappingURL=data:application/json;base64, 