import * as i5 from '@angular/cdk/overlay';
import { OverlayModule } from '@angular/cdk/overlay';
import * as i3 from '@angular/cdk/scrolling';
import { ScrollingModule } from '@angular/cdk/scrolling';
import * as i1 from '@angular/common';
import { CommonModule } from '@angular/common';
import * as i0 from '@angular/core';
import { input, model, output, Component, signal, computed, viewChild, inject, forwardRef } from '@angular/core';
import { takeUntilDestroyed } from '@angular/core/rxjs-interop';
import * as i2 from '@angular/forms';
import { FormGroup, FormControl, NG_VALUE_ACCESSOR, ReactiveFormsModule } from '@angular/forms';
import * as i4 from '@ngx-translate/core';
import { TranslateService, TranslateModule } from '@ngx-translate/core';
import { CheckboxComponent } from '@seniorsistemas/angular-components/checkbox';
import { debounceTime, distinctUntilChanged } from 'rxjs/operators';

class SelectOptionComponent {
    id = input.required();
    label = input.required();
    multiple = input.required();
    checkmark = input.required();
    isGrouper = input.required();
    isFocused = input.required();
    isSelected = model.required();
    selected = output();
    onClick() {
        if (this.isGrouper()) {
            return;
        }
        this.selected.emit();
    }
    static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "18.2.14", ngImport: i0, type: SelectOptionComponent, deps: [], target: i0.ɵɵFactoryTarget.Component });
    static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "18.2.14", type: SelectOptionComponent, isStandalone: true, selector: "s-select-option", inputs: { id: { classPropertyName: "id", publicName: "id", isSignal: true, isRequired: true, transformFunction: null }, label: { classPropertyName: "label", publicName: "label", isSignal: true, isRequired: true, transformFunction: null }, multiple: { classPropertyName: "multiple", publicName: "multiple", isSignal: true, isRequired: true, transformFunction: null }, checkmark: { classPropertyName: "checkmark", publicName: "checkmark", isSignal: true, isRequired: true, transformFunction: null }, isGrouper: { classPropertyName: "isGrouper", publicName: "isGrouper", isSignal: true, isRequired: true, transformFunction: null }, isFocused: { classPropertyName: "isFocused", publicName: "isFocused", isSignal: true, isRequired: true, transformFunction: null }, isSelected: { classPropertyName: "isSelected", publicName: "isSelected", isSignal: true, isRequired: true, transformFunction: null } }, outputs: { isSelected: "isSelectedChange", selected: "selected" }, ngImport: i0, template: "<li\n    [attr.id]=\"id()\"\n    class=\"flex select-none items-center gap-3 px-3 py-2\"\n    [class.hover:bg-grayscale-10]=\"!isGrouper()\"\n    [class.bg-grayscale-10]=\"!isGrouper() && isFocused()\"\n    (click)=\"onClick()\"\n>\n    @if (!isGrouper() && checkmark() && !multiple() && isSelected()) {\n        <i class=\"far fa-check text-grayscale-60\"></i>\n    }\n\n    @if (!isGrouper() && multiple()) {\n        <s-checkbox [checked]=\"isSelected()\"></s-checkbox>\n    }\n    <span\n        class=\"text-grayscale-90\"\n        [class.font-bold]=\"isGrouper()\"\n    >\n        {{ label() }}\n    </span>\n</li>\n", dependencies: [{ kind: "ngmodule", type: CommonModule }, { kind: "component", type: CheckboxComponent, selector: "s-checkbox", inputs: ["disabled", "checked", "indeterminate", "label"], outputs: ["disabledChange", "checkedChange", "indeterminateChange"] }] });
}
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "18.2.14", ngImport: i0, type: SelectOptionComponent, decorators: [{
            type: Component,
            args: [{ selector: 's-select-option', standalone: true, imports: [CommonModule, CheckboxComponent], template: "<li\n    [attr.id]=\"id()\"\n    class=\"flex select-none items-center gap-3 px-3 py-2\"\n    [class.hover:bg-grayscale-10]=\"!isGrouper()\"\n    [class.bg-grayscale-10]=\"!isGrouper() && isFocused()\"\n    (click)=\"onClick()\"\n>\n    @if (!isGrouper() && checkmark() && !multiple() && isSelected()) {\n        <i class=\"far fa-check text-grayscale-60\"></i>\n    }\n\n    @if (!isGrouper() && multiple()) {\n        <s-checkbox [checked]=\"isSelected()\"></s-checkbox>\n    }\n    <span\n        class=\"text-grayscale-90\"\n        [class.font-bold]=\"isGrouper()\"\n    >\n        {{ label() }}\n    </span>\n</li>\n" }]
        }] });

