@asoftwareworld/form-builder-pro
Version:
ASW Form Builder Pro helps you with rapid development and designed web forms which includes several controls. The key feature of Form Builder is to make your content attractive and effective. We can customize our control at run time and preview the same b
561 lines (554 loc) • 38.4 kB
JavaScript
import { A, Z, ZERO, NINE, SPACE, HOME, END, ENTER, ESCAPE, UP_ARROW, DOWN_ARROW } from '@angular/cdk/keycodes';
import * as i0 from '@angular/core';
import { InjectionToken, EventEmitter, ElementRef, forwardRef, ContentChild, ViewChild, Output, Input, Inject, Optional, ChangeDetectionStrategy, Component, NgModule } from '@angular/core';
import * as i3 from '@angular/forms';
import { FormControl, NG_VALUE_ACCESSOR, FormsModule, ReactiveFormsModule } from '@angular/forms';
import * as i12 from '@angular/material/core';
import { MatOption } from '@angular/material/core';
import * as i13 from '@angular/material/form-field';
import { MatFormField } from '@angular/material/form-field';
import * as i11 from '@angular/material/select';
import { MatSelect } from '@angular/material/select';
import { AswSelectSearchClearDirective, AswSelectNoEntriesFoundDirective, MaterialModule, AswPipeModule, AswDirectiveModule } from '@asoftwareworld/form-builder-pro/common';
import { BehaviorSubject, of, combineLatest, Subject } from 'rxjs';
import { switchMap, map, startWith, delay, takeUntil, take, tap, filter } from 'rxjs/operators';
import * as i1 from '@angular/cdk/scrolling';
import * as i2 from '@angular/common';
import { CommonModule } from '@angular/common';
import * as i4 from '@angular/material/button';
import * as i5 from '@angular/material/checkbox';
import * as i6 from '@angular/material/divider';
import * as i7 from '@angular/material/input';
import * as i8 from '@angular/material/tooltip';
import * as i9 from '@angular/material/icon';
import * as i10 from '@angular/material/progress-spinner';
import { MatProgressSpinnerModule } from '@angular/material/progress-spinner';
import { AswTranslateModule } from '@asoftwareworld/form-builder-pro/core';
import { AswConfirmDialogModule } from '@asoftwareworld/form-builder-pro/form-control/confirm-dialog';
import { AswSharedDialogModule } from '@asoftwareworld/form-builder-pro/form-control/shared';
const configurableDefaultOptions = [
'ariaLabel',
'clearSearchInput',
'closeIcon',
'closeSvgIcon',
'disableInitialFocus',
'disableScrollToActiveOnOptionsChanged',
'enableClearOnEscapePressed',
'hideClearSearchButton',
'noEntriesFoundLabel',
'placeholderLabel',
'preventHomeEndKeyPropagation',
'searching'
];
/**
* InjectionToken that can be used to specify global options. e.g.
*
* ```typescript
* providers: [
* {
* provide: ASW_SELECTSEARCH_DEFAULT_OPTIONS,
* useValue: <AswSelectSearchOptions>{
* closeIcon: 'delete',
* noEntriesFoundLabel: 'No options found'
* }
* }
* ]
* ```
*
* See the corresponding inputs of `AswSelectSearch` for documentation.
*/
const ASW_SELECTSEARCH_DEFAULT_OPTIONS = new InjectionToken('asw-selectsearch-default-options');
class AswSelectSearch {
matSelect;
changeDetectorRef;
_viewportRuler;
matOption;
matFormField;
/** Label of the search placeholder */
placeholderLabel = 'Search';
/** Type of the search input field */
type = 'text';
/** Font-based icon used for displaying Close-Icon */
closeIcon = 'close';
/** Svg-based icon used for displaying Close-Icon. If set, closeIcon is overridden */
closeSvgIcon = '';
/** Label to be shown when no entries are found. Set to null if no message should be shown. */
noEntriesFoundLabel = 'No results found';
/**
* Whether or not the search field should be cleared after the dropdown menu is closed.
*/
clearSearchInput = true;
/** Whether to show the search-in-progress indicator */
searching = false;
/** Disables initial focusing of the input field */
disableInitialFocus = false;
/** Enable clear input on escape pressed */
enableClearOnEscapePressed = false;
/**
* Prevents home / end key being propagated to mat-select,
* allowing to move the cursor within the search input instead of navigating the options
*/
preventHomeEndKeyPropagation = false;
/** Disables scrolling to active options when option list changes. Useful for server-side search */
disableScrollToActiveOnOptionsChanged = false;
/** Adds 508 screen reader support for search box */
ariaLabel = 'dropdown search';
/** Whether to show Select All Checkbox (for mat-select[multi=true]) */
showToggleAllCheckbox = false;
/** select all checkbox checked state */
toggleAllCheckboxChecked = false;
/** select all checkbox indeterminate state */
toggleAllCheckboxIndeterminate = false;
/** Display a message in a tooltip on the toggle-all checkbox */
toggleAllCheckboxTooltipMessage = '';
/** Define the position of the tooltip on the toggle-all checkbox. */
toggleAllCheckboxTooltipPosition = 'below';
/** Show/Hide the search clear button of the search input */
hideClearSearchButton = false;
/**
* Always restore selected options on selectionChange for mode multi (e.g. for lazy loading/infinity scrolling).
* Defaults to false, so selected options are only restored while filtering is active.
*/
alwaysRestoreSelectedOptionsMulti = false;
/** Output emitter to send to parent component with the toggle all boolean */
toggleAll = new EventEmitter();
/** Reference to the search input field */
searchSelectInput;
/** Reference to the search input field */
innerSelectSearch;
/** Reference to custom search input clear icon */
clearIcon;
/** Reference to custom no entries found element */
noEntriesFound;
/** Current search value */
get value() {
return this._formControl.value;
}
_lastExternalInputValue;
onTouched = (_) => { };
/** Reference to the MatSelect options */
set _options(_options) {
this._options$.next(_options);
}
get _options() {
return this._options$.getValue();
}
_options$ = new BehaviorSubject(null);
optionsList$ = this._options$.pipe(switchMap((_options) => _options
? _options.changes.pipe(map((options) => options.toArray()), startWith(_options.toArray()))
: of(null)));
optionsLength$ = this.optionsList$.pipe(map((options) => (options ? options.length : 0)));
/** Previously selected values when using <mat-select [multiple]="true">*/
previousSelectedValues = [];
_formControl = new FormControl('');
/** whether to show the no entries found message */
_showNoEntriesFound$ = combineLatest([this._formControl.valueChanges, this.optionsLength$]).pipe(map(([value, optionsLength]) => this.noEntriesFoundLabel && value && optionsLength === this.getOptionsLengthOffset()));
/** Subject that emits when the component has been destroyed. */
_onDestroy = new Subject();
/** Reference to active descendant for ARIA Support. */
activeDescendant;
constructor(matSelect, changeDetectorRef, _viewportRuler, matOption, matFormField, defaultOptions) {
this.matSelect = matSelect;
this.changeDetectorRef = changeDetectorRef;
this._viewportRuler = _viewportRuler;
this.matOption = matOption;
this.matFormField = matFormField;
this.applyDefaultOptions(defaultOptions);
}
applyDefaultOptions(defaultOptions) {
if (!defaultOptions) {
return;
}
for (const key of configurableDefaultOptions) {
if (defaultOptions.hasOwnProperty(key)) {
this[key] = defaultOptions[key];
}
}
}
ngOnInit() {
// set custom mat-option class if the component was placed inside a mat-option
if (this.matOption) {
this.matOption.disabled = true;
this.matOption._getHostElement().classList.add('contains-mat-select-search');
this.matOption._getHostElement().setAttribute('aria-hidden', 'true');
}
else {
console.error('<asw-select-search> must be placed inside a <mat-option> element');
}
// when the select dropdown panel is opened or closed
this.matSelect.openedChange.pipe(delay(1), takeUntil(this._onDestroy)).subscribe((opened) => {
if (opened) {
this.updateInputWidth();
// focus the search field when opening
if (!this.disableInitialFocus) {
this._focus();
}
}
else {
// clear it when closing
if (this.clearSearchInput) {
this._reset();
}
}
});
// set the first item active after the options changed
this.matSelect.openedChange
.pipe(take(1), switchMap((_) => {
this._options = this.matSelect.options;
// Closure variable for tracking the most recent first option.
// In order to avoid avoid causing the list to
// scroll to the top when options are added to the bottom of
// the list (eg: infinite scroll), we compare only
// the changes to the first options to determine if we
// should set the first item as active.
// This prevents unnecessary scrolling to the top of the list
// when options are appended, but allows the first item
// in the list to be set as active by default when there
// is no active selection
let previousFirstOption = this._options.toArray()[this.getOptionsLengthOffset()];
return this._options.changes.pipe(tap(() => {
// avoid "expression has been changed" error
setTimeout(() => {
// Convert the QueryList to an array
const options = this._options.toArray();
// The true first item is offset by 1
const currentFirstOption = options[this.getOptionsLengthOffset()];
const keyManager = this.matSelect._keyManager;
if (keyManager && this.matSelect.panelOpen && currentFirstOption) {
// set first item active and input width
// Check to see if the first option in these changes is different from the previous.
const firstOptionIsChanged = !previousFirstOption || !this.matSelect.compareWith(previousFirstOption.value, currentFirstOption.value);
// CASE: The first option is different now.
// Indiciates we should set it as active and scroll to the top.
if (firstOptionIsChanged || !keyManager.activeItem || !options.find((option) => this.matSelect.compareWith(option.value, keyManager.activeItem?.value))) {
keyManager.setActiveItem(this.getOptionsLengthOffset());
}
// wait for panel width changes
setTimeout(() => {
this.updateInputWidth();
});
}
// Update our reference
previousFirstOption = currentFirstOption;
});
}));
}))
.pipe(takeUntil(this._onDestroy))
.subscribe();
// add or remove css class depending on whether to show the no entries found message
// note: this is hacky
this._showNoEntriesFound$.pipe(takeUntil(this._onDestroy)).subscribe((showNoEntriesFound) => {
// set no entries found class on mat option
if (this.matOption) {
if (showNoEntriesFound) {
this.matOption._getHostElement().classList.add('mat-select-search-no-entries-found');
}
else {
this.matOption._getHostElement().classList.remove('mat-select-search-no-entries-found');
}
}
});
// resize the input width when the viewport is resized, i.e. the trigger width could potentially be resized
this._viewportRuler
.change()
.pipe(takeUntil(this._onDestroy))
.subscribe(() => {
if (this.matSelect.panelOpen) {
this.updateInputWidth();
}
});
this.initMultipleHandling();
this.optionsList$.pipe(takeUntil(this._onDestroy)).subscribe(() => {
// update view when available options change
this.changeDetectorRef.markForCheck();
});
}
_emitSelectAllBooleanToParent(state) {
this.toggleAll.emit(state);
}
ngOnDestroy() {
this._onDestroy.next();
this._onDestroy.complete();
}
_isToggleAllCheckboxVisible() {
return this.matSelect.multiple && this.showToggleAllCheckbox;
}
/**
* Handles the key down event with MatSelect.
* Allows e.g. selecting with enter key, navigation with arrow keys, etc.
* @param event
*/
_handleKeydown(event) {
// Prevent propagation for all alphanumeric characters in order to avoid selection issues
if ((event.key && event.key.length === 1) ||
(event.keyCode >= A && event.keyCode <= Z) ||
(event.keyCode >= ZERO && event.keyCode <= NINE) ||
event.keyCode === SPACE ||
(this.preventHomeEndKeyPropagation && (event.keyCode === HOME || event.keyCode === END))) {
event.stopPropagation();
}
if (this.matSelect.multiple && event.key && event.keyCode === ENTER) {
// Regain focus after multiselect, so we can further type
setTimeout(() => this._focus());
}
// Special case if click Escape, if input is empty, close the dropdown, if not, empty out the search field
if (this.enableClearOnEscapePressed === true && event.keyCode === ESCAPE && this.value) {
this._reset(true);
event.stopPropagation();
}
}
/**
* Handles the key up event with MatSelect.
* Allows e.g. the announcing of the currently activeDescendant by screen readers.
*/
_handleKeyup(event) {
if (event.keyCode === UP_ARROW || event.keyCode === DOWN_ARROW) {
const ariaActiveDescendantId = this.matSelect._getAriaActiveDescendant();
const index = this._options.toArray().findIndex((item) => item.id === ariaActiveDescendantId);
if (index !== -1) {
this.unselectActiveDescendant();
this.activeDescendant = this._options.toArray()[index]._getHostElement();
this.activeDescendant.setAttribute('aria-selected', 'true');
this.searchSelectInput?.nativeElement.setAttribute('aria-activedescendant', ariaActiveDescendantId);
}
}
}
writeValue(value) {
this._lastExternalInputValue = value;
this._formControl.setValue(value);
this.changeDetectorRef.markForCheck();
}
onBlur() {
this.unselectActiveDescendant();
this.onTouched();
}
registerOnChange(fn) {
this._formControl.valueChanges
.pipe(filter((value) => value !== this._lastExternalInputValue), tap(() => (this._lastExternalInputValue = undefined)), takeUntil(this._onDestroy))
.subscribe(fn);
}
registerOnTouched(fn) {
this.onTouched = fn;
}
/**
* Focuses the search input field
*/
_focus() {
if (!this.searchSelectInput || !this.matSelect.panel) {
return;
}
// save and restore scrollTop of panel, since it will be reset by focus()
// note: this is hacky
const panel = this.matSelect.panel.nativeElement;
const scrollTop = panel.scrollTop;
// focus
this.searchSelectInput.nativeElement.focus();
panel.scrollTop = scrollTop;
}
/**
* Resets the current search value
* @param focus whether to focus after resetting
*/
_reset(focus) {
this._formControl.setValue('');
if (focus) {
this._focus();
}
}
/**
* Initializes handling <mat-select [multiple]="true">
* Note: to improve this code, mat-select should be extended to allow disabling resetting the selection while filtering.
*/
initMultipleHandling() {
if (!this.matSelect.ngControl) {
if (this.matSelect.multiple) {
// note: the access to matSelect.ngControl (instead of matSelect.value / matSelect.valueChanges)
// is necessary to properly work in multi-selection mode.
console.error('the mat-select containing asw-select-search must have a ngModel or formControl directive when multiple=true');
}
return;
}
// if <mat-select [multiple]="true">
// store previously selected values and restore them when they are deselected
// because the option is not available while we are currently filtering
this.previousSelectedValues = this.matSelect.ngControl.value;
this.matSelect.ngControl.valueChanges?.pipe(takeUntil(this._onDestroy)).subscribe((values) => {
let restoreSelectedValues = false;
if (this.matSelect.multiple) {
if ((this.alwaysRestoreSelectedOptionsMulti || (this._formControl.value && this._formControl.value.length)) && this.previousSelectedValues && Array.isArray(this.previousSelectedValues)) {
if (!values || !Array.isArray(values)) {
values = [];
}
const optionValues = this.matSelect.options.map((option) => option.value);
this.previousSelectedValues.forEach((previousValue) => {
if (!values.some((v) => this.matSelect.compareWith(v, previousValue)) && !optionValues.some((v) => this.matSelect.compareWith(v, previousValue))) {
// if a value that was selected before is deselected and not found in the options, it was deselected
// due to the filtering, so we restore it.
values.push(previousValue);
restoreSelectedValues = true;
}
});
}
}
this.previousSelectedValues = values;
if (restoreSelectedValues) {
this.matSelect._onChange(values);
}
});
}
/**
* Set the width of the innerSelectSearch to fit even custom scrollbars
* And support all Operation Systems
*/
updateInputWidth() {
if (!this.innerSelectSearch || !this.innerSelectSearch.nativeElement) {
return;
}
let element = this.innerSelectSearch.nativeElement;
let panelElement; // Initialize it;
while ((element = element?.parentElement)) {
if (element.classList.contains('mat-select-panel')) {
panelElement = element;
break;
}
}
if (panelElement) {
this.innerSelectSearch.nativeElement.style.width = panelElement.clientWidth + 'px';
}
}
/**
* Determine the offset to length that can be caused by the optional matOption used as a search input.
*/
getOptionsLengthOffset() {
if (this.matOption) {
return 1;
}
else {
return 0;
}
}
unselectActiveDescendant() {
this.activeDescendant?.removeAttribute('aria-selected');
this.searchSelectInput?.nativeElement.removeAttribute('aria-activedescendant');
}
static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "18.2.8", ngImport: i0, type: AswSelectSearch, deps: [{ token: MatSelect }, { token: i0.ChangeDetectorRef }, { token: i1.ViewportRuler }, { token: MatOption, optional: true }, { token: MatFormField, optional: true }, { token: ASW_SELECTSEARCH_DEFAULT_OPTIONS, optional: true }], target: i0.ɵɵFactoryTarget.Component });
static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "14.0.0", version: "18.2.8", type: AswSelectSearch, selector: "asw-select-search", inputs: { placeholderLabel: "placeholderLabel", type: "type", closeIcon: "closeIcon", closeSvgIcon: "closeSvgIcon", noEntriesFoundLabel: "noEntriesFoundLabel", clearSearchInput: "clearSearchInput", searching: "searching", disableInitialFocus: "disableInitialFocus", enableClearOnEscapePressed: "enableClearOnEscapePressed", preventHomeEndKeyPropagation: "preventHomeEndKeyPropagation", disableScrollToActiveOnOptionsChanged: "disableScrollToActiveOnOptionsChanged", ariaLabel: "ariaLabel", showToggleAllCheckbox: "showToggleAllCheckbox", toggleAllCheckboxChecked: "toggleAllCheckboxChecked", toggleAllCheckboxIndeterminate: "toggleAllCheckboxIndeterminate", toggleAllCheckboxTooltipMessage: "toggleAllCheckboxTooltipMessage", toggleAllCheckboxTooltipPosition: "toggleAllCheckboxTooltipPosition", hideClearSearchButton: "hideClearSearchButton", alwaysRestoreSelectedOptionsMulti: "alwaysRestoreSelectedOptionsMulti" }, outputs: { toggleAll: "toggleAll" }, providers: [
{
provide: NG_VALUE_ACCESSOR,
useExisting: forwardRef(() => AswSelectSearch),
multi: true
}
], queries: [{ propertyName: "clearIcon", first: true, predicate: AswSelectSearchClearDirective, descendants: true }, { propertyName: "noEntriesFound", first: true, predicate: AswSelectNoEntriesFoundDirective, descendants: true }], viewQueries: [{ propertyName: "searchSelectInput", first: true, predicate: ["searchSelectInput"], descendants: true, read: ElementRef, static: true }, { propertyName: "innerSelectSearch", first: true, predicate: ["innerSelectSearch"], descendants: true, read: ElementRef, static: true }], ngImport: i0, template: "<input matInput class=\"mat-select-search-input mat-select-search-hidden\" />\r\n\r\n<!-- Note: the mat-datepicker-content mat-tab-header are needed to inherit the material theme colors, see PR #22 -->\r\n<div #innerSelectSearch class=\"mat-select-search-inner mat-typography mat-datepicker-content mat-tab-header\"\r\n [ngClass]=\"{'mat-select-search-inner-multiple': matSelect.multiple, 'mat-select-search-inner-toggle-all': _isToggleAllCheckboxVisible() }\">\r\n\r\n <div class=\"mat-select-search-inner-row\">\r\n <mat-checkbox *ngIf=\"_isToggleAllCheckboxVisible()\" [color]=\"matFormField.color\"\r\n class=\"mat-select-search-toggle-all-checkbox\" [checked]=\"toggleAllCheckboxChecked\"\r\n [indeterminate]=\"toggleAllCheckboxIndeterminate\" [matTooltip]=\"toggleAllCheckboxTooltipMessage\"\r\n matTooltipClass=\"asw-select-search-toggle-all-tooltip\"\r\n [matTooltipPosition]=\"toggleAllCheckboxTooltipPosition\"\r\n (change)=\"_emitSelectAllBooleanToParent($event.checked)\"></mat-checkbox>\r\n\r\n <input class=\"mat-select-search-input\" autocomplete=\"off\" [type]=\"type\" [formControl]=\"_formControl\"\r\n #searchSelectInput (keydown)=\"_handleKeydown($event)\" (keyup)=\"_handleKeyup($event)\" (blur)=\"onBlur()\"\r\n [placeholder]=\"placeholderLabel\" [attr.aria-label]=\"ariaLabel\" />\r\n <mat-spinner *ngIf=\"searching\" class=\"mat-select-search-spinner\" diameter=\"16\"></mat-spinner>\r\n\r\n <button *ngIf=\"!hideClearSearchButton && value && !searching\" mat-icon-button aria-label=\"Clear\"\r\n (click)=\"_reset(true)\" class=\"mat-select-search-clear\">\r\n <ng-content *ngIf=\"clearIcon; else defaultIcon\" select=\"[aswSelectSearchClear]\"></ng-content>\r\n <ng-template #defaultIcon>\r\n <mat-icon [svgIcon]=\"closeSvgIcon\">\r\n {{!closeSvgIcon ? closeIcon : null}}\r\n </mat-icon>\r\n </ng-template>\r\n </button>\r\n\r\n <ng-content select=\".mat-select-search-custom-header-content\"></ng-content>\r\n </div> \r\n\r\n <mat-divider></mat-divider>\r\n</div>\r\n\r\n<div *ngIf=\"_showNoEntriesFound$ | async\" class=\"mat-select-search-no-entries-found\">\r\n <ng-content *ngIf=\"noEntriesFound; else defaultNoEntriesFound\" select=\"[aswSelectNoEntriesFound]\"></ng-content>\r\n <ng-template #defaultNoEntriesFound>{{noEntriesFoundLabel}}</ng-template>\r\n</div>", styles: [".mat-select-search-hidden{visibility:hidden}.mat-select-search-inner{position:absolute;top:0;left:0;width:100%;z-index:100;font-size:inherit;box-shadow:none;background-color:var(--mat-select-panel-background-color)}.mat-select-search-inner.mat-select-search-inner-multiple.mat-select-search-inner-toggle-all .mat-select-search-inner-row{display:flex;align-items:center}.mat-select-search-input{box-sizing:border-box;width:100%;border:none;font-family:inherit;font-size:inherit;color:currentColor;outline:none;background-color:var(--mat-select-panel-background-color);padding:0 44px 0 16px;height:calc(3em - 1px);line-height:calc(3em - 1px)}:host-context([dir=rtl]) .mat-select-search-input{padding-right:16px;padding-left:44px}.mat-select-search-inner-toggle-all .mat-select-search-input{padding-left:5px}.mat-select-search-no-entries-found{padding-top:8px}.mat-select-search-clear{position:absolute;right:4px;top:0}:host-context([dir=rtl]) .mat-select-search-clear{right:auto;left:4px}.mat-select-search-spinner{position:absolute;right:16px;top:calc(50% - 8px)}:host-context([dir=rtl]) .mat-select-search-spinner{right:auto;left:16px}::ng-deep .mat-mdc-option[aria-disabled=true].contains-mat-select-search{position:sticky;top:-8px;z-index:1;opacity:1;margin-top:-8px;pointer-events:all}::ng-deep .mat-mdc-option[aria-disabled=true].contains-mat-select-search .mat-icon{margin-right:0;margin-left:0}::ng-deep .mat-mdc-option[aria-disabled=true].contains-mat-select-search mat-pseudo-checkbox{display:none}::ng-deep .mat-mdc-option[aria-disabled=true].contains-mat-select-search .mdc-list-item__primary-text{opacity:1}.mat-select-search-toggle-all-checkbox{padding-left:5px}:host-context([dir=rtl]) .mat-select-search-toggle-all-checkbox{padding-left:0;padding-right:5px}\n"], dependencies: [{ kind: "directive", type: i2.NgClass, selector: "[ngClass]", inputs: ["class", "ngClass"] }, { kind: "directive", type: i2.NgIf, selector: "[ngIf]", inputs: ["ngIf", "ngIfThen", "ngIfElse"] }, { kind: "directive", type: i3.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: i3.NgControlStatus, selector: "[formControlName],[ngModel],[formControl]" }, { kind: "directive", type: i3.FormControlDirective, selector: "[formControl]", inputs: ["formControl", "disabled", "ngModel"], outputs: ["ngModelChange"], exportAs: ["ngForm"] }, { kind: "component", type: i4.MatIconButton, selector: "button[mat-icon-button]", exportAs: ["matButton"] }, { kind: "component", type: i5.MatCheckbox, selector: "mat-checkbox", inputs: ["aria-label", "aria-labelledby", "aria-describedby", "id", "required", "labelPosition", "name", "value", "disableRipple", "tabIndex", "color", "disabledInteractive", "checked", "disabled", "indeterminate"], outputs: ["change", "indeterminateChange"], exportAs: ["matCheckbox"] }, { kind: "component", type: i6.MatDivider, selector: "mat-divider", inputs: ["vertical", "inset"] }, { kind: "directive", type: i7.MatInput, selector: "input[matInput], textarea[matInput], select[matNativeControl], input[matNativeControl], textarea[matNativeControl]", inputs: ["disabled", "id", "placeholder", "name", "required", "type", "errorStateMatcher", "aria-describedby", "value", "readonly"], exportAs: ["matInput"] }, { kind: "directive", type: i8.MatTooltip, selector: "[matTooltip]", inputs: ["matTooltipPosition", "matTooltipPositionAtOrigin", "matTooltipDisabled", "matTooltipShowDelay", "matTooltipHideDelay", "matTooltipTouchGestures", "matTooltip", "matTooltipClass"], exportAs: ["matTooltip"] }, { kind: "component", type: i9.MatIcon, selector: "mat-icon", inputs: ["color", "inline", "svgIcon", "fontSet", "fontIcon"], exportAs: ["matIcon"] }, { kind: "component", type: i10.MatProgressSpinner, selector: "mat-progress-spinner, mat-spinner", inputs: ["color", "mode", "value", "diameter", "strokeWidth"], exportAs: ["matProgressSpinner"] }, { kind: "pipe", type: i2.AsyncPipe, name: "async" }], changeDetection: i0.ChangeDetectionStrategy.OnPush });
}
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "18.2.8", ngImport: i0, type: AswSelectSearch, decorators: [{
type: Component,
args: [{ selector: 'asw-select-search', providers: [
{
provide: NG_VALUE_ACCESSOR,
useExisting: forwardRef(() => AswSelectSearch),
multi: true
}
], changeDetection: ChangeDetectionStrategy.OnPush, template: "<input matInput class=\"mat-select-search-input mat-select-search-hidden\" />\r\n\r\n<!-- Note: the mat-datepicker-content mat-tab-header are needed to inherit the material theme colors, see PR #22 -->\r\n<div #innerSelectSearch class=\"mat-select-search-inner mat-typography mat-datepicker-content mat-tab-header\"\r\n [ngClass]=\"{'mat-select-search-inner-multiple': matSelect.multiple, 'mat-select-search-inner-toggle-all': _isToggleAllCheckboxVisible() }\">\r\n\r\n <div class=\"mat-select-search-inner-row\">\r\n <mat-checkbox *ngIf=\"_isToggleAllCheckboxVisible()\" [color]=\"matFormField.color\"\r\n class=\"mat-select-search-toggle-all-checkbox\" [checked]=\"toggleAllCheckboxChecked\"\r\n [indeterminate]=\"toggleAllCheckboxIndeterminate\" [matTooltip]=\"toggleAllCheckboxTooltipMessage\"\r\n matTooltipClass=\"asw-select-search-toggle-all-tooltip\"\r\n [matTooltipPosition]=\"toggleAllCheckboxTooltipPosition\"\r\n (change)=\"_emitSelectAllBooleanToParent($event.checked)\"></mat-checkbox>\r\n\r\n <input class=\"mat-select-search-input\" autocomplete=\"off\" [type]=\"type\" [formControl]=\"_formControl\"\r\n #searchSelectInput (keydown)=\"_handleKeydown($event)\" (keyup)=\"_handleKeyup($event)\" (blur)=\"onBlur()\"\r\n [placeholder]=\"placeholderLabel\" [attr.aria-label]=\"ariaLabel\" />\r\n <mat-spinner *ngIf=\"searching\" class=\"mat-select-search-spinner\" diameter=\"16\"></mat-spinner>\r\n\r\n <button *ngIf=\"!hideClearSearchButton && value && !searching\" mat-icon-button aria-label=\"Clear\"\r\n (click)=\"_reset(true)\" class=\"mat-select-search-clear\">\r\n <ng-content *ngIf=\"clearIcon; else defaultIcon\" select=\"[aswSelectSearchClear]\"></ng-content>\r\n <ng-template #defaultIcon>\r\n <mat-icon [svgIcon]=\"closeSvgIcon\">\r\n {{!closeSvgIcon ? closeIcon : null}}\r\n </mat-icon>\r\n </ng-template>\r\n </button>\r\n\r\n <ng-content select=\".mat-select-search-custom-header-content\"></ng-content>\r\n </div> \r\n\r\n <mat-divider></mat-divider>\r\n</div>\r\n\r\n<div *ngIf=\"_showNoEntriesFound$ | async\" class=\"mat-select-search-no-entries-found\">\r\n <ng-content *ngIf=\"noEntriesFound; else defaultNoEntriesFound\" select=\"[aswSelectNoEntriesFound]\"></ng-content>\r\n <ng-template #defaultNoEntriesFound>{{noEntriesFoundLabel}}</ng-template>\r\n</div>", styles: [".mat-select-search-hidden{visibility:hidden}.mat-select-search-inner{position:absolute;top:0;left:0;width:100%;z-index:100;font-size:inherit;box-shadow:none;background-color:var(--mat-select-panel-background-color)}.mat-select-search-inner.mat-select-search-inner-multiple.mat-select-search-inner-toggle-all .mat-select-search-inner-row{display:flex;align-items:center}.mat-select-search-input{box-sizing:border-box;width:100%;border:none;font-family:inherit;font-size:inherit;color:currentColor;outline:none;background-color:var(--mat-select-panel-background-color);padding:0 44px 0 16px;height:calc(3em - 1px);line-height:calc(3em - 1px)}:host-context([dir=rtl]) .mat-select-search-input{padding-right:16px;padding-left:44px}.mat-select-search-inner-toggle-all .mat-select-search-input{padding-left:5px}.mat-select-search-no-entries-found{padding-top:8px}.mat-select-search-clear{position:absolute;right:4px;top:0}:host-context([dir=rtl]) .mat-select-search-clear{right:auto;left:4px}.mat-select-search-spinner{position:absolute;right:16px;top:calc(50% - 8px)}:host-context([dir=rtl]) .mat-select-search-spinner{right:auto;left:16px}::ng-deep .mat-mdc-option[aria-disabled=true].contains-mat-select-search{position:sticky;top:-8px;z-index:1;opacity:1;margin-top:-8px;pointer-events:all}::ng-deep .mat-mdc-option[aria-disabled=true].contains-mat-select-search .mat-icon{margin-right:0;margin-left:0}::ng-deep .mat-mdc-option[aria-disabled=true].contains-mat-select-search mat-pseudo-checkbox{display:none}::ng-deep .mat-mdc-option[aria-disabled=true].contains-mat-select-search .mdc-list-item__primary-text{opacity:1}.mat-select-search-toggle-all-checkbox{padding-left:5px}:host-context([dir=rtl]) .mat-select-search-toggle-all-checkbox{padding-left:0;padding-right:5px}\n"] }]
}], ctorParameters: () => [{ type: i11.MatSelect, decorators: [{
type: Inject,
args: [MatSelect]
}] }, { type: i0.ChangeDetectorRef }, { type: i1.ViewportRuler }, { type: i12.MatOption, decorators: [{
type: Optional
}, {
type: Inject,
args: [MatOption]
}] }, { type: i13.MatFormField, decorators: [{
type: Optional
}, {
type: Inject,
args: [MatFormField]
}] }, { type: undefined, decorators: [{
type: Optional
}, {
type: Inject,
args: [ASW_SELECTSEARCH_DEFAULT_OPTIONS]
}] }], propDecorators: { placeholderLabel: [{
type: Input
}], type: [{
type: Input
}], closeIcon: [{
type: Input
}], closeSvgIcon: [{
type: Input
}], noEntriesFoundLabel: [{
type: Input
}], clearSearchInput: [{
type: Input
}], searching: [{
type: Input
}], disableInitialFocus: [{
type: Input
}], enableClearOnEscapePressed: [{
type: Input
}], preventHomeEndKeyPropagation: [{
type: Input
}], disableScrollToActiveOnOptionsChanged: [{
type: Input
}], ariaLabel: [{
type: Input
}], showToggleAllCheckbox: [{
type: Input
}], toggleAllCheckboxChecked: [{
type: Input
}], toggleAllCheckboxIndeterminate: [{
type: Input
}], toggleAllCheckboxTooltipMessage: [{
type: Input
}], toggleAllCheckboxTooltipPosition: [{
type: Input
}], hideClearSearchButton: [{
type: Input
}], alwaysRestoreSelectedOptionsMulti: [{
type: Input
}], toggleAll: [{
type: Output
}], searchSelectInput: [{
type: ViewChild,
args: ['searchSelectInput', { read: ElementRef, static: true }]
}], innerSelectSearch: [{
type: ViewChild,
args: ['innerSelectSearch', { read: ElementRef, static: true }]
}], clearIcon: [{
type: ContentChild,
args: [AswSelectSearchClearDirective]
}], noEntriesFound: [{
type: ContentChild,
args: [AswSelectNoEntriesFoundDirective]
}] } });
/**
* @license
* Copyright ASW (A Software World) All Rights Reserved.
*
* Use of this source code is governed by an MIT-style license that can be
* found in the LICENSE file
*/
class AswSelectSearchModule {
static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "18.2.8", ngImport: i0, type: AswSelectSearchModule, deps: [], target: i0.ɵɵFactoryTarget.NgModule });
static ɵmod = i0.ɵɵngDeclareNgModule({ minVersion: "14.0.0", version: "18.2.8", ngImport: i0, type: AswSelectSearchModule, declarations: [AswSelectSearch], imports: [CommonModule, FormsModule, ReactiveFormsModule, MaterialModule, AswConfirmDialogModule, AswSharedDialogModule, AswTranslateModule, AswPipeModule, MatProgressSpinnerModule, AswDirectiveModule], exports: [AswSelectSearch] });
static ɵinj = i0.ɵɵngDeclareInjector({ minVersion: "12.0.0", version: "18.2.8", ngImport: i0, type: AswSelectSearchModule, imports: [CommonModule, FormsModule, ReactiveFormsModule, MaterialModule, AswConfirmDialogModule, AswSharedDialogModule, AswTranslateModule, AswPipeModule, MatProgressSpinnerModule, AswDirectiveModule] });
}
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "18.2.8", ngImport: i0, type: AswSelectSearchModule, decorators: [{
type: NgModule,
args: [{
imports: [CommonModule, FormsModule, ReactiveFormsModule, MaterialModule, AswConfirmDialogModule, AswSharedDialogModule, AswTranslateModule, AswPipeModule, MatProgressSpinnerModule, AswDirectiveModule],
declarations: [AswSelectSearch],
exports: [AswSelectSearch]
}]
}] });
/**
* @license
* Copyright ASW (A Software World) All Rights Reserved.
*
* Use of this source code is governed by an MIT-style license that can be
* found in the LICENSE file
*/
/**
* Generated bundle index. Do not edit.
*/
export { ASW_SELECTSEARCH_DEFAULT_OPTIONS, AswSelectSearch, AswSelectSearchModule, configurableDefaultOptions };
//# sourceMappingURL=asoftwareworld-form-builder-pro-form-control-select-search.mjs.map