bit-ng-library 18.1.10 → 18.1.11

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/README.md CHANGED
@@ -26,6 +26,11 @@ To get more help on the Angular CLI use `ng help` or go check out the [Angular C
26
26
 
27
27
  ## changelog
28
28
 
29
+ ## [18.1.11] - 2025-07-16
30
+
31
+ El bit-autocomplete permite especificar una plantilla "itemTemplate" para personalizar la forma en que se muestran los elementos de la lista desplegable.
32
+ (ver proyecto demo para ejemplos de uso)
33
+
29
34
  ## [18.1.10] - 2025-07-11
30
35
 
31
36
  Corregido error en MessageService.hideNotificacionPanel().
@@ -1,27 +1,47 @@
1
- import { Component, EventEmitter, forwardRef, Input, Output } from "@angular/core";
1
+ import { Component, ContentChild, EventEmitter, forwardRef, Input, Output, TemplateRef } from '@angular/core';
2
2
  import { NG_VALUE_ACCESSOR } from "@angular/forms";
3
3
  import { BitCustomComponent } from "../bit-custom.component";
4
4
  import * as i0 from "@angular/core";
5
5
  import * as i1 from "../../../services";
6
- import * as i2 from "primeng/autocomplete";
7
- import * as i3 from "@angular/forms";
8
- import * as i4 from "../../contol-messages/bit-control-messages.component";
6
+ import * as i2 from "primeng/api";
7
+ import * as i3 from "primeng/autocomplete";
8
+ import * as i4 from "@angular/common";
9
+ import * as i5 from "@angular/forms";
10
+ import * as i6 from "../../contol-messages/bit-control-messages.component";
9
11
  export class BitAutoCompleteComponent extends BitCustomComponent {
10
12
  constructor(ayudaService) {
11
13
  super(ayudaService);
12
14
  this.ayudaService = ayudaService;
13
15
  this.multiple = false;
14
16
  this.id = "id";
17
+ this.customTemplate = false; // si se usa un template personalizado para mostrar los items
15
18
  this.completeMethod = new EventEmitter();
16
19
  this.onSelect = new EventEmitter();
17
20
  this.onClear = new EventEmitter();
18
21
  }
22
+ ngAfterViewInit() {
23
+ // Control de errores:
24
+ // 1. Si se quiere usar una template personalizada, se debe especificar el input customTemplate.
25
+ // 2. Si se usa customTemplate, se debe especificar el input suggestionField para poder mapear el objeto en el campo de texto.
26
+ // 3. Si se usa itemTemplate, se debe especificar customTemplate a true. (warning)
27
+ if (this.customTemplate && !this.itemTemplate) {
28
+ throw new Error("BitAutoCompleteComponent: Si se especifica el input customTemplate se debe proporcionar una template a través de '<ng-template #itemTemplate let-item>'");
29
+ }
30
+ else if (this.customTemplate && !this.suggestionField) {
31
+ throw new Error("BitAutoCompleteComponent: Si se especifica el input customTemplate, se debe especificar el input suggestionField para poder mapear el objeto en el campo de texto cuando elijamos uno de la lista.");
32
+ }
33
+ else if (!this.customTemplate && this.itemTemplate) {
34
+ console.warn("BitAutoCompleteComponent: Se ha proporcionado una template personalizada a través de 'itemTemplate', pero se está pasando de ella. Para usarla, debe establecer customTemplate a true.");
35
+ }
36
+ }
19
37
  ngOnChanges(changes) {
20
38
  for (let propName in changes) {
21
39
  if (propName === "suggestions") {
22
40
  let changedProp = changes[propName];
23
41
  let newList = changedProp.currentValue;
24
- this.suggestions_mapped = newList && newList.map((obj) => (obj instanceof Object ? obj[this.suggestionField] : obj));
42
+ // El mapeo tiene que ser con todo el objeto, no solo con el campo suggestionField, porque si se usa un template personalizado
43
+ // se necesita el objeto completo para poder pasarlos a la template y que se pinte correctamente.
44
+ this.suggestions_mapped = newList && newList.map((obj) => ((obj instanceof Object && !this.customTemplate) ? obj[this.suggestionField] : obj));
25
45
  //console.log("newList", this.suggestions_mapped);
26
46
  }
27
47
  }
@@ -86,16 +106,22 @@ export class BitAutoCompleteComponent extends BitCustomComponent {
86
106
  this.onClear.emit();
87
107
  }
88
108
  _findObject(value) {
89
- return value && this.suggestions.find((obj) => obj[this.suggestionField] === value);
109
+ // Si se usa un template personalizado, devolvemos el valor directamente, porque ya estará allí, no hace falta buscarlo en la lista de sugerencias
110
+ if (this.customTemplate) {
111
+ return this.value;
112
+ }
113
+ else {
114
+ return value && this.suggestions.find((obj) => obj[this.suggestionField] === value);
115
+ }
90
116
  }
91
117
  static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "18.2.12", ngImport: i0, type: BitAutoCompleteComponent, deps: [{ token: i1.AyudaService }], target: i0.ɵɵFactoryTarget.Component }); }
92
- static { this.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "18.2.12", type: BitAutoCompleteComponent, selector: "bit-autocomplete", inputs: { suggestions: "suggestions", suggestionField: "suggestionField", multiple: "multiple", inputStyleClass: "inputStyleClass", id: "id", displayValue: "displayValue" }, outputs: { completeMethod: "completeMethod", onSelect: "onSelect", onClear: "onClear" }, providers: [
118
+ static { this.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "18.2.12", type: BitAutoCompleteComponent, selector: "bit-autocomplete", inputs: { suggestions: "suggestions", suggestionField: "suggestionField", multiple: "multiple", inputStyleClass: "inputStyleClass", id: "id", displayValue: "displayValue", customTemplate: "customTemplate" }, outputs: { completeMethod: "completeMethod", onSelect: "onSelect", onClear: "onClear" }, providers: [
93
119
  {
94
120
  provide: NG_VALUE_ACCESSOR,
95
121
  useExisting: forwardRef(() => BitAutoCompleteComponent),
96
122
  multi: true
97
123
  }
98
- ], usesInheritance: true, usesOnChanges: true, ngImport: i0, template: "@if (!hideLabel) {\r\n <label>\r\n <ng-content></ng-content>&nbsp;@if (obligatorio) {\r\n <span class=\"obligatorio fa fa-asterisk\"></span>\r\n }&nbsp;&nbsp;\r\n @if (ayuda) {\r\n <i class=\"btn-ayuda fa fa-question\" (click)=\"showAyuda()\"></i>\r\n }\r\n </label>\r\n}\r\n@if (readOnly) {\r\n <p class=\"lectura\" [id]=\"nombre\">{{ value_lectura }}</p>\r\n}\r\n@if (!readOnly) {\r\n <p-autoComplete\r\n [(ngModel)]=\"value\"\r\n id=\"{{ nombre }}\"\r\n name=\"{{ nombre }}\"\r\n [disabled]=\"isDisabled\"\r\n [placeholder]=\"placeholder\"\r\n delay=\"400\"\r\n [suggestions]=\"suggestions_mapped\"\r\n [multiple]=\"multiple\"\r\n [inputStyleClass]=\"inputStyleClass\"\r\n appendTo=\"body\"\r\n (completeMethod)=\"search($event)\"\r\n (onSelect)=\"_onSelect($event)\"\r\n (onClear)=\"_onClear()\"\r\n (onBlur)=\"_onBlur()\"\r\n (onFocus)=\"_onFocus()\"\r\n attr.data-testid=\"{{ dataTestId }}\"\r\n ></p-autoComplete>\r\n}\r\n@if (control != null) {\r\n <control-messages [control]=\"control\" [field]=\"nombre\"></control-messages>\r\n}\r\n", dependencies: [{ kind: "component", type: i2.AutoComplete, selector: "p-autoComplete", inputs: ["minLength", "delay", "style", "panelStyle", "styleClass", "panelStyleClass", "inputStyle", "inputId", "inputStyleClass", "placeholder", "readonly", "disabled", "scrollHeight", "lazy", "virtualScroll", "virtualScrollItemSize", "virtualScrollOptions", "maxlength", "name", "required", "size", "appendTo", "autoHighlight", "forceSelection", "type", "autoZIndex", "baseZIndex", "ariaLabel", "dropdownAriaLabel", "ariaLabelledBy", "dropdownIcon", "unique", "group", "completeOnFocus", "showClear", "field", "dropdown", "showEmptyMessage", "dropdownMode", "multiple", "tabindex", "dataKey", "emptyMessage", "showTransitionOptions", "hideTransitionOptions", "autofocus", "autocomplete", "optionGroupChildren", "optionGroupLabel", "overlayOptions", "suggestions", "itemSize", "optionLabel", "optionValue", "id", "searchMessage", "emptySelectionMessage", "selectionMessage", "autoOptionFocus", "selectOnFocus", "searchLocale", "optionDisabled", "focusOnHover", "variant"], outputs: ["completeMethod", "onSelect", "onUnselect", "onFocus", "onBlur", "onDropdownClick", "onClear", "onKeyUp", "onShow", "onHide", "onLazyLoad"] }, { kind: "directive", type: i3.NgControlStatus, selector: "[formControlName],[ngModel],[formControl]" }, { kind: "directive", type: i3.NgModel, selector: "[ngModel]:not([formControlName]):not([formControl])", inputs: ["name", "disabled", "ngModel", "ngModelOptions"], outputs: ["ngModelChange"], exportAs: ["ngModel"] }, { kind: "component", type: i4.BitControlMessages, selector: "control-messages", inputs: ["control", "field"] }] }); }
124
+ ], queries: [{ propertyName: "itemTemplate", first: true, predicate: ["itemTemplate"], descendants: true, read: TemplateRef }], usesInheritance: true, usesOnChanges: true, ngImport: i0, template: "@if (!hideLabel) {\r\n <label>\r\n <ng-content></ng-content>&nbsp;\r\n @if (obligatorio) {\r\n <span class=\"obligatorio fa fa-asterisk\"></span>\r\n }&nbsp;&nbsp;\r\n @if (ayuda) {\r\n <i class=\"btn-ayuda fa fa-question\" (click)=\"showAyuda()\"></i>\r\n }\r\n </label>\r\n}\r\n@if (readOnly) {\r\n <p class=\"lectura\" [id]=\"nombre\">{{ value_lectura }}</p>\r\n}\r\n@if (!readOnly) {\r\n <!-- Si usamos un template personalizado, hay que indicar el optionLabel para que sepa cu\u00E1l es el campo a mostrar al seleccionar un elemento -->\r\n <p-autoComplete\r\n [(ngModel)]=\"value\"\r\n id=\"{{ nombre }}\"\r\n name=\"{{ nombre }}\"\r\n [disabled]=\"isDisabled\"\r\n [placeholder]=\"placeholder\"\r\n [delay]=\"400\"\r\n [suggestions]=\"suggestions_mapped\"\r\n [multiple]=\"multiple\"\r\n [inputStyleClass]=\"inputStyleClass\"\r\n optionLabel=\"{{ customTemplate ? this.suggestionField : '' }}\"\r\n appendTo=\"body\"\r\n (completeMethod)=\"search($event)\"\r\n (onSelect)=\"_onSelect($event)\"\r\n (onClear)=\"_onClear()\"\r\n (onBlur)=\"_onBlur()\"\r\n (onFocus)=\"_onFocus()\"\r\n attr.data-testid=\"{{ dataTestId }}\"\r\n >\r\n @if (customTemplate && itemTemplate) {\r\n <ng-template pTemplate=\"item\" let-item>\r\n <ng-container *ngTemplateOutlet=\"itemTemplate; context: { $implicit: item }\"></ng-container>\r\n </ng-template>\r\n }\r\n </p-autoComplete>\r\n}\r\n@if (control != null) {\r\n <control-messages [control]=\"control\" [field]=\"nombre\"></control-messages>\r\n}\r\n", dependencies: [{ kind: "directive", type: i2.PrimeTemplate, selector: "[pTemplate]", inputs: ["type", "pTemplate"] }, { kind: "component", type: i3.AutoComplete, selector: "p-autoComplete", inputs: ["minLength", "delay", "style", "panelStyle", "styleClass", "panelStyleClass", "inputStyle", "inputId", "inputStyleClass", "placeholder", "readonly", "disabled", "scrollHeight", "lazy", "virtualScroll", "virtualScrollItemSize", "virtualScrollOptions", "maxlength", "name", "required", "size", "appendTo", "autoHighlight", "forceSelection", "type", "autoZIndex", "baseZIndex", "ariaLabel", "dropdownAriaLabel", "ariaLabelledBy", "dropdownIcon", "unique", "group", "completeOnFocus", "showClear", "field", "dropdown", "showEmptyMessage", "dropdownMode", "multiple", "tabindex", "dataKey", "emptyMessage", "showTransitionOptions", "hideTransitionOptions", "autofocus", "autocomplete", "optionGroupChildren", "optionGroupLabel", "overlayOptions", "suggestions", "itemSize", "optionLabel", "optionValue", "id", "searchMessage", "emptySelectionMessage", "selectionMessage", "autoOptionFocus", "selectOnFocus", "searchLocale", "optionDisabled", "focusOnHover", "variant"], outputs: ["completeMethod", "onSelect", "onUnselect", "onFocus", "onBlur", "onDropdownClick", "onClear", "onKeyUp", "onShow", "onHide", "onLazyLoad"] }, { kind: "directive", type: i4.NgTemplateOutlet, selector: "[ngTemplateOutlet]", inputs: ["ngTemplateOutletContext", "ngTemplateOutlet", "ngTemplateOutletInjector"] }, { kind: "directive", type: i5.NgControlStatus, selector: "[formControlName],[ngModel],[formControl]" }, { kind: "directive", type: i5.NgModel, selector: "[ngModel]:not([formControlName]):not([formControl])", inputs: ["name", "disabled", "ngModel", "ngModelOptions"], outputs: ["ngModelChange"], exportAs: ["ngModel"] }, { kind: "component", type: i6.BitControlMessages, selector: "control-messages", inputs: ["control", "field"] }] }); }
99
125
  }
