bit-ng-library 17.1.12 → 17.1.14

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,15 @@ 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
+ ## [17.1.14] - 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
+
34
+ ## [17.1.13] - 2025-07-15
35
+
36
+ Versión con errores, sustituida por [17.1.14]
37
+
29
38
  ## [17.1.12] - 2025-07-11
30
39
 
31
40
  Mejoras finales en BitNotificacion: tipado mejorado de la clase de notificación y constante para el tiempo máximo de vida de la notificación.
@@ -37,7 +46,7 @@ para el caso en el que no tenemos paginador
37
46
  ## [17.1.11] - 2025-07-11
38
47
  ## [17.1.10] - 2025-07-11
39
48
 
40
- Librerías con errores, sustituidas por [17.1.12]
49
+ Versiones con errores, sustituidas por [17.1.12]
41
50
 
42
51
  ## [17.1.9] - 2025-06-03
43
52
 
@@ -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: "17.3.12", ngImport: i0, type: BitAutoCompleteComponent, deps: [{ token: i1.AyudaService }], target: i0.ɵɵFactoryTarget.Component }); }
92
- static { this.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "17.3.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: "17.3.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", "id", "searchMessage", "emptySelectionMessage", "selectionMessage", "autoOptionFocus", "selectOnFocus", "searchLocale", "optionDisabled", "focusOnHover"], 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;@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", "id", "searchMessage", "emptySelectionMessage", "selectionMessage", "autoOptionFocus", "selectOnFocus", "searchLocale", "optionDisabled", "focusOnHover"], 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: "17.3.12", ngImport: i0, type: BitAutoCompleteComponent, decorators: [{
101
127
  type: Component,
@@ -105,7 +131,7 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "17.3.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;@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: "17.3.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,eyJ2ZXJzaW9uIjozLCJmaWxlIjoiYml0LWF1dG9jb21wbGV0ZS5jb21wb25lbnQuanMiLCJzb3VyY2VSb290IjoiIiwic291cmNlcyI6WyIuLi8uLi8uLi8uLi8uLi8uLi8uLi8uLi9wcm9qZWN0cy9iaXQtbmctbGlicmFyeS9zcmMvbGliL3NoYXJlZGxpYnJhcnkvY29tcG9uZW50cy9mb3JtL2F1dG9jb21wbGV0ZS9iaXQtYXV0b2NvbXBsZXRlLmNvbXBvbmVudC50cyIsIi4uLy4uLy4uLy4uLy4uLy4uLy4uLy4uL3Byb2plY3RzL2JpdC1uZy1saWJyYXJ5L3NyYy9saWIvc2hhcmVkbGlicmFyeS9jb21wb25lbnRzL2Zvcm0vYXV0b2NvbXBsZXRlL2JpdC1hdXRvY29tcGxldGUuY29tcG9uZW50Lmh0bWwiXSwibmFtZXMiOltdLCJtYXBwaW5ncyI6IkFBQUEsT0FBTyxFQUFpQixTQUFTLEVBQUUsWUFBWSxFQUFFLFlBQVksRUFBRSxVQUFVLEVBQUUsS0FBSyxFQUFhLE1BQU0sRUFBZ0IsV0FBVyxFQUFFLE1BQU0sZUFBZSxDQUFDO0FBQ3RKLE9BQU8sRUFBd0IsaUJBQWlCLEVBQUUsTUFBTSxnQkFBZ0IsQ0FBQztBQUd6RSxPQUFPLEVBQUUsa0JBQWtCLEVBQUUsTUFBTSx5QkFBeUIsQ0FBQzs7Ozs7Ozs7QUFjN0QsTUFBTSxPQUFPLHdCQUF5QixTQUFRLGtCQUFrQjtJQTZCOUQsWUFBc0IsWUFBMEI7UUFDOUMsS0FBSyxDQUFDLFlBQVksQ0FBQyxDQUFDO1FBREEsaUJBQVksR0FBWixZQUFZLENBQWM7UUF2QmhELGFBQVEsR0FBWSxLQUFLLENBQUM7UUFJMUIsT0FBRSxHQUFXLElBQUksQ0FBQztRQUlsQixtQkFBYyxHQUFZLEtBQUssQ0FBQyxDQUFDLDZEQUE2RDtRQUU5RixtQkFBYyxHQUFHLElBQUksWUFBWSxFQUFVLENBQUM7UUFFNUMsYUFBUSxHQUFHLElBQUksWUFBWSxFQUFVLENBQUM7UUFFdEMsWUFBTyxHQUFHLElBQUksWUFBWSxFQUFPLENBQUM7SUFXbEMsQ0FBQztJQUVELGVBQWU7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LGVBQWUsQ0FBQyxLQUFLLEtBQUssQ0FBQyxDQUFDO1FBQ3RGLENBQUM7SUFDSCxDQUFDOytHQWhJVSx3QkFBd0I7bUdBQXhCLHdCQUF3QixvVkFSeEI7WUFDVDtnQkFDRSxPQUFPLEVBQUUsaUJBQWlCO2dCQUMxQixXQUFXLEVBQUUsVUFBVSxDQUFDLEdBQUcsRUFBRSxDQUFDLHdCQUF3QixDQUFDO2dCQUN2RCxLQUFLLEVBQUUsSUFBSTthQUNaO1NBQ0YsK0dBd0JxQyxXQUFXLHlFQ3hDbkQscWpEQTRDQTs7NEZEMUJhLHdCQUF3QjtrQkFYcEMsU0FBUzsrQkFDRSxrQkFBa0IsYUFFakI7d0JBQ1Q7NEJBQ0UsT0FBTyxFQUFFLGlCQUFpQjs0QkFDMUIsV0FBVyxFQUFFLFVBQVUsQ0FBQyxHQUFHLEVBQUUseUJBQXlCLENBQUM7NEJBQ3ZELEtBQUssRUFBRSxJQUFJO3lCQUNaO3FCQUNGO2lGQUlELFdBQVc7c0JBRFYsS0FBSztnQkFHTixlQUFlO3NCQURkLEtBQUs7Z0JBR04sUUFBUTtzQkFEUCxLQUFLO2dCQUdOLGVBQWU7c0JBRGQsS0FBSztnQkFHTixFQUFFO3NCQURELEtBQUs7Z0JBR04sWUFBWTtzQkFEWCxLQUFLO2dCQUdOLGNBQWM7c0JBRGIsS0FBSztnQkFHTixjQUFjO3NCQURiLE1BQU07Z0JBR1AsUUFBUTtzQkFEUCxNQUFNO2dCQUdQLE9BQU87c0JBRE4sTUFBTTtnQkFJUCxZQUFZO3NCQURYLFlBQVk7dUJBQUMsY0FBYyxFQUFFLEVBQUUsSUFBSSxFQUFFLFdBQVcsRUFBRSIsInNvdXJjZXNDb250ZW50IjpbImltcG9ydCB7IEFmdGVyVmlld0luaXQsIENvbXBvbmVudCwgQ29udGVudENoaWxkLCBFdmVudEVtaXR0ZXIsIGZvcndhcmRSZWYsIElucHV0LCBPbkNoYW5nZXMsIE91dHB1dCwgU2ltcGxlQ2hhbmdlLCBUZW1wbGF0ZVJlZiB9IGZyb20gXCJAYW5ndWxhci9jb3JlXCI7XHJcbmltcG9ydCB7IENvbnRyb2xWYWx1ZUFjY2Vzc29yLCBOR19WQUxVRV9BQ0NFU1NPUiB9IGZyb20gXCJAYW5ndWxhci9mb3Jtc1wiO1xyXG5cclxuaW1wb3J0IHsgQXl1ZGFTZXJ2aWNlIH0gZnJvbSBcIi4uLy4uLy4uL3NlcnZpY2VzXCI7XHJcbmltcG9ydCB7IEJpdEN1c3RvbUNvbXBvbmVudCB9IGZyb20gXCIuLi9iaXQtY3VzdG9tLmNvbXBvbmVudFwiO1xyXG5pbXBvcnQgeyBBdXRvQ29tcGxldGVTZWxlY3RFdmVudCB9IGZyb20gXCJwcmltZW5nL2F1dG9jb21wbGV0ZVwiO1xyXG5cclxuQENvbXBvbmVudCh7XHJcbiAgc2VsZWN0b3I6IFwiYml0LWF1dG9jb21wbGV0ZVwiLFxyXG4gIHRlbXBsYXRlVXJsOiBcImJpdC1hdXRvY29tcGxldGUuY29tcG9uZW50Lmh0bWxcIixcclxuICBwcm92aWRlcnM6IFtcclxuICAgIHtcclxuICAgICAgcHJvdmlkZTogTkdfVkFMVUVfQUNDRVNTT1IsXHJcbiAgICAgIHVzZUV4aXN0aW5nOiBmb3J3YXJkUmVmKCgpID0+IEJpdEF1dG9Db21wbGV0ZUNvbXBvbmVudCksXHJcbiAgICAgIG11bHRpOiB0cnVlXHJcbiAgICB9XHJcbiAgXVxyXG59KVxyXG5leHBvcnQgY2xhc3MgQml0QXV0b0NvbXBsZXRlQ29tcG9uZW50IGV4dGVuZHMgQml0Q3VzdG9tQ29tcG9uZW50IGltcGxlbWVudHMgQ29udHJvbFZhbHVlQWNjZXNzb3IsIEFmdGVyVmlld0luaXQsIE9uQ2hhbmdlcyB7XHJcbiAgQElucHV0KClcclxuICBzdWdnZXN0aW9uczogYW55W107XHJcbiAgQElucHV0KClcclxuICBzdWdnZXN0aW9uRmllbGQ6IHN0cmluZztcclxuICBASW5wdXQoKVxyXG4gIG11bHRpcGxlOiBib29sZWFuID0gZmFsc2U7XHJcbiAgQElucHV0KClcclxuICBpbnB1dFN0eWxlQ2xhc3M6IHN0cmluZztcclxuICBASW5wdXQoKVxyXG4gIGlkOiBzdHJpbmcgPSBcImlkXCI7XHJcbiAgQElucHV0KClcclxuICBkaXNwbGF5VmFsdWU6IHN0cmluZztcclxuICBASW5wdXQoKVxyXG4gIGN1c3RvbVRlbXBsYXRlOiBib29sZWFuID0gZmFsc2U7IC8vIHNpIHNlIHVzYSB1biB0ZW1wbGF0ZSBwZXJzb25hbGl6YWRvIHBhcmEgbW9zdHJhciBsb3MgaXRlbXNcclxuICBAT3V0cHV0KClcclxuICBjb21wbGV0ZU1ldGhvZCA9IG5ldyBFdmVudEVtaXR0ZXI8c3RyaW5nPigpO1xyXG4gIEBPdXRwdXQoKVxyXG4gIG9uU2VsZWN0ID0gbmV3IEV2ZW50RW1pdHRlcjxzdHJpbmc+KCk7XHJcbiAgQE91dHB1dCgpXHJcbiAgb25DbGVhciA9IG5ldyBFdmVudEVtaXR0ZXI8YW55PigpO1xyXG5cclxuICBAQ29udGVudENoaWxkKCdpdGVtVGVtcGxhdGUnLCB7IHJlYWQ6IFRlbXBsYXRlUmVmIH0pXHJcbiAgaXRlbVRlbXBsYXRlOiBUZW1wbGF0ZVJlZjxhbnk+O1xyXG5cclxuICBzdWdnZXN0aW9uc19tYXBwZWQ6IHN0cmluZ1tdO1xyXG5cclxuICB2YWx1ZTogc3RyaW5nO1xyXG5cclxuICBjb25zdHJ1Y3Rvcihwcm90ZWN0ZWQgYXl1ZGFTZXJ2aWNlOiBBeXVkYVNlcnZpY2UpIHtcclxuICAgIHN1cGVyKGF5dWRhU2VydmljZSk7XHJcbiAgfVxyXG5cclxuICBuZ0FmdGVyVmlld0luaXQoKSB7XHJcbiAgICAvLyBDb250cm9sIGRlIGVycm9yZXM6XHJcbiAgICAvLyAxLiBTaSBzZSBxdWllcmUgdXNhciB1bmEgdGVtcGxhdGUgcGVyc29uYWxpemFkYSwgc2UgZGViZSBlc3BlY2lmaWNhciBlbCBpbnB1dCBjdXN0b21UZW1wbGF0ZS5cclxuICAgIC8vIDIuIFNpIHNlIHVzYSBjdXN0b21UZW1wbGF0ZSwgc2UgZGViZSBlc3BlY2lmaWNhciBlbCBpbnB1dCBzdWdnZXN0aW9uRmllbGQgcGFyYSBwb2RlciBtYXBlYXIgZWwgb2JqZXRvIGVuIGVsIGNhbXBvIGRlIHRleHRvLlxyXG4gICAgLy8gMy4gU2kgc2UgdXNhIGl0ZW1UZW1wbGF0ZSwgc2UgZGViZSBlc3BlY2lmaWNhciBjdXN0b21UZW1wbGF0ZSBhIHRydWUuICh3YXJuaW5nKVxyXG4gICAgaWYgKHRoaXMuY3VzdG9tVGVtcGxhdGUgJiYgIXRoaXMuaXRlbVRlbXBsYXRlKSB7XHJcbiAgICAgIHRocm93IG5ldyBFcnJvcihcIkJpdEF1dG9Db21wbGV0ZUNvbXBvbmVudDogU2kgc2UgZXNwZWNpZmljYSBlbCBpbnB1dCBjdXN0b21UZW1wbGF0ZSBzZSBkZWJlIHByb3BvcmNpb25hciB1bmEgdGVtcGxhdGUgYSB0cmF2w6lzIGRlICc8bmctdGVtcGxhdGUgI2l0ZW1UZW1wbGF0ZSBsZXQtaXRlbT4nXCIpO1xyXG4gICAgfSBlbHNlIGlmICh0aGlzLmN1c3RvbVRlbXBsYXRlICYmICF0aGlzLnN1Z2dlc3Rpb25GaWVsZCkge1xyXG4gICAgICB0aHJvdyBuZXcgRXJyb3IoXCJCaXRBdXRvQ29tcGxldGVDb21wb25lbnQ6IFNpIHNlIGVzcGVjaWZpY2EgZWwgaW5wdXQgY3VzdG9tVGVtcGxhdGUsIHNlIGRlYmUgZXNwZWNpZmljYXIgZWwgaW5wdXQgc3VnZ2VzdGlvbkZpZWxkIHBhcmEgcG9kZXIgbWFwZWFyIGVsIG9iamV0byBlbiBlbCBjYW1wbyBkZSB0ZXh0byBjdWFuZG8gZWxpamFtb3MgdW5vIGRlIGxhIGxpc3RhLlwiKTtcclxuICAgIH0gZWxzZSBpZiAoIXRoaXMuY3VzdG9tVGVtcGxhdGUgJiYgdGhpcy5pdGVtVGVtcGxhdGUpIHtcclxuICAgICAgY29uc29sZS53YXJuKFwiQml0QXV0b0NvbXBsZXRlQ29tcG9uZW50OiBTZSBoYSBwcm9wb3JjaW9uYWRvIHVuYSB0ZW1wbGF0ZSBwZXJzb25hbGl6YWRhIGEgdHJhdsOpcyBkZSAnaXRlbVRlbXBsYXRlJywgcGVybyBzZSBlc3TDoSBwYXNhbmRvIGRlIGVsbGEuIFBhcmEgdXNhcmxhLCBkZWJlIGVzdGFibGVjZXIgY3VzdG9tVGVtcGxhdGUgYSB0cnVlLlwiKTtcclxuICAgIH1cclxuICB9XHJcblxyXG4gIG5nT25DaGFuZ2VzKGNoYW5nZXM6IHsgW3Byb3BLZXk6IHN0cmluZ106IFNpbXBsZUNoYW5nZSB9KSB7XHJcbiAgICBmb3IgKGxldCBwcm9wTmFtZSBpbiBjaGFuZ2VzKSB7XHJcbiAgICAgIGlmIChwcm9wTmFtZSA9PT0gXCJzdWdnZXN0aW9uc1wiKSB7XHJcbiAgICAgICAgbGV0IGNoYW5nZWRQcm9wID0gY2hhbmdlc1twcm9wTmFtZV07XHJcbiAgICAgICAgbGV0IG5ld0xpc3QgPSBjaGFuZ2VkUHJvcC5jdXJyZW50VmFsdWU7XHJcbiAgICAgICAgLy8gRWwgbWFwZW8gdGllbmUgcXVlIHNlciBjb24gdG9kbyBlbCBvYmpldG8sIG5vIHNvbG8gY29uIGVsIGNhbXBvIHN1Z2dlc3Rpb25GaWVsZCwgcG9ycXVlIHNpIHNlIHVzYSB1biB0ZW1wbGF0ZSBwZXJzb25hbGl6YWRvXHJcbiAgICAgICAgLy8gc2UgbmVjZXNpdGEgZWwgb2JqZXRvIGNvbXBsZXRvIHBhcmEgcG9kZXIgcGFzYXJsb3MgYSBsYSB0ZW1wbGF0ZSB5IHF1ZSBzZSBwaW50ZSBjb3JyZWN0YW1lbnRlLlxyXG4gICAgICAgIHRoaXMuc3VnZ2VzdGlvbnNfbWFwcGVkID0gbmV3TGlzdCAmJiBuZXdMaXN0Lm1hcCgob2JqOiB7IFt4OiBzdHJpbmddOiBhbnkgfSkgPT4gKChvYmogaW5zdGFuY2VvZiBPYmplY3QgJiYgIXRoaXMuY3VzdG9tVGVtcGxhdGUpID8gb2JqW3RoaXMuc3VnZ2VzdGlvbkZpZWxkXSA6IG9iaikpO1xyXG4gICAgICAgIC8vY29uc29sZS5sb2coXCJuZXdMaXN0XCIsIHRoaXMuc3VnZ2VzdGlvbnNfbWFwcGVkKTtcclxuICAgICAgfVxyXG4gICAgfVxyXG4gIH1cclxuXHJcbiAgc2VhcmNoKGV2ZW50OiBhbnkpIHtcclxuICAgIHRoaXMuY29tcGxldGVNZXRob2QuZW1pdChldmVudCk7XHJcbiAgfVxyXG5cclxuICBnZXQgdmFsdWVfbGVjdHVyYSgpOiBzdHJpbmcge1xyXG4gICAgaWYgKHRoaXMudmFsdWUgPT0gbnVsbCkge1xyXG4gICAgICByZXR1cm4gXCJcIjtcclxuICAgIH0gLy8gc2kgZXMgbnVsbCBvIHVuZGVmaW5lZCAoZXMgbG8gcXVlIGV2YWzDumEgZWwgXCI9PW51bGxcIilcclxuICAgIGVsc2Uge1xyXG4gICAgICByZXR1cm4gdGhpcy52YWx1ZTtcclxuICAgIH1cclxuICB9XHJcblxyXG4gIHdyaXRlVmFsdWUodjogbnVtYmVyIHwgc3RyaW5nKTogdm9pZCB7XHJcbiAgICAvLyBFbCAwIGVzIHVuIHZhbG9yIHbDoWxpZG9cclxuICAgIGlmICh2ID09PSBudWxsIHx8IHYgPT09IHVuZGVmaW5lZCB8fCB2ID09PSBcIlwiKSB7XHJcbiAgICAgIHRoaXMudmFsdWUgPSBcIlwiO1xyXG4gICAgfSBlbHNlIHtcclxuICAgICAgaWYgKHR5cGVvZiB2ID09PSBcInN0cmluZ1wiKSB7XHJcbiAgICAgICAgdGhpcy52YWx1ZSA9IHYudG9TdHJpbmcoKTtcclxuICAgICAgfSBlbHNlIHtcclxuICAgICAgICB0aGlzLnZhbHVlID0gdGhpcy5kaXNwbGF5VmFsdWU7XHJcbiAgICAgIH1cclxuICAgIH1cclxuICB9XHJcblxyXG4gIGNoYW5nZUNvbXBvbmVudFZhbHVlKHZhbHVlOiBhbnkpIHtcclxuICAgIGxldCB2YWx1ZUNvbnZlcnRlZDogYW55O1xyXG4gICAgaWYgKHRoaXMuc3VnZ2VzdGlvbkZpZWxkKSB7XHJcbiAgICAgIC8vIHNpIGVzdGFtb3MgZXNwZWNpZmljYW5kbyBxdWUgbG8gcXVlIGVsIGF1dG9jb21wbGV0YXIgaGFjZSBlcyBvcGVyYXIgc29icmUgdW5hIGxpc3RhIGRlIG9iamV0b3NcclxuICAgICAgLy8gcmVjdXBlcmFtb3MgZWwgb2JqZXRvIGRlbnRybyBkZSBsYSBsaXN0YSBjb24gZWwgdmFsb3IgZGVsIGNhbXBvIHN1Z2dlc3Rpb25GaWVsZCBpZ3VhbCBhbCBzZWxlY2Npb25hZG9cclxuICAgICAgbGV0IHNlbGVjdGVkT2JqZWN0ID0gdGhpcy5fZmluZE9iamVjdCh2YWx1ZSk7XHJcbiAgICAgIC8vIGVsIHZhbG9yIHJlY29udmVydGlkbyBzZXLDoSBlbCBJRCBkZWwgb2JqZXRvIHF1ZSBlcyBsbyBxdWUgdmFtb3MgYSBtZXRlciBlbiBlbCBGb3JtQ29udHJvbFxyXG4gICAgICB2YWx1ZUNvbnZlcnRlZCA9IHNlbGVjdGVkT2JqZWN0ICYmIHNlbGVjdGVkT2JqZWN0W3RoaXMuaWRdO1xyXG4gICAgICAvLyBlbWl0aW1vcyBxdWUgaGEgY2FtYmlhZG8gZWwgb2JqZXRvXHJcbiAgICAgIHRoaXMub25DaGFuZ2UuZW1pdChzZWxlY3RlZE9iamVjdCk7XHJcbiAgICB9IGVsc2Uge1xyXG4gICAgICAvLyBzaSBubyBlcyB1bmEgbGlzdGEgZGUgb2JqZXRvcyBlbCBjb21wb3J0YW1pZW50byBlcyBlbCBkZSBzaWVtcHJlXHJcbiAgICAgIHZhbHVlQ29udmVydGVkID0gdmFsdWU7XHJcbiAgICAgIHRoaXMub25DaGFuZ2UuZW1pdCh2YWx1ZUNvbnZlcnRlZCk7XHJcbiAgICB9XHJcbiAgICB0aGlzLl9vbkNoYW5nZSh2YWx1ZUNvbnZlcnRlZCk7XHJcbiAgfVxyXG5cclxuICBfb25TZWxlY3QoZXZlbnQ6IEF1dG9Db21wbGV0ZVNlbGVjdEV2ZW50KSB7XHJcbiAgICB0aGlzLnZhbHVlID0gZXZlbnQudmFsdWU7XHJcbiAgICB0aGlzLmNoYW5nZUNvbXBvbmVudFZhbHVlKHRoaXMudmFsdWUpO1xyXG4gICAgaWYgKHRoaXMuc3VnZ2VzdGlvbkZpZWxkKSB7XHJcbiAgICAgIGxldCBzZWxlY3RlZE9iamVjdCA9IHRoaXMuX2ZpbmRPYmplY3QoZXZlbnQudmFsdWUpO1xyXG4gICAgICB0aGlzLm9uU2VsZWN0LmVtaXQoc2VsZWN0ZWRPYmplY3QpO1xyXG4gICAgfSBlbHNlIHtcclxuICAgICAgdGhpcy5vblNlbGVjdC5lbWl0KHRoaXMudmFsdWUpO1xyXG4gICAgfVxyXG4gIH1cclxuXHJcbiAgX29uQ2xlYXIoKSB7XHJcbiAgICB0aGlzLnZhbHVlID0gXCJcIjtcclxuICAgIHRoaXMuY2hhbmdlQ29tcG9uZW50VmFsdWUodGhpcy52YWx1ZSk7XHJcbiAgICB0aGlzLm9uQ2xlYXIuZW1pdCgpO1xyXG4gIH1cclxuXHJcbiAgX2ZpbmRPYmplY3QodmFsdWU6IGFueSkge1xyXG4gICAgLy8gU2kgc2UgdXNhIHVuIHRlbXBsYXRlIHBlcnNvbmFsaXphZG8sIGRldm9sdmVtb3MgZWwgdmFsb3IgZGlyZWN0YW1lbnRlLCBwb3JxdWUgeWEgZXN0YXLDoSBhbGzDrSwgbm8gaGFjZSBmYWx0YSBidXNjYXJsbyBlbiBsYSBsaXN0YSBkZSBzdWdlcmVuY2lhc1xyXG4gICAgaWYgKHRoaXMuY3VzdG9tVGVtcGxhdGUpIHtcclxuICAgICAgcmV0dXJuIHRoaXMudmFsdWU7XHJcbiAgICB9IGVsc2Uge1xyXG4gICAgICByZXR1cm4gdmFsdWUgJiYgdGhpcy5zdWdnZXN0aW9ucy5maW5kKChvYmopID0+IG9ialt0aGlzLnN1Z2dlc3Rpb25GaWVsZF0gPT09IHZhbHVlKTtcclxuICAgIH1cclxuICB9XHJcbn1cclxuIiwiQGlmICghaGlkZUxhYmVsKSB7XHJcbiAgPGxhYmVsPlxyXG4gICAgPG5nLWNvbnRlbnQ+PC9uZy1jb250ZW50PiZuYnNwO0BpZiAob2JsaWdhdG9yaW8pIHtcclxuICAgIDxzcGFuIGNsYXNzPVwib2JsaWdhdG9yaW8gZmEgZmEtYXN0ZXJpc2tcIj48L3NwYW4+XHJcbiAgfSZuYnNwOyZuYnNwO1xyXG4gICAgQGlmIChheXVkYSkge1xyXG4gICAgICA8aSBjbGFzcz1cImJ0bi1heXVkYSBmYSBmYS1xdWVzdGlvblwiIChjbGljayk9XCJzaG93QXl1ZGEoKVwiPjwvaT5cclxuICAgIH1cclxuICA8L2xhYmVsPlxyXG59XHJcbkBpZiAocmVhZE9ubHkpIHtcclxuICA8cCBjbGFzcz1cImxlY3R1cmFcIiBbaWRdPVwibm9tYnJlXCI+e3sgdmFsdWVfbGVjdHVyYSB9fTwvcD5cclxufVxyXG5AaWYgKCFyZWFkT25seSkge1xyXG4gIDwhLS0gU2kgdXNhbW9zIHVuIHRlbXBsYXRlIHBlcnNvbmFsaXphZG8sIGhheSBxdWUgaW5kaWNhciBlbCBvcHRpb25MYWJlbCBwYXJhIHF1ZSBzZXBhIGN1w6FsIGVzIGVsIGNhbXBvIGEgbW9zdHJhciBhbCBzZWxlY2Npb25hciB1biBlbGVtZW50byAtLT5cclxuICA8cC1hdXRvQ29tcGxldGVcclxuICAgIFsobmdNb2RlbCldPVwidmFsdWVcIlxyXG4gICAgaWQ9XCJ7eyBub21icmUgfX1cIlxyXG4gICAgbmFtZT1cInt7IG5vbWJyZSB9fVwiXHJcbiAgICBbZGlzYWJsZWRdPVwiaXNEaXNhYmxlZFwiXHJcbiAgICBbcGxhY2Vob2xkZXJdPVwicGxhY2Vob2xkZXJcIlxyXG4gICAgW2RlbGF5XT1cIjQwMFwiXHJcbiAgICBbc3VnZ2VzdGlvbnNdPVwic3VnZ2VzdGlvbnNfbWFwcGVkXCJcclxuICAgIFttdWx0aXBsZV09XCJtdWx0aXBsZVwiXHJcbiAgICBbaW5wdXRTdHlsZUNsYXNzXT1cImlucHV0U3R5bGVDbGFzc1wiXHJcbiAgICBvcHRpb25MYWJlbD1cInt7IGN1c3RvbVRlbXBsYXRlID8gdGhpcy5zdWdnZXN0aW9uRmllbGQgOiAnJyB9fVwiXHJcbiAgICBhcHBlbmRUbz1cImJvZHlcIlxyXG4gICAgKGNvbXBsZXRlTWV0aG9kKT1cInNlYXJjaCgkZXZlbnQpXCJcclxuICAgIChvblNlbGVjdCk9XCJfb25TZWxlY3QoJGV2ZW50KVwiXHJcbiAgICAob25DbGVhcik9XCJfb25DbGVhcigpXCJcclxuICAgIChvbkJsdXIpPVwiX29uQmx1cigpXCJcclxuICAgIChvbkZvY3VzKT1cIl9vbkZvY3VzKClcIlxyXG4gICAgYXR0ci5kYXRhLXRlc3RpZD1cInt7IGRhdGFUZXN0SWQgfX1cIlxyXG4gID5cclxuICAgIEBpZiAoY3VzdG9tVGVtcGxhdGUgJiYgaXRlbVRlbXBsYXRlKSB7XHJcbiAgICAgIDxuZy10ZW1wbGF0ZSBwVGVtcGxhdGU9XCJpdGVtXCIgbGV0LWl0ZW0+XHJcbiAgICAgICAgPG5nLWNvbnRhaW5lciAqbmdUZW1wbGF0ZU91dGxldD1cIml0ZW1UZW1wbGF0ZTsgY29udGV4dDogeyAkaW1wbGljaXQ6IGl0ZW0gfVwiPjwvbmctY29udGFpbmVyPlxyXG4gICAgICA8L25nLXRlbXBsYXRlPlxyXG4gICAgfVxyXG4gIDwvcC1hdXRvQ29tcGxldGU+XHJcbn1cclxuQGlmIChjb250cm9sICE9IG51bGwpIHtcclxuICA8Y29udHJvbC1tZXNzYWdlcyBbY29udHJvbF09XCJjb250cm9sXCIgW2ZpZWxkXT1cIm5vbWJyZVwiPjwvY29udHJvbC1tZXNzYWdlcz5cclxufVxyXG4iXX0=
@@ -1,6 +1,6 @@
1
1
  import { Subject, BehaviorSubject, of, ReplaySubject, combineLatest, fromEvent, throwError } from 'rxjs';
2
2
  import * as i0 from '@angular/core';
3
- import { inject, DestroyRef, Directive, Input, ChangeDetectionStrategy, Component, EventEmitter, Injectable, Inject, Pipe, Output, HostListener, ViewChild, forwardRef, ContentChild, ElementRef, signal, NgModule } from '@angular/core';
3
+ import { inject, DestroyRef, Directive, Input, ChangeDetectionStrategy, Component, EventEmitter, Injectable, Inject, Pipe, Output, HostListener, ViewChild, forwardRef, TemplateRef, ContentChild, ElementRef, signal, NgModule } from '@angular/core';
4
4
  import moment from 'moment';
5
5
  import { createEntityAdapter } from '@ngrx/entity';
6
6
  import * as i2$2 from '@angular/forms';
@@ -15,7 +15,7 @@ import * as i3$4 from 'primeng/inputtext';
15
15
  import { InputTextModule } from 'primeng/inputtext';
16
16
  import * as i2$1 from 'primeng/dropdown';
17
17
  import { DropdownModule } from 'primeng/dropdown';
18
- import * as i3$8 from 'primeng/editor';
18
+ import * as i3$9 from 'primeng/editor';
19
19
  import { EditorModule } from 'primeng/editor';
20
20
  import * as i5$1 from 'primeng/multiselect';
21
21
  import { MultiSelectModule } from 'primeng/multiselect';
@@ -27,7 +27,7 @@ import { TabViewModule } from 'primeng/tabview';
27
27
  import * as i3 from 'primeng/dialog';
28
28
  import { DialogModule } from 'primeng/dialog';
29
29
  import { AccordionModule } from 'primeng/accordion';
30
- import * as i2$5 from 'primeng/autocomplete';
30
+ import * as i3$8 from 'primeng/autocomplete';
31
31
  import { AutoCompleteModule } from 'primeng/autocomplete';
32
32
  import * as i3$7 from 'primeng/inputswitch';
33
33
  import { InputSwitchModule } from 'primeng/inputswitch';
@@ -4453,16 +4453,34 @@ class BitAutoCompleteComponent extends BitCustomComponent {
4453
4453
  this.ayudaService = ayudaService;
4454
4454
  this.multiple = false;
4455
4455
  this.id = "id";
4456
+ this.customTemplate = false; // si se usa un template personalizado para mostrar los items
4456
4457
  this.completeMethod = new EventEmitter();
4457
4458
  this.onSelect = new EventEmitter();
4458
4459
  this.onClear = new EventEmitter();
4459
4460
  }
4461
+ ngAfterViewInit() {
4462
+ // Control de errores:
4463
+ // 1. Si se quiere usar una template personalizada, se debe especificar el input customTemplate.
4464
+ // 2. Si se usa customTemplate, se debe especificar el input suggestionField para poder mapear el objeto en el campo de texto.
4465
+ // 3. Si se usa itemTemplate, se debe especificar customTemplate a true. (warning)
4466
+ if (this.customTemplate && !this.itemTemplate) {
4467
+ throw new Error("BitAutoCompleteComponent: Si se especifica el input customTemplate se debe proporcionar una template a través de '<ng-template #itemTemplate let-item>'");
4468
+ }
4469
+ else if (this.customTemplate && !this.suggestionField) {
4470
+ 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.");
4471
+ }
4472
+ else if (!this.customTemplate && this.itemTemplate) {
4473
+ 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.");
4474
+ }
4475
+ }
4460
4476
  ngOnChanges(changes) {
4461
4477
  for (let propName in changes) {
4462
4478
  if (propName === "suggestions") {
4463
4479
  let changedProp = changes[propName];
4464
4480
  let newList = changedProp.currentValue;
4465
- this.suggestions_mapped = newList && newList.map((obj) => (obj instanceof Object ? obj[this.suggestionField] : obj));
4481
+ // El mapeo tiene que ser con todo el objeto, no solo con el campo suggestionField, porque si se usa un template personalizado
4482
+ // se necesita el objeto completo para poder pasarlos a la template y que se pinte correctamente.
4483
+ this.suggestions_mapped = newList && newList.map((obj) => ((obj instanceof Object && !this.customTemplate) ? obj[this.suggestionField] : obj));
4466
4484
  //console.log("newList", this.suggestions_mapped);
4467
4485
  }
4468
4486
  }
@@ -4527,16 +4545,22 @@ class BitAutoCompleteComponent extends BitCustomComponent {
4527
4545
  this.onClear.emit();
4528
4546
  }
4529
4547
  _findObject(value) {
4530
- return value && this.suggestions.find((obj) => obj[this.suggestionField] === value);
4548
+ // Si se usa un template personalizado, devolvemos el valor directamente, porque ya estará allí, no hace falta buscarlo en la lista de sugerencias
4549
+ if (this.customTemplate) {
4550
+ return this.value;
4551
+ }
4552
+ else {
4553
+ return value && this.suggestions.find((obj) => obj[this.suggestionField] === value);
4554
+ }
4531
4555
  }
4532
4556
  static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "17.3.12", ngImport: i0, type: BitAutoCompleteComponent, deps: [{ token: AyudaService }], target: i0.ɵɵFactoryTarget.Component }); }