class SelectComponent {
    static nextId = 0;
    placeholder = input('');
    multiple = input(false);
    options = input.required();
    optionLabel = input();
    optionValue = input();
    showClear = input(false);
    filter = input(false);
    checkmark = input(false);
    filterBy = input();
    group = input(false);
    virtualScroll = input(false);
    virtualScrollItemSize = input(37);
    emptyMessage = input(null);
    disabled = model(false);
    showOptions = model(false);
    value = signal(null);
    values = signal([]);
    filterValue = signal('');
    focusedIndex = signal(-1);
    componentId = `select${SelectComponent.nextId++}`;
    /**
     * Computed que indica se todas as opções filtradas estão selecionadas.
     * Retorna `true` se todas as opções disponíveis (excluindo agrupadores) estiverem presentes
     * na lista de valores selecionados, e `false` caso contrário.
     * @returns {boolean} `true` se todas as opções filtradas estão selecionadas, `false` caso contrário.
     */
    allSelected = computed(() => {
        const options = this.filteredOptions().filter((option) => !option.grouper);
        const selectedIds = this.values().map((option) => option.id);
        const ret = options.length > 0 && options.every((option) => selectedIds.includes(option.id));
        return ret;
    });
    /**
     * Retorna o item atualmente focado na lista de opções filtradas.
     * @returns O dado do item focado ou `null` caso nenhum item esteja focado.
     */
    focusedItem = computed(() => this.filteredOptions().at(this.focusedIndex())?.data ?? null);
    /**
     * Computa e retorna a lista interna de opções do dropdown.
     * - Se as opções estiverem agrupadas (`group()` retorna verdadeiro),
     *   utiliza `_grouperToFlat` para transformar as opções agrupadas em uma lista plana.
     * - Caso contrário, retorna as opções com IDs adicionados.
     * @returns Um array de `InternalDropdownOption<T>` representando as opções disponíveis para o componente select.
     */
    internalOptions = computed(() => {
        const opts = this.options();
        const optionsWithId = this._addIdToOptions(opts);
        return this.group() ? this._grouperToFlat(optionsWithId) : optionsWithId;
    });
    /**
     * Retorna uma string representando a seleção atual do componente.
     * - Se o modo múltiplo estiver ativado e mais de um item estiver selecionado,
     *   retorna uma mensagem traduzida indicando o número total de registros selecionados.
     * - Se apenas um item estiver selecionado, retorna o rótulo desse item.
     * - Se o modo múltiplo não estiver ativado, retorna o rótulo do item selecionado ou uma string vazia caso nenhum item esteja selecionado.
     * @returns {string} Texto representando a seleção atual.
     */
    print = computed(() => {
        if (this.multiple()) {
            const selected = this.values();
            if (selected.length > 1) {
                return this._translateService.instant(`platform.angular_components.total_records_selected`, {
                    count: selected.length,
                });
            }
            else if (selected.length === 1) {
                return this._getLabelFromOption(selected[0].data);
            }
        }
        else {
            const selected = this.value();
            return selected ? this._getLabelFromOption(selected.data) : '';
        }
        return '';
    });
    /**
     * Indica se o seletor está "limpo", ou seja, sem nenhum valor selecionado.
     * - No modo múltiplo (`multiple`), retorna `true` se não houver nenhum valor selecionado (`values` está vazio).
     * - No modo simples, retorna `true` se não houver valor selecionado (`value` é falsy).
     * @returns `true` se não houver seleção, `false` caso contrário.
     */
    isClean = computed(() => {
        return this.multiple() ? !this.values().length : !this.value();
    });
    /**
     * Computed que indica se o estado de seleção "Selecionar Todos" está indeterminado.
     * Retorna `true` quando nem todos os itens filtrados estão selecionados e nem todos estão desmarcados,
     * ou seja, quando há uma seleção parcial dos itens disponíveis.
     * @returns {boolean} `true` se a seleção for parcial, `false` caso contrário.
     */
    selectAllIsIndeterminate = computed(() => {
        const selected = this.internalOptions().filter((option) => {
            return this.values().some((o) => o.id === option.id);
        });
        const options = this.filteredOptions().filter((option) => !option.grouper);
        const all = options.length > 0 && options.every((option) => selected.includes(option));
        const none = options.every((option) => !selected.includes(option));
        return !all && !none;
    });
    /**
     * Retorna uma lista de opções filtradas com base no valor de busca (`filterValue`) e nos critérios definidos.
     * - Se o filtro estiver desabilitado ou o valor de busca estiver vazio, retorna todas as opções.
     * - Caso contrário, filtra as opções utilizando o(s) campo(s) especificado(s) em `filterBy`.
     * - Ignora opções que possuem a propriedade `grouper` definida.
     * @returns As opções filtradas conforme o valor de busca e critérios de filtro.
     */
    filteredOptions = computed(() => {
        const allOptions = this.internalOptions();
        const search = this.filterValue().toLowerCase().trim();
        if (!this.filter() || !search) {
            return allOptions;
        }
        const filterBy = this.filterBy();
        return allOptions.filter((option) => {
            if (option.grouper) {
                return false;
            }
            let label = '';
            const optionLabel = this.optionLabel();
            if (!filterBy) {
                label = optionLabel ? String(option.data[optionLabel]) : String(option.data);
            }
            else if (Array.isArray(filterBy)) {
                label = filterBy.map((by) => String(option.data[by] ?? '')).join(' ');
            }
            else {
                label = String(option.data[filterBy] ?? '');
            }
            return label.toLowerCase().includes(search);
        });
    });
    filterForm = new FormGroup({
        filter: new FormControl('', { nonNullable: true }),
    });
    _containerDiv = viewChild('containerDiv');
    _onChange = () => { };
    _onTouched = () => { };
    _translateService = inject(TranslateService);
    constructor() {
        this.filterForm
            .get('filter')
            .valueChanges.pipe(debounceTime(300), distinctUntilChanged(), takeUntilDestroyed())
            .subscribe((value) => {
            this.filterValue.set(value);
        });
    }
    ngOnInit() {
        this._validateInputs();
    }
    /**
     * Define o valor selecionado do componente select.
     * @param value O valor a ser definido. Pode ser um objeto do tipo `T`, um array de `T` (quando múltipla seleção está habilitada), ou `null`.
     * @throws Se o modo múltiplo estiver ativado e o valor não for um array, lança um erro.
     * @throws Se o modo múltiplo estiver desativado e o valor for um array, lança um erro.
     * Este método mapeia o(s) valor(es) fornecido(s) para as opções internas do componente,
     * garantindo que apenas opções válidas sejam selecionadas conforme o modo de seleção (único ou múltiplo).
     */
    writeValue(value) {
        if (value && this.multiple()) {
            if (Array.isArray(value)) {
                const mapped = value
                    .map((val) => {
                    return this.internalOptions().find((option) => {
                        return JSON.stringify(option.data) === JSON.stringify(val);
                    });
                })
                    .filter((option) => !!option);
                this.values.set(mapped);
            }
            else {
                throw new Error('Value must be an array when "multiple" is true.');
            }
        }
        else {
            const optionValue = this.optionValue();
            let mapped = null;
            if (Array.isArray(value)) {
                throw new Error('Value must not be an array when "multiple" is false.');
            }
            if (optionValue && value) {
                mapped =
                    this.internalOptions().find((option) => option.data[optionValue] === value[optionValue]) ?? null;
            }
            else {
                mapped =
                    this.internalOptions().find((option) => JSON.stringify(option.data) === JSON.stringify(value)) ??
                        null;
            }
            this.value.set(mapped ?? null);
        }
    }
    /**
     * Registra uma função de callback que será chamada sempre que o valor do componente mudar.
     * @param onChange Função de callback que recebe o novo valor selecionado ou null.
     */
    registerOnChange(onChange) {
        this._onChange = onChange;
    }
    /**
     * Registra uma função de callback que será chamada quando o componente for tocado (perder o foco).
     * @param onTouched Função de callback a ser executada quando o componente for marcado como "tocado".
     */
    registerOnTouched(onTouched) {
        this._onTouched = onTouched;
    }
    /**
     * Define o estado de desabilitado do componente.
     * @param disabled Indica se o componente deve ser desabilitado (`true`) ou habilitado (`false`).
     */
    setDisabledState(disabled) {
        this.disabled.set(disabled);
    }
    /**
     * Alterna a exibição das opções do componente select.
     * Se o componente estiver desabilitado, não realiza nenhuma ação.
     * Caso contrário, inverte o estado de exibição das opções.
     */
    toggle() {
        if (this.disabled()) {
            return;
        }
        const shouldOpen = !this.showOptions();
        this.showOptions.set(shouldOpen);
    }
    /**
     * Seleciona um item no componente de seleção.
     * @param item O item a ser selecionado ou desmarcado.
     * Se o componente estiver desabilitado, a função retorna imediatamente.
     * No modo múltiplo, adiciona ou remove o item da lista de valores selecionados.
     * No modo simples, define o item como valor selecionado e fecha o dropdown.
     * Sempre notifica as mudanças e marca o componente como tocado.
     */
    selectItem(item) {
        if (this.disabled()) {
            return;
        }
        const optionValue = this.optionValue();
        if (this.multiple()) {
            const store = [...this.values()];
            const index = store.findIndex((selectedItem) => {
                return selectedItem === item;
            });
            if (index !== -1) {
                store.splice(index, 1);
            }
            else {
                store.push(item);
            }
            this.values.set(store);
            const result = optionValue ? store.map((item) => item.data[optionValue]) : store;
            this._onChange(result);
        }
        else {
            this.value.set(item);
            const result = optionValue ? item.data[optionValue] : item.data;
            this._onChange(result);
            this._closeDropdown();
        }
        this._onTouched();
    }
    /**
     * Limpa o valor selecionado no componente select.
     * Se o componente estiver desabilitado, não executa nenhuma ação.
     * Para seleção múltipla, remove todos os valores selecionados e notifica a alteração.
     * Para seleção única, define o valor como nulo e notifica a alteração.
     * Fecha o dropdown e marca o componente como "tocado".
     * Impede a propagação do evento do mouse.
     * @param event Evento do mouse que acionou a limpeza da seleção.
     */
    clear(event) {
        if (this.disabled()) {
            return;
        }
        if (this.multiple()) {
            this.values.set([]);
            this._onChange(this.values());
        }
        else {
            this.value.set(null);
            this._onChange(this.value());
        }
        this._closeDropdown();
        this._onTouched();
        event.stopPropagation();
    }
    /**
     * Limpa o filtro do formulário, resetando o campo 'filter' do formulário de filtro.
     * Este método redefine o valor do campo 'filter' para seu estado inicial,
     * removendo qualquer texto ou valor previamente inserido pelo usuário.
     */
    clearFilter() {
        this.filterForm.get('filter')?.reset();
    }
    /**
     * Manipula o evento de redimensionamento da janela.
     * Fecha o dropdown de opções caso ele esteja visível ao redimensionar a janela.
     * @param _ Evento de redimensionamento da janela (não utilizado).
     */
    onWindowResize(_) {
        if (this.showOptions()) {
            this._closeDropdown();
        }
    }
    /**
     * Manipula o evento de clique no elemento container da seleção.
     * Este método alterna o estado de exibição do componente select e,
     * em seguida, define o foco no elemento container correspondente.
     */
    onContainerDivClick() {
        this.toggle();
        this._containerDiv()?.nativeElement.focus();
    }
    /**
     * Manipula eventos de teclado para navegação e seleção de opções no componente select.
     * - 'ArrowDown': Move o foco para a próxima opção disponível.
     * - 'ArrowUp': Move o foco para a opção anterior.
     * - 'Tab': Seleciona a opção atualmente focada e fecha o dropdown.
     * - 'Enter': Seleciona a opção focada se o dropdown estiver aberto, ou alterna a abertura do dropdown.
     * - 'Escape': Fecha o dropdown.
     * - ' ': (barra de espaço) Seleciona a opção focada se o dropdown estiver aberto, ou alterna a abertura do dropdown.
     * Previne o comportamento padrão do navegador quando necessário para garantir a navegação adequada pelo teclado.
     * @param event O evento de teclado disparado pelo usuário.
     */
    onKeyDown(event) {
        const options = this.filteredOptions();
        if (!options.length) {
            return;
        }
        const _selectOption = () => {
            if (this.focusedIndex() >= 0 && this.focusedIndex() < options.length) {
                event.preventDefault();
                this.selectItem(options[this.focusedIndex()]);
            }
        };
        switch (event.key) {
            case 'ArrowDown':
                event.preventDefault();
                this._focusNextOption(options);
                break;
            case 'ArrowUp':
                event.preventDefault();
                this._focusPreviousOption(options);
                break;
            case 'Tab':
                _selectOption();
                this._closeDropdown();
                break;
            case 'Enter':
                if (this.showOptions()) {
                    _selectOption();
                }
                else {
                    this.toggle();
                }
                break;
            case 'Escape':
                this._closeDropdown();
                break;
            case ' ':
                event.preventDefault();
                if (this.showOptions()) {
                    _selectOption();
                }
                else {
                    this.toggle();
                }
                break;
        }
    }
    /**
     * Retorna o rótulo (label) associado a uma opção fornecida.
     * @param option - A opção do tipo T para a qual o rótulo deve ser obtido.
     * @returns O rótulo da opção como uma string.
     */
    getOptionLabel(option) {
        return this._getLabelFromOption(option);
    }
    /**
     * Função de trackBy utilizada em diretivas *ngFor para otimizar a renderização de listas.
     * Retorna o identificador único (`id`) de cada item do tipo `InternalDropdownOption<T>`.
     * @param _ - Índice do item na lista (não utilizado).
     * @param item - O item atual da lista do tipo `InternalDropdownOption<T>`.
     * @returns O identificador único do item como uma string.
     */
    trackById(_, item) {
        return item.id;
    }
    /**
     * Verifica se a opção fornecida está selecionada.
     * @param option - A opção interna do dropdown a ser verificada.
     * @returns `true` se a opção estiver selecionada, caso contrário `false`.
     */
    isOptionSelected(option) {
        return (this.values().find((o) => {
            return o === option;
        }) !== undefined);
    }
    /**
     * Alterna a seleção de todos os itens disponíveis.
     * Se o modo múltiplo estiver ativado, seleciona todos os itens filtrados que não são agrupadores
     * caso nem todos estejam selecionados, ou limpa a seleção caso todos já estejam selecionados.
     * Após a alteração, notifica a mudança de valor.
     */
    toggleSelectAll() {
        if (!this.multiple()) {
            return;
        }
        const options = this.filteredOptions().filter((option) => !option.grouper);
        if (this.allSelected()) {
            this.values.set([]);
        }
        else {
            this.values.set(options);
        }
        this._onChange(this.values());
    }
    /**
     * Retorna o rótulo (label) de uma opção fornecida.
     * Este método utiliza a propriedade definida por `optionLabel` para extrair o valor do rótulo da opção.
     * Caso `optionLabel` não esteja definido, retorna a representação em string da própria opção.
     * @private
     * @param option A opção da qual o rótulo será extraído.
     * @returns O rótulo da opção como uma string.
     */
    _getLabelFromOption(option) {
        const optionLabel = this.optionLabel();
        return optionLabel ? String(option[optionLabel]) : String(option);
    }
    /**
     * Valida as entradas do componente de seleção.
     * Este método verifica se as opções fornecidas são válidas. Caso as opções sejam objetos,
     * garante que a propriedade `optionLabel` esteja definida, lançando um erro caso contrário.
     * Se não houver opções, a validação é ignorada.
     * @private
     * @throws {Error} Se as opções forem objetos e `optionLabel` não estiver definido.
     */
    _validateInputs() {
        const options = this.options();
        if (!options.length) {
            return;
        }
        const hasObjectOptions = options.some((option) => typeof option === 'object' && option !== null);
        if (hasObjectOptions) {
            if (!this.optionLabel()) {
                throw new Error('The "optionLabel" input is required when options are objects.');
            }
        }
    }
    /**
     * Fecha o dropdown de opções do componente select.
     * Este método oculta as opções disponíveis e redefine o índice do item focado para -1,
     * indicando que nenhum item está atualmente focado.
     * @private
     */
    _closeDropdown() {
        this.showOptions.set(false);
        this.focusedIndex.set(-1);
    }
    /**
     * Adiciona um identificador único a cada opção fornecida.
     * Para cada item no array de opções, gera um objeto `InternalDropdownOption` contendo o dado original
     * e um campo `id` único baseado no timestamp atual e no índice do item. Caso a opção seja um grupo
     * (detectado pela presença de um array `items`), adiciona também a propriedade `grouper: true`.
     * @private
     * @param options Array de opções do tipo `T` a serem processadas.
     * @returns Um array de objetos `InternalDropdownOption<T>` com identificadores únicos.
     */
    _addIdToOptions(options) {
        const timestamp = Date.now();
        return options.map((option, index) => {
            if (this.group() && Array.isArray(option.items)) {
                return {
                    data: option,
                    id: `id_${timestamp}_${index++}`,
                    grouper: true,
                };
            }
            return {
                data: option,
                id: `id_${timestamp}_${index++}`,
            };
        });
    }
    /**
     * Converte uma lista de opções possivelmente agrupadas em uma lista plana de opções.
     * Para cada opção que possui um agrupador (`grouper`) e um array de itens em `data.items`,
     * adiciona a opção do agrupador e, em seguida, adiciona cada item do grupo como uma nova opção
     * individual, atribuindo um `id` único para cada item do grupo.
     * Caso a opção não seja um agrupador, ela é adicionada diretamente ao resultado.
     * @private
     * @param options Lista de opções internas do dropdown, podendo conter agrupadores.
     * @returns Lista plana de opções, incluindo agrupadores e seus itens expandidos.
     */
    _grouperToFlat(options) {
        const result = [];
        options.forEach((option) => {
            if (option.grouper && Array.isArray(option.data.items)) {
                result.push(option);
                const groupItems = option.data.items.map((item, index) => ({
                    data: item,
                    id: `${option.id}_item_${index}`,
                }));
                result.push(...groupItems);
            }
            else {
                result.push(option);
            }
        });
        return result;
    }
    /**
     * Move o foco para a próxima opção disponível na lista, ignorando opções que sejam agrupadores.
     * @private
     * @param options Lista de opções internas do dropdown.
     */
    _focusNextOption(options) {
        let nextIndex = this.focusedIndex() + 1;
        while (nextIndex < options.length && options[nextIndex].grouper) {
            nextIndex++;
        }
        if (nextIndex < options.length) {
            this.focusedIndex.set(nextIndex);
            this._scrollToFocusedOption();
        }
    }
    /**
     * Move o foco para a opção anterior na lista, ignorando opções do tipo "grouper".
     * @private
     * @param options Lista de opções internas do dropdown.
     */
    _focusPreviousOption(options) {
        let prevIndex = this.focusedIndex() - 1;
        while (prevIndex >= 0 && options[prevIndex].grouper) {
            prevIndex--;
        }
        if (prevIndex >= 0) {
            this.focusedIndex.set(prevIndex);
            this._scrollToFocusedOption();
        }
    }
    /**
     * Rola a lista de opções para garantir que a opção atualmente focada esteja visível.
     * Este método obtém o ID da opção atualmente focada a partir da lista de opções filtradas.
     * Se um ID válido for encontrado, busca o elemento correspondente no DOM e utiliza
     * `scrollIntoView` para rolar até a opção, alinhando-a ao bloco mais próximo.
     * @private
     */
    _scrollToFocusedOption() {
        const id = this.filteredOptions()[this.focusedIndex()]?.id;
        if (!id) {
            return;
        }
        const el = document.getElementById(id);
        el?.scrollIntoView({ block: 'nearest' });
    }
    static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "18.2.14", ngImport: i0, type: SelectComponent, deps: [], target: i0.ɵɵFactoryTarget.Component });
    static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "18.2.14", type: SelectComponent, isStandalone: true, selector: "s-select", inputs: { placeholder: { classPropertyName: "placeholder", publicName: "placeholder", isSignal: true, isRequired: false, transformFunction: null }, multiple: { classPropertyName: "multiple", publicName: "multiple", isSignal: true, isRequired: false, transformFunction: null }, options: { classPropertyName: "options", publicName: "options", isSignal: true, isRequired: true, transformFunction: null }, optionLabel: { classPropertyName: "optionLabel", publicName: "optionLabel", isSignal: true, isRequired: false, transformFunction: null }, optionValue: { classPropertyName: "optionValue", publicName: "optionValue", isSignal: true, isRequired: false, transformFunction: null }, showClear: { classPropertyName: "showClear", publicName: "showClear", isSignal: true, isRequired: false, transformFunction: null }, filter: { classPropertyName: "filter", publicName: "filter", isSignal: true, isRequired: false, transformFunction: null }, checkmark: { classPropertyName: "checkmark", publicName: "checkmark", isSignal: true, isRequired: false, transformFunction: null }, filterBy: { classPropertyName: "filterBy", publicName: "filterBy", isSignal: true, isRequired: false, transformFunction: null }, group: { classPropertyName: "group", publicName: "group", isSignal: true, isRequired: false, transformFunction: null }, virtualScroll: { classPropertyName: "virtualScroll", publicName: "virtualScroll", isSignal: true, isRequired: false, transformFunction: null }, virtualScrollItemSize: { classPropertyName: "virtualScrollItemSize", publicName: "virtualScrollItemSize", isSignal: true, isRequired: false, transformFunction: null }, emptyMessage: { classPropertyName: "emptyMessage", publicName: "emptyMessage", isSignal: true, isRequired: false, transformFunction: null }, disabled: { classPropertyName: "disabled", publicName: "disabled", isSignal: true, isRequired: false, transformFunction: null }, showOptions: { classPropertyName: "showOptions", publicName: "showOptions", isSignal: true, isRequired: false, transformFunction: null } }, outputs: { disabled: "disabledChange", showOptions: "showOptionsChange" }, host: { attributes: { "role": "combobox" }, listeners: { "window:resize": "onWindowResize($event)" }, properties: { "attr.aria-expanded": "showOptions()", "attr.aria-haspopup": "\"listbox\"", "attr.aria-owns": "showOptions() ? componentId + \"-listbox\" : null", "attr.aria-activedescendant": "focusedIndex() >= 0 ? filteredOptions()[focusedIndex()]?.id : null", "attr.aria-label": "placeholder() || \"Select option\"", "attr.aria-disabled": "disabled()" } }, providers: [
            {
                provide: NG_VALUE_ACCESSOR,
                useExisting: forwardRef(() => SelectComponent),
                multi: true,
            },
        ], viewQueries: [{ propertyName: "_containerDiv", first: true, predicate: ["containerDiv"], descendants: true, isSignal: true }], ngImport: i0, template: "<div\n    #containerDiv\n    cdkOverlayOrigin\n    #trigger=\"cdkOverlayOrigin\"\n    class=\"select-container group flex h-[35px] w-full overflow-hidden rounded-[3px] border outline-1 outline-primary focus:outline\"\n    [ngClass]=\"{\n        'pointer-events-none border-grayscale-20 bg-grayscale-5': disabled(),\n        'pointer-events-auto border-grayscale-30 bg-grayscale-0': !disabled(),\n    }\"\n    [attr.aria-disabled]=\"disabled()\"\n    [attr.aria-expanded]=\"showOptions()\"\n    [attr.aria-haspopup]=\"'listbox'\"\n    [attr.aria-owns]=\"'dropdown-container-' + componentId\"\n    [attr.aria-labelledby]=\"componentId + '-label'\"\n    role=\"combobox\"\n    (click)=\"onContainerDivClick()\"\n    (keydown)=\"onKeyDown($event)\"\n    tabindex=\"0\"\n>\n    <span\n        class=\"flex flex-grow select-none px-3 py-[7px]\"\n        [ngClass]=\"{\n            'text-grayscale-90': !disabled() && !isClean(),\n            'text-grayscale-60': !disabled() && isClean(),\n            'text-grayscale-30': disabled(),\n        }\"\n    >\n        {{ print() || placeholder() }}\n    </span>\n\n    @if (!disabled() && showClear() && !isClean()) {\n        <button\n            class=\"mx-3\"\n            (click)=\"clear($event)\"\n        >\n            <i class=\"fas fa-times flex items-center\"></i>\n        </button>\n    }\n\n    <div\n        class=\"dropdown-container flex items-center border-l px-3 group-hover:bg-grayscale-10 group-focus:border-primary\"\n        [ngClass]=\"{ 'border-grayscale-20': disabled(), 'border-grayscale-30': !disabled() }\"\n    >\n        <i\n            class=\"fas\"\n            [ngClass]=\"{\n                'text-grayscale-30': disabled(),\n                'text-grayscale-90': !disabled(),\n                'fa-caret-down': !showOptions(),\n                'fa-caret-up': showOptions(),\n            }\"\n        ></i>\n    </div>\n</div>\n\n<ng-template\n    #dropdownTemplate\n    cdkConnectedOverlay\n    [cdkConnectedOverlayOrigin]=\"trigger\"\n    [cdkConnectedOverlayOpen]=\"showOptions()\"\n    [cdkConnectedOverlayHasBackdrop]=\"true\"\n    (backdropClick)=\"showOptions.set(false)\"\n    cdkConnectedOverlayBackdropClass=\"cdk-overlay-transparent-backdrop\"\n    (detach)=\"showOptions.set(false)\"\n>\n    <div\n        [id]=\"'dropdown-container-' + componentId\"\n        class=\"dropdown-body-class z-[1000] rounded-[3px] bg-grayscale-0 py-1 shadow-md\"\n        (click)=\"$event.stopPropagation()\"\n        [style.width.px]=\"containerDiv.offsetWidth\"\n    >\n        @if (filter()) {\n            <div class=\"flex w-full items-center gap-3 px-3 py-1.5\">\n                @if (multiple()) {\n                    <s-checkbox\n                        #selectAllCheckbox\n                        [checked]=\"allSelected()\"\n                        [indeterminate]=\"selectAllIsIndeterminate()\"\n                        (checkedChange)=\"toggleSelectAll()\"\n                    ></s-checkbox>\n                }\n\n                <div class=\"relative flex h-[35px] grow\">\n                    <form\n                        class=\"flex grow\"\n                        [formGroup]=\"filterForm\"\n                    >\n                        <input\n                            class=\"w-full grow rounded-[3px] border border-grayscale-30 pl-2.5 pr-7 outline-1 outline-primary\"\n                            type=\"text\"\n                            formControlName=\"filter\"\n                            (click)=\"$event.stopPropagation()\"\n                        />\n                    </form>\n                    <i class=\"fas fa-search absolute right-2.5 top-2.5 text-grayscale-90\"></i>\n                </div>\n                <button (click)=\"clearFilter()\">\n                    <i class=\"fas fa-times flex items-center\"></i>\n                </button>\n            </div>\n        }\n\n        <!-- Virtual scroll -->\n        @if (virtualScroll() && filteredOptions().length > 10) {\n            <cdk-virtual-scroll-viewport\n                [itemSize]=\"virtualScrollItemSize()\"\n                class=\"h-52 overflow-auto\"\n            >\n                <ng-container *cdkVirtualFor=\"let option of filteredOptions(); trackBy: trackById\">\n                    <s-select-option\n                        [id]=\"option.id\"\n                        [label]=\"getOptionLabel(option.data)\"\n                        [multiple]=\"multiple()\"\n                        [checkmark]=\"checkmark()\"\n                        [isSelected]=\"isOptionSelected(option)\"\n                        (selected)=\"selectItem(option)\"\n                        [isGrouper]=\"option.grouper\"\n                        [isFocused]=\"option.data === focusedItem()\"\n                    ></s-select-option>\n                </ng-container>\n            </cdk-virtual-scroll-viewport>\n        }\n\n        <!-- Normal list -->\n        @if (!virtualScroll() || filteredOptions().length <= 10) {\n            <ul class=\"max-h-52 overflow-auto\">\n                @for (option of filteredOptions(); track option.id) {\n                    <s-select-option\n                        [id]=\"option.id\"\n                        [label]=\"getOptionLabel(option.data)\"\n                        [multiple]=\"multiple()\"\n                        [checkmark]=\"checkmark()\"\n                        [isSelected]=\"isOptionSelected(option)\"\n                        (selected)=\"selectItem(option)\"\n                        [isGrouper]=\"option.grouper ?? false\"\n                        [isFocused]=\"option.data === focusedItem()\"\n                    ></s-select-option>\n                }\n            </ul>\n        }\n\n        @if (filteredOptions().length === 0) {\n            <span class=\"m-3 text-grayscale-60\">{{\n                emptyMessage() ?? 'platform.angular_components.no_records_found' | translate\n            }}</span>\n        }\n    </div>\n</ng-template>\n", styles: [":host.ng-dirty.ng-invalid{.dropdown-container,.select-container{border-color:#c13018;outline:none}}\n"], dependencies: [{ kind: "ngmodule", type: CommonModule }, { kind: "directive", type: i1.NgClass, selector: "[ngClass]", inputs: ["class", "ngClass"] }, { kind: "ngmodule", type: ReactiveFormsModule }, { kind: "directive", type: i2.ɵNgNoValidate, selector: "form:not([ngNoForm]):not([ngNativeValidate])" }, { 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.NgControlStatusGroup, selector: "[formGroupName],[formArrayName],[ngModelGroup],[formGroup],form:not([ngNoForm]),[ngForm]" }, { kind: "directive", type: i2.FormGroupDirective, selector: "[formGroup]", inputs: ["formGroup"], outputs: ["ngSubmit"], exportAs: ["ngForm"] }, { kind: "directive", type: i2.FormControlName, selector: "[formControlName]", inputs: ["formControlName", "disabled", "ngModel"], outputs: ["ngModelChange"] }, { kind: "ngmodule", type: ScrollingModule }, { kind: "directive", type: i3.CdkFixedSizeVirtualScroll, selector: "cdk-virtual-scroll-viewport[itemSize]", inputs: ["itemSize", "minBufferPx", "maxBufferPx"] }, { kind: "directive", type: i3.CdkVirtualForOf, selector: "[cdkVirtualFor][cdkVirtualForOf]", inputs: ["cdkVirtualForOf", "cdkVirtualForTrackBy", "cdkVirtualForTemplate", "cdkVirtualForTemplateCacheSize"] }, { kind: "component", type: i3.CdkVirtualScrollViewport, selector: "cdk-virtual-scroll-viewport", inputs: ["orientation", "appendOnly"], outputs: ["scrolledIndexChange"] }, { kind: "component", type: SelectOptionComponent, selector: "s-select-option", inputs: ["id", "label", "multiple", "checkmark", "isGrouper", "isFocused", "isSelected"], outputs: ["isSelectedChange", "selected"] }, { kind: "component", type: CheckboxComponent, selector: "s-checkbox", inputs: ["disabled", "checked", "indeterminate", "label"], outputs: ["disabledChange", "checkedChange", "indeterminateChange"] }, { kind: "ngmodule", type: TranslateModule }, { kind: "pipe", type: i4.TranslatePipe, name: "translate" }, { kind: "ngmodule", type: OverlayModule }, { kind: "directive", type: i5.CdkConnectedOverlay, selector: "[cdk-connected-overlay], [connected-overlay], [cdkConnectedOverlay]", inputs: ["cdkConnectedOverlayOrigin", "cdkConnectedOverlayPositions", "cdkConnectedOverlayPositionStrategy", "cdkConnectedOverlayOffsetX", "cdkConnectedOverlayOffsetY", "cdkConnectedOverlayWidth", "cdkConnectedOverlayHeight", "cdkConnectedOverlayMinWidth", "cdkConnectedOverlayMinHeight", "cdkConnectedOverlayBackdropClass", "cdkConnectedOverlayPanelClass", "cdkConnectedOverlayViewportMargin", "cdkConnectedOverlayScrollStrategy", "cdkConnectedOverlayOpen", "cdkConnectedOverlayDisableClose", "cdkConnectedOverlayTransformOriginOn", "cdkConnectedOverlayHasBackdrop", "cdkConnectedOverlayLockPosition", "cdkConnectedOverlayFlexibleDimensions", "cdkConnectedOverlayGrowAfterOpen", "cdkConnectedOverlayPush", "cdkConnectedOverlayDisposeOnNavigation"], outputs: ["backdropClick", "positionChange", "attach", "detach", "overlayKeydown", "overlayOutsideClick"], exportAs: ["cdkConnectedOverlay"] }, { kind: "directive", type: i5.CdkOverlayOrigin, selector: "[cdk-overlay-origin], [overlay-origin], [cdkOverlayOrigin]", exportAs: ["cdkOverlayOrigin"] }] });
}
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "18.2.14", ngImport: i0, type: SelectComponent, decorators: [{
            type: Component,
            args: [{ selector: 's-select', standalone: true, imports: [
                        CommonModule,
                        ReactiveFormsModule,
                        ScrollingModule,
                        SelectOptionComponent,
                        CheckboxComponent,
                        TranslateModule,
                        OverlayModule,
                    ], host: {
                        '(window:resize)': 'onWindowResize($event)',
                        '[attr.aria-expanded]': 'showOptions()',
                        '[attr.aria-haspopup]': '"listbox"',
                        '[attr.aria-owns]': 'showOptions() ? componentId + "-listbox" : null',
                        '[attr.aria-activedescendant]': 'focusedIndex() >= 0 ? filteredOptions()[focusedIndex()]?.id : null',
                        '[attr.aria-label]': 'placeholder() || "Select option"',
                        '[attr.aria-disabled]': 'disabled()',
                        role: 'combobox',
                    }, providers: [
                        {
                            provide: NG_VALUE_ACCESSOR,
                            useExisting: forwardRef(() => SelectComponent),
                            multi: true,
                        },
                    ], template: "<div\n    #containerDiv\n    cdkOverlayOrigin\n    #trigger=\"cdkOverlayOrigin\"\n    class=\"select-container group flex h-[35px] w-full overflow-hidden rounded-[3px] border outline-1 outline-primary focus:outline\"\n    [ngClass]=\"{\n        'pointer-events-none border-grayscale-20 bg-grayscale-5': disabled(),\n        'pointer-events-auto border-grayscale-30 bg-grayscale-0': !disabled(),\n    }\"\n    [attr.aria-disabled]=\"disabled()\"\n    [attr.aria-expanded]=\"showOptions()\"\n    [attr.aria-haspopup]=\"'listbox'\"\n    [attr.aria-owns]=\"'dropdown-container-' + componentId\"\n    [attr.aria-labelledby]=\"componentId + '-label'\"\n    role=\"combobox\"\n    (click)=\"onContainerDivClick()\"\n    (keydown)=\"onKeyDown($event)\"\n    tabindex=\"0\"\n>\n    <span\n        class=\"flex flex-grow select-none px-3 py-[7px]\"\n        [ngClass]=\"{\n            'text-grayscale-90': !disabled() && !isClean(),\n            'text-grayscale-60': !disabled() && isClean(),\n            'text-grayscale-30': disabled(),\n        }\"\n    >\n        {{ print() || placeholder() }}\n    </span>\n\n    @if (!disabled() && showClear() && !isClean()) {\n        <button\n            class=\"mx-3\"\n            (click)=\"clear($event)\"\n        >\n            <i class=\"fas fa-times flex items-center\"></i>\n        </button>\n    }\n\n    <div\n        class=\"dropdown-container flex items-center border-l px-3 group-hover:bg-grayscale-10 group-focus:border-primary\"\n        [ngClass]=\"{ 'border-grayscale-20': disabled(), 'border-grayscale-30': !disabled() }\"\n    >\n        <i\n            class=\"fas\"\n            [ngClass]=\"{\n                'text-grayscale-30': disabled(),\n                'text-grayscale-90': !disabled(),\n                'fa-caret-down': !showOptions(),\n                'fa-caret-up': showOptions(),\n            }\"\n        ></i>\n    </div>\n</div>\n\n<ng-template\n    #dropdownTemplate\n    cdkConnectedOverlay\n    [cdkConnectedOverlayOrigin]=\"trigger\"\n    [cdkConnectedOverlayOpen]=\"showOptions()\"\n    [cdkConnectedOverlayHasBackdrop]=\"true\"\n    (backdropClick)=\"showOptions.set(false)\"\n    cdkConnectedOverlayBackdropClass=\"cdk-overlay-transparent-backdrop\"\n    (detach)=\"showOptions.set(false)\"\n>\n    <div\n        [id]=\"'dropdown-container-' + componentId\"\n        class=\"dropdown-body-class z-[1000] rounded-[3px] bg-grayscale-0 py-1 shadow-md\"\n        (click)=\"$event.stopPropagation()\"\n        [style.width.px]=\"containerDiv.offsetWidth\"\n    >\n        @if (filter()) {\n            <div class=\"flex w-full items-center gap-3 px-3 py-1.5\">\n                @if (multiple()) {\n                    <s-checkbox\n                        #selectAllCheckbox\n                        [checked]=\"allSelected()\"\n                        [indeterminate]=\"selectAllIsIndeterminate()\"\n                        (checkedChange)=\"toggleSelectAll()\"\n                    ></s-checkbox>\n                }\n\n                <div class=\"relative flex h-[35px] grow\">\n                    <form\n                        class=\"flex grow\"\n                        [formGroup]=\"filterForm\"\n                    >\n                        <input\n                            class=\"w-full grow rounded-[3px] border border-grayscale-30 pl-2.5 pr-7 outline-1 outline-primary\"\n                            type=\"text\"\n                            formControlName=\"filter\"\n                            (click)=\"$event.stopPropagation()\"\n                        />\n                    </form>\n                    <i class=\"fas fa-search absolute right-2.5 top-2.5 text-grayscale-90\"></i>\n                </div>\n                <button (click)=\"clearFilter()\">\n                    <i class=\"fas fa-times flex items-center\"></i>\n                </button>\n            </div>\n        }\n\n        <!-- Virtual scroll -->\n        @if (virtualScroll() && filteredOptions().length > 10) {\n            <cdk-virtual-scroll-viewport\n                [itemSize]=\"virtualScrollItemSize()\"\n                class=\"h-52 overflow-auto\"\n            >\n                <ng-container *cdkVirtualFor=\"let option of filteredOptions(); trackBy: trackById\">\n                    <s-select-option\n                        [id]=\"option.id\"\n                        [label]=\"getOptionLabel(option.data)\"\n                        [multiple]=\"multiple()\"\n                        [checkmark]=\"checkmark()\"\n                        [isSelected]=\"isOptionSelected(option)\"\n                        (selected)=\"selectItem(option)\"\n                        [isGrouper]=\"option.grouper\"\n                        [isFocused]=\"option.data === focusedItem()\"\n                    ></s-select-option>\n                </ng-container>\n            </cdk-virtual-scroll-viewport>\n        }\n\n        <!-- Normal list -->\n        @if (!virtualScroll() || filteredOptions().length <= 10) {\n            <ul class=\"max-h-52 overflow-auto\">\n                @for (option of filteredOptions(); track option.id) {\n                    <s-select-option\n                        [id]=\"option.id\"\n                        [label]=\"getOptionLabel(option.data)\"\n                        [multiple]=\"multiple()\"\n                        [checkmark]=\"checkmark()\"\n                        [isSelected]=\"isOptionSelected(option)\"\n                        (selected)=\"selectItem(option)\"\n                        [isGrouper]=\"option.grouper ?? false\"\n                        [isFocused]=\"option.data === focusedItem()\"\n                    ></s-select-option>\n                }\n            </ul>\n        }\n\n        @if (filteredOptions().length === 0) {\n            <span class=\"m-3 text-grayscale-60\">{{\n                emptyMessage() ?? 'platform.angular_components.no_records_found' | translate\n            }}</span>\n        }\n    </div>\n</ng-template>\n", styles: [":host.ng-dirty.ng-invalid{.dropdown-container,.select-container{border-color:#c13018;outline:none}}\n"] }]
        }], ctorParameters: () => [] });

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

export { SelectComponent };
//# sourceMappingURL=seniorsistemas-angular-components-select.mjs.map