100
126
  i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "18.2.12", ngImport: i0, type: BitAutoCompleteComponent, decorators: [{
101
127
  type: Component,
@@ -105,7 +131,7 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "18.2.12", ngImpo
105
131
  useExisting: forwardRef(() => BitAutoCompleteComponent),
106
132
  multi: true
107
133
  }
108
- ], template: "@if (!hideLabel) {\r\n <label>\r\n <ng-content></ng-content>&nbsp;@if (obligatorio) {\r\n <span class=\"obligatorio fa fa-asterisk\"></span>\r\n }&nbsp;&nbsp;\r\n @if (ayuda) {\r\n <i class=\"btn-ayuda fa fa-question\" (click)=\"showAyuda()\"></i>\r\n }\r\n </label>\r\n}\r\n@if (readOnly) {\r\n <p class=\"lectura\" [id]=\"nombre\">{{ value_lectura }}</p>\r\n}\r\n@if (!readOnly) {\r\n <p-autoComplete\r\n [(ngModel)]=\"value\"\r\n id=\"{{ nombre }}\"\r\n name=\"{{ nombre }}\"\r\n [disabled]=\"isDisabled\"\r\n [placeholder]=\"placeholder\"\r\n delay=\"400\"\r\n [suggestions]=\"suggestions_mapped\"\r\n [multiple]=\"multiple\"\r\n [inputStyleClass]=\"inputStyleClass\"\r\n appendTo=\"body\"\r\n (completeMethod)=\"search($event)\"\r\n (onSelect)=\"_onSelect($event)\"\r\n (onClear)=\"_onClear()\"\r\n (onBlur)=\"_onBlur()\"\r\n (onFocus)=\"_onFocus()\"\r\n attr.data-testid=\"{{ dataTestId }}\"\r\n ></p-autoComplete>\r\n}\r\n@if (control != null) {\r\n <control-messages [control]=\"control\" [field]=\"nombre\"></control-messages>\r\n}\r\n" }]
134
+ ], template: "@if (!hideLabel) {\r\n <label>\r\n <ng-content></ng-content>&nbsp;\r\n @if (obligatorio) {\r\n <span class=\"obligatorio fa fa-asterisk\"></span>\r\n }&nbsp;&nbsp;\r\n @if (ayuda) {\r\n <i class=\"btn-ayuda fa fa-question\" (click)=\"showAyuda()\"></i>\r\n }\r\n </label>\r\n}\r\n@if (readOnly) {\r\n <p class=\"lectura\" [id]=\"nombre\">{{ value_lectura }}</p>\r\n}\r\n@if (!readOnly) {\r\n <!-- Si usamos un template personalizado, hay que indicar el optionLabel para que sepa cu\u00E1l es el campo a mostrar al seleccionar un elemento -->\r\n <p-autoComplete\r\n [(ngModel)]=\"value\"\r\n id=\"{{ nombre }}\"\r\n name=\"{{ nombre }}\"\r\n [disabled]=\"isDisabled\"\r\n [placeholder]=\"placeholder\"\r\n [delay]=\"400\"\r\n [suggestions]=\"suggestions_mapped\"\r\n [multiple]=\"multiple\"\r\n [inputStyleClass]=\"inputStyleClass\"\r\n optionLabel=\"{{ customTemplate ? this.suggestionField : '' }}\"\r\n appendTo=\"body\"\r\n (completeMethod)=\"search($event)\"\r\n (onSelect)=\"_onSelect($event)\"\r\n (onClear)=\"_onClear()\"\r\n (onBlur)=\"_onBlur()\"\r\n (onFocus)=\"_onFocus()\"\r\n attr.data-testid=\"{{ dataTestId }}\"\r\n >\r\n @if (customTemplate && itemTemplate) {\r\n <ng-template pTemplate=\"item\" let-item>\r\n <ng-container *ngTemplateOutlet=\"itemTemplate; context: { $implicit: item }\"></ng-container>\r\n </ng-template>\r\n }\r\n </p-autoComplete>\r\n}\r\n@if (control != null) {\r\n <control-messages [control]=\"control\" [field]=\"nombre\"></control-messages>\r\n}\r\n" }]
109
135
  }], ctorParameters: () => [{ type: i1.AyudaService }], propDecorators: { suggestions: [{
110
136
  type: Input
111
137
  }], suggestionField: [{
@@ -118,11 +144,16 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "18.2.12", ngImpo
118
144
  type: Input
119
145
  }], displayValue: [{
120
146
  type: Input
147
+ }], customTemplate: [{
148
+ type: Input
121
149
  }], completeMethod: [{
122
150
  type: Output
123
151
  }], onSelect: [{
124
152
  type: Output
125
153
  }], onClear: [{
126
154
  type: Output
155
+ }], itemTemplate: [{
156
+ type: ContentChild,
157
+ args: ['itemTemplate', { read: TemplateRef }]
127
158
  }] } });