4533
- static { this.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "17.3.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: [
4557
+ static { this.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "17.3.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: [
4534
4558
  {
4535
4559
  provide: NG_VALUE_ACCESSOR,
4536
4560
  useExisting: forwardRef(() => BitAutoCompleteComponent),
4537
4561
  multi: true
4538
4562
  }
4539
- ], 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", "id", "searchMessage", "emptySelectionMessage", "selectionMessage", "autoOptionFocus", "selectOnFocus", "searchLocale", "optionDisabled", "focusOnHover"], 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"] }] }); }
4563
+ ], 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;@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", "id", "searchMessage", "emptySelectionMessage", "selectionMessage", "autoOptionFocus", "selectOnFocus", "searchLocale", "optionDisabled", "focusOnHover"], 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"] }] }); }
4540
4564
  }
4541
4565
  i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "17.3.12", ngImport: i0, type: BitAutoCompleteComponent, decorators: [{
4542
4566
  type: Component,
@@ -4546,7 +4570,7 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "17.3.12", ngImpo
4546
4570
  useExisting: forwardRef(() => BitAutoCompleteComponent),
4547
4571
  multi: true
4548
4572
  }
4549
- ], 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" }]
4573
+ ], 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 <!-- 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" }]
4550
4574
  }], ctorParameters: () => [{ type: AyudaService }], propDecorators: { suggestions: [{
4551
4575
  type: Input
4552
4576
  }], suggestionField: [{
@@ -4559,12 +4583,17 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "17.3.12", ngImpo
4559
4583
  type: Input
4560
4584
  }], displayValue: [{
4561
4585
  type: Input
4586
+ }], customTemplate: [{
4587
+ type: Input
4562
4588
  }], completeMethod: [{
4563
4589
  type: Output
4564
4590
  }], onSelect: [{
4565
4591
  type: Output
4566
4592
  }], onClear: [{
4567
4593
  type: Output
4594
+ }], itemTemplate: [{
4595
+ type: ContentChild,
4596
+ args: ['itemTemplate', { read: TemplateRef }]
4568
4597
  }] } });
4569
4598
 
4570
4599
  /**
@@ -4973,7 +5002,7 @@ class BitEditorComponent extends BitCustomComponent {
4973
5002
  provide: NG_VALUE_ACCESSOR,
4974
5003
  useExisting: forwardRef(() => BitEditorComponent),
4975
5004
  multi: true
4976
- }], 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" }] }); }
5005
+ }], 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" }] }); }
4977
5006
  }
4978
5007
  i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "17.3.12", ngImport: i0, type: BitEditorComponent, decorators: [{
4979
5008
  type: Component,