UNPKG

@koalarx/ui

Version:

Koala UI is a modern and accessible component library designed to speed up interface development in Angular projects. With simple integration and clear documentation, you can easily build robust and visually appealing applications.

458 lines (442 loc) 29 kB
import * as i0 from '@angular/core'; import { afterRenderEffect, isSignal, runInInjectionContext, effect, ChangeDetectionStrategy, Component, createComponent, inject, ApplicationRef, DestroyRef, Injector, viewChild, signal, model, input, booleanAttribute, output, Injectable } from '@angular/core'; import * as i1 from '@angular/forms'; import { FormsModule, ReactiveFormsModule } from '@angular/forms'; import { Loader } from '@koalarx/ui/core/components/loader'; import { AppConfig } from '@koalarx/ui/core/config'; import { FieldErrors } from '@koalarx/ui/shared/components/field-errors'; import { InputFieldBase } from '@koalarx/ui/shared/components/input-field'; import { delay } from '@koalarx/utils/KlDelay'; import { toObservable, takeUntilDestroyed } from '@angular/core/rxjs-interop'; import { debounceTime } from 'rxjs/internal/operators/debounceTime'; import { isEmpty } from '@koalarx/ui/shared/utils'; function changeSelectedOption(component, direction = 'down') { if (!component.selectElement.classList.contains('opened')) { return; } const options = component.selectElement.querySelectorAll('option, .kl-select-options-content .kl-select-option-content'); const selectedOption = component.selectElement.querySelector('option:checked') ?? component.selectElement.querySelector('label.kl-select-option-content:has(input:checked)'); let newIndex = 0; if (selectedOption) { const currentIndex = Array.from(options).indexOf(selectedOption); if (direction === 'down') { newIndex = currentIndex + 1 < options.length ? currentIndex + 1 : currentIndex; } else { newIndex = currentIndex - 1 >= 0 ? currentIndex - 1 : currentIndex; } } const option = options[newIndex]; const event = new Event('change', { bubbles: true }); if (option instanceof HTMLOptionElement) { option.selected = true; component.selectElement.dispatchEvent(event); } else { option.querySelector('input').checked = true; options.forEach((opt) => opt.classList.remove('active')); option.classList.toggle('active'); option.querySelector('input').dispatchEvent(event); } } function updateScrollPosition(component, direction = 'down') { if (!component.selectElement.classList.contains('opened')) { return; } setTimeout(() => { const optionsContainer = component.selectElement.querySelector('.kl-select-options-content'); const focusedOptionElement = optionsContainer.querySelector('option:checked') ?? component.selectElement.querySelector('label.kl-select-option-content:has(input:checked)'); if (focusedOptionElement) { optionsContainer.scrollTo({ top: direction === 'down' ? optionsContainer.scrollTop + focusedOptionElement.getBoundingClientRect().height : optionsContainer.scrollTop - focusedOptionElement.getBoundingClientRect().height, }); } }, 50); } function initOnKeyDownListener(component) { function onKeyDown(event) { switch (event.key) { case 'ArrowDown': { event.stopPropagation(); event.preventDefault(); changeSelectedOption(component, 'down'); updateScrollPosition(component, 'down'); break; } case 'ArrowUp': { event.stopPropagation(); event.preventDefault(); changeSelectedOption(component, 'up'); updateScrollPosition(component, 'up'); break; } } } addEventListener('keydown', onKeyDown); component.destroyRef.onDestroy(() => { removeEventListener('keydown', onKeyDown); }); } function assessibility(component) { initOnKeyDownListener(component); } function ajustOptionsContainerSize(component) { afterRenderEffect(() => { const selectElement = component.selectElement; const optionsContainer = selectElement.parentElement?.querySelector('.kl-select-options-container'); function setMaxWidth() { const currentWidth = selectElement.offsetWidth; selectElement.style.setProperty('--select-width', `${currentWidth}px`); } function setMaxHeight() { const optionsRect = selectElement.getBoundingClientRect(); const viewportHeight = window.innerHeight; const sizeDiscount = 16 + optionsRect.height; let availableHeight = viewportHeight - optionsRect.top - sizeDiscount; if (availableHeight < 150) { availableHeight = viewportHeight - (viewportHeight - optionsRect.bottom) - sizeDiscount; selectElement.style.setProperty('--select-position-area', 'top'); } else { selectElement.style.setProperty('--select-position-area', 'bottom'); } optionsContainer.style.maxHeight = `${availableHeight}px`; } function getFilterInput() { return optionsContainer.querySelector('.kl-select-filter-container input'); } function disableFilter() { const filterInput = getFilterInput(); if (filterInput) { filterInput.disabled = true; } } function enableAndFocusFilter() { const filterInput = getFilterInput(); if (filterInput) { filterInput.disabled = false; filterInput.focus(); } } function touchControl() { component.control().markAsTouched(); } const observer = new IntersectionObserver((entries) => { entries.forEach((entry) => { if (entry.isIntersecting) { component.selectElement.classList.add('opened'); setMaxWidth(); setMaxHeight(); enableAndFocusFilter(); touchControl(); } else { component.selectElement.classList.remove('opened'); disableFilter(); } }); }); setMaxWidth(); observer.observe(optionsContainer); component.destroyRef.onDestroy(() => observer.unobserve(optionsContainer)); }); } function generateOptionsResource(component) { const options = component.options(); let optionsResource; if (Object.hasOwn(options, 'value')) { optionsResource = { onServer: options }; } else if (isSignal(options)) { optionsResource = { inMemoryWithLoading: options, }; } else if (typeof options === 'function') { const resourceFnOptions = options; optionsResource = { onDemand: runInInjectionContext(component.injector, () => resourceFnOptions(component.requestOptionsParams)), }; } else { optionsResource = { inMemory: options }; } component.optionsResource.set(optionsResource); } function isLoadingFeedback(component) { effect(async () => { const isLoading = component.isLoading(); if (!isLoading) { while (!component.selectField()) { await delay(50); } const selectedContent = component.selectElement.querySelector('.selectcontent'); selectedContent.style.opacity = '0'; if (!component.disabled()) { component.isDisabled.set(false); } await delay(1); selectedContent.style.opacity = '1'; } else { component.isDisabled.set(true); } }); } function onServerFilter(component) { toObservable(component.filter, { injector: component.injector }) .pipe(debounceTime(300), takeUntilDestroyed(component.destroyRef)) .subscribe((value) => component.filteredValue.set(value ?? null)); effect(() => { if (component.optionsResource()?.onDemand) { component.requestOptionsParams.set({ filter: component.filteredValue(), internalFilter: component.internalFilter(), currentValue: component.control().value, }); } }, { injector: component.injector }); } function loadOptions(component) { effect(() => { const options = component.optionsResource(); if (!options) { return; } const { onDemand, onServer, inMemory, inMemoryWithLoading } = options; if (onDemand) { component.optionList.set(onDemand.value()); component.isLoading.set(onDemand.isLoading()); } else if (onServer) { component.optionList.set(component.applyFilter(onServer.value())); component.isLoading.set(onServer.isLoading()); } else if (inMemory) { component.optionList.set(component.applyFilter(inMemory)); component.isLoading.set(false); } else if (inMemoryWithLoading) { const optionsWithLoading = inMemoryWithLoading(); component.optionList.set(component.applyFilter(optionsWithLoading ?? [])); component.isLoading.set(!optionsWithLoading); } }); } class SelectOptionBadge { removeCallback = () => { throw new Error('Remove callback not set'); }; static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "21.0.6", ngImport: i0, type: SelectOptionBadge, deps: [], target: i0.ɵɵFactoryTarget.Component }); static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "14.0.0", version: "21.0.6", type: SelectOptionBadge, isStandalone: true, selector: "kl-select-option-badge", ngImport: i0, template: "<span class=\"flex items-center badge badge-primary badge-sm rounded-sm\">\n <ng-content />\n <i class=\"fa-solid fa-xmark text-neutral-400 hover:cursor-pointer\"\n (click)=\"removeCallback($event)\">\n </i>\n</span>\n", changeDetection: i0.ChangeDetectionStrategy.OnPush }); } i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.0.6", ngImport: i0, type: SelectOptionBadge, decorators: [{ type: Component, args: [{ selector: 'kl-select-option-badge', changeDetection: ChangeDetectionStrategy.OnPush, template: "<span class=\"flex items-center badge badge-primary badge-sm rounded-sm\">\n <ng-content />\n <i class=\"fa-solid fa-xmark text-neutral-400 hover:cursor-pointer\"\n (click)=\"removeCallback($event)\">\n </i>\n</span>\n" }] }] }); function hasValue(value) { return Array.isArray(value) ? value.length > 0 : !isEmpty(value); } function createBadgeElement(component, content, value) { const badgeComponent = createComponent(SelectOptionBadge, { environmentInjector: component.appRef.injector, projectableNodes: [[content]], }); badgeComponent.instance.removeCallback = (event) => component.removeOption(event); const element = badgeComponent.location.nativeElement; const spanElement = element.firstElementChild; spanElement.dataset['value'] = value; return element; } async function appendSelectedOptionContent(component, value) { while (component.isLoading()) { await delay(50); } const selectedContent = component.selectElement.querySelector('.selectcontent'); if (!Array.isArray(value)) { value = isEmpty(value) ? [] : [value]; } if (!component.multiple()) { selectedContent.innerHTML = ''; } selectedContent .querySelectorAll('span[data-value]') .forEach((node) => { if (!value.map(String).includes(node.dataset['value'])) { node.parentElement.remove(); } }); for (const v of value) { const optionData = component .selectedOptions() .find((item) => String(item.value) === String(v)); if (!optionData) { continue; } const optionContent = document.createElement('span'); optionContent.dataset['value'] = String(v); optionContent.innerHTML = optionData?.label ?? v; if (selectedContent.querySelector(`[data-value="${v}"]`)) { continue; } const optionBadge = component.multiple() ? createBadgeElement(component, optionContent, v) : optionContent; selectedContent.appendChild(optionBadge); } component.hasValue.set(hasValue(value)); component.selectElement .querySelectorAll('input[type=checkbox]') .forEach((input) => { input.checked = value.map(String).includes(input.value); }); } function setSelectedOptionsOnComponent(component, value) { component.selectedOptions.set(component .optionList() .filter((item) => Array.isArray(value) ? value.map(String).includes(String(item.value)) : String(item.value) === String(value))); } async function setSelectedOptionContent(component) { const value = component.control().value; component.hasValue.set(hasValue(value)); while (component.isLoading()) { await delay(50); } setSelectedOptionsOnComponent(component, value); await appendSelectedOptionContent(component, value); component .control() .valueChanges.pipe(debounceTime(50), takeUntilDestroyed(component.destroyRef)) .subscribe((value) => { setSelectedOptionsOnComponent(component, value); appendSelectedOptionContent(component, value); }); } class Select extends InputFieldBase { appRef = inject(ApplicationRef); destroyRef = inject(DestroyRef); injector = inject(Injector); selectField = viewChild('selectField', ...(ngDevMode ? [{ debugName: "selectField" }] : [])); optionsResource = signal(null, ...(ngDevMode ? [{ debugName: "optionsResource" }] : [])); optionList = signal([], ...(ngDevMode ? [{ debugName: "optionList" }] : [])); selectedOptions = signal([], ...(ngDevMode ? [{ debugName: "selectedOptions" }] : [])); isLoading = signal(true, ...(ngDevMode ? [{ debugName: "isLoading" }] : [])); requestOptionsParams = signal({ filter: null, currentValue: null, internalFilter: null, }, ...(ngDevMode ? [{ debugName: "requestOptionsParams" }] : [])); translations = inject(AppConfig).translation.form; supportsExperimentalSelect = !CSS.supports('appearance', 'base-select'); hasValue = signal(false, ...(ngDevMode ? [{ debugName: "hasValue" }] : [])); filter = model(...(ngDevMode ? [undefined, { debugName: "filter" }] : [])); filteredValue = signal(null, ...(ngDevMode ? [{ debugName: "filteredValue" }] : [])); options = input.required(...(ngDevMode ? [{ debugName: "options" }] : [])); internalFilter = input(null, ...(ngDevMode ? [{ debugName: "internalFilter" }] : [])); withoutFilter = input(false, { ...(ngDevMode ? { debugName: "withoutFilter" } : {}), transform: booleanAttribute }); multiple = input(false, { ...(ngDevMode ? { debugName: "multiple" } : {}), transform: booleanAttribute }); selectedItem = output(); get selectElement() { const selectField = this.selectField(); if (!selectField) { throw new Error('Select element not found'); } return selectField.nativeElement; } constructor() { super(); loadOptions(this); ajustOptionsContainerSize(this); isLoadingFeedback(this); assessibility(this); } ngOnInit() { onServerFilter(this); generateOptionsResource(this); setSelectedOptionContent(this); } applyFilter(options) { const filter = this.filter() ?? ''; return options.filter((option) => option.label.toLowerCase().includes(filter.toLowerCase())); } setValue(event) { const select = event.target; const value = select.value; if (this.multiple()) { const selectedOptionsElements = this.selectElement.querySelectorAll('.kl-select-options-content input[type="checkbox"]:checked'); const values = []; selectedOptionsElements.forEach((option) => values.push(option.value)); if (select.checked) { this.selectedOptions.update((current) => [ ...current, this.optionList().find((item) => String(item.value) === value), ]); } else { this.selectedOptions.update((current) => current.filter((item) => String(item.value) !== value)); } const selectedValues = this.selectedOptions().map((item) => item.value); this.control().setValue(selectedValues, { emitEvent: true }); return; } const selectedOption = this.optionList().find((item) => String(item.value) === value); if (selectedOption) { this.selectedOptions.set([selectedOption]); this.control().setValue(selectedOption.value, { emitEvent: true }); } this.selectedItem.emit(selectedOption?.data ?? null); } clear(event) { event.preventDefault(); this.selectedOptions.set([]); this.control().setValue(null); } removeOption(event) { event.preventDefault(); const target = event.target; const value = target.parentElement?.dataset['value']; const inputValue = this.selectElement.querySelector(`.kl-select-options-content input[value="${value}"]`); inputValue.click(); } static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "21.0.6", ngImport: i0, type: Select, deps: [], target: i0.ɵɵFactoryTarget.Component }); static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "21.0.6", type: Select, isStandalone: true, selector: "kl-select", inputs: { filter: { classPropertyName: "filter", publicName: "filter", isSignal: true, isRequired: false, transformFunction: null }, options: { classPropertyName: "options", publicName: "options", isSignal: true, isRequired: true, transformFunction: null }, internalFilter: { classPropertyName: "internalFilter", publicName: "internalFilter", isSignal: true, isRequired: false, transformFunction: null }, withoutFilter: { classPropertyName: "withoutFilter", publicName: "withoutFilter", isSignal: true, isRequired: false, transformFunction: null }, multiple: { classPropertyName: "multiple", publicName: "multiple", isSignal: true, isRequired: false, transformFunction: null } }, outputs: { filter: "filterChange", selectedItem: "selectedItem" }, viewQueries: [{ propertyName: "selectField", first: true, predicate: ["selectField"], descendants: true, isSignal: true }], usesInheritance: true, ngImport: i0, template: "<div class=\"kl-select-container relative w-full has-[select:disabled]:cursor-not-allowed\"\n [class.has-value]=\"hasValue()\">\n\n @if (label(); as label) {\n <label class=\"kl-select-label flex items-center gap-2 whitespace-nowrap text-neutral-900 dark:text-neutral-300\"\n [attr.for]=\"fieldId\">\n @if (isDisabled()) {\n <span class=\"text-neutral-200 dark:text-neutral-600\">\n {{ label }} {{ isRequired() ? '*' : '' }}\n </span>\n } @else {\n <span>{{ label }} {{ isRequired() ? '*' : '' }}</span>\n }\n </label>\n }\n\n @if (!isDisabled() && hasValue()) {\n <div class=\"flex items-center justify-center h-full absolute top-0 right-7 z-10 pr-2\">\n <button class=\"kl-select-clear-button text-neutral-400 hover:cursor-pointer text-sm focus:shadow-none!\"\n type=\"button\"\n (click)=\"clear($event)\">\n <i class=\"fa-solid fa-xmark\"></i>\n </button>\n </div>\n }\n\n <div class=\"kl-select-content\" #selectField>\n <button type=\"button\" class=\"kl-select-button flex disabled:border-neutral-200! disabled:dark:border-neutral-800!\"\n [attr.popovertarget]=\"fieldId\"\n popovertargetaction=\"toggle\">\n\n <span class=\"selectcontent flex flex-wrap gap-1 items-center w-full h-full\" [class.py-3]=\"multiple()\"></span>\n\n <span class=\"picker\">\n @if (isLoading()) {\n <kl-loader size=\"small\" />\n } @else {\n <i class=\"fa-solid fa-caret-down\"></i>\n }\n </span>\n </button>\n\n <div [id]=\"fieldId\" popover class=\"kl-select-options-container with-popover relative flex flex-col overflow-hidden\">\n @if (!withoutFilter()) {\n <div class=\"kl-select-filter-container border-b border-neutral-200 dark:border-neutral-700\">\n <label class=\"flex items-center text-sm\">\n <i class=\"fa-solid fa-magnifying-glass opacity-60 absolute top-3 left-4\"></i>\n <input class=\"w-full p-2 pr-3 pl-10 outline-none placeholder:opacity-60\"\n #searchInput\n type=\"search\"\n [(ngModel)]=\"filter\"\n [placeholder]=\"translations.selectTypeSearch\"\n />\n </label>\n </div>\n }\n\n <div class=\"kl-select-options-content p-1 overflow-auto\">\n @for (item of optionList(); track $index) {\n @let optionLabelId = fieldId + '-' + item.value;\n\n <label class=\"kl-select-option-content relative py-1 px-2 pr-8 rounded-md\"\n [attr.for]=\"optionLabelId\"\n [attr.data-index]=\"$index\">\n <span class=\"w-full\">\n @let isChecked = multiple() ? (control().value || []).includes(item.value) : item.value === control().value;\n\n <input\n [type]=\"multiple() ? 'checkbox' : 'radio'\"\n [id]=\"optionLabelId\"\n [name]=\"fieldId\"\n [attr.value]=\"item.value\"\n [checked]=\"isChecked\"\n (change)=\"setValue($event)\"\n />\n <span>{{ item.label }}</span>\n </span>\n </label>\n }\n </div>\n </div>\n </div>\n</div>\n\n@if (hint()) {\n <span class=\"hint-content\">\n <i class=\"fa-regular fa-circle-question\"></i> {{hint()}}\n </span>\n}\n\n<kl-field-errors [field]=\"control()\">\n <ng-container errors>\n <ng-content select=\"[errors]\" />\n </ng-container>\n</kl-field-errors>\n", dependencies: [{ kind: "ngmodule", type: FormsModule }, { kind: "directive", type: i1.DefaultValueAccessor, selector: "input:not([type=checkbox])[formControlName],textarea[formControlName],input:not([type=checkbox])[formControl],textarea[formControl],input:not([type=checkbox])[ngModel],textarea[ngModel],[ngDefaultControl]" }, { kind: "directive", type: i1.NgControlStatus, selector: "[formControlName],[ngModel],[formControl]" }, { kind: "directive", type: i1.NgModel, selector: "[ngModel]:not([formControlName]):not([formControl])", inputs: ["name", "disabled", "ngModel", "ngModelOptions"], outputs: ["ngModelChange"], exportAs: ["ngModel"] }, { kind: "ngmodule", type: ReactiveFormsModule }, { kind: "component", type: FieldErrors, selector: "kl-field-errors", inputs: ["field"] }, { kind: "component", type: Loader, selector: "kl-loader", inputs: ["size"] }], changeDetection: i0.ChangeDetectionStrategy.OnPush }); } i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.0.6", ngImport: i0, type: Select, decorators: [{ type: Component, args: [{ selector: 'kl-select', imports: [FormsModule, ReactiveFormsModule, FieldErrors, Loader], changeDetection: ChangeDetectionStrategy.OnPush, template: "<div class=\"kl-select-container relative w-full has-[select:disabled]:cursor-not-allowed\"\n [class.has-value]=\"hasValue()\">\n\n @if (label(); as label) {\n <label class=\"kl-select-label flex items-center gap-2 whitespace-nowrap text-neutral-900 dark:text-neutral-300\"\n [attr.for]=\"fieldId\">\n @if (isDisabled()) {\n <span class=\"text-neutral-200 dark:text-neutral-600\">\n {{ label }} {{ isRequired() ? '*' : '' }}\n </span>\n } @else {\n <span>{{ label }} {{ isRequired() ? '*' : '' }}</span>\n }\n </label>\n }\n\n @if (!isDisabled() && hasValue()) {\n <div class=\"flex items-center justify-center h-full absolute top-0 right-7 z-10 pr-2\">\n <button class=\"kl-select-clear-button text-neutral-400 hover:cursor-pointer text-sm focus:shadow-none!\"\n type=\"button\"\n (click)=\"clear($event)\">\n <i class=\"fa-solid fa-xmark\"></i>\n </button>\n </div>\n }\n\n <div class=\"kl-select-content\" #selectField>\n <button type=\"button\" class=\"kl-select-button flex disabled:border-neutral-200! disabled:dark:border-neutral-800!\"\n [attr.popovertarget]=\"fieldId\"\n popovertargetaction=\"toggle\">\n\n <span class=\"selectcontent flex flex-wrap gap-1 items-center w-full h-full\" [class.py-3]=\"multiple()\"></span>\n\n <span class=\"picker\">\n @if (isLoading()) {\n <kl-loader size=\"small\" />\n } @else {\n <i class=\"fa-solid fa-caret-down\"></i>\n }\n </span>\n </button>\n\n <div [id]=\"fieldId\" popover class=\"kl-select-options-container with-popover relative flex flex-col overflow-hidden\">\n @if (!withoutFilter()) {\n <div class=\"kl-select-filter-container border-b border-neutral-200 dark:border-neutral-700\">\n <label class=\"flex items-center text-sm\">\n <i class=\"fa-solid fa-magnifying-glass opacity-60 absolute top-3 left-4\"></i>\n <input class=\"w-full p-2 pr-3 pl-10 outline-none placeholder:opacity-60\"\n #searchInput\n type=\"search\"\n [(ngModel)]=\"filter\"\n [placeholder]=\"translations.selectTypeSearch\"\n />\n </label>\n </div>\n }\n\n <div class=\"kl-select-options-content p-1 overflow-auto\">\n @for (item of optionList(); track $index) {\n @let optionLabelId = fieldId + '-' + item.value;\n\n <label class=\"kl-select-option-content relative py-1 px-2 pr-8 rounded-md\"\n [attr.for]=\"optionLabelId\"\n [attr.data-index]=\"$index\">\n <span class=\"w-full\">\n @let isChecked = multiple() ? (control().value || []).includes(item.value) : item.value === control().value;\n\n <input\n [type]=\"multiple() ? 'checkbox' : 'radio'\"\n [id]=\"optionLabelId\"\n [name]=\"fieldId\"\n [attr.value]=\"item.value\"\n [checked]=\"isChecked\"\n (change)=\"setValue($event)\"\n />\n <span>{{ item.label }}</span>\n </span>\n </label>\n }\n </div>\n </div>\n </div>\n</div>\n\n@if (hint()) {\n <span class=\"hint-content\">\n <i class=\"fa-regular fa-circle-question\"></i> {{hint()}}\n </span>\n}\n\n<kl-field-errors [field]=\"control()\">\n <ng-container errors>\n <ng-content select=\"[errors]\" />\n </ng-container>\n</kl-field-errors>\n" }] }], ctorParameters: () => [], propDecorators: { selectField: [{ type: i0.ViewChild, args: ['selectField', { isSignal: true }] }], filter: [{ type: i0.Input, args: [{ isSignal: true, alias: "filter", required: false }] }, { type: i0.Output, args: ["filterChange"] }], options: [{ type: i0.Input, args: [{ isSignal: true, alias: "options", required: true }] }], internalFilter: [{ type: i0.Input, args: [{ isSignal: true, alias: "internalFilter", required: false }] }], withoutFilter: [{ type: i0.Input, args: [{ isSignal: true, alias: "withoutFilter", required: false }] }], multiple: [{ type: i0.Input, args: [{ isSignal: true, alias: "multiple", required: false }] }], selectedItem: [{ type: i0.Output, args: ["selectedItem"] }] } }); class SelectBuilder { onDemand(config) { return config; } onServer(config) { return config; } inMemory(config) { return config; } inMemoryWithLoading(config) { return config; } static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "21.0.6", ngImport: i0, type: SelectBuilder, deps: [], target: i0.ɵɵFactoryTarget.Injectable }); static ɵprov = i0.ɵɵngDeclareInjectable({ minVersion: "12.0.0", version: "21.0.6", ngImport: i0, type: SelectBuilder, providedIn: 'root' }); } i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.0.6", ngImport: i0, type: SelectBuilder, decorators: [{ type: Injectable, args: [{ providedIn: 'root' }] }] }); /** * Generated bundle index. Do not edit. */ export { Select, SelectBuilder }; //# sourceMappingURL=koalarx-ui-shared-components-input-field-select.mjs.map