128
- //# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoiYml0LWF1dG9jb21wbGV0ZS5jb21wb25lbnQuanMiLCJzb3VyY2VSb290IjoiIiwic291cmNlcyI6WyIuLi8uLi8uLi8uLi8uLi8uLi8uLi8uLi9wcm9qZWN0cy9iaXQtbmctbGlicmFyeS9zcmMvbGliL3NoYXJlZGxpYnJhcnkvY29tcG9uZW50cy9mb3JtL2F1dG9jb21wbGV0ZS9iaXQtYXV0b2NvbXBsZXRlLmNvbXBvbmVudC50cyIsIi4uLy4uLy4uLy4uLy4uLy4uLy4uLy4uL3Byb2plY3RzL2JpdC1uZy1saWJyYXJ5L3NyYy9saWIvc2hhcmVkbGlicmFyeS9jb21wb25lbnRzL2Zvcm0vYXV0b2NvbXBsZXRlL2JpdC1hdXRvY29tcGxldGUuY29tcG9uZW50Lmh0bWwiXSwibmFtZXMiOltdLCJtYXBwaW5ncyI6IkFBQUEsT0FBTyxFQUFFLFNBQVMsRUFBRSxZQUFZLEVBQUUsVUFBVSxFQUFFLEtBQUssRUFBYSxNQUFNLEVBQWdCLE1BQU0sZUFBZSxDQUFDO0FBQzVHLE9BQU8sRUFBd0IsaUJBQWlCLEVBQUUsTUFBTSxnQkFBZ0IsQ0FBQztBQUd6RSxPQUFPLEVBQUUsa0JBQWtCLEVBQUUsTUFBTSx5QkFBeUIsQ0FBQzs7Ozs7O0FBYzdELE1BQU0sT0FBTyx3QkFBeUIsU0FBUSxrQkFBa0I7SUF3QjlELFlBQXNCLFlBQTBCO1FBQzlDLEtBQUssQ0FBQyxZQUFZLENBQUMsQ0FBQztRQURBLGlCQUFZLEdBQVosWUFBWSxDQUFjO1FBbEJoRCxhQUFRLEdBQVksS0FBSyxDQUFDO1FBSTFCLE9BQUUsR0FBVyxJQUFJLENBQUM7UUFJbEIsbUJBQWMsR0FBRyxJQUFJLFlBQVksRUFBVSxDQUFDO1FBRTVDLGFBQVEsR0FBRyxJQUFJLFlBQVksRUFBVSxDQUFDO1FBRXRDLFlBQU8sR0FBRyxJQUFJLFlBQVksRUFBTyxDQUFDO0lBUWxDLENBQUM7SUFFRCxXQUFXLENBQUMsT0FBNEM7UUFDdEQsS0FBSyxJQUFJLFFBQVEsSUFBSSxPQUFPLEVBQUUsQ0FBQztZQUM3QixJQUFJ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LFFBQVE7UUFDTixJQUFJLENBQUMsS0FBSyxHQUFHLEVBQUUsQ0FBQztRQUNoQixJQUFJLENBQUMsb0JBQW9CLENBQUMsSUFBSSxDQUFDLEtBQUssQ0FBQyxDQUFDO1FBQ3RDLElBQUksQ0FBQyxPQUFPLENBQUMsSUFBSSxFQUFFLENBQUM7SUFDdEIsQ0FBQztJQUVELFdBQVcsQ0FBQyxLQUFVO1FBQ3BCLE9BQU8sS0FBSyxJQUFJLElBQUksQ0FBQyxXQUFXLENBQUMsSUFBSSxDQUFDLENBQUMsR0FBRyxFQUFFLEVBQUUsQ0FBQyxHQUFHLENBQUMsSUFBSSxDQUFDLGVBQWUsQ0FBQyxLQUFLLEtBQUssQ0FBQyxDQUFDO0lBQ3RGLENBQUM7K0dBdEdVLHdCQUF3QjttR0FBeEIsd0JBQXdCLGtUQVJ4QjtZQUNUO2dCQUNFLE9BQU8sRUFBRSxpQkFBaUI7Z0JBQzFCLFdBQVcsRUFBRSxVQUFVLENBQUMsR0FBRyxFQUFFLENBQUMsd0JBQXdCLENBQUM7Z0JBQ3ZELEtBQUssRUFBRSxJQUFJO2FBQ1o7U0FDRixzRUNoQkgsZ21DQW9DQTs7NEZEbEJhLHdCQUF3QjtrQkFYcEMsU0FBUzsrQkFDRSxrQkFBa0IsYUFFakI7d0JBQ1Q7NEJBQ0UsT0FBTyxFQUFFLGlCQUFpQjs0QkFDMUIsV0FBVyxFQUFFLFVBQVUsQ0FBQyxHQUFHLEVBQUUseUJBQXlCLENBQUM7NEJBQ3ZELEtBQUssRUFBRSxJQUFJO3lCQUNaO3FCQUNGO2lGQUlELFdBQVc7c0JBRFYsS0FBSztnQkFHTixlQUFlO3NCQURkLEtBQUs7Z0JBR04sUUFBUTtzQkFEUCxLQUFLO2dCQUdOLGVBQWU7c0JBRGQsS0FBSztnQkFHTixFQUFFO3NCQURELEtBQUs7Z0JBR04sWUFBWTtzQkFEWCxLQUFLO2dCQUdOLGNBQWM7c0JBRGIsTUFBTTtnQkFHUCxRQUFRO3NCQURQLE1BQU07Z0JBR1AsT0FBTztzQkFETixNQUFNIiwic291cmNlc0NvbnRlbnQiOlsiaW1wb3J0IHsgQ29tcG9uZW50LCBFdmVudEVtaXR0ZXIsIGZvcndhcmRSZWYsIElucHV0LCBPbkNoYW5nZXMsIE91dHB1dCwgU2ltcGxlQ2hhbmdlIH0gZnJvbSBcIkBhbmd1bGFyL2NvcmVcIjtcclxuaW1wb3J0IHsgQ29udHJvbFZhbHVlQWNjZXNzb3IsIE5HX1ZBTFVFX0FDQ0VTU09SIH0gZnJvbSBcIkBhbmd1bGFyL2Zvcm1zXCI7XHJcblxyXG5pbXBvcnQgeyBBeXVkYVNlcnZpY2UgfSBmcm9tIFwiLi4vLi4vLi4vc2VydmljZXNcIjtcclxuaW1wb3J0IHsgQml0Q3VzdG9tQ29tcG9uZW50IH0gZnJvbSBcIi4uL2JpdC1jdXN0b20uY29tcG9uZW50XCI7XHJcbmltcG9ydCB7IEF1dG9Db21wbGV0ZVNlbGVjdEV2ZW50IH0gZnJvbSBcInByaW1lbmcvYXV0b2NvbXBsZXRlXCI7XHJcblxyXG5AQ29tcG9uZW50KHtcclxuICBzZWxlY3RvcjogXCJiaXQtYXV0b2NvbXBsZXRlXCIsXHJcbiAgdGVtcGxhdGVVcmw6IFwiYml0LWF1dG9jb21wbGV0ZS5jb21wb25lbnQuaHRtbFwiLFxyXG4gIHByb3ZpZGVyczogW1xyXG4gICAge1xyXG4gICAgICBwcm92aWRlOiBOR19WQUxVRV9BQ0NFU1NPUixcclxuICAgICAgdXNlRXhpc3Rpbmc6IGZvcndhcmRSZWYoKCkgPT4gQml0QXV0b0NvbXBsZXRlQ29tcG9uZW50KSxcclxuICAgICAgbXVsdGk6IHRydWVcclxuICAgIH1cclxuICBdXHJcbn0pXHJcbmV4cG9ydCBjbGFzcyBCaXRBdXRvQ29tcGxldGVDb21wb25lbnQgZXh0ZW5kcyBCaXRDdXN0b21Db21wb25lbnQgaW1wbGVtZW50cyBDb250cm9sVmFsdWVBY2Nlc3NvciwgT25DaGFuZ2VzIHtcclxuICBASW5wdXQoKVxyXG4gIHN1Z2dlc3Rpb25zOiBhbnlbXTtcclxuICBASW5wdXQoKVxyXG4gIHN1Z2dlc3Rpb25GaWVsZDogc3RyaW5nO1xyXG4gIEBJbnB1dCgpXHJcbiAgbXVsdGlwbGU6IGJvb2xlYW4gPSBmYWxzZTtcclxuICBASW5wdXQoKVxyXG4gIGlucHV0U3R5bGVDbGFzczogc3RyaW5nO1xyXG4gIEBJbnB1dCgpXHJcbiAgaWQ6IHN0cmluZyA9IFwiaWRcIjtcclxuICBASW5wdXQoKVxyXG4gIGRpc3BsYXlWYWx1ZTogc3RyaW5nO1xyXG4gIEBPdXRwdXQoKVxyXG4gIGNvbXBsZXRlTWV0aG9kID0gbmV3IEV2ZW50RW1pdHRlcjxzdHJpbmc+KCk7XHJcbiAgQE91dHB1dCgpXHJcbiAgb25TZWxlY3QgPSBuZXcgRXZlbnRFbWl0dGVyPHN0cmluZz4oKTtcclxuICBAT3V0cHV0KClcclxuICBvbkNsZWFyID0gbmV3IEV2ZW50RW1pdHRlcjxhbnk+KCk7XHJcblxyXG4gIHN1Z2dlc3Rpb25zX21hcHBlZDogc3RyaW5nW107XHJcblxyXG4gIHZhbHVlOiBzdHJpbmc7XHJcblxyXG4gIGNvbnN0cnVjdG9yKHByb3RlY3RlZCBheXVkYVNlcnZpY2U6IEF5dWRhU2VydmljZSkge1xyXG4gICAgc3VwZXIoYXl1ZGFTZXJ2aWNlKTtcclxuICB9XHJcblxyXG4gIG5nT25DaGFuZ2VzKGNoYW5nZXM6IHsgW3Byb3BLZXk6IHN0cmluZ106IFNpbXBsZUNoYW5nZSB9KSB7XHJcbiAgICBmb3IgKGxldCBwcm9wTmFtZSBpbiBjaGFuZ2VzKSB7XHJcbiAgICAgIGlmIChwcm9wTmFtZSA9PT0gXCJzdWdnZXN0aW9uc1wiKSB7XHJcbiAgICAgICAgbGV0IGNoYW5nZWRQcm9wID0gY2hhbmdlc1twcm9wTmFtZV07XHJcbiAgICAgICAgbGV0IG5ld0xpc3QgPSBjaGFuZ2VkUHJvcC5jdXJyZW50VmFsdWU7XHJcbiAgICAgICAgdGhpcy5zdWdnZXN0aW9uc19tYXBwZWQgPSBuZXdMaXN0ICYmIG5ld0xpc3QubWFwKChvYmo6IHsgW3g6IHN0cmluZ106IGFueSB9KSA9PiAob2JqIGluc3RhbmNlb2YgT2JqZWN0ID8gb2JqW3RoaXMuc3VnZ2VzdGlvbkZpZWxkXSA6IG9iaikpO1xyXG4gICAgICAgIC8vY29uc29sZS5sb2coXCJuZXdMaXN0XCIsIHRoaXMuc3VnZ2VzdGlvbnNfbWFwcGVkKTtcclxuICAgICAgfVxyXG4gICAgfVxyXG4gIH1cclxuXHJcbiAgc2VhcmNoKGV2ZW50OiBhbnkpIHtcclxuICAgIHRoaXMuY29tcGxldGVNZXRob2QuZW1pdChldmVudCk7XHJcbiAgfVxyXG5cclxuICBnZXQgdmFsdWVfbGVjdHVyYSgpOiBzdHJpbmcge1xyXG4gICAgaWYgKHRoaXMudmFsdWUgPT0gbnVsbCkge1xyXG4gICAgICByZXR1cm4gXCJcIjtcclxuICAgIH0gLy8gc2kgZXMgbnVsbCBvIHVuZGVmaW5lZCAoZXMgbG8gcXVlIGV2YWzDumEgZWwgXCI9PW51bGxcIilcclxuICAgIGVsc2Uge1xyXG4gICAgICByZXR1cm4gdGhpcy52YWx1ZTtcclxuICAgIH1cclxuICB9XHJcblxyXG4gIHdyaXRlVmFsdWUodjogbnVtYmVyIHwgc3RyaW5nKTogdm9pZCB7XHJcbiAgICAvLyBFbCAwIGVzIHVuIHZhbG9yIHbDoWxpZG9cclxuICAgIGlmICh2ID09PSBudWxsIHx8IHYgPT09IHVuZGVmaW5lZCB8fCB2ID09PSBcIlwiKSB7XHJcbiAgICAgIHRoaXMudmFsdWUgPSBcIlwiO1xyXG4gICAgfSBlbHNlIHtcclxuICAgICAgaWYgKHR5cGVvZiB2ID09PSBcInN0cmluZ1wiKSB7XHJcbiAgICAgICAgdGhpcy52YWx1ZSA9IHYudG9TdHJpbmcoKTtcclxuICAgICAgfSBlbHNlIHtcclxuICAgICAgICB0aGlzLnZhbHVlID0gdGhpcy5kaXNwbGF5VmFsdWU7XHJcbiAgICAgIH1cclxuICAgIH1cclxuICB9XHJcblxyXG4gIGNoYW5nZUNvbXBvbmVudFZhbHVlKHZhbHVlOiBhbnkpIHtcclxuICAgIGxldCB2YWx1ZUNvbnZlcnRlZDogYW55O1xyXG4gICAgaWYgKHRoaXMuc3VnZ2VzdGlvbkZpZWxkKSB7XHJcbiAgICAgIC8vIHNpIGVzdGFtb3MgZXNwZWNpZmljYW5kbyBxdWUgbG8gcXVlIGVsIGF1dG9jb21wbGV0YXIgaGFjZSBlcyBvcGVyYXIgc29icmUgdW5hIGxpc3RhIGRlIG9iamV0b3NcclxuICAgICAgLy8gcmVjdXBlcmFtb3MgZWwgb2JqZXRvIGRlbnRybyBkZSBsYSBsaXN0YSBjb24gZWwgdmFsb3IgZGVsIGNhbXBvIHN1Z2dlc3Rpb25GaWVsZCBpZ3VhbCBhbCBzZWxlY2Npb25hZG9cclxuICAgICAgbGV0IHNlbGVjdGVkT2JqZWN0ID0gdGhpcy5fZmluZE9iamVjdCh2YWx1ZSk7XHJcbiAgICAgIC8vIGVsIHZhbG9yIHJlY29udmVydGlkbyBzZXLDoSBlbCBJRCBkZWwgb2JqZXRvIHF1ZSBlcyBsbyBxdWUgdmFtb3MgYSBtZXRlciBlbiBlbCBGb3JtQ29udHJvbFxyXG4gICAgICB2YWx1ZUNvbnZlcnRlZCA9IHNlbGVjdGVkT2JqZWN0ICYmIHNlbGVjdGVkT2JqZWN0W3RoaXMuaWRdO1xyXG4gICAgICAvLyBlbWl0aW1vcyBxdWUgaGEgY2FtYmlhZG8gZWwgb2JqZXRvXHJcbiAgICAgIHRoaXMub25DaGFuZ2UuZW1pdChzZWxlY3RlZE9iamVjdCk7XHJcbiAgICB9IGVsc2Uge1xyXG4gICAgICAvLyBzaSBubyBlcyB1bmEgbGlzdGEgZGUgb2JqZXRvcyBlbCBjb21wb3J0YW1pZW50byBlcyBlbCBkZSBzaWVtcHJlXHJcbiAgICAgIHZhbHVlQ29udmVydGVkID0gdmFsdWU7XHJcbiAgICAgIHRoaXMub25DaGFuZ2UuZW1pdCh2YWx1ZUNvbnZlcnRlZCk7XHJcbiAgICB9XHJcbiAgICB0aGlzLl9vbkNoYW5nZSh2YWx1ZUNvbnZlcnRlZCk7XHJcbiAgfVxyXG5cclxuICBfb25TZWxlY3QoZXZlbnQ6IEF1dG9Db21wbGV0ZVNlbGVjdEV2ZW50KSB7XHJcbiAgICB0aGlzLnZhbHVlID0gZXZlbnQudmFsdWU7XHJcbiAgICB0aGlzLmNoYW5nZUNvbXBvbmVudFZhbHVlKHRoaXMudmFsdWUpO1xyXG4gICAgaWYgKHRoaXMuc3VnZ2VzdGlvbkZpZWxkKSB7XHJcbiAgICAgIGxldCBzZWxlY3RlZE9iamVjdCA9IHRoaXMuX2ZpbmRPYmplY3QoZXZlbnQudmFsdWUpO1xyXG4gICAgICB0aGlzLm9uU2VsZWN0LmVtaXQoc2VsZWN0ZWRPYmplY3QpO1xyXG4gICAgfSBlbHNlIHtcclxuICAgICAgdGhpcy5vblNlbGVjdC5lbWl0KHRoaXMudmFsdWUpO1xyXG4gICAgfVxyXG4gIH1cclxuXHJcbiAgX29uQ2xlYXIoKSB7XHJcbiAgICB0aGlzLnZhbHVlID0gXCJcIjtcclxuICAgIHRoaXMuY2hhbmdlQ29tcG9uZW50VmFsdWUodGhpcy52YWx1ZSk7XHJcbiAgICB0aGlzLm9uQ2xlYXIuZW1pdCgpO1xyXG4gIH1cclxuXHJcbiAgX2ZpbmRPYmplY3QodmFsdWU6IGFueSkge1xyXG4gICAgcmV0dXJuIHZhbHVlICYmIHRoaXMuc3VnZ2VzdGlvbnMuZmluZCgob2JqKSA9PiBvYmpbdGhpcy5zdWdnZXN0aW9uRmllbGRdID09PSB2YWx1ZSk7XHJcbiAgfVxyXG59XHJcbiIsIkBpZiAoIWhpZGVMYWJlbCkge1xyXG4gIDxsYWJlbD5cclxuICAgIDxuZy1jb250ZW50PjwvbmctY29udGVudD4mbmJzcDtAaWYgKG9ibGlnYXRvcmlvKSB7XHJcbiAgICA8c3BhbiBjbGFzcz1cIm9ibGlnYXRvcmlvIGZhIGZhLWFzdGVyaXNrXCI+PC9zcGFuPlxyXG4gICAgfSZuYnNwOyZuYnNwO1xyXG4gICAgQGlmIChheXVkYSkge1xyXG4gICAgICA8aSBjbGFzcz1cImJ0bi1heXVkYSBmYSBmYS1xdWVzdGlvblwiIChjbGljayk9XCJzaG93QXl1ZGEoKVwiPjwvaT5cclxuICAgIH1cclxuICA8L2xhYmVsPlxyXG59XHJcbkBpZiAocmVhZE9ubHkpIHtcclxuICA8cCBjbGFzcz1cImxlY3R1cmFcIiBbaWRdPVwibm9tYnJlXCI+e3sgdmFsdWVfbGVjdHVyYSB9fTwvcD5cclxufVxyXG5AaWYgKCFyZWFkT25seSkge1xyXG4gIDxwLWF1dG9Db21wbGV0ZVxyXG4gICAgWyhuZ01vZGVsKV09XCJ2YWx1ZVwiXHJcbiAgICBpZD1cInt7IG5vbWJyZSB9fVwiXHJcbiAgICBuYW1lPVwie3sgbm9tYnJlIH19XCJcclxuICAgIFtkaXNhYmxlZF09XCJpc0Rpc2FibGVkXCJcclxuICAgIFtwbGFjZWhvbGRlcl09XCJwbGFjZWhvbGRlclwiXHJcbiAgICBkZWxheT1cIjQwMFwiXHJcbiAgICBbc3VnZ2VzdGlvbnNdPVwic3VnZ2VzdGlvbnNfbWFwcGVkXCJcclxuICAgIFttdWx0aXBsZV09XCJtdWx0aXBsZVwiXHJcbiAgICBbaW5wdXRTdHlsZUNsYXNzXT1cImlucHV0U3R5bGVDbGFzc1wiXHJcbiAgICBhcHBlbmRUbz1cImJvZHlcIlxyXG4gICAgKGNvbXBsZXRlTWV0aG9kKT1cInNlYXJjaCgkZXZlbnQpXCJcclxuICAgIChvblNlbGVjdCk9XCJfb25TZWxlY3QoJGV2ZW50KVwiXHJcbiAgICAob25DbGVhcik9XCJfb25DbGVhcigpXCJcclxuICAgIChvbkJsdXIpPVwiX29uQmx1cigpXCJcclxuICAgIChvbkZvY3VzKT1cIl9vbkZvY3VzKClcIlxyXG4gICAgYXR0ci5kYXRhLXRlc3RpZD1cInt7IGRhdGFUZXN0SWQgfX1cIlxyXG4gID48L3AtYXV0b0NvbXBsZXRlPlxyXG59XHJcbkBpZiAoY29udHJvbCAhPSBudWxsKSB7XHJcbiAgPGNvbnRyb2wtbWVzc2FnZXMgW2NvbnRyb2xdPVwiY29udHJvbFwiIFtmaWVsZF09XCJub21icmVcIj48L2NvbnRyb2wtbWVzc2FnZXM+XHJcbn1cclxuIl19
159
+ //# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoiYml0LWF1dG9jb21wbGV0ZS5jb21wb25lbnQuanMiLCJzb3VyY2VSb290IjoiIiwic291cmNlcyI6WyIuLi8uLi8uLi8uLi8uLi8uLi8uLi8uLi9wcm9qZWN0cy9iaXQtbmctbGlicmFyeS9zcmMvbGliL3NoYXJlZGxpYnJhcnkvY29tcG9uZW50cy9mb3JtL2F1dG9jb21wbGV0ZS9iaXQtYXV0b2NvbXBsZXRlLmNvbXBvbmVudC50cyIsIi4uLy4uLy4uLy4uLy4uLy4uLy4uLy4uL3Byb2plY3RzL2JpdC1uZy1saWJyYXJ5L3NyYy9saWIvc2hhcmVkbGlicmFyeS9jb21wb25lbnRzL2Zvcm0vYXV0b2NvbXBsZXRlL2JpdC1hdXRvY29tcGxldGUuY29tcG9uZW50Lmh0bWwiXSwibmFtZXMiOltdLCJtYXBwaW5ncyI6IkFBQUEsT0FBTyxFQUVMLFNBQVMsRUFDVCxZQUFZLEVBQ1osWUFBWSxFQUNaLFVBQVUsRUFDVixLQUFLLEVBRUwsTUFBTSxFQUVOLFdBQVcsRUFDWixNQUFNLGVBQWUsQ0FBQztBQUN2QixPQUFPLEVBQXdCLGlCQUFpQixFQUFFLE1BQU0sZ0JBQWdCLENBQUM7QUFHekUsT0FBTyxFQUFFLGtCQUFrQixFQUFFLE1BQU0seUJBQXlCLENBQUM7Ozs7Ozs7O0FBYzdELE1BQU0sT0FBTyx3QkFBeUIsU0FBUSxrQkFBa0I7SUE2QjlELFlBQXNCLFlBQTBCO1FBQzlDLEtBQUssQ0FBQyxZQUFZLENBQUMsQ0FBQztRQURBLGlCQUFZLEdBQVosWUFBWSxDQUFjO1FBdkJoRCxhQUFRLEdBQVksS0FBSyxDQUFDO1FBSTFCLE9BQUUsR0FBVyxJQUFJLENBQUM7UUFJbEIsbUJBQWMsR0FBWSxLQUFLLENBQUMsQ0FBQyw2REFBNkQ7UUFFOUYsbUJBQWMsR0FBRyxJQUFJLFlBQVksRUFBVSxDQUFDO1FBRTVDLGFBQVEsR0FBRyxJQUFJLFlBQVksRUFBVSxDQUFDO1FBRXRDLFlBQU8sR0FBRyxJQUFJLFlBQVksRUFBTyxDQUFDO0lBV2xDLENBQUM7SUFFRCxlQUFlO1FB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QUFlLENBQUMsS0FBSyxLQUFLLENBQUMsQ0FBQztRQUN0RixDQUFDO0lBQ0gsQ0FBQzsrR0FoSVUsd0JBQXdCO21HQUF4Qix3QkFBd0Isb1ZBUnhCO1lBQ1Q7Z0JBQ0UsT0FBTyxFQUFFLGlCQUFpQjtnQkFDMUIsV0FBVyxFQUFFLFVBQVUsQ0FBQyxHQUFHLEVBQUUsQ0FBQyx3QkFBd0IsQ0FBQztnQkFDdkQsS0FBSyxFQUFFLElBQUk7YUFDWjtTQUNGLCtHQXdCcUMsV0FBVyx5RUNuRG5ELGlrREE2Q0E7OzRGRGhCYSx3QkFBd0I7a0JBWHBDLFNBQVM7K0JBQ0Usa0JBQWtCLGFBRWpCO3dCQUNUOzRCQUNFLE9BQU8sRUFBRSxpQkFBaUI7NEJBQzFCLFdBQVcsRUFBRSxVQUFVLENBQUMsR0FBRyxFQUFFLHlCQUF5QixDQUFDOzRCQUN2RCxLQUFLLEVBQUUsSUFBSTt5QkFDWjtxQkFDRjtpRkFJRCxXQUFXO3NCQURWLEtBQUs7Z0JBR04sZUFBZTtzQkFEZCxLQUFLO2dCQUdOLFFBQVE7c0JBRFAsS0FBSztnQkFHTixlQUFlO3NCQURkLEtBQUs7Z0JBR04sRUFBRTtzQkFERCxLQUFLO2dCQUdOLFlBQVk7c0JBRFgsS0FBSztnQkFHTixjQUFjO3NCQURiLEtBQUs7Z0JBR04sY0FBYztzQkFEYixNQUFNO2dCQUdQLFFBQVE7c0JBRFAsTUFBTTtnQkFHUCxPQUFPO3NCQUROLE1BQU07Z0JBSVAsWUFBWTtzQkFEWCxZQUFZO3VCQUFDLGNBQWMsRUFBRSxFQUFFLElBQUksRUFBRSxXQUFXLEVBQUUiLCJzb3VyY2VzQ29udGVudCI6WyJpbXBvcnQge1xyXG4gIEFmdGVyVmlld0luaXQsXHJcbiAgQ29tcG9uZW50LFxyXG4gIENvbnRlbnRDaGlsZCxcclxuICBFdmVudEVtaXR0ZXIsXHJcbiAgZm9yd2FyZFJlZixcclxuICBJbnB1dCxcclxuICBPbkNoYW5nZXMsXHJcbiAgT3V0cHV0LFxyXG4gIFNpbXBsZUNoYW5nZSxcclxuICBUZW1wbGF0ZVJlZlxyXG59IGZyb20gJ0Bhbmd1bGFyL2NvcmUnO1xyXG5pbXBvcnQgeyBDb250cm9sVmFsdWVBY2Nlc3NvciwgTkdfVkFMVUVfQUNDRVNTT1IgfSBmcm9tIFwiQGFuZ3VsYXIvZm9ybXNcIjtcclxuXHJcbmltcG9ydCB7IEF5dWRhU2VydmljZSB9IGZyb20gXCIuLi8uLi8uLi9zZXJ2aWNlc1wiO1xyXG5pbXBvcnQgeyBCaXRDdXN0b21Db21wb25lbnQgfSBmcm9tIFwiLi4vYml0LWN1c3RvbS5jb21wb25lbnRcIjtcclxuaW1wb3J0IHsgQXV0b0NvbXBsZXRlU2VsZWN0RXZlbnQgfSBmcm9tIFwicHJpbWVuZy9hdXRvY29tcGxldGVcIjtcclxuXHJcbkBDb21wb25lbnQoe1xyXG4gIHNlbGVjdG9yOiBcImJpdC1hdXRvY29tcGxldGVcIixcclxuICB0ZW1wbGF0ZVVybDogXCJiaXQtYXV0b2NvbXBsZXRlLmNvbXBvbmVudC5odG1sXCIsXHJcbiAgcHJvdmlkZXJzOiBbXHJcbiAgICB7XHJcbiAgICAgIHByb3ZpZGU6IE5HX1ZBTFVFX0FDQ0VTU09SLFxyXG4gICAgICB1c2VFeGlzdGluZzogZm9yd2FyZFJlZigoKSA9PiBCaXRBdXRvQ29tcGxldGVDb21wb25lbnQpLFxyXG4gICAgICBtdWx0aTogdHJ1ZVxyXG4gICAgfVxyXG4gIF1cclxufSlcclxuZXhwb3J0IGNsYXNzIEJpdEF1dG9Db21wbGV0ZUNvbXBvbmVudCBleHRlbmRzIEJpdEN1c3RvbUNvbXBvbmVudCBpbXBsZW1lbnRzIENvbnRyb2xWYWx1ZUFjY2Vzc29yLCBBZnRlclZpZXdJbml0LCBPbkNoYW5nZXMge1xyXG4gIEBJbnB1dCgpXHJcbiAgc3VnZ2VzdGlvbnM6IGFueVtdO1xyXG4gIEBJbnB1dCgpXHJcbiAgc3VnZ2VzdGlvbkZpZWxkOiBzdHJpbmc7XHJcbiAgQElucHV0KClcclxuICBtdWx0aXBsZTogYm9vbGVhbiA9IGZhbHNlO1xyXG4gIEBJbnB1dCgpXHJcbiAgaW5wdXRTdHlsZUNsYXNzOiBzdHJpbmc7XHJcbiAgQElucHV0KClcclxuICBpZDogc3RyaW5nID0gXCJpZFwiO1xyXG4gIEBJbnB1dCgpXHJcbiAgZGlzcGxheVZhbHVlOiBzdHJpbmc7XHJcbiAgQElucHV0KClcclxuICBjdXN0b21UZW1wbGF0ZTogYm9vbGVhbiA9IGZhbHNlOyAvLyBzaSBzZSB1c2EgdW4gdGVtcGxhdGUgcGVyc29uYWxpemFkbyBwYXJhIG1vc3RyYXIgbG9zIGl0ZW1zXHJcbiAgQE91dHB1dCgpXHJcbiAgY29tcGxldGVNZXRob2QgPSBuZXcgRXZlbnRFbWl0dGVyPHN0cmluZz4oKTtcclxuICBAT3V0cHV0KClcclxuICBvblNlbGVjdCA9IG5ldyBFdmVudEVtaXR0ZXI8c3RyaW5nPigpO1xyXG4gIEBPdXRwdXQoKVxyXG4gIG9uQ2xlYXIgPSBuZXcgRXZlbnRFbWl0dGVyPGFueT4oKTtcclxuXHJcbiAgQENvbnRlbnRDaGlsZCgnaXRlbVRlbXBsYXRlJywgeyByZWFkOiBUZW1wbGF0ZVJlZiB9KVxyXG4gIGl0ZW1UZW1wbGF0ZTogVGVtcGxhdGVSZWY8YW55PjtcclxuXHJcbiAgc3VnZ2VzdGlvbnNfbWFwcGVkOiBzdHJpbmdbXTtcclxuXHJcbiAgdmFsdWU6IHN0cmluZztcclxuXHJcbiAgY29uc3RydWN0b3IocHJvdGVjdGVkIGF5dWRhU2VydmljZTogQXl1ZGFTZXJ2aWNlKSB7XHJcbiAgICBzdXBlcihheXVkYVNlcnZpY2UpO1xyXG4gIH1cclxuXHJcbiAgbmdBZnRlclZpZXdJbml0KCkge1xyXG4gICAgLy8gQ29udHJvbCBkZSBlcnJvcmVzOlxyXG4gICAgLy8gMS4gU2kgc2UgcXVpZXJlIHVzYXIgdW5hIHRlbXBsYXRlIHBlcnNvbmFsaXphZGEsIHNlIGRlYmUgZXNwZWNpZmljYXIgZWwgaW5wdXQgY3VzdG9tVGVtcGxhdGUuXHJcbiAgICAvLyAyLiBTaSBzZSB1c2EgY3VzdG9tVGVtcGxhdGUsIHNlIGRlYmUgZXNwZWNpZmljYXIgZWwgaW5wdXQgc3VnZ2VzdGlvbkZpZWxkIHBhcmEgcG9kZXIgbWFwZWFyIGVsIG9iamV0byBlbiBlbCBjYW1wbyBkZSB0ZXh0by5cclxuICAgIC8vIDMuIFNpIHNlIHVzYSBpdGVtVGVtcGxhdGUsIHNlIGRlYmUgZXNwZWNpZmljYXIgY3VzdG9tVGVtcGxhdGUgYSB0cnVlLiAod2FybmluZylcclxuICAgIGlmICh0aGlzLmN1c3RvbVRlbXBsYXRlICYmICF0aGlzLml0ZW1UZW1wbGF0ZSkge1xyXG4gICAgICB0aHJvdyBuZXcgRXJyb3IoXCJCaXRBdXRvQ29tcGxldGVDb21wb25lbnQ6IFNpIHNlIGVzcGVjaWZpY2EgZWwgaW5wdXQgY3VzdG9tVGVtcGxhdGUgc2UgZGViZSBwcm9wb3JjaW9uYXIgdW5hIHRlbXBsYXRlIGEgdHJhdsOpcyBkZSAnPG5nLXRlbXBsYXRlICNpdGVtVGVtcGxhdGUgbGV0LWl0ZW0+J1wiKTtcclxuICAgIH0gZWxzZSBpZiAodGhpcy5jdXN0b21UZW1wbGF0ZSAmJiAhdGhpcy5zdWdnZXN0aW9uRmllbGQpIHtcclxuICAgICAgdGhyb3cgbmV3IEVycm9yKFwiQml0QXV0b0NvbXBsZXRlQ29tcG9uZW50OiBTaSBzZSBlc3BlY2lmaWNhIGVsIGlucHV0IGN1c3RvbVRlbXBsYXRlLCBzZSBkZWJlIGVzcGVjaWZpY2FyIGVsIGlucHV0IHN1Z2dlc3Rpb25GaWVsZCBwYXJhIHBvZGVyIG1hcGVhciBlbCBvYmpldG8gZW4gZWwgY2FtcG8gZGUgdGV4dG8gY3VhbmRvIGVsaWphbW9zIHVubyBkZSBsYSBsaXN0YS5cIik7XHJcbiAgICB9IGVsc2UgaWYgKCF0aGlzLmN1c3RvbVRlbXBsYXRlICYmIHRoaXMuaXRlbVRlbXBsYXRlKSB7XHJcbiAgICAgIGNvbnNvbGUud2FybihcIkJpdEF1dG9Db21wbGV0ZUNvbXBvbmVudDogU2UgaGEgcHJvcG9yY2lvbmFkbyB1bmEgdGVtcGxhdGUgcGVyc29uYWxpemFkYSBhIHRyYXbDqXMgZGUgJ2l0ZW1UZW1wbGF0ZScsIHBlcm8gc2UgZXN0w6EgcGFzYW5kbyBkZSBlbGxhLiBQYXJhIHVzYXJsYSwgZGViZSBlc3RhYmxlY2VyIGN1c3RvbVRlbXBsYXRlIGEgdHJ1ZS5cIik7XHJcbiAgICB9XHJcbiAgfVxyXG5cclxuICBuZ09uQ2hhbmdlcyhjaGFuZ2VzOiB7IFtwcm9wS2V5OiBzdHJpbmddOiBTaW1wbGVDaGFuZ2UgfSkge1xyXG4gICAgZm9yIChsZXQgcHJvcE5hbWUgaW4gY2hhbmdlcykge1xyXG4gICAgICBpZiAocHJvcE5hbWUgPT09IFwic3VnZ2VzdGlvbnNcIikge1xyXG4gICAgICAgIGxldCBjaGFuZ2VkUHJvcCA9IGNoYW5nZXNbcHJvcE5hbWVdO1xyXG4gICAgICAgIGxldCBuZXdMaXN0ID0gY2hhbmdlZFByb3AuY3VycmVudFZhbHVlO1xyXG4gICAgICAgIC8vIEVsIG1hcGVvIHRpZW5lIHF1ZSBzZXIgY29uIHRvZG8gZWwgb2JqZXRvLCBubyBzb2xvIGNvbiBlbCBjYW1wbyBzdWdnZXN0aW9uRmllbGQsIHBvcnF1ZSBzaSBzZSB1c2EgdW4gdGVtcGxhdGUgcGVyc29uYWxpemFkb1xyXG4gICAgICAgIC8vIHNlIG5lY2VzaXRhIGVsIG9iamV0byBjb21wbGV0byBwYXJhIHBvZGVyIHBhc2FybG9zIGEgbGEgdGVtcGxhdGUgeSBxdWUgc2UgcGludGUgY29ycmVjdGFtZW50ZS5cclxuICAgICAgICB0aGlzLnN1Z2dlc3Rpb25zX21hcHBlZCA9IG5ld0xpc3QgJiYgbmV3TGlzdC5tYXAoKG9iajogeyBbeDogc3RyaW5nXTogYW55IH0pID0+ICgob2JqIGluc3RhbmNlb2YgT2JqZWN0ICYmICF0aGlzLmN1c3RvbVRlbXBsYXRlKSA/IG9ialt0aGlzLnN1Z2dlc3Rpb25GaWVsZF0gOiBvYmopKTtcclxuICAgICAgICAvL2NvbnNvbGUubG9nKFwibmV3TGlzdFwiLCB0aGlzLnN1Z2dlc3Rpb25zX21hcHBlZCk7XHJcbiAgICAgIH1cclxuICAgIH1cclxuICB9XHJcblxyXG4gIHNlYXJjaChldmVudDogYW55KSB7XHJcbiAgICB0aGlzLmNvbXBsZXRlTWV0aG9kLmVtaXQoZXZlbnQpO1xyXG4gIH1cclxuXHJcbiAgZ2V0IHZhbHVlX2xlY3R1cmEoKTogc3RyaW5nIHtcclxuICAgIGlmICh0aGlzLnZhbHVlID09IG51bGwpIHtcclxuICAgICAgcmV0dXJuIFwiXCI7XHJcbiAgICB9IC8vIHNpIGVzIG51bGwgbyB1bmRlZmluZWQgKGVzIGxvIHF1ZSBldmFsw7phIGVsIFwiPT1udWxsXCIpXHJcbiAgICBlbHNlIHtcclxuICAgICAgcmV0dXJuIHRoaXMudmFsdWU7XHJcbiAgICB9XHJcbiAgfVxyXG5cclxuICB3cml0ZVZhbHVlKHY6IG51bWJlciB8IHN0cmluZyk6IHZvaWQge1xyXG4gICAgLy8gRWwgMCBlcyB1biB2YWxvciB2w6FsaWRvXHJcbiAgICBpZiAodiA9PT0gbnVsbCB8fCB2ID09PSB1bmRlZmluZWQgfHwgdiA9PT0gXCJcIikge1xyXG4gICAgICB0aGlzLnZhbHVlID0gXCJcIjtcclxuICAgIH0gZWxzZSB7XHJcbiAgICAgIGlmICh0eXBlb2YgdiA9PT0gXCJzdHJpbmdcIikge1xyXG4gICAgICAgIHRoaXMudmFsdWUgPSB2LnRvU3RyaW5nKCk7XHJcbiAgICAgIH0gZWxzZSB7XHJcbiAgICAgICAgdGhpcy52YWx1ZSA9IHRoaXMuZGlzcGxheVZhbHVlO1xyXG4gICAgICB9XHJcbiAgICB9XHJcbiAgfVxyXG5cclxuICBjaGFuZ2VDb21wb25lbnRWYWx1ZSh2YWx1ZTogYW55KSB7XHJcbiAgICBsZXQgdmFsdWVDb252ZXJ0ZWQ6IGFueTtcclxuICAgIGlmICh0aGlzLnN1Z2dlc3Rpb25GaWVsZCkge1xyXG4gICAgICAvLyBzaSBlc3RhbW9zIGVzcGVjaWZpY2FuZG8gcXVlIGxvIHF1ZSBlbCBhdXRvY29tcGxldGFyIGhhY2UgZXMgb3BlcmFyIHNvYnJlIHVuYSBsaXN0YSBkZSBvYmpldG9zXHJcbiAgICAgIC8vIHJlY3VwZXJhbW9zIGVsIG9iamV0byBkZW50cm8gZGUgbGEgbGlzdGEgY29uIGVsIHZhbG9yIGRlbCBjYW1wbyBzdWdnZXN0aW9uRmllbGQgaWd1YWwgYWwgc2VsZWNjaW9uYWRvXHJcbiAgICAgIGxldCBzZWxlY3RlZE9iamVjdCA9IHRoaXMuX2ZpbmRPYmplY3QodmFsdWUpO1xyXG4gICAgICAvLyBlbCB2YWxvciByZWNvbnZlcnRpZG8gc2Vyw6EgZWwgSUQgZGVsIG9iamV0byBxdWUgZXMgbG8gcXVlIHZhbW9zIGEgbWV0ZXIgZW4gZWwgRm9ybUNvbnRyb2xcclxuICAgICAgdmFsdWVDb252ZXJ0ZWQgPSBzZWxlY3RlZE9iamVjdCAmJiBzZWxlY3RlZE9iamVjdFt0aGlzLmlkXTtcclxuICAgICAgLy8gZW1pdGltb3MgcXVlIGhhIGNhbWJpYWRvIGVsIG9iamV0b1xyXG4gICAgICB0aGlzLm9uQ2hhbmdlLmVtaXQoc2VsZWN0ZWRPYmplY3QpO1xyXG4gICAgfSBlbHNlIHtcclxuICAgICAgLy8gc2kgbm8gZXMgdW5hIGxpc3RhIGRlIG9iamV0b3MgZWwgY29tcG9ydGFtaWVudG8gZXMgZWwgZGUgc2llbXByZVxyXG4gICAgICB2YWx1ZUNvbnZlcnRlZCA9IHZhbHVlO1xyXG4gICAgICB0aGlzLm9uQ2hhbmdlLmVtaXQodmFsdWVDb252ZXJ0ZWQpO1xyXG4gICAgfVxyXG4gICAgdGhpcy5fb25DaGFuZ2UodmFsdWVDb252ZXJ0ZWQpO1xyXG4gIH1cclxuXHJcbiAgX29uU2VsZWN0KGV2ZW50OiBBdXRvQ29tcGxldGVTZWxlY3RFdmVudCkge1xyXG4gICAgdGhpcy52YWx1ZSA9IGV2ZW50LnZhbHVlO1xyXG4gICAgdGhpcy5jaGFuZ2VDb21wb25lbnRWYWx1ZSh0aGlzLnZhbHVlKTtcclxuICAgIGlmICh0aGlzLnN1Z2dlc3Rpb25GaWVsZCkge1xyXG4gICAgICBsZXQgc2VsZWN0ZWRPYmplY3QgPSB0aGlzLl9maW5kT2JqZWN0KGV2ZW50LnZhbHVlKTtcclxuICAgICAgdGhpcy5vblNlbGVjdC5lbWl0KHNlbGVjdGVkT2JqZWN0KTtcclxuICAgIH0gZWxzZSB7XHJcbiAgICAgIHRoaXMub25TZWxlY3QuZW1pdCh0aGlzLnZhbHVlKTtcclxuICAgIH1cclxuICB9XHJcblxyXG4gIF9vbkNsZWFyKCkge1xyXG4gICAgdGhpcy52YWx1ZSA9IFwiXCI7XHJcbiAgICB0aGlzLmNoYW5nZUNvbXBvbmVudFZhbHVlKHRoaXMudmFsdWUpO1xyXG4gICAgdGhpcy5vbkNsZWFyLmVtaXQoKTtcclxuICB9XHJcblxyXG4gIF9maW5kT2JqZWN0KHZhbHVlOiBhbnkpIHtcclxuICAgIC8vIFNpIHNlIHVzYSB1biB0ZW1wbGF0ZSBwZXJzb25hbGl6YWRvLCBkZXZvbHZlbW9zIGVsIHZhbG9yIGRpcmVjdGFtZW50ZSwgcG9ycXVlIHlhIGVzdGFyw6EgYWxsw60sIG5vIGhhY2UgZmFsdGEgYnVzY2FybG8gZW4gbGEgbGlzdGEgZGUgc3VnZXJlbmNpYXNcclxuICAgIGlmICh0aGlzLmN1c3RvbVRlbXBsYXRlKSB7XHJcbiAgICAgIHJldHVybiB0aGlzLnZhbHVlO1xyXG4gICAgfSBlbHNlIHtcclxuICAgICAgcmV0dXJuIHZhbHVlICYmIHRoaXMuc3VnZ2VzdGlvbnMuZmluZCgob2JqKSA9PiBvYmpbdGhpcy5zdWdnZXN0aW9uRmllbGRdID09PSB2YWx1ZSk7XHJcbiAgICB9XHJcbiAgfVxyXG59XHJcbiIsIkBpZiAoIWhpZGVMYWJlbCkge1xyXG4gIDxsYWJlbD5cclxuICAgIDxuZy1jb250ZW50PjwvbmctY29udGVudD4mbmJzcDtcclxuICAgIEBpZiAob2JsaWdhdG9yaW8pIHtcclxuICAgICAgPHNwYW4gY2xhc3M9XCJvYmxpZ2F0b3JpbyBmYSBmYS1hc3Rlcmlza1wiPjwvc3Bhbj5cclxuICAgIH0mbmJzcDsmbmJzcDtcclxuICAgIEBpZiAoYXl1ZGEpIHtcclxuICAgICAgPGkgY2xhc3M9XCJidG4tYXl1ZGEgZmEgZmEtcXVlc3Rpb25cIiAoY2xpY2spPVwic2hvd0F5dWRhKClcIj48L2k+XHJcbiAgICB9XHJcbiAgPC9sYWJlbD5cclxufVxyXG5AaWYgKHJlYWRPbmx5KSB7XHJcbiAgPHAgY2xhc3M9XCJsZWN0dXJhXCIgW2lkXT1cIm5vbWJyZVwiPnt7IHZhbHVlX2xlY3R1cmEgfX08L3A+XHJcbn1cclxuQGlmICghcmVhZE9ubHkpIHtcclxuICA8IS0tIFNpIHVzYW1vcyB1biB0ZW1wbGF0ZSBwZXJzb25hbGl6YWRvLCBoYXkgcXVlIGluZGljYXIgZWwgb3B0aW9uTGFiZWwgcGFyYSBxdWUgc2VwYSBjdcOhbCBlcyBlbCBjYW1wbyBhIG1vc3RyYXIgYWwgc2VsZWNjaW9uYXIgdW4gZWxlbWVudG8gLS0+XHJcbiAgPHAtYXV0b0NvbXBsZXRlXHJcbiAgICBbKG5nTW9kZWwpXT1cInZhbHVlXCJcclxuICAgIGlkPVwie3sgbm9tYnJlIH19XCJcclxuICAgIG5hbWU9XCJ7eyBub21icmUgfX1cIlxyXG4gICAgW2Rpc2FibGVkXT1cImlzRGlzYWJsZWRcIlxyXG4gICAgW3BsYWNlaG9sZGVyXT1cInBsYWNlaG9sZGVyXCJcclxuICAgIFtkZWxheV09XCI0MDBcIlxyXG4gICAgW3N1Z2dlc3Rpb25zXT1cInN1Z2dlc3Rpb25zX21hcHBlZFwiXHJcbiAgICBbbXVsdGlwbGVdPVwibXVsdGlwbGVcIlxyXG4gICAgW2lucHV0U3R5bGVDbGFzc109XCJpbnB1dFN0eWxlQ2xhc3NcIlxyXG4gICAgb3B0aW9uTGFiZWw9XCJ7eyBjdXN0b21UZW1wbGF0ZSA/IHRoaXMuc3VnZ2VzdGlvbkZpZWxkIDogJycgfX1cIlxyXG4gICAgYXBwZW5kVG89XCJib2R5XCJcclxuICAgIChjb21wbGV0ZU1ldGhvZCk9XCJzZWFyY2goJGV2ZW50KVwiXHJcbiAgICAob25TZWxlY3QpPVwiX29uU2VsZWN0KCRldmVudClcIlxyXG4gICAgKG9uQ2xlYXIpPVwiX29uQ2xlYXIoKVwiXHJcbiAgICAob25CbHVyKT1cIl9vbkJsdXIoKVwiXHJcbiAgICAob25Gb2N1cyk9XCJfb25Gb2N1cygpXCJcclxuICAgIGF0dHIuZGF0YS10ZXN0aWQ9XCJ7eyBkYXRhVGVzdElkIH19XCJcclxuICA+XHJcbiAgICBAaWYgKGN1c3RvbVRlbXBsYXRlICYmIGl0ZW1UZW1wbGF0ZSkge1xyXG4gICAgICA8bmctdGVtcGxhdGUgcFRlbXBsYXRlPVwiaXRlbVwiIGxldC1pdGVtPlxyXG4gICAgICAgIDxuZy1jb250YWluZXIgKm5nVGVtcGxhdGVPdXRsZXQ9XCJpdGVtVGVtcGxhdGU7IGNvbnRleHQ6IHsgJGltcGxpY2l0OiBpdGVtIH1cIj48L25nLWNvbnRhaW5lcj5cclxuICAgICAgPC9uZy10ZW1wbGF0ZT5cclxuICAgIH1cclxuICA8L3AtYXV0b0NvbXBsZXRlPlxyXG59XHJcbkBpZiAoY29udHJvbCAhPSBudWxsKSB7XHJcbiAgPGNvbnRyb2wtbWVzc2FnZXMgW2NvbnRyb2xdPVwiY29udHJvbFwiIFtmaWVsZF09XCJub21icmVcIj48L2NvbnRyb2wtbWVzc2FnZXM+XHJcbn1cclxuIl19
@@ -1,6 +1,6 @@
1
1
  import { Subject, BehaviorSubject, lastValueFrom, of, ReplaySubject, combineLatest, fromEvent, throwError } from 'rxjs';
