import * as i0 from '@angular/core';
import { inject, input, viewChild, Component } from '@angular/core';
import * as i1 from '@angular/forms';
import { FormControl, FormsModule, ReactiveFormsModule } from '@angular/forms';
import { Autocomplete, AutocompleteTrigger } from '@ngstarter-ui/components/autocomplete';
import { Option } from '@ngstarter-ui/components/option';
import { ChipGrid, ChipInput, ChipRemove, ChipRow } from '@ngstarter-ui/components/chips';
import { ENTER, COMMA } from '@angular/cdk/keycodes';
import { Error, FormField, Hint, Label } from '@ngstarter-ui/components/form-field';
import { Icon } from '@ngstarter-ui/components/icon';
import { startWith, tap, debounceTime, distinctUntilChanged, switchMap, of } from 'rxjs';
import { ProgressSpinner } from '@ngstarter-ui/components/spinner';
import { AsyncPipe } from '@angular/common';
import { HttpClient, HttpParams } from '@angular/common/http';

class AutocompleteManyField {
    httpClient = inject(HttpClient);
    control = input.required(...(ngDevMode ? [{ debugName: "control" }] : /* istanbul ignore next */ []));
    config = input.required(...(ngDevMode ? [{ debugName: "config" }] : /* istanbul ignore next */ []));
    separatorKeysCodes = [ENTER, COMMA];
    chipsCtrl = new FormControl('');
    input = viewChild.required('input');
    value = [];
    filteredOptions$;
    isLoading = false;
    ngOnInit() {
        this.filteredOptions$ = this.chipsCtrl.valueChanges.pipe(startWith(''), tap(() => this.isLoading = true), debounceTime(300), distinctUntilChanged(), switchMap((query) => {
            if (!query || !query.trim()) {
                return of([]);
            }
            const params = new HttpParams().set('query', query || '');
            return this.httpClient.get(this.config().payload?.['autocompleteUrl'], {
                params
            });
        }), tap(() => this.isLoading = false));
    }
    getErrorMessage() {
        const errors = this.control().errors;
        if (!errors) {
            return '';
        }
        const errorKey = Object.keys(errors)[0];
        const validator = this.config().validators?.find((v) => v.type === errorKey);
        return validator?.message || 'Некорректное значение';
    }
    get options() {
        return this.config()?.payload?.['options'] || [];
    }
    get bindValue() {
        return this.config().bindValue || 'id';
    }
    get bindName() {
        return this.config().bindName || 'name';
    }
    add(event) {
        const name = (event.value || '').trim();
        const hasValue = this.value.find(v => v[this.bindName].toLowerCase() === name.toLowerCase());
        if (name && !hasValue) {
            this.value.push({
                [this.bindValue]: null,
                [this.bindName]: name,
            });
        }
        event.chipInput.clear();
        this.chipsCtrl.setValue(null);
        this.isLoading = false;
        this.calculateControlValue();
    }
    remove(chip) {
        const index = this.value.indexOf(chip);
        if (index >= 0) {
            this.value.splice(index, 1);
            this.calculateControlValue();
        }
    }
    onSelected(event) {
        const hasValue = this.value.find(v => v[this.bindName].toLowerCase() === event.option.value[this.bindName].toLowerCase());
        if (!hasValue) {
            this.value.push(event.option.value);
        }
        this.input().nativeElement.value = '';
        this.chipsCtrl.setValue(null);
        this.calculateControlValue();
        this.isLoading = false;
    }
    calculateControlValue() {
        const value = this.value.map(v => {
            const itemValue = v[this.bindValue];
            if (itemValue) {
                return {
                    [this.bindValue]: itemValue,
                };
            }
            return v;
        });
        this.control().setValue(value);
    }
    static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "21.2.4", ngImport: i0, type: AutocompleteManyField, deps: [], target: i0.ɵɵFactoryTarget.Component });
    static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "21.2.4", type: AutocompleteManyField, isStandalone: true, selector: "ngs-autocomplete-many-field", inputs: { control: { classPropertyName: "control", publicName: "control", isSignal: true, isRequired: true, transformFunction: null }, config: { classPropertyName: "config", publicName: "config", isSignal: true, isRequired: true, transformFunction: null } }, viewQueries: [{ propertyName: "input", first: true, predicate: ["input"], descendants: true, isSignal: true }], ngImport: i0, template: "@if (control() && config()) {\n  <ngs-form-field>\n    <ngs-label>{{ config().label }}</ngs-label>\n    <ngs-chip-grid #chipGrid>\n      @for (option of value; track option) {\n        <ngs-chip-row (removed)=\"remove(option)\">\n          {{ option[bindName] }}\n          <button ngsChipRemove>\n            <ngs-icon name=\"fluent:dismiss-circle-24-regular\"/>\n          </button>\n        </ngs-chip-row>\n      }\n    </ngs-chip-grid>\n    <input [placeholder]=\"config().placeholder\"\n           #input\n           maxlength=\"30\"\n           [formControl]=\"chipsCtrl\"\n           [ngsChipInputFor]=\"chipGrid\"\n           [ngsAutocomplete]=\"autocomplete\"\n           [ngsChipInputSeparatorKeyCodes]=\"separatorKeysCodes\"\n           (chipInputTokenEnd)=\"add($event)\">\n    @if (isLoading) {\n      <div class=\"loader\">\n        <ngs-progress-spinner\n          mode=\"indeterminate\"\n          [diameter]=\"20\"/>\n      </div>\n    }\n    <ngs-autocomplete #autocomplete=\"ngsAutocomplete\" (optionSelected)=\"onSelected($event)\">\n      @for (option of filteredOptions$ | async; track option) {\n        <ngs-option [value]=\"option\">{{ option[bindName] }}</ngs-option>\n      }\n\n      @if (!(filteredOptions$ | async)?.length && !isLoading && chipsCtrl.value) {\n        <ngs-option disabled>\n          No search results found.\n        </ngs-option>\n      }\n    </ngs-autocomplete>\n    <ngs-hint>{{ config().hint }}</ngs-hint>\n    @if (control().invalid && control().touched) {\n      <ngs-error>{{ getErrorMessage() }}</ngs-error>\n    }\n  </ngs-form-field>\n}\n", styles: [":host{display:block}:host ngs-form-field{width:100%}:host .loader{position:absolute;right:0;top:50%;transform:translateY(-50%)}\n/*! tailwindcss v4.2.2 | MIT License | https://tailwindcss.com */\n"], dependencies: [{ kind: "ngmodule", type: FormsModule }, { kind: "directive", type: i1.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: i1.NgControlStatus, selector: "[formControlName],[ngModel],[formControl]" }, { kind: "directive", type: i1.MaxLengthValidator, selector: "[maxlength][formControlName],[maxlength][formControl],[maxlength][ngModel]", inputs: ["maxlength"] }, { kind: "component", type: Autocomplete, selector: "ngs-autocomplete", inputs: ["aria-label", "aria-labelledby", "autoActiveFirstOption", "autoSelectActiveOption", "class", "disableRipple", "displayWith", "hideSingleSelectionIndicator", "panelWidth", "requireSelection"], outputs: ["closed", "opened", "optionActivated", "optionSelected"], exportAs: ["ngsAutocomplete"] }, { kind: "directive", type: AutocompleteTrigger, selector: "[ngsAutocomplete]", inputs: ["ngsAutocomplete"], exportAs: ["ngsAutocompleteTrigger"] }, { kind: "component", type: ChipGrid, selector: "ngs-chip-grid", inputs: ["id", "placeholder", "required", "disabled"], outputs: ["valueChange"] }, { kind: "directive", type: ChipInput, selector: "input[ngsChipInputFor]", inputs: ["ngsChipInputFor", "ngsChipInputSeparatorKeyCodes", "ngsChipInputAddOnBlur"], outputs: ["chipInputTokenEnd"] }, { kind: "directive", type: ChipRemove, selector: "ngs-chip-remove, [ngsChipRemove]" }, { kind: "component", type: ChipRow, selector: "ngs-chip-row", inputs: ["editable"], outputs: ["edited"] }, { kind: "component", type: Error, selector: "ngs-error" }, { kind: "component", type: FormField, selector: "ngs-form-field", inputs: ["subscriptHiddenIfEmpty"], exportAs: ["ngsFormField"] }, { kind: "component", type: Hint, selector: "ngs-hint", inputs: ["align"] }, { kind: "component", type: Icon, selector: "ngs-icon", inputs: ["name"], exportAs: ["ngsIcon"] }, { kind: "component", type: Label, selector: "ngs-label" }, { kind: "component", type: Option, selector: "ngs-option", inputs: ["value", "disabled", "selected"], outputs: ["onSelectionChange"], exportAs: ["ngsOption"] }, { kind: "ngmodule", type: ReactiveFormsModule }, { kind: "directive", type: i1.FormControlDirective, selector: "[formControl]", inputs: ["formControl", "disabled", "ngModel"], outputs: ["ngModelChange"], exportAs: ["ngForm"] }, { kind: "component", type: ProgressSpinner, selector: "ngs-progress-spinner", inputs: ["color", "mode", "value", "diameter", "strokeWidth"], exportAs: ["ngsProgressSpinner"] }, { kind: "pipe", type: AsyncPipe, name: "async" }] });
}
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.4", ngImport: i0, type: AutocompleteManyField, decorators: [{
            type: Component,
            args: [{ selector: 'ngs-autocomplete-many-field', imports: [
                        FormsModule,
                        Autocomplete,
                        AutocompleteTrigger,
                        ChipGrid,
                        ChipInput,
                        ChipRemove,
                        ChipRow,
                        Error,
                        FormField,
                        Hint,
                        Icon,
                        Label,
                        Option,
                        ReactiveFormsModule,
                        ProgressSpinner,
                        AsyncPipe
                    ], template: "@if (control() && config()) {\n  <ngs-form-field>\n    <ngs-label>{{ config().label }}</ngs-label>\n    <ngs-chip-grid #chipGrid>\n      @for (option of value; track option) {\n        <ngs-chip-row (removed)=\"remove(option)\">\n          {{ option[bindName] }}\n          <button ngsChipRemove>\n            <ngs-icon name=\"fluent:dismiss-circle-24-regular\"/>\n          </button>\n        </ngs-chip-row>\n      }\n    </ngs-chip-grid>\n    <input [placeholder]=\"config().placeholder\"\n           #input\n           maxlength=\"30\"\n           [formControl]=\"chipsCtrl\"\n           [ngsChipInputFor]=\"chipGrid\"\n           [ngsAutocomplete]=\"autocomplete\"\n           [ngsChipInputSeparatorKeyCodes]=\"separatorKeysCodes\"\n           (chipInputTokenEnd)=\"add($event)\">\n    @if (isLoading) {\n      <div class=\"loader\">\n        <ngs-progress-spinner\n          mode=\"indeterminate\"\n          [diameter]=\"20\"/>\n      </div>\n    }\n    <ngs-autocomplete #autocomplete=\"ngsAutocomplete\" (optionSelected)=\"onSelected($event)\">\n      @for (option of filteredOptions$ | async; track option) {\n        <ngs-option [value]=\"option\">{{ option[bindName] }}</ngs-option>\n      }\n\n      @if (!(filteredOptions$ | async)?.length && !isLoading && chipsCtrl.value) {\n        <ngs-option disabled>\n          No search results found.\n        </ngs-option>\n      }\n    </ngs-autocomplete>\n    <ngs-hint>{{ config().hint }}</ngs-hint>\n    @if (control().invalid && control().touched) {\n      <ngs-error>{{ getErrorMessage() }}</ngs-error>\n    }\n  </ngs-form-field>\n}\n", styles: [":host{display:block}:host ngs-form-field{width:100%}:host .loader{position:absolute;right:0;top:50%;transform:translateY(-50%)}\n/*! tailwindcss v4.2.2 | MIT License | https://tailwindcss.com */\n"] }]
        }], propDecorators: { control: [{ type: i0.Input, args: [{ isSignal: true, alias: "control", required: true }] }], config: [{ type: i0.Input, args: [{ isSignal: true, alias: "config", required: true }] }], input: [{ type: i0.ViewChild, args: ['input', { isSignal: true }] }] } });

export { AutocompleteManyField };
//# sourceMappingURL=ngstarter-ui-components-form-renderer-autocomplete-many-field-BKQVlZHV.mjs.map
