costimize-mat-select-autocomplete
Version:
Angular material select component with autocomplete and select all features
496 lines (488 loc) • 36.2 kB
JavaScript
import * as i0 from '@angular/core';
import { Injectable, forwardRef, Component, Input, ViewChild, ViewChildren, NgModule } from '@angular/core';
import * as i2 from '@angular/forms';
import { UntypedFormControl, NG_VALUE_ACCESSOR, FormsModule, ReactiveFormsModule } from '@angular/forms';
import * as i10 from '@angular/material/button-toggle';
import { MatButtonToggleGroup, MatButtonToggleModule } from '@angular/material/button-toggle';
import * as i1 from '@angular/cdk/scrolling';
import { CdkVirtualScrollViewport, ScrollingModule } from '@angular/cdk/scrolling';
import * as i8 from '@angular/material/core';
import { MatOption } from '@angular/material/core';
import { distinctUntilChanged, filter } from 'rxjs/operators';
import * as i3 from '@angular/common';
import { CommonModule } from '@angular/common';
import * as i4 from '@angular/material/icon';
import { MatIconModule } from '@angular/material/icon';
import * as i5 from '@angular/material/button';
import { MatButtonModule } from '@angular/material/button';
import * as i6 from '@angular/material/form-field';
import { MatFormFieldModule } from '@angular/material/form-field';
import * as i7 from '@angular/material/select';
import { MatSelectModule } from '@angular/material/select';
import * as i9 from '@angular/material/checkbox';
import { MatCheckboxModule } from '@angular/material/checkbox';
import * as i11 from '@angular/material/tooltip';
import { MatTooltipModule } from '@angular/material/tooltip';
import { MatListModule } from '@angular/material/list';
class SelectAutocompleteService {
constructor() { }
/** @nocollapse */ static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "16.2.12", ngImport: i0, type: SelectAutocompleteService, deps: [], target: i0.ɵɵFactoryTarget.Injectable }); }
/** @nocollapse */ static { this.ɵprov = i0.ɵɵngDeclareInjectable({ minVersion: "12.0.0", version: "16.2.12", ngImport: i0, type: SelectAutocompleteService, providedIn: 'root' }); }
}
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "16.2.12", ngImport: i0, type: SelectAutocompleteService, decorators: [{
type: Injectable,
args: [{
providedIn: 'root'
}]
}], ctorParameters: function () { return []; } });
class SelectAutocompleteComponent {
constructor(cd, sd) {
this.cd = cd;
this.sd = sd;
this.selectPlaceholder = 'search...';
this.options = [];
this.errorMsg = 'Field is required';
this.showErrorMsg = false;
this.multiple = true;
this.favourites = false;
this.filterButtons = [];
this.appearance = 'standard';
this.filteredOptions = [];
this.selectAllChecked = false;
this.customSelectAllChecked = false;
this.displayString = '';
this.formControl = new UntypedFormControl([]);
this.searchInputFormControl = new UntypedFormControl('');
this.lastEmittedValue = undefined;
this.trackByFn = (index, item) => item.value;
this.onTouch = () => {
};
this.propagateChange = (_) => {
};
}
ngOnInit() {
if (this.selectAll) {
this.filterButtons.push({
name: this.selectAll,
filterCallback: () => true
});
}
this.filteredOptions = this.options;
}
ngAfterViewInit() {
this.searchInputFormControlSubscription = this.searchInputFormControl.valueChanges
.pipe(distinctUntilChanged())
.subscribe(newValue => {
this.filterItem(newValue);
});
this.sd
.scrolled()
.pipe(filter(scrollable => this.cdkVirtualScrollViewPort === scrollable))
.subscribe(() => {
let needUpdate = false;
this.matOptions.forEach(option => {
const selected = this.multiple ? this.selected.includes(option.value) : this.selected === option.value;
if (selected && !option.selected) {
option.select();
needUpdate = true;
}
else if (!selected && option.selected) {
option.deselect();
needUpdate = true;
}
});
if (needUpdate) {
this.cd.detectChanges();
}
});
}
ngOnChanges(changes) {
if (changes.options) {
this.filteredOptions = changes.options.currentValue;
this.writeValue(this.selected, true);
}
}
toggleDropdown() {
this.selectElem.toggle();
}
toggleSelectAll(event) {
this.deselectButtons();
this.customSelectAllChecked = false;
if (event.checked) {
this.selected = this.getFilteredOptionsValues();
}
else {
this.selected = [];
}
this.patchValue(this.selected);
}
filterItem(value) {
this.filteredOptions = this.options.filter(item => {
let valueIndex = 0;
const splitItem = item.display.split(/(?=[A-Z])|(-)|(\.)|(\s+)|(_)/).filter(Boolean);
for (let word of splitItem) {
let wordIndex = 0;
word = word.charAt(0).toUpperCase() + word.slice(1);
if (value.charAt(0).toUpperCase() === word.charAt(0) && valueIndex === 1) {
valueIndex = 0;
}
while (wordIndex < word.length) {
if (valueIndex < value.length && value[valueIndex].toUpperCase() === word[wordIndex]) {
valueIndex++;
wordIndex++;
while (valueIndex < value.length && value[valueIndex].toLowerCase() === word[wordIndex]) {
valueIndex++;
wordIndex++;
}
}
else {
wordIndex++;
}
}
}
return valueIndex === value.length;
});
this.selectAllChecked = !this.customSelectAllChecked
&& this.multiple
&& this.filteredOptions.length > 0
&& !this.filteredOptions.some(item => !this.selected.includes(item.value));
this.cdkVirtualScrollViewPort.scrollToIndex(1);
this.cdkVirtualScrollViewPort.checkViewportSize();
}
getFilteredOptionsValues() {
return this.filteredOptions.map(option => option.value);
}
getDisplayString() {
if (this.customSelectAllChecked) {
return this.selectAll;
}
let displayString = '';
if (this.selected && this.selected.length) {
if (this.multiple && this.selected.length === 1) {
displayString = this.options.find(option => option.value === this.selected[0]).display;
}
else if (this.multiple) {
displayString = this.selected.length + '/' + this.options.length;
}
else {
displayString = this.options.find(option => option.value === this.selected).display;
}
}
return displayString;
}
onSelectionChange(change) {
if (!change.isUserInput) {
return;
}
const value = change.source.value;
if (this.multiple) {
if (change.source.selected) {
this.selected.push(value);
if (this.selected.length === this.options.length) {
this.selectAllChecked = true;
}
}
else {
const elementIndex = this.selected.indexOf(change.source.value);
this.selected.splice(elementIndex, 1);
this.selectAllChecked = false;
}
}
else {
this.selected = value;
}
}
changeSelectedValues(clickedButtonEvent, filterCallback) {
this.selectedOptions = [];
this.selectAllChecked = false;
this.customSelectAllChecked = false;
if (clickedButtonEvent.source.checked) {
this.toggleGroup.value = [clickedButtonEvent.source.value];
this.selectedOptions = this.filteredOptions.filter(option => filterCallback(option.value, option.display));
if (clickedButtonEvent.value === this.selectAll) {
this.customSelectAllChecked = true;
this.selectedOptions = this.options.filter(option => filterCallback(option.value, option.display));
this.filterItem('');
}
this.toggleDropdown();
}
this.selected = this.selectedOptions.map(item => item.value);
this.patchValue(this.selected);
}
writeValue(selectedElements, clearLastEmittedValue = true) {
this.deselectButtons();
const allElementsValues = this.options.map(it => it.value);
if (this.multiple && selectedElements) {
this.customSelectAllChecked = false;
const filteredElements = selectedElements.filter(it => allElementsValues.includes(it));
this.selected = filteredElements;
this.selectAllChecked = selectedElements.length === allElementsValues.length;
this.patchValue(filteredElements);
}
else if (this.multiple && selectedElements == null) {
if (this.selectAll) {
this.selectAllChecked = false;
this.customSelectAllChecked = true;
setTimeout(() => this.toggleGroup.value = [this.selectAll]);
this.selected = allElementsValues;
this.patchValue(allElementsValues);
}
else {
this.customSelectAllChecked = false;
this.selected = [];
this.patchValue([]);
}
}
else if (!this.multiple
&& (selectedElements == null || selectedElements.length === 0 || !allElementsValues.includes(selectedElements))) {
this.customSelectAllChecked = false;
this.selected = null;
this.patchValue([]);
}
else {
this.customSelectAllChecked = false;
this.selected = selectedElements;
this.patchValue(selectedElements);
}
this.displayString = this.getDisplayString();
if (clearLastEmittedValue) {
this.lastEmittedValue = undefined;
}
this.emitValueIfChanged();
this.reorderOptionsSelectedFirst();
if (this.favourites)
this.reorderOptionsFavouritesFirst();
}
registerOnChange(fn) {
this.propagateChange = fn;
}
registerOnTouched(fn) {
this.onTouch = fn;
}
setDisabledState(isDisabled) {
if (isDisabled) {
this.formControl.disable({ emitEvent: false });
}
else {
this.formControl.enable({ emitEvent: false });
}
}
onClickOpen() {
try {
document.getElementById('costimize-dropdown-input').focus();
}
catch (error) {
}
this.cdkVirtualScrollViewPort.scrollToIndex(0);
this.cdkVirtualScrollViewPort.checkViewportSize();
}
onClickClose() {
this.searchInputFormControl.setValue('');
this.onTouch();
if (this.customSelectAllChecked) {
this.displayString = this.getDisplayString();
this.emitValueIfChanged();
}
else {
this.writeValue(this.selected, false);
}
this.cdkVirtualScrollViewPort.scrollToIndex(0);
this.cdkVirtualScrollViewPort.checkViewportSize();
}
emitValueIfChanged() {
const valueToEmit = this.getValueToPropagate();
if (this.valueChanged(valueToEmit, this.lastEmittedValue)) {
this.propagateChange(valueToEmit);
this.lastEmittedValue = valueToEmit;
}
}
deselectButtons() {
if (this.toggleGroup) {
this.toggleGroup.value = null;
}
}
reorderOptionsFavouritesFirst() {
const favouriteOptions = [], notFavouriteOptions = [];
this.options.forEach(option => {
if (option.favourite) {
favouriteOptions.push(option);
}
else {
notFavouriteOptions.push(option);
}
});
this.options = [...favouriteOptions, ...notFavouriteOptions];
this.filteredOptions = [...this.options];
}
reorderOptionsSelectedFirst() {
const selectedOptions = [], notSelectedOptions = [];
this.options.forEach(option => {
if (this.selected && this.optionIsSelected(option, this.selected)) {
selectedOptions.push(option);
}
else {
notSelectedOptions.push(option);
}
});
this.options = [...selectedOptions, ...notSelectedOptions];
this.filteredOptions = [...this.options];
}
optionIsSelected(option, selected) {
return (this.multiple && selected.some(it => it === option.value)) ||
(!this.multiple && selected === option.value);
}
patchValue(newValue) {
if (this.multiple && newValue != null) {
this.formControl.patchValue([...newValue]);
}
else {
this.formControl.patchValue(newValue);
if (this.favourites) {
this.isSelectedFavourite = this.filteredOptions.find(option => option.value == newValue)?.favourite;
}
}
}
ngOnDestroy() {
this.searchInputFormControlSubscription.unsubscribe();
}
getValueToPropagate() {
if (this.customSelectAllChecked) {
return null;
}
else {
return this.multiple ? [...this.selected] : this.selected;
}
}
valueChanged(newValue, oldValue) {
return oldValue === undefined ||
(!this.multiple && newValue !== oldValue) ||
(this.multiple && !this.arraysHaveTheSameElements(newValue, oldValue));
}
arraysHaveTheSameElements(array1, array2) {
if (array1 === array2) { // if they are both null
return true;
}
else if (array1?.length === array2?.length) {
const sortedArray2 = [...array2].sort();
return ![...array1].sort().some((array1Value, index) => array1Value !== sortedArray2[index]);
}
else {
return false;
}
}
/** @nocollapse */ static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "16.2.12", ngImport: i0, type: SelectAutocompleteComponent, deps: [{ token: i0.ChangeDetectorRef }, { token: i1.ScrollDispatcher }], target: i0.ɵɵFactoryTarget.Component }); }
/** @nocollapse */ static { this.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "14.0.0", version: "16.2.12", type: SelectAutocompleteComponent, selector: "mat-select-autocomplete", inputs: { selectPlaceholder: "selectPlaceholder", placeholder: "placeholder", options: "options", errorMsg: "errorMsg", showErrorMsg: "showErrorMsg", selectedOptions: "selectedOptions", multiple: "multiple", favourites: "favourites", filterButtons: "filterButtons", selectAll: "selectAll", appearance: "appearance" }, providers: [
{
provide: NG_VALUE_ACCESSOR,
useExisting: forwardRef((() => SelectAutocompleteComponent)),
multi: true
}
], viewQueries: [{ propertyName: "selectElem", first: true, predicate: ["selectElem"], descendants: true }, { propertyName: "toggleGroup", first: true, predicate: MatButtonToggleGroup, descendants: true }, { propertyName: "cdkVirtualScrollViewPort", first: true, predicate: CdkVirtualScrollViewport, descendants: true }, { propertyName: "matOptions", predicate: MatOption, descendants: true }], usesOnChanges: true, ngImport: i0, template: "<mat-form-field appearance=\"{{ appearance }}\">\r\n <mat-label>{{placeholder}}</mat-label>\r\n <mat-select\r\n panelClass=\"custom-select-pane\"\r\n #selectElem\r\n [formControl]=\"formControl\"\r\n [multiple]=\"multiple\"\r\n (openedChange)=\"$event ? onClickOpen() : onClickClose()\"\r\n >\r\n <div class=\"box-search\">\r\n <mat-checkbox\r\n *ngIf=\"multiple\"\r\n color=\"primary\"\r\n class=\"box-select-all\"\r\n matTooltip=\"Select all listed items\"\r\n [(ngModel)]=\"selectAllChecked\"\r\n (change)=\"toggleSelectAll($event)\"\r\n ></mat-checkbox>\r\n <input\r\n id=\"costimize-dropdown-input\"\r\n type='text'\r\n [ngClass]=\"{ 'pl-1': !multiple }\"\r\n [formControl]=\"searchInputFormControl\"\r\n [placeholder]=\"selectPlaceholder\"\r\n autocomplete=\"off\"\r\n (keydown)=\"$event.stopPropagation()\"\r\n />\r\n <div\r\n class=\"box-search-icon\"\r\n (click)=\"searchInputFormControl.setValue('')\"\r\n >\r\n <button mat-icon-button class=\"search-button\">\r\n <mat-icon class=\"mat-24\" aria-label=\"Search icon\">clear</mat-icon>\r\n </button>\r\n </div>\r\n </div>\r\n <mat-select-trigger class=\"option-container\">\r\n <span class=\"ellipsis-text\">{{ displayString }}</span>\r\n <mat-icon *ngIf=\"favourites && isSelectedFavourite\" class=\"input-icon icon-container fav-icon\">star_border</mat-icon>\r\n </mat-select-trigger>\r\n <div *ngIf=\"multiple && filterButtons.length > 0\" class=\"filter-buttons\">\r\n <mat-button-toggle-group multiple=\"true\" class=\"filter-buttons-group\">\r\n <mat-button-toggle class=\"filter-button\" *ngFor=\"let button of filterButtons;\"\r\n [value]=\"button.name\"\r\n (change)=\"changeSelectedValues($event, button.filterCallback)\">{{button.name}}\r\n </mat-button-toggle>\r\n </mat-button-toggle-group>\r\n </div>\r\n <cdk-virtual-scroll-viewport [itemSize]=\"24\" [style.height.px]=\"240\" class=\"cdk-viewport-format\">\r\n <mat-option\r\n *cdkVirtualFor=\"let option of filteredOptions; trackBy: trackByFn\"\r\n [disabled]=\"customSelectAllChecked\"\r\n [value]=\"option.value\"\r\n (onSelectionChange)=\"onSelectionChange($event)\"\r\n >\r\n <div class=\"option-container\">\r\n <span>{{ option.display }}</span>\r\n <span class=\"icon-container\" *ngIf=\"favourites && option?.favourite\">\r\n <mat-icon class=\"fav-icon\">star_border</mat-icon>\r\n </span>\r\n </div>\r\n </mat-option>\r\n </cdk-virtual-scroll-viewport>\r\n </mat-select>\r\n <mat-hint style=\"color:red\" *ngIf=\"showErrorMsg\">{{ errorMsg }}</mat-hint>\r\n</mat-form-field>\r\n", styles: [".box-search{margin:8px;border-radius:2px;box-shadow:0 2px 2px #00000029,0 0 0 1px #00000014;transition:box-shadow .2s cubic-bezier(.4,0,.2,1);background-color:transparent!important;display:flex;height:36px;justify-content:center;align-items:center}mat-select{font-size:14px!important}::ng-deep .mdc-text-field--filled:not(.mdc-text-field--disabled){background-color:transparent!important;height:39px;display:flex;justify-content:center;align-items:center;padding:0;font-size:14px}::ng-deep .mdc-text-field--filled:not(.mdc-text-field--disabled):hover .mdc-line-ripple:before{border-bottom-color:#0000006b}.mat-icon{height:21px}.mat-mdc-focus-indicator{display:flex;justify-content:center;align-items:center}::ng-deep .mat-mdc-form-field:hover .mat-mdc-form-field-focus-overlay{opacity:0}::ng-deep .mat-mdc-form-field .mat-mdc-form-field-focus-overlay{background-color:transparent!important}::ng-deep .cdk-overlay-pane:not(.mat-mdc-select-panel-above) .mdc-menu-surface.mat-mdc-select-panel{font-size:14px;position:relative;bottom:40px}::ng-deep .mat-mdc-checkbox .mdc-checkbox .mdc-checkbox__background{height:16px;width:16px}::ng-deep .mat-pseudo-checkbox{height:16px!important;width:16px!important}::ng-deep .mat-mdc-select-arrow svg{padding-right:5px}::ng-deep .cdk-overlay-pane:not(.mat-mdc-select-panel-above) .mdc-menu-surface.mat-mdc-select-panel{padding:0}.mat-mdc-icon-button.mat-mdc-button-base{width:36px;height:36px;padding:0}::ng-deep .mat-mdc-option .mat-pseudo-checkbox-minimal{display:none!important}.box-search input{flex:1;border:none;outline:none}.box-select-all{width:36px;line-height:33px;color:gray;text-align:center}.search-button{line-height:33px;color:gray}::ng-deep .mat-mdc-icon-button:hover{--mat-mdc-button-persistent-ripple-color: rgba(0, 0, 0, 0) !important}.pl-1{padding-left:1rem}.filter-buttons ::ng-deep .mat-button-toggle-label-content{text-align:center;line-height:34px!important}.filter-buttons .mat-button-toggle-group{line-height:20px!important;border:none;flex-wrap:wrap;width:100%}.filter-buttons .mat-button-toggle{border:solid 1px rgba(0,0,0,.1215686275);border-radius:4px;margin:5px 10px;height:34px;line-height:20px!important;width:100%}::-webkit-scrollbar{width:0;background:transparent}::ng-deep .mdc-menu-surface.mat-mdc-select-panel:has(input){min-width:calc(100% + 64px)}::ng-deep .mdc-menu-surface.mat-mdc-select-panel:has(input) .mat-mdc-option{word-break:break-all}::ng-deep .mdc-menu-surface.mat-mdc-select-panel:has(.mat-mdc-checkbox input){min-width:calc(100% + 96px)}::ng-deep .mdc-menu-surface.mat-mdc-select-panel{min-width:-moz-fit-content;min-width:fit-content}.cdk-viewport-format{overflow-x:hidden;overflow-y:auto;border:1px solid transparent;display:block}.cdk-viewport-format mat-option{font-size:14px;display:flex}::ng-deep .custom-select-pane.mat-mdc-select-panel.mdc-menu-surface{max-height:500px}.input-icon{font-size:18px;vertical-align:middle}.option-container{display:flex;justify-content:space-between;align-items:center;width:100%}.icon-container{margin-left:auto}.fav-icon{margin:0!important;color:#f90}::ng-deep .mdc-list-item__primary-text{width:100%}.ellipsis-text{width:100%;white-space:nowrap;overflow:hidden;text-overflow:ellipsis}\n"], dependencies: [{ kind: "directive", type: i2.DefaultValueAccessor, selector: "input:not([type=checkbox])[formControlName],textarea[formControlName],input:not([type=checkbox])[formControl],textarea[formControl],input:not([type=checkbox])[ngModel],textarea[ngModel],[ngDefaultControl]" }, { kind: "directive", type: i2.NgControlStatus, selector: "[formControlName],[ngModel],[formControl]" }, { kind: "directive", type: i2.NgModel, selector: "[ngModel]:not([formControlName]):not([formControl])", inputs: ["name", "disabled", "ngModel", "ngModelOptions"], outputs: ["ngModelChange"], exportAs: ["ngModel"] }, { kind: "directive", type: i3.NgClass, selector: "[ngClass]", inputs: ["class", "ngClass"] }, { kind: "directive", type: i3.NgForOf, selector: "[ngFor][ngForOf]", inputs: ["ngForOf", "ngForTrackBy", "ngForTemplate"] }, { kind: "directive", type: i3.NgIf, selector: "[ngIf]", inputs: ["ngIf", "ngIfThen", "ngIfElse"] }, { kind: "component", type: i4.MatIcon, selector: "mat-icon", inputs: ["color", "inline", "svgIcon", "fontSet", "fontIcon"], exportAs: ["matIcon"] }, { kind: "component", type: i5.MatIconButton, selector: "button[mat-icon-button]", inputs: ["disabled", "disableRipple", "color"], exportAs: ["matButton"] }, { kind: "component", type: i6.MatFormField, selector: "mat-form-field", inputs: ["hideRequiredMarker", "color", "floatLabel", "appearance", "subscriptSizing", "hintLabel"], exportAs: ["matFormField"] }, { kind: "directive", type: i6.MatLabel, selector: "mat-label" }, { kind: "directive", type: i6.MatHint, selector: "mat-hint", inputs: ["align", "id"] }, { kind: "component", type: i7.MatSelect, selector: "mat-select", inputs: ["disabled", "disableRipple", "tabIndex", "panelWidth", "hideSingleSelectionIndicator"], exportAs: ["matSelect"] }, { kind: "directive", type: i7.MatSelectTrigger, selector: "mat-select-trigger" }, { kind: "component", type: i8.MatOption, selector: "mat-option", exportAs: ["matOption"] }, { kind: "component", type: i9.MatCheckbox, selector: "mat-checkbox", inputs: ["disableRipple", "color", "tabIndex"], exportAs: ["matCheckbox"] }, { kind: "directive", type: i2.FormControlDirective, selector: "[formControl]", inputs: ["formControl", "disabled", "ngModel"], outputs: ["ngModelChange"], exportAs: ["ngForm"] }, { kind: "directive", type: i10.MatButtonToggleGroup, selector: "mat-button-toggle-group", inputs: ["appearance", "name", "vertical", "value", "multiple", "disabled"], outputs: ["valueChange", "change"], exportAs: ["matButtonToggleGroup"] }, { kind: "component", type: i10.MatButtonToggle, selector: "mat-button-toggle", inputs: ["disableRipple", "aria-label", "aria-labelledby", "id", "name", "value", "tabIndex", "appearance", "checked", "disabled"], outputs: ["change"], exportAs: ["matButtonToggle"] }, { kind: "directive", type: i11.MatTooltip, selector: "[matTooltip]", exportAs: ["matTooltip"] }, { kind: "directive", type: i1.CdkFixedSizeVirtualScroll, selector: "cdk-virtual-scroll-viewport[itemSize]", inputs: ["itemSize", "minBufferPx", "maxBufferPx"] }, { kind: "directive", type: i1.CdkVirtualForOf, selector: "[cdkVirtualFor][cdkVirtualForOf]", inputs: ["cdkVirtualForOf", "cdkVirtualForTrackBy", "cdkVirtualForTemplate", "cdkVirtualForTemplateCacheSize"] }, { kind: "component", type: i1.CdkVirtualScrollViewport, selector: "cdk-virtual-scroll-viewport", inputs: ["orientation", "appendOnly"], outputs: ["scrolledIndexChange"] }] }); }
}
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "16.2.12", ngImport: i0, type: SelectAutocompleteComponent, decorators: [{
type: Component,
args: [{ selector: 'mat-select-autocomplete', providers: [
{
provide: NG_VALUE_ACCESSOR,
useExisting: forwardRef((() => SelectAutocompleteComponent)),
multi: true
}
], template: "<mat-form-field appearance=\"{{ appearance }}\">\r\n <mat-label>{{placeholder}}</mat-label>\r\n <mat-select\r\n panelClass=\"custom-select-pane\"\r\n #selectElem\r\n [formControl]=\"formControl\"\r\n [multiple]=\"multiple\"\r\n (openedChange)=\"$event ? onClickOpen() : onClickClose()\"\r\n >\r\n <div class=\"box-search\">\r\n <mat-checkbox\r\n *ngIf=\"multiple\"\r\n color=\"primary\"\r\n class=\"box-select-all\"\r\n matTooltip=\"Select all listed items\"\r\n [(ngModel)]=\"selectAllChecked\"\r\n (change)=\"toggleSelectAll($event)\"\r\n ></mat-checkbox>\r\n <input\r\n id=\"costimize-dropdown-input\"\r\n type='text'\r\n [ngClass]=\"{ 'pl-1': !multiple }\"\r\n [formControl]=\"searchInputFormControl\"\r\n [placeholder]=\"selectPlaceholder\"\r\n autocomplete=\"off\"\r\n (keydown)=\"$event.stopPropagation()\"\r\n />\r\n <div\r\n class=\"box-search-icon\"\r\n (click)=\"searchInputFormControl.setValue('')\"\r\n >\r\n <button mat-icon-button class=\"search-button\">\r\n <mat-icon class=\"mat-24\" aria-label=\"Search icon\">clear</mat-icon>\r\n </button>\r\n </div>\r\n </div>\r\n <mat-select-trigger class=\"option-container\">\r\n <span class=\"ellipsis-text\">{{ displayString }}</span>\r\n <mat-icon *ngIf=\"favourites && isSelectedFavourite\" class=\"input-icon icon-container fav-icon\">star_border</mat-icon>\r\n </mat-select-trigger>\r\n <div *ngIf=\"multiple && filterButtons.length > 0\" class=\"filter-buttons\">\r\n <mat-button-toggle-group multiple=\"true\" class=\"filter-buttons-group\">\r\n <mat-button-toggle class=\"filter-button\" *ngFor=\"let button of filterButtons;\"\r\n [value]=\"button.name\"\r\n (change)=\"changeSelectedValues($event, button.filterCallback)\">{{button.name}}\r\n </mat-button-toggle>\r\n </mat-button-toggle-group>\r\n </div>\r\n <cdk-virtual-scroll-viewport [itemSize]=\"24\" [style.height.px]=\"240\" class=\"cdk-viewport-format\">\r\n <mat-option\r\n *cdkVirtualFor=\"let option of filteredOptions; trackBy: trackByFn\"\r\n [disabled]=\"customSelectAllChecked\"\r\n [value]=\"option.value\"\r\n (onSelectionChange)=\"onSelectionChange($event)\"\r\n >\r\n <div class=\"option-container\">\r\n <span>{{ option.display }}</span>\r\n <span class=\"icon-container\" *ngIf=\"favourites && option?.favourite\">\r\n <mat-icon class=\"fav-icon\">star_border</mat-icon>\r\n </span>\r\n </div>\r\n </mat-option>\r\n </cdk-virtual-scroll-viewport>\r\n </mat-select>\r\n <mat-hint style=\"color:red\" *ngIf=\"showErrorMsg\">{{ errorMsg }}</mat-hint>\r\n</mat-form-field>\r\n", styles: [".box-search{margin:8px;border-radius:2px;box-shadow:0 2px 2px #00000029,0 0 0 1px #00000014;transition:box-shadow .2s cubic-bezier(.4,0,.2,1);background-color:transparent!important;display:flex;height:36px;justify-content:center;align-items:center}mat-select{font-size:14px!important}::ng-deep .mdc-text-field--filled:not(.mdc-text-field--disabled){background-color:transparent!important;height:39px;display:flex;justify-content:center;align-items:center;padding:0;font-size:14px}::ng-deep .mdc-text-field--filled:not(.mdc-text-field--disabled):hover .mdc-line-ripple:before{border-bottom-color:#0000006b}.mat-icon{height:21px}.mat-mdc-focus-indicator{display:flex;justify-content:center;align-items:center}::ng-deep .mat-mdc-form-field:hover .mat-mdc-form-field-focus-overlay{opacity:0}::ng-deep .mat-mdc-form-field .mat-mdc-form-field-focus-overlay{background-color:transparent!important}::ng-deep .cdk-overlay-pane:not(.mat-mdc-select-panel-above) .mdc-menu-surface.mat-mdc-select-panel{font-size:14px;position:relative;bottom:40px}::ng-deep .mat-mdc-checkbox .mdc-checkbox .mdc-checkbox__background{height:16px;width:16px}::ng-deep .mat-pseudo-checkbox{height:16px!important;width:16px!important}::ng-deep .mat-mdc-select-arrow svg{padding-right:5px}::ng-deep .cdk-overlay-pane:not(.mat-mdc-select-panel-above) .mdc-menu-surface.mat-mdc-select-panel{padding:0}.mat-mdc-icon-button.mat-mdc-button-base{width:36px;height:36px;padding:0}::ng-deep .mat-mdc-option .mat-pseudo-checkbox-minimal{display:none!important}.box-search input{flex:1;border:none;outline:none}.box-select-all{width:36px;line-height:33px;color:gray;text-align:center}.search-button{line-height:33px;color:gray}::ng-deep .mat-mdc-icon-button:hover{--mat-mdc-button-persistent-ripple-color: rgba(0, 0, 0, 0) !important}.pl-1{padding-left:1rem}.filter-buttons ::ng-deep .mat-button-toggle-label-content{text-align:center;line-height:34px!important}.filter-buttons .mat-button-toggle-group{line-height:20px!important;border:none;flex-wrap:wrap;width:100%}.filter-buttons .mat-button-toggle{border:solid 1px rgba(0,0,0,.1215686275);border-radius:4px;margin:5px 10px;height:34px;line-height:20px!important;width:100%}::-webkit-scrollbar{width:0;background:transparent}::ng-deep .mdc-menu-surface.mat-mdc-select-panel:has(input){min-width:calc(100% + 64px)}::ng-deep .mdc-menu-surface.mat-mdc-select-panel:has(input) .mat-mdc-option{word-break:break-all}::ng-deep .mdc-menu-surface.mat-mdc-select-panel:has(.mat-mdc-checkbox input){min-width:calc(100% + 96px)}::ng-deep .mdc-menu-surface.mat-mdc-select-panel{min-width:-moz-fit-content;min-width:fit-content}.cdk-viewport-format{overflow-x:hidden;overflow-y:auto;border:1px solid transparent;display:block}.cdk-viewport-format mat-option{font-size:14px;display:flex}::ng-deep .custom-select-pane.mat-mdc-select-panel.mdc-menu-surface{max-height:500px}.input-icon{font-size:18px;vertical-align:middle}.option-container{display:flex;justify-content:space-between;align-items:center;width:100%}.icon-container{margin-left:auto}.fav-icon{margin:0!important;color:#f90}::ng-deep .mdc-list-item__primary-text{width:100%}.ellipsis-text{width:100%;white-space:nowrap;overflow:hidden;text-overflow:ellipsis}\n"] }]
}], ctorParameters: function () { return [{ type: i0.ChangeDetectorRef }, { type: i1.ScrollDispatcher }]; }, propDecorators: { selectPlaceholder: [{
type: Input
}], placeholder: [{
type: Input
}], options: [{
type: Input
}], errorMsg: [{
type: Input
}], showErrorMsg: [{
type: Input
}], selectedOptions: [{
type: Input
}], multiple: [{
type: Input
}], favourites: [{
type: Input
}], filterButtons: [{
type: Input
}], selectAll: [{
type: Input
}], appearance: [{
type: Input
}], selectElem: [{
type: ViewChild,
args: ['selectElem']
}], toggleGroup: [{
type: ViewChild,
args: [MatButtonToggleGroup]
}], cdkVirtualScrollViewPort: [{
type: ViewChild,
args: [CdkVirtualScrollViewport]
}], matOptions: [{
type: ViewChildren,
args: [MatOption]
}] } });
class SelectAutocompleteModule {
/** @nocollapse */ static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "16.2.12", ngImport: i0, type: SelectAutocompleteModule, deps: [], target: i0.ɵɵFactoryTarget.NgModule }); }
/** @nocollapse */ static { this.ɵmod = i0.ɵɵngDeclareNgModule({ minVersion: "14.0.0", version: "16.2.12", ngImport: i0, type: SelectAutocompleteModule, declarations: [SelectAutocompleteComponent], imports: [FormsModule,
CommonModule,
MatIconModule,
MatButtonModule,
MatSelectModule,
MatCheckboxModule,
MatFormFieldModule,
ReactiveFormsModule,
MatButtonToggleModule,
MatTooltipModule,
ScrollingModule,
MatListModule], exports: [SelectAutocompleteComponent] }); }
/** @nocollapse */ static { this.ɵinj = i0.ɵɵngDeclareInjector({ minVersion: "12.0.0", version: "16.2.12", ngImport: i0, type: SelectAutocompleteModule, imports: [FormsModule,
CommonModule,
MatIconModule,
MatButtonModule,
MatSelectModule,
MatCheckboxModule,
MatFormFieldModule,
ReactiveFormsModule,
MatButtonToggleModule,
MatTooltipModule,
ScrollingModule,
MatListModule] }); }
}
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "16.2.12", ngImport: i0, type: SelectAutocompleteModule, decorators: [{
type: NgModule,
args: [{
imports: [
FormsModule,
CommonModule,
MatIconModule,
MatButtonModule,
MatSelectModule,
MatCheckboxModule,
MatFormFieldModule,
ReactiveFormsModule,
MatButtonToggleModule,
MatTooltipModule,
ScrollingModule,
MatListModule,
],
declarations: [SelectAutocompleteComponent],
exports: [SelectAutocompleteComponent]
}]
}] });
class DropdownKeyValue {
constructor(id, name, favourite = false) {
this.value = id;
this.display = name;
this.favourite = favourite;
}
}
/*
* Public API Surface of select-autocomplete
*/
/**
* Generated bundle index. Do not edit.
*/
export { DropdownKeyValue, SelectAutocompleteComponent, SelectAutocompleteModule, SelectAutocompleteService };
//# sourceMappingURL=costimize-mat-select-autocomplete.mjs.map