2
2
  import * as i0 from '@angular/core';
3
- import { inject, DestroyRef, Directive, Component, ChangeDetectionStrategy, Input, EventEmitter, Injectable, Inject, signal, Pipe, Output, HostListener, ViewChild, forwardRef, ContentChild, ElementRef, NgModule, computed } from '@angular/core';
3
+ import { inject, DestroyRef, Directive, Component, ChangeDetectionStrategy, Input, EventEmitter, Injectable, Inject, signal, Pipe, Output, HostListener, ViewChild, forwardRef, TemplateRef, ContentChild, ElementRef, NgModule, computed } from '@angular/core';
4
4
  import moment from 'moment';
5
5
  import * as i2$2 from '@angular/forms';
6
6
  import { FormGroup, UntypedFormControl, UntypedFormArray, NG_VALUE_ACCESSOR, FormsModule, ReactiveFormsModule } from '@angular/forms';
@@ -14,7 +14,7 @@ import * as i3$4 from 'primeng/inputtext';
14
14
  import { InputTextModule } from 'primeng/inputtext';
15
15
  import * as i2$1 from 'primeng/dropdown';
16
16
  import { DropdownModule } from 'primeng/dropdown';
17
- import * as i3$8 from 'primeng/editor';
17
+ import * as i3$9 from 'primeng/editor';
18
18
  import { EditorModule } from 'primeng/editor';
