UNPKG

cfc-ds

Version:

Design System do Conselho Federal de Contabilidade baseado no govbr-ds

531 lines 89.5 kB
import { Component, EventEmitter, forwardRef, HostListener, Input, Output } from '@angular/core'; import { NG_VALUE_ACCESSOR, NG_VALIDATORS } from '@angular/forms'; import { SelectType } from '../../enums/select-type.enum'; import * as i0 from "@angular/core"; import * as i1 from "@angular/common"; import * as i2 from "@angular/flex-layout/flex"; import * as i3 from "@angular/flex-layout/extended"; export class SelectComponent { renderer; el; cdr; // Inputs options = []; id; label; placeholder = ''; labelInline = false; multiSelect = false; feedbackMessage; feedbackState; showSearchIcon = true; showSelectAll = false; required = false; ariaLabel; ariaDescribedBy; disabled = false; type = SelectType.default; // Outputs onChange = new EventEmitter(); onOpen = new EventEmitter(); onClose = new EventEmitter(); // Internal properties inputId; searchTerm = ''; selectedValues = []; filteredOptions = []; selectAllChecked = false; isOptionsListVisible = false; highlightedIndex = -1; displayValue = ''; isTooltipVisible = false; tooltipPosition = { top: 0, left: 0 }; // ControlValueAccessor properties onModelChange = (_) => { }; onModelTouched = () => { }; constructor(renderer, el, cdr) { this.renderer = renderer; this.el = el; this.cdr = cdr; this.inputId = this.id || `select-${Math.random().toString(36).substring(2, 9)}`; } ngOnInit() { if (this.required && this.ariaDescribedBy) { this.ariaDescribedBy = `${this.ariaDescribedBy} feedback-${this.inputId}`; } else if (this.required) { this.ariaDescribedBy = `feedback-${this.inputId}`; } } ngAfterViewInit() { // Garante que filteredOptions sempre começa com todas as opções disponíveis this.filteredOptions = [...this.options]; this.updateDisplayValue(); this.cdr.detectChanges(); } // Handle keyboard navigation handleKeyDown(event) { if (this.disabled) return; switch (event.key) { case 'ArrowDown': event.preventDefault(); if (!this.isOptionsListVisible) { this.openOptionsList(); } else { this.highlightNextItem(); } break; case 'ArrowUp': event.preventDefault(); if (!this.isOptionsListVisible) { this.openOptionsList(); } else { this.highlightPreviousItem(); } break; case 'Enter': if (this.isOptionsListVisible && this.highlightedIndex >= 0) { event.preventDefault(); if (this.highlightedIndex === 0 && this.showSelectAll && this.multiSelect) { this.toggleSelectAll(); } else { const adjustedIndex = this.showSelectAll && this.multiSelect ? this.highlightedIndex - 1 : this.highlightedIndex; if (adjustedIndex >= 0 && adjustedIndex < this.filteredOptions.length) { this.toggleSelection(this.filteredOptions[adjustedIndex]); } } } else if (!this.isOptionsListVisible) { this.openOptionsList(); } break; case ' ': // Space key if (this.isOptionsListVisible && this.highlightedIndex >= 0) { event.preventDefault(); if (this.highlightedIndex === 0 && this.showSelectAll && this.multiSelect) { this.toggleSelectAll(); } else { const adjustedIndex = this.showSelectAll && this.multiSelect ? this.highlightedIndex - 1 : this.highlightedIndex; if (adjustedIndex >= 0 && adjustedIndex < this.filteredOptions.length) { this.toggleSelection(this.filteredOptions[adjustedIndex]); } } } break; case 'Escape': if (this.isOptionsListVisible) { event.preventDefault(); this.closeOptionsList(); } break; case 'Tab': if (this.isOptionsListVisible) { this.closeOptionsList(); } break; default: // Para filtro por primeira letra quando as teclas são letras ou números if (event.key.length === 1 && /[a-zA-Z0-9]/.test(event.key)) { // Implementação para filtrar por primeira letra this.filterByFirstLetter(event.key); } break; } } handleItemKeyDown(event, option) { if (this.disabled) return; if (event.key === 'Enter' || event.key === ' ') { event.preventDefault(); if (option === null && this.showSelectAll && this.multiSelect) { this.toggleSelectAll(); } else { this.toggleSelection(option); } } } // Filter options by first letter filterByFirstLetter(letter) { if (this.disabled) return; letter = letter.toLowerCase(); // Find the first option that starts with the letter const index = this.filteredOptions.findIndex(option => option.label.toLowerCase().startsWith(letter)); if (index >= 0) { this.highlightedIndex = this.showSelectAll && this.multiSelect ? index + 1 : index; // Scroll to the item setTimeout(() => { const listElement = this.el.nativeElement.querySelector('.options-list'); const optionElement = listElement?.querySelector(`li:nth-child(${this.highlightedIndex + 1})`); if (listElement && optionElement) { listElement.scrollTop = optionElement.offsetTop - listElement.offsetTop; } }); } } // Highlight navigation highlightNextItem() { if (this.disabled) return; const maxIndex = this.getOptionsLength() - 1; if (this.highlightedIndex < maxIndex) { this.highlightedIndex++; this.scrollToHighlightedItem(); } } highlightPreviousItem() { if (this.disabled) return; if (this.highlightedIndex > 0) { this.highlightedIndex--; this.scrollToHighlightedItem(); } } scrollToHighlightedItem() { if (this.disabled) return; setTimeout(() => { const listElement = this.el.nativeElement.querySelector('.options-list'); const optionElement = listElement?.querySelector(`li:nth-child(${this.highlightedIndex + 1})`); if (listElement && optionElement) { const optionTop = optionElement.offsetTop; const optionBottom = optionTop + optionElement.offsetHeight; const listTop = listElement.scrollTop; const listBottom = listTop + listElement.offsetHeight; if (optionTop < listTop) { listElement.scrollTop = optionTop; } else if (optionBottom > listBottom) { listElement.scrollTop = optionBottom - listElement.offsetHeight; } } }); } getOptionsLength() { return this.filteredOptions.length + (this.showSelectAll && this.multiSelect ? 1 : 0); } // Open/close the options list openOptionsList() { if (this.disabled) return; // Resetar os filtros quando abrir a lista if (this.searchTerm === '') { this.filteredOptions = [...this.options]; } this.isOptionsListVisible = true; this.highlightedIndex = 0; this.onOpen.emit(); this.cdr.detectChanges(); } closeOptionsList() { if (this.disabled) return; this.isOptionsListVisible = false; this.highlightedIndex = -1; this.onClose.emit(); } toggleOptionsList() { if (this.disabled) return; if (this.isOptionsListVisible) { this.closeOptionsList(); } else { this.openOptionsList(); } } onInputFocus() { if (this.disabled) return; this.openOptionsList(); this.onModelTouched(); } // Selection logic toggleSelection(option, event) { if (this.disabled) return; // Se recebemos um evento, impedir a propagação padrão if (event) { event.preventDefault(); event.stopPropagation(); } // Garantir que estamos trabalhando com o objeto correto const targetOption = this.options.find(opt => opt.value === option.value); if (!targetOption) { console.warn('Option not found:', option); return; } if (this.multiSelect) { const index = this.selectedValues.findIndex(item => item.value === targetOption.value); if (index > -1) { // Remove do array de selecionados this.selectedValues.splice(index, 1); } else { // Adiciona ao array de selecionados this.selectedValues.push(targetOption); } // Importante: force a detecção de mudanças após a alteração this.updateSelectAllState(); this.cdr.detectChanges(); } else { this.selectedValues = [targetOption]; this.closeOptionsList(); } this.updateDisplayValue(); // Notifica o FormControl const valueToEmit = this.multiSelect ? this.selectedValues : (this.selectedValues.length > 0 ? this.selectedValues[0].value : null); this.onModelChange(valueToEmit); this.onModelTouched(); // Emite evento para componente pai this.onChange.emit(this.selectedValues); } isOptionSelected(option) { return this.selectedValues.some(item => item.value === option.value); } toggleSelectAll(event) { if (this.disabled) return; if (event) { event.preventDefault(); event.stopPropagation(); } if (this.selectAllChecked) { this.selectedValues = []; this.selectAllChecked = false; } else { this.selectedValues = [...this.filteredOptions]; this.selectAllChecked = true; } this.cdr.detectChanges(); // Force a detecção de mudanças this.updateDisplayValue(); // Notifica o FormControl this.onModelChange(this.selectedValues); this.onModelTouched(); // Emite evento para componente pai this.onChange.emit(this.selectedValues); if (!this.multiSelect) { this.closeOptionsList(); } } updateSelectAllState() { if (this.disabled) return; if (this.filteredOptions.length === 0) { this.selectAllChecked = false; return; } if (this.selectedValues.length === 0) { this.selectAllChecked = false; } else if (this.filteredOptions.every(option => this.selectedValues.some(selected => selected.value === option.value))) { this.selectAllChecked = true; } else { // Estado intermediário - alguns selecionados, mas não todos this.selectAllChecked = false; } } // Search functionality onSearchChange(event) { if (this.disabled) return; const target = event.target; this.searchTerm = target.value.toLowerCase(); this.filteredOptions = this.options.filter(option => option.label.toLowerCase().includes(this.searchTerm)); // Reset highlight position this.highlightedIndex = 0; // Se não tiver a lista aberta, abre if (!this.isOptionsListVisible) { this.openOptionsList(); } // Update select all state based on filtered options this.updateSelectAllState(); } // Display value formatting updateDisplayValue() { if (this.selectedValues.length === 0) { this.displayValue = ''; return; } if (this.multiSelect) { if (this.selectedValues.length === 1) { // Quando há apenas um item selecionado this.displayValue = this.selectedValues[0].label; } else { // Quando há múltiplos itens: primeiro item + (número dos demais) this.displayValue = `${this.selectedValues[0].label} + (${this.selectedValues.length - 1})`; } } else { // Para seleção única this.displayValue = this.selectedValues[0].label; } } // Click outside to close onClick(event) { const clickedInside = this.el.nativeElement.contains(event.target); if (!clickedInside && this.isOptionsListVisible) { this.closeOptionsList(); } } getFullSelectedText() { if (this.selectedValues.length === 0) { return ''; } return this.selectedValues.map(v => v.label).join(', '); } showTooltip(event) { if (this.disabled) return; if ((this.isTextTruncated() || this.selectedValues.length > 1) && this.selectedValues.length > 0) { const containerElement = this.el.nativeElement.querySelector('.select-container'); const rect = containerElement.getBoundingClientRect(); // Calcula posição melhor this.tooltipPosition = { top: rect.height, // Logo abaixo do container left: rect.width / 2 // Centralizado }; this.isTooltipVisible = true; this.cdr.detectChanges(); } } hideTooltip() { this.isTooltipVisible = false; } isTextTruncated() { const inputElement = this.el.nativeElement.querySelector('.select-input'); if (inputElement) { // Certifique-se de que há um pequeno buffer para considerarmos truncado return (inputElement.scrollWidth > inputElement.clientWidth + 2); } return false; } // Implementação ControlValueAccessor writeValue(value) { if (value === null || value === undefined) { this.selectedValues = []; } else if (Array.isArray(value)) { this.selectedValues = this.options.filter(option => value.some((val) => { if (typeof val === 'object' && val !== null) { return val.value === option.value; } else { return val === option.value; } })); } else { const selectedOption = this.options.find(option => option.value === value || (typeof value === 'object' && value !== null && JSON.stringify(option.value) === JSON.stringify(value))); this.selectedValues = selectedOption ? [selectedOption] : []; } this.updateDisplayValue(); this.updateSelectAllState(); this.cdr.detectChanges(); } registerOnChange(fn) { this.onModelChange = fn; } registerOnTouched(fn) { this.onModelTouched = fn; } setDisabledState(isDisabled) { this.disabled = isDisabled; if (isDisabled) { // Ensure the dropdown is closed when disabled this.isOptionsListVisible = false; } this.cdr.detectChanges(); } // Implementação do Validator validate(control) { if (this.required) { const value = control.value; if (value === null || value === undefined || (Array.isArray(value) && value.length === 0) || value === '') { return { required: true }; } } return null; } static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "18.2.13", ngImport: i0, type: SelectComponent, deps: [{ token: i0.Renderer2 }, { token: i0.ElementRef }, { token: i0.ChangeDetectorRef }], target: i0.ɵɵFactoryTarget.Component }); static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "14.0.0", version: "18.2.13", type: SelectComponent, selector: "cfc-select", inputs: { options: "options", id: "id", label: "label", placeholder: "placeholder", labelInline: "labelInline", multiSelect: "multiSelect", feedbackMessage: "feedbackMessage", feedbackState: "feedbackState", showSearchIcon: "showSearchIcon", showSelectAll: "showSelectAll", required: "required", ariaLabel: "ariaLabel", ariaDescribedBy: "ariaDescribedBy", disabled: "disabled", type: "type" }, outputs: { onChange: "onChange", onOpen: "onOpen", onClose: "onClose" }, host: { listeners: { "document:click": "onClick($event)" } }, providers: [ { provide: NG_VALUE_ACCESSOR, useExisting: forwardRef(() => SelectComponent), multi: true }, { provide: NG_VALIDATORS, useExisting: forwardRef(() => SelectComponent), multi: true } ], ngImport: i0, template: "<div\r\n [fxLayout]=\"labelInline ? 'row' : 'column'\"\r\n [fxLayoutAlign]=\"labelInline ? 'center center' : ''\"\r\n [ngClass]=\"{'pagination-select': type === 'pagination'}\">\r\n\r\n <label\r\n *ngIf=\"label\"\r\n class=\"input-label\"\r\n [for]=\"inputId\"\r\n [class.required]=\"required\">\r\n {{ label }}\r\n </label>\r\n\r\n <div class=\"select-container\">\r\n <div\r\n class=\"input-with-icon\"\r\n [ngClass]=\"{'pagination-input': type === 'pagination'}\"\r\n [class.disabled]=\"disabled\"\r\n role=\"combobox\"\r\n [attr.aria-expanded]=\"isOptionsListVisible && !disabled\"\r\n [attr.aria-haspopup]=\"!disabled\"\r\n [attr.aria-owns]=\"'list-' + inputId\"\r\n [attr.aria-required]=\"required\"\r\n [attr.aria-disabled]=\"disabled\"\r\n (mouseenter)=\"!disabled && showTooltip($event)\"\r\n (mouseleave)=\"hideTooltip()\">\r\n <i class=\"fa fa-search search-icon\" *ngIf=\"showSearchIcon\" aria-hidden=\"true\"></i>\r\n <input\r\n [id]=\"inputId\"\r\n type=\"text\"\r\n [placeholder]=\"placeholder\"\r\n [attr.aria-label]=\"ariaLabel || label || 'Select'\"\r\n [attr.aria-describedby]=\"ariaDescribedBy\"\r\n [attr.aria-autocomplete]=\"'list'\"\r\n [attr.aria-controls]=\"'list-' + inputId\"\r\n [value]=\"displayValue\"\r\n [disabled]=\"disabled\"\r\n (input)=\"onSearchChange($event)\"\r\n (focus)=\"onInputFocus()\"\r\n (keydown)=\"handleKeyDown($event)\"\r\n class=\"select-input\"\r\n [class.has-search-icon]=\"showSearchIcon\"\r\n [class.disabled]=\"disabled\"\r\n [class.required]=\"required\" />\r\n <button\r\n type=\"button\"\r\n class=\"toggle-button\"\r\n tabindex=\"-1\"\r\n [disabled]=\"disabled\"\r\n (click)=\"toggleOptionsList()\"\r\n aria-hidden=\"true\">\r\n <i class=\"fa\" [ngClass]=\"isOptionsListVisible ? 'fa-caret-up' : 'fa-caret-down'\"></i>\r\n </button>\r\n </div>\r\n\r\n <!-- Tooltip customizado -->\r\n <div *ngIf=\"isTooltipVisible && !disabled\"\r\n class=\"custom-tooltip\"\r\n [style.top.px]=\"tooltipPosition.top\"\r\n [style.left.px]=\"tooltipPosition.left\">\r\n {{ getFullSelectedText() }}\r\n </div>\r\n\r\n <ul\r\n *ngIf=\"isOptionsListVisible && !disabled\"\r\n [id]=\"'list-' + inputId\"\r\n role=\"listbox\"\r\n [attr.aria-multiselectable]=\"multiSelect\"\r\n [attr.aria-labelledby]=\"inputId\"\r\n class=\"options-list\"\r\n [ngClass]=\"{'pagination-options': type === 'pagination'}\"\r\n tabindex=\"-1\">\r\n <li *ngIf=\"showSelectAll && multiSelect\"\r\n role=\"option\"\r\n class=\"select-all-option\"\r\n [class.selected]=\"selectAllChecked\"\r\n (click)=\"toggleSelectAll($event)\"\r\n (keydown)=\"handleItemKeyDown($event, null)\">\r\n <div class=\"option-content\">\r\n <div class=\"checkbox-wrapper\">\r\n <input\r\n type=\"checkbox\"\r\n [id]=\"'select-all-' + inputId\"\r\n [checked]=\"selectAllChecked\"\r\n tabindex=\"-1\"\r\n aria-hidden=\"true\" />\r\n <span class=\"checkbox-label\">\r\n {{ selectAllChecked ? 'Desselecionar todos' : 'Selecionar todos' }}\r\n </span>\r\n </div>\r\n </div>\r\n </li>\r\n <li *ngFor=\"let option of filteredOptions; let i = index\"\r\n role=\"option\"\r\n [id]=\"'option-' + inputId + '-' + i\"\r\n [attr.aria-selected]=\"isOptionSelected(option)\"\r\n [class.selected]=\"isOptionSelected(option)\"\r\n [class.highlighted]=\"highlightedIndex === i\"\r\n (click)=\"toggleSelection(option, $event)\"\r\n (keydown)=\"handleItemKeyDown($event, option)\">\r\n <div class=\"option-content\">\r\n <div class=\"checkbox-wrapper\" *ngIf=\"multiSelect\">\r\n <input\r\n type=\"checkbox\"\r\n [id]=\"'option-checkbox-' + inputId + '-' + i\"\r\n [checked]=\"isOptionSelected(option)\"\r\n tabindex=\"-1\"\r\n aria-hidden=\"true\"\r\n (click)=\"$event.stopPropagation()\" />\r\n <span class=\"checkbox-label\">{{ option.label }}</span>\r\n </div>\r\n <span *ngIf=\"!multiSelect\">{{ option.label }}</span>\r\n </div>\r\n </li>\r\n <li *ngIf=\"filteredOptions.length === 0\"\r\n class=\"empty-state\"\r\n role=\"option\"\r\n aria-disabled=\"true\">\r\n Nenhum item encontrado.\r\n </li>\r\n </ul>\r\n </div>\r\n\r\n <div\r\n *ngIf=\"feedbackMessage\"\r\n [ngClass]=\"feedbackState\"\r\n [id]=\"'feedback-' + inputId\"\r\n aria-live=\"polite\">\r\n {{ feedbackMessage }}\r\n </div>\r\n</div>\r\n", styles: ["@charset \"UTF-8\";:host{width:100%;display:block}.select-container{position:relative;width:100%}.input-with-icon{position:relative;display:flex;align-items:center;border:1px solid #ccc;border-radius:4px;background-color:#fff;transition:border-color .2s,box-shadow .2s}.input-with-icon:hover{border-color:#999}.input-with-icon:focus-within{border-color:#007bff;box-shadow:0 0 0 2px #007bff40}.search-icon{position:absolute;left:12px;color:#666;pointer-events:none}.toggle-button{background:transparent;border:none;padding:0 12px;cursor:pointer;color:#666;font-size:16px;height:100%;display:flex;align-items:center;justify-content:center}.toggle-button:hover{color:#333}.select-input{flex:1;padding:10px 40px 10px 12px;border:none;border-radius:4px;font-size:16px;background:transparent;width:100%;text-overflow:ellipsis;white-space:nowrap;overflow:hidden}.select-input:focus{outline:none}.select-input.has-search-icon{padding-left:36px}.options-list{position:absolute;top:100%;left:0;right:0;max-height:250px;overflow-y:auto;margin:4px 0 0;padding:0;list-style:none;background:#fff;border-radius:4px;border:1px solid #ccc;z-index:1000;box-shadow:0 4px 12px #0000001a}.options-list li.selected{background-color:#e6f7ff}.checkbox-wrapper{display:flex;align-items:center;width:100%}.checkbox-label{margin-left:8px;cursor:pointer}.options-list li{cursor:pointer;display:flex;align-items:center;-webkit-user-select:none;user-select:none;width:100%}.options-list li:hover{background-color:#f5f5f5}.options-list li.selected{background-color:#007bff;color:#fff}.options-list li.selected .checkbox label{color:#fff}.options-list li.highlighted{background-color:#e8f0fe}.options-list li.selected.highlighted{background-color:#0069d9}.option-content{width:100%;padding:10px 12px;display:flex;align-items:center}.checkbox{display:flex;align-items:center}.checkbox input{margin-right:8px}.select-all-option{border-bottom:1px solid #eee;font-weight:600;background-color:#f9f9f9}.empty-state{padding:12px;text-align:center;color:#999;font-style:italic;cursor:default}.input-label{margin-bottom:6px;font-weight:500;color:#333}.input-label.required:after{content:\"*\";color:#dc3545;margin-left:4px}.error{color:#dc3545;font-size:14px;margin-top:4px}.warning{color:#ffc107;font-size:14px;margin-top:4px}.success{color:#28a745;font-size:14px;margin-top:4px}.custom-tooltip{position:absolute;background-color:#06c;color:#fff;padding:8px 12px;border-radius:4px;z-index:2000;max-width:300px;word-wrap:break-word;box-shadow:0 2px 8px #00000026;pointer-events:none;transition:opacity .2s;white-space:normal;transform:translate(-50%)}.custom-tooltip:after{content:\"\";position:absolute;top:-8px;left:50%;transform:translate(-50%);border-width:0 8px 8px;border-style:solid;border-color:transparent transparent #0066cc transparent}.pagination-select .pagination-input{height:36px;min-width:64px;border:transparent}.pagination-select .pagination-input:hover{background-color:#e8e8e8}.pagination-select .pagination-input .select-input{text-align:center;font-weight:500;padding:8px 24px 8px 12px}.pagination-select .pagination-input .toggle-button{padding:0 6px;position:absolute;right:0}.pagination-select .pagination-options{text-align:center}.pagination-select .pagination-options li{padding:8px;justify-content:center}\n"], dependencies: [{ kind: "directive", type: i1.NgClass, selector: "[ngClass]", inputs: ["class", "ngClass"] }, { kind: "directive", type: i1.NgForOf, selector: "[ngFor][ngForOf]", inputs: ["ngForOf", "ngForTrackBy", "ngForTemplate"] }, { kind: "directive", type: i1.NgIf, selector: "[ngIf]", inputs: ["ngIf", "ngIfThen", "ngIfElse"] }, { kind: "directive", type: i2.DefaultLayoutDirective, selector: " [fxLayout], [fxLayout.xs], [fxLayout.sm], [fxLayout.md], [fxLayout.lg], [fxLayout.xl], [fxLayout.lt-sm], [fxLayout.lt-md], [fxLayout.lt-lg], [fxLayout.lt-xl], [fxLayout.gt-xs], [fxLayout.gt-sm], [fxLayout.gt-md], [fxLayout.gt-lg]", inputs: ["fxLayout", "fxLayout.xs", "fxLayout.sm", "fxLayout.md", "fxLayout.lg", "fxLayout.xl", "fxLayout.lt-sm", "fxLayout.lt-md", "fxLayout.lt-lg", "fxLayout.lt-xl", "fxLayout.gt-xs", "fxLayout.gt-sm", "fxLayout.gt-md", "fxLayout.gt-lg"] }, { kind: "directive", type: i2.DefaultLayoutAlignDirective, selector: " [fxLayoutAlign], [fxLayoutAlign.xs], [fxLayoutAlign.sm], [fxLayoutAlign.md], [fxLayoutAlign.lg], [fxLayoutAlign.xl], [fxLayoutAlign.lt-sm], [fxLayoutAlign.lt-md], [fxLayoutAlign.lt-lg], [fxLayoutAlign.lt-xl], [fxLayoutAlign.gt-xs], [fxLayoutAlign.gt-sm], [fxLayoutAlign.gt-md], [fxLayoutAlign.gt-lg]", inputs: ["fxLayoutAlign", "fxLayoutAlign.xs", "fxLayoutAlign.sm", "fxLayoutAlign.md", "fxLayoutAlign.lg", "fxLayoutAlign.xl", "fxLayoutAlign.lt-sm", "fxLayoutAlign.lt-md", "fxLayoutAlign.lt-lg", "fxLayoutAlign.lt-xl", "fxLayoutAlign.gt-xs", "fxLayoutAlign.gt-sm", "fxLayoutAlign.gt-md", "fxLayoutAlign.gt-lg"] }, { kind: "directive", type: i3.DefaultClassDirective, selector: " [ngClass], [ngClass.xs], [ngClass.sm], [ngClass.md], [ngClass.lg], [ngClass.xl], [ngClass.lt-sm], [ngClass.lt-md], [ngClass.lt-lg], [ngClass.lt-xl], [ngClass.gt-xs], [ngClass.gt-sm], [ngClass.gt-md], [ngClass.gt-lg]", inputs: ["ngClass", "ngClass.xs", "ngClass.sm", "ngClass.md", "ngClass.lg", "ngClass.xl", "ngClass.lt-sm", "ngClass.lt-md", "ngClass.lt-lg", "ngClass.lt-xl", "ngClass.gt-xs", "ngClass.gt-sm", "ngClass.gt-md", "ngClass.gt-lg"] }] }); } i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "18.2.13", ngImport: i0, type: SelectComponent, decorators: [{ type: Component, args: [{ selector: 'cfc-select', providers: [ { provide: NG_VALUE_ACCESSOR, useExisting: forwardRef(() => SelectComponent), multi: true }, { provide: NG_VALIDATORS, useExisting: forwardRef(() => SelectComponent), multi: true } ], template: "<div\r\n [fxLayout]=\"labelInline ? 'row' : 'column'\"\r\n [fxLayoutAlign]=\"labelInline ? 'center center' : ''\"\r\n [ngClass]=\"{'pagination-select': type === 'pagination'}\">\r\n\r\n <label\r\n *ngIf=\"label\"\r\n class=\"input-label\"\r\n [for]=\"inputId\"\r\n [class.required]=\"required\">\r\n {{ label }}\r\n </label>\r\n\r\n <div class=\"select-container\">\r\n <div\r\n class=\"input-with-icon\"\r\n [ngClass]=\"{'pagination-input': type === 'pagination'}\"\r\n [class.disabled]=\"disabled\"\r\n role=\"combobox\"\r\n [attr.aria-expanded]=\"isOptionsListVisible && !disabled\"\r\n [attr.aria-haspopup]=\"!disabled\"\r\n [attr.aria-owns]=\"'list-' + inputId\"\r\n [attr.aria-required]=\"required\"\r\n [attr.aria-disabled]=\"disabled\"\r\n (mouseenter)=\"!disabled && showTooltip($event)\"\r\n (mouseleave)=\"hideTooltip()\">\r\n <i class=\"fa fa-search search-icon\" *ngIf=\"showSearchIcon\" aria-hidden=\"true\"></i>\r\n <input\r\n [id]=\"inputId\"\r\n type=\"text\"\r\n [placeholder]=\"placeholder\"\r\n [attr.aria-label]=\"ariaLabel || label || 'Select'\"\r\n [attr.aria-describedby]=\"ariaDescribedBy\"\r\n [attr.aria-autocomplete]=\"'list'\"\r\n [attr.aria-controls]=\"'list-' + inputId\"\r\n [value]=\"displayValue\"\r\n [disabled]=\"disabled\"\r\n (input)=\"onSearchChange($event)\"\r\n (focus)=\"onInputFocus()\"\r\n (keydown)=\"handleKeyDown($event)\"\r\n class=\"select-input\"\r\n [class.has-search-icon]=\"showSearchIcon\"\r\n [class.disabled]=\"disabled\"\r\n [class.required]=\"required\" />\r\n <button\r\n type=\"button\"\r\n class=\"toggle-button\"\r\n tabindex=\"-1\"\r\n [disabled]=\"disabled\"\r\n (click)=\"toggleOptionsList()\"\r\n aria-hidden=\"true\">\r\n <i class=\"fa\" [ngClass]=\"isOptionsListVisible ? 'fa-caret-up' : 'fa-caret-down'\"></i>\r\n </button>\r\n </div>\r\n\r\n <!-- Tooltip customizado -->\r\n <div *ngIf=\"isTooltipVisible && !disabled\"\r\n class=\"custom-tooltip\"\r\n [style.top.px]=\"tooltipPosition.top\"\r\n [style.left.px]=\"tooltipPosition.left\">\r\n {{ getFullSelectedText() }}\r\n </div>\r\n\r\n <ul\r\n *ngIf=\"isOptionsListVisible && !disabled\"\r\n [id]=\"'list-' + inputId\"\r\n role=\"listbox\"\r\n [attr.aria-multiselectable]=\"multiSelect\"\r\n [attr.aria-labelledby]=\"inputId\"\r\n class=\"options-list\"\r\n [ngClass]=\"{'pagination-options': type === 'pagination'}\"\r\n tabindex=\"-1\">\r\n <li *ngIf=\"showSelectAll && multiSelect\"\r\n role=\"option\"\r\n class=\"select-all-option\"\r\n [class.selected]=\"selectAllChecked\"\r\n (click)=\"toggleSelectAll($event)\"\r\n (keydown)=\"handleItemKeyDown($event, null)\">\r\n <div class=\"option-content\">\r\n <div class=\"checkbox-wrapper\">\r\n <input\r\n type=\"checkbox\"\r\n [id]=\"'select-all-' + inputId\"\r\n [checked]=\"selectAllChecked\"\r\n tabindex=\"-1\"\r\n aria-hidden=\"true\" />\r\n <span class=\"checkbox-label\">\r\n {{ selectAllChecked ? 'Desselecionar todos' : 'Selecionar todos' }}\r\n </span>\r\n </div>\r\n </div>\r\n </li>\r\n <li *ngFor=\"let option of filteredOptions; let i = index\"\r\n role=\"option\"\r\n [id]=\"'option-' + inputId + '-' + i\"\r\n [attr.aria-selected]=\"isOptionSelected(option)\"\r\n [class.selected]=\"isOptionSelected(option)\"\r\n [class.highlighted]=\"highlightedIndex === i\"\r\n (click)=\"toggleSelection(option, $event)\"\r\n (keydown)=\"handleItemKeyDown($event, option)\">\r\n <div class=\"option-content\">\r\n <div class=\"checkbox-wrapper\" *ngIf=\"multiSelect\">\r\n <input\r\n type=\"checkbox\"\r\n [id]=\"'option-checkbox-' + inputId + '-' + i\"\r\n [checked]=\"isOptionSelected(option)\"\r\n tabindex=\"-1\"\r\n aria-hidden=\"true\"\r\n (click)=\"$event.stopPropagation()\" />\r\n <span class=\"checkbox-label\">{{ option.label }}</span>\r\n </div>\r\n <span *ngIf=\"!multiSelect\">{{ option.label }}</span>\r\n </div>\r\n </li>\r\n <li *ngIf=\"filteredOptions.length === 0\"\r\n class=\"empty-state\"\r\n role=\"option\"\r\n aria-disabled=\"true\">\r\n Nenhum item encontrado.\r\n </li>\r\n </ul>\r\n </div>\r\n\r\n <div\r\n *ngIf=\"feedbackMessage\"\r\n [ngClass]=\"feedbackState\"\r\n [id]=\"'feedback-' + inputId\"\r\n aria-live=\"polite\">\r\n {{ feedbackMessage }}\r\n </div>\r\n</div>\r\n", styles: ["@charset \"UTF-8\";:host{width:100%;display:block}.select-container{position:relative;width:100%}.input-with-icon{position:relative;display:flex;align-items:center;border:1px solid #ccc;border-radius:4px;background-color:#fff;transition:border-color .2s,box-shadow .2s}.input-with-icon:hover{border-color:#999}.input-with-icon:focus-within{border-color:#007bff;box-shadow:0 0 0 2px #007bff40}.search-icon{position:absolute;left:12px;color:#666;pointer-events:none}.toggle-button{background:transparent;border:none;padding:0 12px;cursor:pointer;color:#666;font-size:16px;height:100%;display:flex;align-items:center;justify-content:center}.toggle-button:hover{color:#333}.select-input{flex:1;padding:10px 40px 10px 12px;border:none;border-radius:4px;font-size:16px;background:transparent;width:100%;text-overflow:ellipsis;white-space:nowrap;overflow:hidden}.select-input:focus{outline:none}.select-input.has-search-icon{padding-left:36px}.options-list{position:absolute;top:100%;left:0;right:0;max-height:250px;overflow-y:auto;margin:4px 0 0;padding:0;list-style:none;background:#fff;border-radius:4px;border:1px solid #ccc;z-index:1000;box-shadow:0 4px 12px #0000001a}.options-list li.selected{background-color:#e6f7ff}.checkbox-wrapper{display:flex;align-items:center;width:100%}.checkbox-label{margin-left:8px;cursor:pointer}.options-list li{cursor:pointer;display:flex;align-items:center;-webkit-user-select:none;user-select:none;width:100%}.options-list li:hover{background-color:#f5f5f5}.options-list li.selected{background-color:#007bff;color:#fff}.options-list li.selected .checkbox label{color:#fff}.options-list li.highlighted{background-color:#e8f0fe}.options-list li.selected.highlighted{background-color:#0069d9}.option-content{width:100%;padding:10px 12px;display:flex;align-items:center}.checkbox{display:flex;align-items:center}.checkbox input{margin-right:8px}.select-all-option{border-bottom:1px solid #eee;font-weight:600;background-color:#f9f9f9}.empty-state{padding:12px;text-align:center;color:#999;font-style:italic;cursor:default}.input-label{margin-bottom:6px;font-weight:500;color:#333}.input-label.required:after{content:\"*\";color:#dc3545;margin-left:4px}.error{color:#dc3545;font-size:14px;margin-top:4px}.warning{color:#ffc107;font-size:14px;margin-top:4px}.success{color:#28a745;font-size:14px;margin-top:4px}.custom-tooltip{position:absolute;background-color:#06c;color:#fff;padding:8px 12px;border-radius:4px;z-index:2000;max-width:300px;word-wrap:break-word;box-shadow:0 2px 8px #00000026;pointer-events:none;transition:opacity .2s;white-space:normal;transform:translate(-50%)}.custom-tooltip:after{content:\"\";position:absolute;top:-8px;left:50%;transform:translate(-50%);border-width:0 8px 8px;border-style:solid;border-color:transparent transparent #0066cc transparent}.pagination-select .pagination-input{height:36px;min-width:64px;border:transparent}.pagination-select .pagination-input:hover{background-color:#e8e8e8}.pagination-select .pagination-input .select-input{text-align:center;font-weight:500;padding:8px 24px 8px 12px}.pagination-select .pagination-input .toggle-button{padding:0 6px;position:absolute;right:0}.pagination-select .pagination-options{text-align:center}.pagination-select .pagination-options li{padding:8px;justify-content:center}\n"] }] }], ctorParameters: () => [{ type: i0.Renderer2 }, { type: i0.ElementRef }, { type: i0.ChangeDetectorRef }], propDecorators: { options: [{ type: Input }], id: [{ type: Input }], label: [{ type: Input }], placeholder: [{ type: Input }], labelInline: [{ type: Input }], multiSelect: [{ type: Input }], feedbackMessage: [{ type: Input }], feedbackState: [{ type: Input }], showSearchIcon: [{ type: Input }], showSelectAll: [{ type: Input }], required: [{ type: Input }], ariaLabel: [{ type: Input }], ariaDescribedBy: [{ type: Input }], disabled: [{ type: Input }], type: [{ type: Input }], onChange: [{ type: Output }], onOpen: [{ type: Output }], onClose: [{ type: Output }], onClick: [{ type: HostListener, args: ['document:click', ['$event']] }] } }); //# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoic2VsZWN0LmNvbXBvbmVudC5qcyIsInNvdXJjZVJvb3QiOiIiLCJzb3VyY2VzIjpbIi4uLy4uLy4uLy4uLy4uLy4uL3Byb2plY3RzL2NmYy1kcy9zcmMvbGliL2NvbXBvbmVudHMvc2VsZWN0L3NlbGVjdC5jb21wb25lbnQudHMiLCIuLi8uLi8uLi8uLi8uLi8uLi9wcm9qZWN0cy9jZmMtZHMvc3JjL2xpYi9jb21wb25lbnRzL3NlbGVjdC9zZWxlY3QuY29tcG9uZW50Lmh0bWwiXSwibmFtZXMiOltdLCJtYXBwaW5ncyI6IkFBQUEsT0FBTyxFQUdMLFNBQVMsRUFFVCxZQUFZLEVBQ1osVUFBVSxFQUNWLFlBQVksRUFDWixLQUFLLEVBRUwsTUFBTSxFQUdQLE1BQU0sZUFBZSxDQUFDO0FBQ3ZCLE9BQU8sRUFBd0IsaUJBQWlCLEVBQUUsYUFBYSxFQUFnRCxNQUFNLGdCQUFnQixDQUFDO0FBRXRJLE9BQU8sRUFBRSxVQUFVLEVBQUUsTUFBTSw4QkFBOEIsQ0FBQTs7Ozs7QUFtQnpELE1BQU0sT0FBTyxlQUFlO0lBeUNoQjtJQUNBO0lBQ0E7SUExQ1YsU0FBUztJQUNBLE9BQU8sR0FBVSxFQUFFLENBQUM7SUFDcEIsRUFBRSxDQUFVO0lBQ1osS0FBSyxDQUFVO0lBQ2YsV0FBVyxHQUFZLEVBQUUsQ0FBQztJQUMxQixXQUFXLEdBQUcsS0FBSyxDQUFDO0lBQ3BCLFdBQVcsR0FBRyxLQUFLLENBQUM7SUFDcEIsZUFBZSxDQUFVO0lBQ3pCLGFBQWEsQ0FBZ0I7SUFDN0IsY0FBYyxHQUFZLElBQUksQ0FBQztJQUMvQixhQUFhLEdBQVksS0FBSyxDQUFDO0lBQy9CLFFBQVEsR0FBWSxLQUFLLENBQUM7SUFDMUIsU0FBUyxDQUFVO0lBQ25CLGVBQWUsQ0FBVTtJQUN6QixRQUFRLEdBQVksS0FBSyxDQUFDO0lBQzFCLElBQUksR0FBZSxVQUFVLENBQUMsT0FBTyxDQUFDO0lBRS9DLFVBQVU7SUFDQSxRQUFRLEdBQXdCLElBQUksWUFBWSxFQUFTLENBQUM7SUFDMUQsTUFBTSxH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