19
19
  import * as i5$1 from 'primeng/multiselect';
20
20
  import { MultiSelectModule } from 'primeng/multiselect';
@@ -26,7 +26,7 @@ import { TabViewModule } from 'primeng/tabview';
26
26
  import * as i3 from 'primeng/dialog';
27
27
  import { DialogModule } from 'primeng/dialog';
28
28
  import { AccordionModule } from 'primeng/accordion';
29
- import * as i2$5 from 'primeng/autocomplete';
29
+ import * as i3$8 from 'primeng/autocomplete';
30
30
  import { AutoCompleteModule } from 'primeng/autocomplete';
31
31
  import * as i3$7 from 'primeng/inputswitch';
32
32
  import { InputSwitchModule } from 'primeng/inputswitch';
@@ -4142,16 +4142,34 @@ class BitAutoCompleteComponent extends BitCustomComponent {
4142
4142
  this.ayudaService = ayudaService;
4143
4143
  this.multiple = false;
4144
4144
  this.id = "id";
4145
+ this.customTemplate = false; // si se usa un template personalizado para mostrar los items
4145
4146
  this.completeMethod = new EventEmitter();
4146
4147
  this.onSelect = new EventEmitter();
4147
4148
  this.onClear = new EventEmitter();
4148
4149
  }
4150
+ ngAfterViewInit() {
4151
+ // Control de errores:
4152
+ // 1. Si se quiere usar una template personalizada, se debe especificar el input customTemplate.
4153
+ // 2. Si se usa customTemplate, se debe especificar el input suggestionField para poder mapear el objeto en el campo de texto.
4154
+ // 3. Si se usa itemTemplate, se debe especificar customTemplate a true. (warning)
4155
+ if (this.customTemplate && !this.itemTemplate) {
4156
+ throw new Error("BitAutoCompleteComponent: Si se especifica el input customTemplate se debe proporcionar una template a través de '<ng-template #itemTemplate let-item>'");
4157
+ }
4158
+ else if (this.customTemplate && !this.suggestionField) {
4159
+ throw new Error("BitAutoCompleteComponent: Si se especifica el input customTemplate, se debe especificar el input suggestionField para poder mapear el objeto en el campo de texto cuando elijamos uno de la lista.");
4160
+ }
4161
+ else if (!this.customTemplate && this.itemTemplate) {
4162
+ console.warn("BitAutoCompleteComponent: Se ha proporcionado una template personalizada a través de 'itemTemplate', pero se está pasando de ella. Para usarla, debe establecer customTemplate a true.");
4163
+ }
4164
+ }
4149
4165
  ngOnChanges(changes) {
4150
4166
  for (let propName in changes) {
4151
4167
  if (propName === "suggestions") {
4152
4168
  let changedProp = changes[propName];
4153
4169
  let newList = changedProp.currentValue;
4154
- this.suggestions_mapped = newList && newList.map((obj) => (obj instanceof Object ? obj[this.suggestionField] : obj));
4170
+ // El mapeo tiene que ser con todo el objeto, no solo con el campo suggestionField, porque si se usa un template personalizado
4171
+ // se necesita el objeto completo para poder pasarlos a la template y que se pinte correctamente.
4172
+ this.suggestions_mapped = newList && newList.map((obj) => ((obj instanceof Object && !this.customTemplate) ? obj[this.suggestionField] : obj));
4155
4173
  //console.log("newList", this.suggestions_mapped);
4156
4174
  }
4157
4175
  }
@@ -4216,16 +4234,22 @@ class BitAutoCompleteComponent extends BitCustomComponent {
4216
4234
  this.onClear.emit();
4217
4235
  }
4218
4236
  _findObject(value) {
4219
- return value && this.suggestions.find((obj) => obj[this.suggestionField] === value);
4237
+ // Si se usa un template personalizado, devolvemos el valor directamente, porque ya estará allí, no hace falta buscarlo en la lista de sugerencias
4238
+ if (this.customTemplate) {
4239
+ return this.value;
4240
+ }
4241
+ else {
4242
+ return value && this.suggestions.find((obj) => obj[this.suggestionField] === value);
4243
+ }
4220
4244
  }
4221
4245
  static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "18.2.12", ngImport: i0, type: BitAutoCompleteComponent, deps: [{ token: AyudaService }], target: i0.ɵɵFactoryTarget.Component }); }
4222
- static { this.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "18.2.12", type: BitAutoCompleteComponent, selector: "bit-autocomplete", inputs: { suggestions: "suggestions", suggestionField: "suggestionField", multiple: "multiple", inputStyleClass: "inputStyleClass", id: "id", displayValue: "displayValue" }, outputs: { completeMethod: "completeMethod", onSelect: "onSelect", onClear: "onClear" }, providers: [
4246
+ static { this.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "18.2.12", type: BitAutoCompleteComponent, selector: "bit-autocomplete", inputs: { suggestions: "suggestions", suggestionField: "suggestionField", multiple: "multiple", inputStyleClass: "inputStyleClass", id: "id", displayValue: "displayValue", customTemplate: "customTemplate" }, outputs: { completeMethod: "completeMethod", onSelect: "onSelect", onClear: "onClear" }, providers: [
4223
4247
  {
4224
4248
  provide: NG_VALUE_ACCESSOR,
4225
4249
  useExisting: forwardRef(() => BitAutoCompleteComponent),
4226
4250
  multi: true
4227
4251
  }
4228
- ], usesInheritance: true, usesOnChanges: true, ngImport: i0, template: "@if (!hideLabel) {\r\n <label>\r\n <ng-content></ng-content>&nbsp;@if (obligatorio) {\r\n <span class=\"obligatorio fa fa-asterisk\"></span>\r\n }&nbsp;&nbsp;\r\n @if (ayuda) {\r\n <i class=\"btn-ayuda fa fa-question\" (click)=\"showAyuda()\"></i>\r\n }\r\n </label>\r\n}\r\n@if (readOnly) {\r\n <p class=\"lectura\" [id]=\"nombre\">{{ value_lectura }}</p>\r\n}\r\n@if (!readOnly) {\r\n <p-autoComplete\r\n [(ngModel)]=\"value\"\r\n id=\"{{ nombre }}\"\r\n name=\"{{ nombre }}\"\r\n [disabled]=\"isDisabled\"\r\n [placeholder]=\"placeholder\"\r\n delay=\"400\"\r\n [suggestions]=\"suggestions_mapped\"\r\n [multiple]=\"multiple\"\r\n [inputStyleClass]=\"inputStyleClass\"\r\n appendTo=\"body\"\r\n (completeMethod)=\"search($event)\"\r\n (onSelect)=\"_onSelect($event)\"\r\n (onClear)=\"_onClear()\"\r\n (onBlur)=\"_onBlur()\"\r\n (onFocus)=\"_onFocus()\"\r\n attr.data-testid=\"{{ dataTestId }}\"\r\n ></p-autoComplete>\r\n}\r\n@if (control != null) {\r\n <control-messages [control]=\"control\" [field]=\"nombre\"></control-messages>\r\n}\r\n", dependencies: [{ kind: "component", type: i2$5.AutoComplete, selector: "p-autoComplete", inputs: ["minLength", "delay", "style", "panelStyle", "styleClass", "panelStyleClass", "inputStyle", "inputId", "inputStyleClass", "placeholder", "readonly", "disabled", "scrollHeight", "lazy", "virtualScroll", "virtualScrollItemSize", "virtualScrollOptions", "maxlength", "name", "required", "size", "appendTo", "autoHighlight", "forceSelection", "type", "autoZIndex", "baseZIndex", "ariaLabel", "dropdownAriaLabel", "ariaLabelledBy", "dropdownIcon", "unique", "group", "completeOnFocus", "showClear", "field", "dropdown", "showEmptyMessage", "dropdownMode", "multiple", "tabindex", "dataKey", "emptyMessage", "showTransitionOptions", "hideTransitionOptions", "autofocus", "autocomplete", "optionGroupChildren", "optionGroupLabel", "overlayOptions", "suggestions", "itemSize", "optionLabel", "optionValue", "id", "searchMessage", "emptySelectionMessage", "selectionMessage", "autoOptionFocus", "selectOnFocus", "searchLocale", "optionDisabled", "focusOnHover", "variant"], outputs: ["completeMethod", "onSelect", "onUnselect", "onFocus", "onBlur", "onDropdownClick", "onClear", "onKeyUp", "onShow", "onHide", "onLazyLoad"] }, { kind: "directive", type: i2$2.NgControlStatus, selector: "[formControlName],[ngModel],[formControl]" }, { kind: "directive", type: i2$2.NgModel, selector: "[ngModel]:not([formControlName]):not([formControl])", inputs: ["name", "disabled", "ngModel", "ngModelOptions"], outputs: ["ngModelChange"], exportAs: ["ngModel"] }, { kind: "component", type: BitControlMessages, selector: "control-messages", inputs: ["control", "field"] }] }); }
4252
+ ], queries: [{ propertyName: "itemTemplate", first: true, predicate: ["itemTemplate"], descendants: true, read: TemplateRef }], usesInheritance: true, usesOnChanges: true, ngImport: i0, template: "@if (!hideLabel) {\r\n <label>\r\n <ng-content></ng-content>&nbsp;\r\n @if (obligatorio) {\r\n <span class=\"obligatorio fa fa-asterisk\"></span>\r\n }&nbsp;&nbsp;\r\n @if (ayuda) {\r\n <i class=\"btn-ayuda fa fa-question\" (click)=\"showAyuda()\"></i>\r\n }\r\n </label>\r\n}\r\n@if (readOnly) {\r\n <p class=\"lectura\" [id]=\"nombre\">{{ value_lectura }}</p>\r\n}\r\n@if (!readOnly) {\r\n <!-- Si usamos un template personalizado, hay que indicar el optionLabel para que sepa cu\u00E1l es el campo a mostrar al seleccionar un elemento -->\r\n <p-autoComplete\r\n [(ngModel)]=\"value\"\r\n id=\"{{ nombre }}\"\r\n name=\"{{ nombre }}\"\r\n [disabled]=\"isDisabled\"\r\n [placeholder]=\"placeholder\"\r\n [delay]=\"400\"\r\n [suggestions]=\"suggestions_mapped\"\r\n [multiple]=\"multiple\"\r\n [inputStyleClass]=\"inputStyleClass\"\r\n optionLabel=\"{{ customTemplate ? this.suggestionField : '' }}\"\r\n appendTo=\"body\"\r\n (completeMethod)=\"search($event)\"\r\n (onSelect)=\"_onSelect($event)\"\r\n (onClear)=\"_onClear()\"\r\n (onBlur)=\"_onBlur()\"\r\n (onFocus)=\"_onFocus()\"\r\n attr.data-testid=\"{{ dataTestId }}\"\r\n >\r\n @if (customTemplate && itemTemplate) {\r\n <ng-template pTemplate=\"item\" let-item>\r\n <ng-container *ngTemplateOutlet=\"itemTemplate; context: { $implicit: item }\"></ng-container>\r\n </ng-template>\r\n }\r\n </p-autoComplete>\r\n}\r\n@if (control != null) {\r\n <control-messages [control]=\"control\" [field]=\"nombre\"></control-messages>\r\n}\r\n", dependencies: [{ kind: "directive", type: i2$3.PrimeTemplate, selector: "[pTemplate]", inputs: ["type", "pTemplate"] }, { kind: "component", type: i3$8.AutoComplete, selector: "p-autoComplete", inputs: ["minLength", "delay", "style", "panelStyle", "styleClass", "panelStyleClass", "inputStyle", "inputId", "inputStyleClass", "placeholder", "readonly", "disabled", "scrollHeight", "lazy", "virtualScroll", "virtualScrollItemSize", "virtualScrollOptions", "maxlength", "name", "required", "size", "appendTo", "autoHighlight", "forceSelection", "type", "autoZIndex", "baseZIndex", "ariaLabel", "dropdownAriaLabel", "ariaLabelledBy", "dropdownIcon", "unique", "group", "completeOnFocus", "showClear", "field", "dropdown", "showEmptyMessage", "dropdownMode", "multiple", "tabindex", "dataKey", "emptyMessage", "showTransitionOptions", "hideTransitionOptions", "autofocus", "autocomplete", "optionGroupChildren", "optionGroupLabel", "overlayOptions", "suggestions", "itemSize", "optionLabel", "optionValue", "id", "searchMessage", "emptySelectionMessage", "selectionMessage", "autoOptionFocus", "selectOnFocus", "searchLocale", "optionDisabled", "focusOnHover", "variant"], outputs: ["completeMethod", "onSelect", "onUnselect", "onFocus", "onBlur", "onDropdownClick", "onClear", "onKeyUp", "onShow", "onHide", "onLazyLoad"] }, { kind: "directive", type: i4$1.NgTemplateOutlet, selector: "[ngTemplateOutlet]", inputs: ["ngTemplateOutletContext", "ngTemplateOutlet", "ngTemplateOutletInjector"] }, { kind: "directive", type: i2$2.NgControlStatus, selector: "[formControlName],[ngModel],[formControl]" }, { kind: "directive", type: i2$2.NgModel, selector: "[ngModel]:not([formControlName]):not([formControl])", inputs: ["name", "disabled", "ngModel", "ngModelOptions"], outputs: ["ngModelChange"], exportAs: ["ngModel"] }, { kind: "component", type: BitControlMessages, selector: "control-messages", inputs: ["control", "field"] }] }); }
4229
4253
  }
4230
4254
  i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "18.2.12", ngImport: i0, type: BitAutoCompleteComponent, decorators: [{
4231
4255
  type: Component,
@@ -4235,7 +4259,7 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "18.2.12", ngImpo
4235
4259
  useExisting: forwardRef(() => BitAutoCompleteComponent),
4236
4260
  multi: true
4237
4261
  }
4238
- ], template: "@if (!hideLabel) {\r\n <label>\r\n <ng-content></ng-content>&nbsp;@if (obligatorio) {\r\n <span class=\"obligatorio fa fa-asterisk\"></span>\r\n }&nbsp;&nbsp;\r\n @if (ayuda) {\r\n <i class=\"btn-ayuda fa fa-question\" (click)=\"showAyuda()\"></i>\r\n }\r\n </label>\r\n}\r\n@if (readOnly) {\r\n <p class=\"lectura\" [id]=\"nombre\">{{ value_lectura }}</p>\r\n}\r\n@if (!readOnly) {\r\n <p-autoComplete\r\n [(ngModel)]=\"value\"\r\n id=\"{{ nombre }}\"\r\n name=\"{{ nombre }}\"\r\n [disabled]=\"isDisabled\"\r\n [placeholder]=\"placeholder\"\r\n delay=\"400\"\r\n [suggestions]=\"suggestions_mapped\"\r\n [multiple]=\"multiple\"\r\n [inputStyleClass]=\"inputStyleClass\"\r\n appendTo=\"body\"\r\n (completeMethod)=\"search($event)\"\r\n (onSelect)=\"_onSelect($event)\"\r\n (onClear)=\"_onClear()\"\r\n (onBlur)=\"_onBlur()\"\r\n (onFocus)=\"_onFocus()\"\r\n attr.data-testid=\"{{ dataTestId }}\"\r\n ></p-autoComplete>\r\n}\r\n@if (control != null) {\r\n <control-messages [control]=\"control\" [field]=\"nombre\"></control-messages>\r\n}\r\n" }]
4262
+ ], template: "@if (!hideLabel) {\r\n <label>\r\n <ng-content></ng-content>&nbsp;\r\n @if (obligatorio) {\r\n <span class=\"obligatorio fa fa-asterisk\"></span>\r\n }&nbsp;&nbsp;\r\n @if (ayuda) {\r\n <i class=\"btn-ayuda fa fa-question\" (click)=\"showAyuda()\"></i>\r\n }\r\n </label>\r\n}\r\n@if (readOnly) {\r\n <p class=\"lectura\" [id]=\"nombre\">{{ value_lectura }}</p>\r\n}\r\n@if (!readOnly) {\r\n <!-- Si usamos un template personalizado, hay que indicar el optionLabel para que sepa cu\u00E1l es el campo a mostrar al seleccionar un elemento -->\r\n <p-autoComplete\r\n [(ngModel)]=\"value\"\r\n id=\"{{ nombre }}\"\r\n name=\"{{ nombre }}\"\r\n [disabled]=\"isDisabled\"\r\n [placeholder]=\"placeholder\"\r\n [delay]=\"400\"\r\n [suggestions]=\"suggestions_mapped\"\r\n [multiple]=\"multiple\"\r\n [inputStyleClass]=\"inputStyleClass\"\r\n optionLabel=\"{{ customTemplate ? this.suggestionField : '' }}\"\r\n appendTo=\"body\"\r\n (completeMethod)=\"search($event)\"\r\n (onSelect)=\"_onSelect($event)\"\r\n (onClear)=\"_onClear()\"\r\n (onBlur)=\"_onBlur()\"\r\n (onFocus)=\"_onFocus()\"\r\n attr.data-testid=\"{{ dataTestId }}\"\r\n >\r\n @if (customTemplate && itemTemplate) {\r\n <ng-template pTemplate=\"item\" let-item>\r\n <ng-container *ngTemplateOutlet=\"itemTemplate; context: { $implicit: item }\"></ng-container>\r\n </ng-template>\r\n }\r\n </p-autoComplete>\r\n}\r\n@if (control != null) {\r\n <control-messages [control]=\"control\" [field]=\"nombre\"></control-messages>\r\n}\r\n" }]
4239
4263
  }], ctorParameters: () => [{ type: AyudaService }], propDecorators: { suggestions: [{
4240
4264
  type: Input
4241
4265
  }], suggestionField: [{
@@ -4248,12 +4272,17 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "18.2.12", ngImpo
4248
4272
  type: Input
4249
4273
  }], displayValue: [{
4250
4274
  type: Input
4275
+ }], customTemplate: [{
4276
+ type: Input
4251
4277
  }], completeMethod: [{
4252
4278
  type: Output
4253
4279
  }], onSelect: [{
4254
4280
  type: Output
4255
4281
  }], onClear: [{
4256
4282
  type: Output
4283
+ }], itemTemplate: [{
4284
+ type: ContentChild,
4285
+ args: ['itemTemplate', { read: TemplateRef }]
4257
4286
  }] } });
4258
4287
 
4259
4288
  /**
@@ -4634,7 +4663,7 @@ class BitEditorComponent extends BitCustomComponent {
4634
4663
  provide: NG_VALUE_ACCESSOR,
4635
4664
  useExisting: forwardRef(() => BitEditorComponent),
4636
4665
  multi: true
4637
- }], usesInheritance: true, ngImport: i0, template: "@if (!hideLabel) {\r\n <label>\r\n <ng-content></ng-content>&nbsp; @if (obligatorio) {\r\n <span class=\"obligatorio fa fa-asterisk\"></span>\r\n }&nbsp;&nbsp;\r\n @if (ayuda) {\r\n <i class=\"btn-ayuda fa fa-question\" (click)=\"showAyuda()\"></i>\r\n }\r\n </label>\r\n}\r\n@if (readOnly) {\r\n <p class=\"lectura\">\r\n {{ value_lectura && value_lectura != \"\" ? value_lectura : \"&nbsp;\" }}\r\n </p>\r\n}\r\n@if (!readOnly && tipo == 'custom') {\r\n <p-editor\r\n id=\"{{ nombre }}\"\r\n name=\"{{ nombre }}\"\r\n [ngModel]=\"value\"\r\n styleClass=\"editor\"\r\n [disabled]=\"isDisabled\"\r\n [placeholder]=\"placeholder\"\r\n [style]=\"{ height: height + 'px' }\"\r\n (onInit)=\"onInit($event)\"\r\n (ngModelChange)=\"onChangeValue($event)\"\r\n (onTextChange)=\"_onTextChange($event)\"\r\n attr.data-testid=\"{{ dataTestId }}\"\r\n >\r\n <p-header>\r\n @if (configuracion.fontSize) {\r\n <span class=\"ql-formats\">\r\n <select class=\"ql-size\">\r\n <option value=\"small\">{{ \"bitnglibrary.form.biteditor.small\" | transloco }}</option>\r\n <!-- Note a missing, thus falsy value, is used to reset to default -->\r\n <option selected>{{ \"bitnglibrary.form.biteditor.normal\" | transloco }}</option>\r\n <option value=\"large\">{{ \"bitnglibrary.form.biteditor.large\" | transloco }}</option>\r\n <option value=\"huge\">{{ \"bitnglibrary.form.biteditor.huge\" | transloco }}</option>\r\n </select>\r\n </span>\r\n }\r\n @if (configuracion.fontFormat) {\r\n <span class=\"ql-formats\">\r\n <button class=\"ql-bold\" aria-label=\"Bold\"></button>\r\n <button class=\"ql-italic\" aria-label=\"Italic\"></button>\r\n <button class=\"ql-underline\" aria-label=\"Underline\"></button>\r\n <button class=\"ql-strike\" aria-label=\"Strikethrough\"></button>\r\n </span>\r\n }\r\n @if (configuracion.bullet) {\r\n <span class=\"ql-formats\">\r\n <button class=\"ql-list\" value=\"ordered\" type=\"button\"></button>\r\n <button class=\"ql-list\" value=\"bullet\" type=\"button\"></button>\r\n </span>\r\n }\r\n @if (configuracion.link) {\r\n <span class=\"ql-formats\">\r\n <button class=\"ql-link\" aria-label=\"Insert Link\" type=\"button\"></button>\r\n </span>\r\n }\r\n </p-header>\r\n </p-editor>\r\n}\r\n@if (!readOnly && (!tipo || tipo == 'default')) {\r\n <p-editor\r\n id=\"{{ nombre }}\"\r\n name=\"{{ nombre }}\"\r\n [ngModel]=\"value\"\r\n styleClass=\"editor\"\r\n [placeholder]=\"placeholder\"\r\n [placeholder]=\"placeholder\"\r\n [style]=\"{ height: height + 'px' }\"\r\n (ngModelChange)=\"onChangeValue($event)\"\r\n attr.data-testid=\"{{ dataTestId }}\"\r\n >\r\n </p-editor>\r\n}\r\n@if (control != null) {\r\n <control-messages [control]=\"control\" [field]=\"nombre\"></control-messages>\r\n}\r\n", dependencies: [{ kind: "component", type: i2$3.Header, selector: "p-header" }, { kind: "component", type: i3$8.Editor, selector: "p-editor", inputs: ["style", "styleClass", "placeholder", "formats", "modules", "bounds", "scrollingContainer", "debug", "readonly"], outputs: ["onInit", "onTextChange", "onSelectionChange"] }, { kind: "directive", type: i2$2.NgSelectOption, selector: "option", inputs: ["ngValue", "value"] }, { kind: "directive", type: i2$2.ɵNgSelectMultipleOption, selector: "option", inputs: ["ngValue", "value"] }, { kind: "directive", type: i2$2.NgControlStatus, selector: "[formControlName],[ngModel],[formControl]" }, { kind: "directive", type: i2$2.NgModel, selector: "[ngModel]:not([formControlName]):not([formControl])", inputs: ["name", "disabled", "ngModel", "ngModelOptions"], outputs: ["ngModelChange"], exportAs: ["ngModel"] }, { kind: "directive", type: FocusRegisterDirective, selector: "input,select,textarea,bit-input,bit-select" }, { kind: "component", type: BitControlMessages, selector: "control-messages", inputs: ["control", "field"] }, { kind: "pipe", type: i4.TranslocoPipe, name: "transloco" }] }); }
4666
+ }], usesInheritance: true, ngImport: i0, template: "@if (!hideLabel) {\r\n <label>\r\n <ng-content></ng-content>&nbsp; @if (obligatorio) {\r\n <span class=\"obligatorio fa fa-asterisk\"></span>\r\n }&nbsp;&nbsp;\r\n @if (ayuda) {\r\n <i class=\"btn-ayuda fa fa-question\" (click)=\"showAyuda()\"></i>\r\n }\r\n </label>\r\n}\r\n@if (readOnly) {\r\n <p class=\"lectura\">\r\n {{ value_lectura && value_lectura != \"\" ? value_lectura : \"&nbsp;\" }}\r\n </p>\r\n}\r\n@if (!readOnly && tipo == 'custom') {\r\n <p-editor\r\n id=\"{{ nombre }}\"\r\n name=\"{{ nombre }}\"\r\n [ngModel]=\"value\"\r\n styleClass=\"editor\"\r\n [disabled]=\"isDisabled\"\r\n [placeholder]=\"placeholder\"\r\n [style]=\"{ height: height + 'px' }\"\r\n (onInit)=\"onInit($event)\"\r\n (ngModelChange)=\"onChangeValue($event)\"\r\n (onTextChange)=\"_onTextChange($event)\"\r\n attr.data-testid=\"{{ dataTestId }}\"\r\n >\r\n <p-header>\r\n @if (configuracion.fontSize) {\r\n <span class=\"ql-formats\">\r\n <select class=\"ql-size\">\r\n <option value=\"small\">{{ \"bitnglibrary.form.biteditor.small\" | transloco }}</option>\r\n <!-- Note a missing, thus falsy value, is used to reset to default -->\r\n <option selected>{{ \"bitnglibrary.form.biteditor.normal\" | transloco }}</option>\r\n <option value=\"large\">{{ \"bitnglibrary.form.biteditor.large\" | transloco }}</option>\r\n <option value=\"huge\">{{ \"bitnglibrary.form.biteditor.huge\" | transloco }}</option>\r\n </select>\r\n </span>\r\n }\r\n @if (configuracion.fontFormat) {\r\n <span class=\"ql-formats\">\r\n <button class=\"ql-bold\" aria-label=\"Bold\"></button>\r\n <button class=\"ql-italic\" aria-label=\"Italic\"></button>\r\n <button class=\"ql-underline\" aria-label=\"Underline\"></button>\r\n <button class=\"ql-strike\" aria-label=\"Strikethrough\"></button>\r\n </span>\r\n }\r\n @if (configuracion.bullet) {\r\n <span class=\"ql-formats\">\r\n <button class=\"ql-list\" value=\"ordered\" type=\"button\"></button>\r\n <button class=\"ql-list\" value=\"bullet\" type=\"button\"></button>\r\n </span>\r\n }\r\n @if (configuracion.link) {\r\n <span class=\"ql-formats\">\r\n <button class=\"ql-link\" aria-label=\"Insert Link\" type=\"button\"></button>\r\n </span>\r\n }\r\n </p-header>\r\n </p-editor>\r\n}\r\n@if (!readOnly && (!tipo || tipo == 'default')) {\r\n <p-editor\r\n id=\"{{ nombre }}\"\r\n name=\"{{ nombre }}\"\r\n [ngModel]=\"value\"\r\n styleClass=\"editor\"\r\n [placeholder]=\"placeholder\"\r\n [placeholder]=\"placeholder\"\r\n [style]=\"{ height: height + 'px' }\"\r\n (ngModelChange)=\"onChangeValue($event)\"\r\n attr.data-testid=\"{{ dataTestId }}\"\r\n >\r\n </p-editor>\r\n}\r\n@if (control != null) {\r\n <control-messages [control]=\"control\" [field]=\"nombre\"></control-messages>\r\n}\r\n", dependencies: [{ kind: "component", type: i2$3.Header, selector: "p-header" }, { kind: "component", type: i3$9.Editor, selector: "p-editor", inputs: ["style", "styleClass", "placeholder", "formats", "modules", "bounds", "scrollingContainer", "debug", "readonly"], outputs: ["onInit", "onTextChange", "onSelectionChange"] }, { kind: "directive", type: i2$2.NgSelectOption, selector: "option", inputs: ["ngValue", "value"] }, { kind: "directive", type: i2$2.ɵNgSelectMultipleOption, selector: "option", inputs: ["ngValue", "value"] }, { kind: "directive", type: i2$2.NgControlStatus, selector: "[formControlName],[ngModel],[formControl]" }, { kind: "directive", type: i2$2.NgModel, selector: "[ngModel]:not([formControlName]):not([formControl])", inputs: ["name", "disabled", "ngModel", "ngModelOptions"], outputs: ["ngModelChange"], exportAs: ["ngModel"] }, { kind: "directive", type: FocusRegisterDirective, selector: "input,select,textarea,bit-input,bit-select" }, { kind: "component", type: BitControlMessages, selector: "control-messages", inputs: ["control", "field"] }, { kind: "pipe", type: i4.TranslocoPipe, name: "transloco" }] }); }
4638
4667
  }
4639
4668
  i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "18.2.12", ngImport: i0, type: BitEditorComponent, decorators: [{
4640
4669
  type: Component,