@seniorsistemas/angular-components 17.27.1-feature-sds-110-9a13a8bc → 17.27.1-feature-sds-110-57186492
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/autocomplete/index.d.ts +5 -0
- package/autocomplete/lib/autocomplete/autocomplete.component.d.ts +250 -0
- package/autocomplete/lib/autocomplete/components/autocomplete-chip/autocomplete-chip.component.d.ts +9 -0
- package/autocomplete/public-api.d.ts +1 -0
- package/button/lib/button/button.component.d.ts +1 -1
- package/dynamic-form/lib/dynamic-form/components/lookup/lookup.component.d.ts +1 -2
- package/dynamic-form/lib/dynamic-form/dynamic-form.module.d.ts +3 -2
- package/dynamic-form/lib/dynamic-form/form-field/fields/currency/currency-field.component.d.ts +3 -2
- package/esm2022/autocomplete/lib/autocomplete/autocomplete.component.mjs +554 -0
- package/esm2022/autocomplete/lib/autocomplete/components/autocomplete-chip/autocomplete-chip.component.mjs +17 -0
- package/esm2022/autocomplete/public-api.mjs +2 -0
- package/esm2022/autocomplete/seniorsistemas-angular-components-autocomplete.mjs +5 -0
- package/esm2022/button/lib/button/button.component.mjs +4 -10
- package/esm2022/chips/lib/chips/chips/chips.component.mjs +2 -2
- package/esm2022/control-errors/lib/control-errors/control-errors.component.mjs +2 -2
- package/esm2022/country-phone-picker/lib/country-phone-picker/country-phone-picker.component.mjs +2 -2
- package/esm2022/dynamic-form/lib/dynamic-form/components/lookup/lookup.component.mjs +16 -10
- package/esm2022/dynamic-form/lib/dynamic-form/dynamic-form.module.mjs +5 -1
- package/esm2022/dynamic-form/lib/dynamic-form/form-field/fields/autocomplete/autocomplete-field.component.mjs +7 -6
- package/esm2022/dynamic-form/lib/dynamic-form/form-field/fields/currency/currency-field.component.mjs +18 -8
- package/esm2022/dynamic-form/lib/dynamic-form/form-field/fields/lookup/lookup-field.component.mjs +1 -1
- package/esm2022/dynamic-form/lib/dynamic-form/form-field/fields/password/password-field.component.mjs +2 -2
- package/esm2022/dynamic-form/lib/dynamic-form/form-field/fields/select/select-field.component.mjs +1 -1
- package/esm2022/inline-edit/lib/inline-edit/components/fields/inline-edit-lookup/inline-edit-lookup.component.mjs +1 -1
- package/esm2022/lib/locale/fallback.mjs +2 -1
- package/esm2022/object-card/lib/object-card/object-card.component.mjs +3 -3
- package/esm2022/paginator/lib/paginator/paginator.component.mjs +2 -2
- package/esm2022/panel/lib/panel/panel.component.mjs +3 -3
- package/esm2022/select/lib/select/select.component.mjs +234 -336
- package/esm2022/text-area/lib/text-area/text-area.component.mjs +4 -4
- package/esm2022/text-area-ia/lib/text-area-ia/text-area-ia.component.mjs +4 -4
- package/esm2022/toast/lib/toast/toast.component.mjs +13 -13
- package/esm2022/token-list/lib/token-list/token-list.component.mjs +3 -3
- package/fesm2022/seniorsistemas-angular-components-autocomplete.mjs +575 -0
- package/fesm2022/seniorsistemas-angular-components-autocomplete.mjs.map +1 -0
- package/fesm2022/seniorsistemas-angular-components-button.mjs +3 -9
- package/fesm2022/seniorsistemas-angular-components-button.mjs.map +1 -1
- package/fesm2022/seniorsistemas-angular-components-chips.mjs +2 -2
- package/fesm2022/seniorsistemas-angular-components-chips.mjs.map +1 -1
- package/fesm2022/seniorsistemas-angular-components-control-errors.mjs +1 -1
- package/fesm2022/seniorsistemas-angular-components-control-errors.mjs.map +1 -1
- package/fesm2022/seniorsistemas-angular-components-country-phone-picker.mjs +2 -2
- package/fesm2022/seniorsistemas-angular-components-country-phone-picker.mjs.map +1 -1
- package/fesm2022/seniorsistemas-angular-components-dynamic-form.mjs +38 -19
- package/fesm2022/seniorsistemas-angular-components-dynamic-form.mjs.map +1 -1
- package/fesm2022/seniorsistemas-angular-components-inline-edit.mjs +1 -1
- package/fesm2022/seniorsistemas-angular-components-inline-edit.mjs.map +1 -1
- package/fesm2022/seniorsistemas-angular-components-object-card.mjs +2 -2
- package/fesm2022/seniorsistemas-angular-components-object-card.mjs.map +1 -1
- package/fesm2022/seniorsistemas-angular-components-paginator.mjs +1 -1
- package/fesm2022/seniorsistemas-angular-components-paginator.mjs.map +1 -1
- package/fesm2022/seniorsistemas-angular-components-panel.mjs +2 -2
- package/fesm2022/seniorsistemas-angular-components-panel.mjs.map +1 -1
- package/fesm2022/seniorsistemas-angular-components-select.mjs +232 -334
- package/fesm2022/seniorsistemas-angular-components-select.mjs.map +1 -1
- package/fesm2022/seniorsistemas-angular-components-text-area-ia.mjs +3 -3
- package/fesm2022/seniorsistemas-angular-components-text-area-ia.mjs.map +1 -1
- package/fesm2022/seniorsistemas-angular-components-text-area.mjs +3 -3
- package/fesm2022/seniorsistemas-angular-components-text-area.mjs.map +1 -1
- package/fesm2022/seniorsistemas-angular-components-toast.mjs +12 -12
- package/fesm2022/seniorsistemas-angular-components-toast.mjs.map +1 -1
- package/fesm2022/seniorsistemas-angular-components-token-list.mjs +2 -2
- package/fesm2022/seniorsistemas-angular-components-token-list.mjs.map +1 -1
- package/fesm2022/seniorsistemas-angular-components.mjs +1 -0
- package/fesm2022/seniorsistemas-angular-components.mjs.map +1 -1
- package/package.json +18 -12
- package/select/lib/select/select.component.d.ts +148 -157
- package/styles.css +1 -0
- package/text-area-ia/lib/text-area-ia/text-area-ia.component.d.ts +1 -1
- package/toast/lib/toast/toast.component.d.ts +4 -4
- package/src/lib/styles/tailwind.scss +0 -4
- package/tailwind.css +0 -1088
|
@@ -1,17 +1,18 @@
|
|
|
1
|
-
import
|
|
1
|
+
import * as i5 from '@angular/cdk/overlay';
|
|
2
|
+
import { OverlayModule } from '@angular/cdk/overlay';
|
|
2
3
|
import * as i3 from '@angular/cdk/scrolling';
|
|
3
4
|
import { ScrollingModule } from '@angular/cdk/scrolling';
|
|
4
5
|
import * as i1 from '@angular/common';
|
|
5
|
-
import { CommonModule
|
|
6
|
+
import { CommonModule } from '@angular/common';
|
|
6
7
|
import * as i0 from '@angular/core';
|
|
7
|
-
import { input, model, output, Component, signal, computed,
|
|
8
|
+
import { input, model, output, Component, signal, computed, viewChild, inject, forwardRef } from '@angular/core';
|
|
9
|
+
import { takeUntilDestroyed } from '@angular/core/rxjs-interop';
|
|
8
10
|
import * as i2 from '@angular/forms';
|
|
9
11
|
import { FormGroup, FormControl, NG_VALUE_ACCESSOR, ReactiveFormsModule } from '@angular/forms';
|
|
10
12
|
import * as i4 from '@ngx-translate/core';
|
|
11
13
|
import { TranslateService, TranslateModule } from '@ngx-translate/core';
|
|
12
|
-
import { debounceTime, distinctUntilChanged, takeUntil } from 'rxjs/operators';
|
|
13
14
|
import { CheckboxComponent } from '@seniorsistemas/angular-components/checkbox';
|
|
14
|
-
import {
|
|
15
|
+
import { debounceTime, distinctUntilChanged } from 'rxjs/operators';
|
|
15
16
|
|
|
16
17
|
class SelectOptionComponent {
|
|
17
18
|
id = input.required();
|
|
@@ -37,6 +38,7 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "18.2.14", ngImpo
|
|
|
37
38
|
}] });
|
|
38
39
|
|
|
39
40
|
class SelectComponent {
|
|
41
|
+
static nextId = 0;
|
|
40
42
|
placeholder = input('');
|
|
41
43
|
multiple = input(false);
|
|
42
44
|
options = input.required();
|
|
@@ -50,65 +52,49 @@ class SelectComponent {
|
|
|
50
52
|
virtualScroll = input(false);
|
|
51
53
|
virtualScrollItemSize = input(37);
|
|
52
54
|
emptyMessage = input(null);
|
|
53
|
-
useRawValue = input(false);
|
|
54
|
-
dataKey = input();
|
|
55
55
|
disabled = model(false);
|
|
56
|
-
showOptions =
|
|
56
|
+
showOptions = model(false);
|
|
57
57
|
value = signal(null);
|
|
58
58
|
values = signal([]);
|
|
59
59
|
filterValue = signal('');
|
|
60
60
|
focusedIndex = signal(-1);
|
|
61
|
-
|
|
62
|
-
dropLeft = 0;
|
|
63
|
-
dropWidth = 0;
|
|
64
|
-
_portalHost = null;
|
|
61
|
+
componentId = `select${SelectComponent.nextId++}`;
|
|
65
62
|
/**
|
|
66
|
-
*
|
|
67
|
-
*
|
|
68
|
-
*
|
|
69
|
-
*
|
|
70
|
-
* - Usa `_getCompareValueExtractor()` para comparar os valores de forma consistente.
|
|
71
|
-
*
|
|
72
|
-
* Esse estado é usado para controlar o checkbox de "Selecionar todos" quando todas as opções visíveis estão marcadas.
|
|
63
|
+
* Computed que indica se todas as opções filtradas estão selecionadas.
|
|
64
|
+
* Retorna `true` se todas as opções disponíveis (excluindo agrupadores) estiverem presentes
|
|
65
|
+
* na lista de valores selecionados, e `false` caso contrário.
|
|
66
|
+
* @returns {boolean} `true` se todas as opções filtradas estão selecionadas, `false` caso contrário.
|
|
73
67
|
*/
|
|
74
68
|
allSelected = computed(() => {
|
|
75
|
-
const
|
|
76
|
-
const
|
|
77
|
-
|
|
78
|
-
|
|
69
|
+
const options = this.filteredOptions().filter((option) => !option.grouper);
|
|
70
|
+
const selectedIds = this.values().map((option) => option.id);
|
|
71
|
+
const ret = options.length > 0 && options.every((option) => selectedIds.includes(option.id));
|
|
72
|
+
return ret;
|
|
79
73
|
});
|
|
74
|
+
/**
|
|
75
|
+
* Retorna o item atualmente focado na lista de opções filtradas.
|
|
76
|
+
* @returns O dado do item focado ou `null` caso nenhum item esteja focado.
|
|
77
|
+
*/
|
|
80
78
|
focusedItem = computed(() => this.filteredOptions().at(this.focusedIndex())?.data ?? null);
|
|
81
79
|
/**
|
|
82
|
-
*
|
|
83
|
-
*
|
|
84
|
-
*
|
|
85
|
-
* -
|
|
86
|
-
*
|
|
87
|
-
*
|
|
88
|
-
* Essa estrutura é usada internamente para renderização, filtragem e controle de seleção.
|
|
80
|
+
* Computa e retorna a lista interna de opções do dropdown.
|
|
81
|
+
* - Se as opções estiverem agrupadas (`group()` retorna verdadeiro),
|
|
82
|
+
* utiliza `_grouperToFlat` para transformar as opções agrupadas em uma lista plana.
|
|
83
|
+
* - Caso contrário, retorna as opções com IDs adicionados.
|
|
84
|
+
* @returns Um array de `InternalDropdownOption<T>` representando as opções disponíveis para o componente select.
|
|
89
85
|
*/
|
|
90
86
|
internalOptions = computed(() => {
|
|
91
87
|
const opts = this.options();
|
|
92
|
-
const optionsWithId = this.
|
|
93
|
-
? opts.map((value, index) => ({
|
|
94
|
-
id: `id_primitive_${index}`,
|
|
95
|
-
grouper: false,
|
|
96
|
-
data: value,
|
|
97
|
-
}))
|
|
98
|
-
: this._addIdToOptions(opts);
|
|
88
|
+
const optionsWithId = this._addIdToOptions(opts);
|
|
99
89
|
return this.group() ? this._grouperToFlat(optionsWithId) : optionsWithId;
|
|
100
90
|
});
|
|
101
91
|
/**
|
|
102
|
-
* Retorna
|
|
103
|
-
*
|
|
104
|
-
*
|
|
105
|
-
*
|
|
106
|
-
*
|
|
107
|
-
*
|
|
108
|
-
* - Exibe o label do valor selecionado. *
|
|
109
|
-
* - Se nenhum valor estiver selecionado, retorna uma string vazia.
|
|
110
|
-
*
|
|
111
|
-
* Essa lógica é usada para mostrar o conteúdo atual do campo de seleção.
|
|
92
|
+
* Retorna uma string representando a seleção atual do componente.
|
|
93
|
+
* - Se o modo múltiplo estiver ativado e mais de um item estiver selecionado,
|
|
94
|
+
* retorna uma mensagem traduzida indicando o número total de registros selecionados.
|
|
95
|
+
* - Se apenas um item estiver selecionado, retorna o rótulo desse item.
|
|
96
|
+
* - Se o modo múltiplo não estiver ativado, retorna o rótulo do item selecionado ou uma string vazia caso nenhum item esteja selecionado.
|
|
97
|
+
* @returns {string} Texto representando a seleção atual.
|
|
112
98
|
*/
|
|
113
99
|
print = computed(() => {
|
|
114
100
|
if (this.multiple()) {
|
|
@@ -119,46 +105,45 @@ class SelectComponent {
|
|
|
119
105
|
});
|
|
120
106
|
}
|
|
121
107
|
else if (selected.length === 1) {
|
|
122
|
-
return this._getLabelFromOption(selected[0]);
|
|
108
|
+
return this._getLabelFromOption(selected[0].data);
|
|
123
109
|
}
|
|
124
110
|
}
|
|
125
|
-
else
|
|
126
|
-
|
|
111
|
+
else {
|
|
112
|
+
const selected = this.value();
|
|
113
|
+
return selected ? this._getLabelFromOption(selected.data) : '';
|
|
127
114
|
}
|
|
128
115
|
return '';
|
|
129
116
|
});
|
|
117
|
+
/**
|
|
118
|
+
* Indica se o seletor está "limpo", ou seja, sem nenhum valor selecionado.
|
|
119
|
+
* - No modo múltiplo (`multiple`), retorna `true` se não houver nenhum valor selecionado (`values` está vazio).
|
|
120
|
+
* - No modo simples, retorna `true` se não houver valor selecionado (`value` é falsy).
|
|
121
|
+
* @returns `true` se não houver seleção, `false` caso contrário.
|
|
122
|
+
*/
|
|
130
123
|
isClean = computed(() => {
|
|
131
124
|
return this.multiple() ? !this.values().length : !this.value();
|
|
132
125
|
});
|
|
133
|
-
TIsPrimitive = computed(() => {
|
|
134
|
-
const opts = this.options();
|
|
135
|
-
if (!opts.length)
|
|
136
|
-
return false;
|
|
137
|
-
return ['string', 'number', 'boolean'].includes(typeof opts[0]);
|
|
138
|
-
});
|
|
139
126
|
/**
|
|
140
|
-
*
|
|
141
|
-
*
|
|
142
|
-
*
|
|
143
|
-
*
|
|
144
|
-
* - Ignora opções marcadas como `grouper`.
|
|
145
|
-
*
|
|
146
|
-
* Esse estado é usado, por exemplo, para exibir o checkbox de "Selecionar todos" em modo indeterminado.
|
|
127
|
+
* Computed que indica se o estado de seleção "Selecionar Todos" está indeterminado.
|
|
128
|
+
* Retorna `true` quando nem todos os itens filtrados estão selecionados e nem todos estão desmarcados,
|
|
129
|
+
* ou seja, quando há uma seleção parcial dos itens disponíveis.
|
|
130
|
+
* @returns {boolean} `true` se a seleção for parcial, `false` caso contrário.
|
|
147
131
|
*/
|
|
148
132
|
selectAllIsIndeterminate = computed(() => {
|
|
149
|
-
const selected = this.
|
|
150
|
-
|
|
151
|
-
|
|
152
|
-
const
|
|
133
|
+
const selected = this.internalOptions().filter((option) => {
|
|
134
|
+
return this.values().some((o) => o.id === option.id);
|
|
135
|
+
});
|
|
136
|
+
const options = this.filteredOptions().filter((option) => !option.grouper);
|
|
137
|
+
const all = options.length > 0 && options.every((option) => selected.includes(option));
|
|
138
|
+
const none = options.every((option) => !selected.includes(option));
|
|
153
139
|
return !all && !none;
|
|
154
140
|
});
|
|
155
141
|
/**
|
|
156
|
-
* Retorna
|
|
157
|
-
*
|
|
158
|
-
* -
|
|
159
|
-
* -
|
|
160
|
-
*
|
|
161
|
-
* - Usa o extrator de label para comparar os valores com o texto buscado.
|
|
142
|
+
* Retorna uma lista de opções filtradas com base no valor de busca (`filterValue`) e nos critérios definidos.
|
|
143
|
+
* - Se o filtro estiver desabilitado ou o valor de busca estiver vazio, retorna todas as opções.
|
|
144
|
+
* - Caso contrário, filtra as opções utilizando o(s) campo(s) especificado(s) em `filterBy`.
|
|
145
|
+
* - Ignora opções que possuem a propriedade `grouper` definida.
|
|
146
|
+
* @returns As opções filtradas conforme o valor de busca e critérios de filtro.
|
|
162
147
|
*/
|
|
163
148
|
filteredOptions = computed(() => {
|
|
164
149
|
const allOptions = this.internalOptions();
|
|
@@ -171,10 +156,10 @@ class SelectComponent {
|
|
|
171
156
|
if (option.grouper) {
|
|
172
157
|
return false;
|
|
173
158
|
}
|
|
174
|
-
const labelExtractor = this._getLabelExtractor();
|
|
175
159
|
let label = '';
|
|
160
|
+
const optionLabel = this.optionLabel();
|
|
176
161
|
if (!filterBy) {
|
|
177
|
-
label =
|
|
162
|
+
label = optionLabel ? String(option.data[optionLabel]) : String(option.data);
|
|
178
163
|
}
|
|
179
164
|
else if (Array.isArray(filterBy)) {
|
|
180
165
|
label = filterBy.map((by) => String(option.data[by] ?? '')).join(' ');
|
|
@@ -188,89 +173,88 @@ class SelectComponent {
|
|
|
188
173
|
filterForm = new FormGroup({
|
|
189
174
|
filter: new FormControl('', { nonNullable: true }),
|
|
190
175
|
});
|
|
191
|
-
_elementRef = inject((ElementRef));
|
|
192
|
-
_dropdownTemplate = viewChild('dropdownTemplate');
|
|
193
176
|
_containerDiv = viewChild('containerDiv');
|
|
194
177
|
_onChange = () => { };
|
|
195
178
|
_onTouched = () => { };
|
|
196
|
-
platformId = inject(PLATFORM_ID);
|
|
197
|
-
_viewContainerRef = inject(ViewContainerRef);
|
|
198
179
|
_translateService = inject(TranslateService);
|
|
199
|
-
|
|
200
|
-
/**
|
|
201
|
-
* Inicializa o componente, validando os inputs e configurando o filtro com debounce.
|
|
202
|
-
*/
|
|
203
|
-
ngOnInit() {
|
|
204
|
-
this._validateInputs();
|
|
180
|
+
constructor() {
|
|
205
181
|
this.filterForm
|
|
206
182
|
.get('filter')
|
|
207
|
-
.valueChanges.pipe(debounceTime(300), distinctUntilChanged(),
|
|
183
|
+
.valueChanges.pipe(debounceTime(300), distinctUntilChanged(), takeUntilDestroyed())
|
|
208
184
|
.subscribe((value) => {
|
|
209
185
|
this.filterValue.set(value);
|
|
210
186
|
});
|
|
211
187
|
}
|
|
212
|
-
|
|
213
|
-
|
|
214
|
-
*/
|
|
215
|
-
ngOnDestroy() {
|
|
216
|
-
this._destroyDropdownPortal();
|
|
217
|
-
if (this._portalHost) {
|
|
218
|
-
this._portalHost.dispose();
|
|
219
|
-
this._portalHost = null;
|
|
220
|
-
}
|
|
221
|
-
this.destroy$.next();
|
|
222
|
-
this.destroy$.complete();
|
|
188
|
+
ngOnInit() {
|
|
189
|
+
this._validateInputs();
|
|
223
190
|
}
|
|
224
191
|
/**
|
|
225
|
-
* Define o valor
|
|
226
|
-
* @param value
|
|
192
|
+
* Define o valor selecionado do componente select.
|
|
193
|
+
* @param value O valor a ser definido. Pode ser um objeto do tipo `T`, um array de `T` (quando múltipla seleção está habilitada), ou `null`.
|
|
194
|
+
* @throws Se o modo múltiplo estiver ativado e o valor não for um array, lança um erro.
|
|
195
|
+
* @throws Se o modo múltiplo estiver desativado e o valor for um array, lança um erro.
|
|
196
|
+
* Este método mapeia o(s) valor(es) fornecido(s) para as opções internas do componente,
|
|
197
|
+
* garantindo que apenas opções válidas sejam selecionadas conforme o modo de seleção (único ou múltiplo).
|
|
227
198
|
*/
|
|
228
199
|
writeValue(value) {
|
|
229
|
-
if (this.multiple()) {
|
|
200
|
+
if (value && this.multiple()) {
|
|
230
201
|
if (Array.isArray(value)) {
|
|
231
|
-
const
|
|
232
|
-
|
|
233
|
-
|
|
234
|
-
|
|
235
|
-
|
|
236
|
-
|
|
202
|
+
const mapped = value
|
|
203
|
+
.map((val) => {
|
|
204
|
+
return this.internalOptions().find((option) => {
|
|
205
|
+
return JSON.stringify(option.data) === JSON.stringify(val);
|
|
206
|
+
});
|
|
207
|
+
})
|
|
208
|
+
.filter((option) => !!option);
|
|
209
|
+
this.values.set(mapped);
|
|
237
210
|
}
|
|
238
211
|
else {
|
|
239
|
-
|
|
212
|
+
throw new Error('Value must be an array when "multiple" is true.');
|
|
240
213
|
}
|
|
241
214
|
}
|
|
242
215
|
else {
|
|
243
|
-
const
|
|
244
|
-
|
|
245
|
-
|
|
246
|
-
|
|
247
|
-
|
|
248
|
-
|
|
216
|
+
const optionValue = this.optionValue();
|
|
217
|
+
let mapped = null;
|
|
218
|
+
if (Array.isArray(value)) {
|
|
219
|
+
throw new Error('Value must not be an array when "multiple" is false.');
|
|
220
|
+
}
|
|
221
|
+
if (optionValue && value) {
|
|
222
|
+
mapped =
|
|
223
|
+
this.internalOptions().find((option) => option.data[optionValue] === value[optionValue]) ?? null;
|
|
224
|
+
}
|
|
225
|
+
else {
|
|
226
|
+
mapped =
|
|
227
|
+
this.internalOptions().find((option) => JSON.stringify(option.data) === JSON.stringify(value)) ??
|
|
228
|
+
null;
|
|
229
|
+
}
|
|
230
|
+
this.value.set(mapped ?? null);
|
|
249
231
|
}
|
|
250
232
|
}
|
|
251
233
|
/**
|
|
252
|
-
* Registra
|
|
253
|
-
* @param onChange Função callback.
|
|
234
|
+
* Registra uma função de callback que será chamada sempre que o valor do componente mudar.
|
|
235
|
+
* @param onChange Função de callback que recebe o novo valor selecionado ou null.
|
|
254
236
|
*/
|
|
255
237
|
registerOnChange(onChange) {
|
|
256
238
|
this._onChange = onChange;
|
|
257
239
|
}
|
|
258
240
|
/**
|
|
259
|
-
* Registra
|
|
260
|
-
* @param onTouched Função callback.
|
|
241
|
+
* Registra uma função de callback que será chamada quando o componente for tocado (perder o foco).
|
|
242
|
+
* @param onTouched Função de callback a ser executada quando o componente for marcado como "tocado".
|
|
261
243
|
*/
|
|
262
244
|
registerOnTouched(onTouched) {
|
|
263
245
|
this._onTouched = onTouched;
|
|
264
246
|
}
|
|
265
247
|
/**
|
|
266
248
|
* Define o estado de desabilitado do componente.
|
|
267
|
-
* @param disabled Indica se o componente
|
|
249
|
+
* @param disabled Indica se o componente deve ser desabilitado (`true`) ou habilitado (`false`).
|
|
268
250
|
*/
|
|
269
251
|
setDisabledState(disabled) {
|
|
270
252
|
this.disabled.set(disabled);
|
|
271
253
|
}
|
|
272
254
|
/**
|
|
273
|
-
* Alterna a exibição
|
|
255
|
+
* Alterna a exibição das opções do componente select.
|
|
256
|
+
* Se o componente estiver desabilitado, não realiza nenhuma ação.
|
|
257
|
+
* Caso contrário, inverte o estado de exibição das opções.
|
|
274
258
|
*/
|
|
275
259
|
toggle() {
|
|
276
260
|
if (this.disabled()) {
|
|
@@ -278,29 +262,24 @@ class SelectComponent {
|
|
|
278
262
|
}
|
|
279
263
|
const shouldOpen = !this.showOptions();
|
|
280
264
|
this.showOptions.set(shouldOpen);
|
|
281
|
-
if (shouldOpen) {
|
|
282
|
-
setTimeout(() => {
|
|
283
|
-
this._createDropdownPortal();
|
|
284
|
-
});
|
|
285
|
-
}
|
|
286
|
-
else {
|
|
287
|
-
this._destroyDropdownPortal();
|
|
288
|
-
}
|
|
289
265
|
}
|
|
290
266
|
/**
|
|
291
|
-
* Seleciona
|
|
292
|
-
* @param item
|
|
267
|
+
* Seleciona um item no componente de seleção.
|
|
268
|
+
* @param item O item a ser selecionado ou desmarcado.
|
|
269
|
+
* Se o componente estiver desabilitado, a função retorna imediatamente.
|
|
270
|
+
* No modo múltiplo, adiciona ou remove o item da lista de valores selecionados.
|
|
271
|
+
* No modo simples, define o item como valor selecionado e fecha o dropdown.
|
|
272
|
+
* Sempre notifica as mudanças e marca o componente como tocado.
|
|
293
273
|
*/
|
|
294
274
|
selectItem(item) {
|
|
295
275
|
if (this.disabled()) {
|
|
296
276
|
return;
|
|
297
277
|
}
|
|
298
|
-
const
|
|
278
|
+
const optionValue = this.optionValue();
|
|
299
279
|
if (this.multiple()) {
|
|
300
280
|
const store = [...this.values()];
|
|
301
|
-
const itemValue = getCompareValue(item);
|
|
302
281
|
const index = store.findIndex((selectedItem) => {
|
|
303
|
-
return
|
|
282
|
+
return selectedItem === item;
|
|
304
283
|
});
|
|
305
284
|
if (index !== -1) {
|
|
306
285
|
store.splice(index, 1);
|
|
@@ -309,20 +288,25 @@ class SelectComponent {
|
|
|
309
288
|
store.push(item);
|
|
310
289
|
}
|
|
311
290
|
this.values.set(store);
|
|
312
|
-
const result =
|
|
291
|
+
const result = optionValue ? store.map((item) => item.data[optionValue]) : store;
|
|
313
292
|
this._onChange(result);
|
|
314
293
|
}
|
|
315
294
|
else {
|
|
316
295
|
this.value.set(item);
|
|
317
|
-
const result =
|
|
296
|
+
const result = optionValue ? item.data[optionValue] : item.data;
|
|
318
297
|
this._onChange(result);
|
|
319
298
|
this._closeDropdown();
|
|
320
299
|
}
|
|
321
300
|
this._onTouched();
|
|
322
301
|
}
|
|
323
302
|
/**
|
|
324
|
-
* Limpa
|
|
325
|
-
*
|
|
303
|
+
* Limpa o valor selecionado no componente select.
|
|
304
|
+
* Se o componente estiver desabilitado, não executa nenhuma ação.
|
|
305
|
+
* Para seleção múltipla, remove todos os valores selecionados e notifica a alteração.
|
|
306
|
+
* Para seleção única, define o valor como nulo e notifica a alteração.
|
|
307
|
+
* Fecha o dropdown e marca o componente como "tocado".
|
|
308
|
+
* Impede a propagação do evento do mouse.
|
|
309
|
+
* @param event Evento do mouse que acionou a limpeza da seleção.
|
|
326
310
|
*/
|
|
327
311
|
clear(event) {
|
|
328
312
|
if (this.disabled()) {
|
|
@@ -330,7 +314,7 @@ class SelectComponent {
|
|
|
330
314
|
}
|
|
331
315
|
if (this.multiple()) {
|
|
332
316
|
this.values.set([]);
|
|
333
|
-
this._onChange(this.
|
|
317
|
+
this._onChange(this.values());
|
|
334
318
|
}
|
|
335
319
|
else {
|
|
336
320
|
this.value.set(null);
|
|
@@ -341,25 +325,17 @@ class SelectComponent {
|
|
|
341
325
|
event.stopPropagation();
|
|
342
326
|
}
|
|
343
327
|
/**
|
|
344
|
-
* Limpa o filtro
|
|
328
|
+
* Limpa o filtro do formulário, resetando o campo 'filter' do formulário de filtro.
|
|
329
|
+
* Este método redefine o valor do campo 'filter' para seu estado inicial,
|
|
330
|
+
* removendo qualquer texto ou valor previamente inserido pelo usuário.
|
|
345
331
|
*/
|
|
346
332
|
clearFilter() {
|
|
347
333
|
this.filterForm.get('filter')?.reset();
|
|
348
334
|
}
|
|
349
335
|
/**
|
|
350
|
-
*
|
|
351
|
-
*
|
|
352
|
-
|
|
353
|
-
onDocumentClick(event) {
|
|
354
|
-
const clickTarget = event.target;
|
|
355
|
-
const clickedInsideComponent = this._elementRef.nativeElement.contains(clickTarget);
|
|
356
|
-
const dropdownInBody = document.querySelector('.dropdown-body-class')?.contains(clickTarget);
|
|
357
|
-
if (!clickedInsideComponent && !dropdownInBody) {
|
|
358
|
-
this._closeDropdown();
|
|
359
|
-
}
|
|
360
|
-
}
|
|
361
|
-
/**
|
|
362
|
-
* Fecha o dropdown em eventos de redimensionamento de janela.
|
|
336
|
+
* Manipula o evento de redimensionamento da janela.
|
|
337
|
+
* Fecha o dropdown de opções caso ele esteja visível ao redimensionar a janela.
|
|
338
|
+
* @param _ Evento de redimensionamento da janela (não utilizado).
|
|
363
339
|
*/
|
|
364
340
|
onWindowResize(_) {
|
|
365
341
|
if (this.showOptions()) {
|
|
@@ -367,15 +343,24 @@ class SelectComponent {
|
|
|
367
343
|
}
|
|
368
344
|
}
|
|
369
345
|
/**
|
|
370
|
-
*
|
|
346
|
+
* Manipula o evento de clique no elemento container da seleção.
|
|
347
|
+
* Este método alterna o estado de exibição do componente select e,
|
|
348
|
+
* em seguida, define o foco no elemento container correspondente.
|
|
371
349
|
*/
|
|
372
350
|
onContainerDivClick() {
|
|
373
351
|
this.toggle();
|
|
374
352
|
this._containerDiv()?.nativeElement.focus();
|
|
375
353
|
}
|
|
376
354
|
/**
|
|
377
|
-
*
|
|
378
|
-
*
|
|
355
|
+
* Manipula eventos de teclado para navegação e seleção de opções no componente select.
|
|
356
|
+
* - 'ArrowDown': Move o foco para a próxima opção disponível.
|
|
357
|
+
* - 'ArrowUp': Move o foco para a opção anterior.
|
|
358
|
+
* - 'Tab': Seleciona a opção atualmente focada e fecha o dropdown.
|
|
359
|
+
* - 'Enter': Seleciona a opção focada se o dropdown estiver aberto, ou alterna a abertura do dropdown.
|
|
360
|
+
* - 'Escape': Fecha o dropdown.
|
|
361
|
+
* - ' ': (barra de espaço) Seleciona a opção focada se o dropdown estiver aberto, ou alterna a abertura do dropdown.
|
|
362
|
+
* Previne o comportamento padrão do navegador quando necessário para garantir a navegação adequada pelo teclado.
|
|
363
|
+
* @param event O evento de teclado disparado pelo usuário.
|
|
379
364
|
*/
|
|
380
365
|
onKeyDown(event) {
|
|
381
366
|
const options = this.filteredOptions();
|
|
@@ -385,7 +370,7 @@ class SelectComponent {
|
|
|
385
370
|
const _selectOption = () => {
|
|
386
371
|
if (this.focusedIndex() >= 0 && this.focusedIndex() < options.length) {
|
|
387
372
|
event.preventDefault();
|
|
388
|
-
this.selectItem(options[this.focusedIndex()]
|
|
373
|
+
this.selectItem(options[this.focusedIndex()]);
|
|
389
374
|
}
|
|
390
375
|
};
|
|
391
376
|
switch (event.key) {
|
|
@@ -413,166 +398,113 @@ class SelectComponent {
|
|
|
413
398
|
this._closeDropdown();
|
|
414
399
|
break;
|
|
415
400
|
case ' ':
|
|
416
|
-
|
|
401
|
+
event.preventDefault();
|
|
402
|
+
if (this.showOptions()) {
|
|
403
|
+
_selectOption();
|
|
404
|
+
}
|
|
405
|
+
else {
|
|
406
|
+
this.toggle();
|
|
407
|
+
}
|
|
417
408
|
break;
|
|
418
409
|
}
|
|
419
410
|
}
|
|
420
411
|
/**
|
|
421
|
-
* Retorna o rótulo
|
|
422
|
-
* @param option
|
|
423
|
-
* @returns
|
|
412
|
+
* Retorna o rótulo (label) associado a uma opção fornecida.
|
|
413
|
+
* @param option - A opção do tipo T para a qual o rótulo deve ser obtido.
|
|
414
|
+
* @returns O rótulo da opção como uma string.
|
|
424
415
|
*/
|
|
425
416
|
getOptionLabel(option) {
|
|
426
417
|
return this._getLabelFromOption(option);
|
|
427
418
|
}
|
|
428
419
|
/**
|
|
429
|
-
* Função
|
|
430
|
-
*
|
|
431
|
-
* @param item
|
|
432
|
-
* @
|
|
420
|
+
* Função de trackBy utilizada em diretivas *ngFor para otimizar a renderização de listas.
|
|
421
|
+
* Retorna o identificador único (`id`) de cada item do tipo `InternalDropdownOption<T>`.
|
|
422
|
+
* @param _ - Índice do item na lista (não utilizado).
|
|
423
|
+
* @param item - O item atual da lista do tipo `InternalDropdownOption<T>`.
|
|
424
|
+
* @returns O identificador único do item como uma string.
|
|
433
425
|
*/
|
|
434
426
|
trackById(_, item) {
|
|
435
427
|
return item.id;
|
|
436
428
|
}
|
|
437
429
|
/**
|
|
438
|
-
* Verifica se
|
|
439
|
-
* @param option
|
|
440
|
-
* @returns
|
|
430
|
+
* Verifica se a opção fornecida está selecionada.
|
|
431
|
+
* @param option - A opção interna do dropdown a ser verificada.
|
|
432
|
+
* @returns `true` se a opção estiver selecionada, caso contrário `false`.
|
|
441
433
|
*/
|
|
442
434
|
isOptionSelected(option) {
|
|
443
|
-
|
|
444
|
-
|
|
445
|
-
|
|
446
|
-
return selectedValues.includes(getCompareValue(option));
|
|
447
|
-
}
|
|
448
|
-
else {
|
|
449
|
-
const currentValue = this.value();
|
|
450
|
-
return currentValue !== null && getCompareValue(currentValue) === getCompareValue(option);
|
|
451
|
-
}
|
|
435
|
+
return (this.values().find((o) => {
|
|
436
|
+
return o === option;
|
|
437
|
+
}) !== undefined);
|
|
452
438
|
}
|
|
453
439
|
/**
|
|
454
|
-
* Alterna a seleção de todos os itens
|
|
440
|
+
* Alterna a seleção de todos os itens disponíveis.
|
|
441
|
+
* Se o modo múltiplo estiver ativado, seleciona todos os itens filtrados que não são agrupadores
|
|
442
|
+
* caso nem todos estejam selecionados, ou limpa a seleção caso todos já estejam selecionados.
|
|
443
|
+
* Após a alteração, notifica a mudança de valor.
|
|
455
444
|
*/
|
|
456
445
|
toggleSelectAll() {
|
|
457
446
|
if (!this.multiple()) {
|
|
458
447
|
return;
|
|
459
448
|
}
|
|
460
|
-
const options = this.filteredOptions().filter((
|
|
449
|
+
const options = this.filteredOptions().filter((option) => !option.grouper);
|
|
461
450
|
if (this.allSelected()) {
|
|
462
451
|
this.values.set([]);
|
|
463
452
|
}
|
|
464
453
|
else {
|
|
465
|
-
this.values.set(options
|
|
466
|
-
}
|
|
467
|
-
this._onChange(this._removeInternalProperties(this.values()));
|
|
468
|
-
}
|
|
469
|
-
/**
|
|
470
|
-
* Procura e retorna uma opção com valor primitivo igual ao informado.
|
|
471
|
-
*
|
|
472
|
-
* @param value Valor primitivo (string, number ou boolean).
|
|
473
|
-
* @returns A opção correspondente, ou `null` se não encontrada.
|
|
474
|
-
*/
|
|
475
|
-
_findOptionByPrimitiveValue(value) {
|
|
476
|
-
return this.internalOptions().find((opt) => opt.data === value)?.data ?? null;
|
|
477
|
-
}
|
|
478
|
-
/**
|
|
479
|
-
* Remove propriedades internas adicionadas pelo componente, retornando apenas os dados crus.
|
|
480
|
-
*
|
|
481
|
-
* Usado para garantir que apenas os objetos de dados reais sejam emitidos ao formulário,
|
|
482
|
-
* especialmente no modo múltiplo.
|
|
483
|
-
*
|
|
484
|
-
* @param value Valor armazenado internamente (com ou sem `InternalDropdownOption`).
|
|
485
|
-
* @returns Os dados "puros", sem propriedades adicionais.
|
|
486
|
-
*/
|
|
487
|
-
_removeInternalProperties(value) {
|
|
488
|
-
if (this.TIsPrimitive()) {
|
|
489
|
-
return value;
|
|
454
|
+
this.values.set(options);
|
|
490
455
|
}
|
|
491
|
-
|
|
492
|
-
? value.map((opt) => opt.data)
|
|
493
|
-
: value.data;
|
|
456
|
+
this._onChange(this.values());
|
|
494
457
|
}
|
|
495
458
|
/**
|
|
496
|
-
* Retorna o
|
|
497
|
-
*
|
|
498
|
-
*
|
|
499
|
-
* @
|
|
500
|
-
* @
|
|
459
|
+
* Retorna o rótulo (label) de uma opção fornecida.
|
|
460
|
+
* Este método utiliza a propriedade definida por `optionLabel` para extrair o valor do rótulo da opção.
|
|
461
|
+
* Caso `optionLabel` não esteja definido, retorna a representação em string da própria opção.
|
|
462
|
+
* @private
|
|
463
|
+
* @param option A opção da qual o rótulo será extraído.
|
|
464
|
+
* @returns O rótulo da opção como uma string.
|
|
501
465
|
*/
|
|
502
466
|
_getLabelFromOption(option) {
|
|
503
|
-
|
|
504
|
-
|
|
505
|
-
}
|
|
506
|
-
const labelKey = this.optionLabel();
|
|
507
|
-
if (!labelKey) {
|
|
508
|
-
return String(option.label ?? '');
|
|
509
|
-
}
|
|
510
|
-
return String(option[labelKey]);
|
|
467
|
+
const optionLabel = this.optionLabel();
|
|
468
|
+
return optionLabel ? String(option[optionLabel]) : String(option);
|
|
511
469
|
}
|
|
512
470
|
/**
|
|
513
|
-
* Valida
|
|
471
|
+
* Valida as entradas do componente de seleção.
|
|
472
|
+
* Este método verifica se as opções fornecidas são válidas. Caso as opções sejam objetos,
|
|
473
|
+
* garante que a propriedade `optionLabel` esteja definida, lançando um erro caso contrário.
|
|
474
|
+
* Se não houver opções, a validação é ignorada.
|
|
475
|
+
* @private
|
|
476
|
+
* @throws {Error} Se as opções forem objetos e `optionLabel` não estiver definido.
|
|
514
477
|
*/
|
|
515
478
|
_validateInputs() {
|
|
516
|
-
|
|
517
|
-
|
|
518
|
-
|
|
519
|
-
if (!this.TIsPrimitive() && !this.optionValue() && !this.dataKey()) {
|
|
520
|
-
throw new Error('Either the optionValue or dataKey input must be provided for non-primitive options.');
|
|
521
|
-
}
|
|
522
|
-
if (!this.TIsPrimitive() && !this.optionLabel()) {
|
|
523
|
-
throw new Error(`The 'optionLabel' input must be provided for non-primitive options.`);
|
|
524
|
-
}
|
|
525
|
-
}
|
|
526
|
-
_findOptionByValue(value) {
|
|
527
|
-
if (this.useRawValue()) {
|
|
528
|
-
return this.options().find((option) => option === value) ?? null;
|
|
529
|
-
}
|
|
530
|
-
const getValue = this._getValueExtractor();
|
|
531
|
-
return this.options().find((option) => getValue(option) === value) ?? null;
|
|
532
|
-
}
|
|
533
|
-
/**
|
|
534
|
-
* Extrai o valor final de uma opção, com base em `optionValue`.
|
|
535
|
-
* @returns Função que retorna o valor da opção.
|
|
536
|
-
*/
|
|
537
|
-
_getValueExtractor() {
|
|
538
|
-
if (this.TIsPrimitive()) {
|
|
539
|
-
return (option) => option;
|
|
540
|
-
}
|
|
541
|
-
if (this.useRawValue()) {
|
|
542
|
-
return (option) => option;
|
|
543
|
-
}
|
|
544
|
-
const valueInput = this.optionValue();
|
|
545
|
-
if (valueInput) {
|
|
546
|
-
return (option) => option[valueInput];
|
|
547
|
-
}
|
|
548
|
-
throw new Error(`optionValue is required for non-primitive options.`);
|
|
549
|
-
}
|
|
550
|
-
/**
|
|
551
|
-
* Extrai o valor comparável de uma opção.
|
|
552
|
-
* @returns Função que retorna a chave de comparação.
|
|
553
|
-
*/
|
|
554
|
-
_getCompareValueExtractor() {
|
|
555
|
-
if (this.TIsPrimitive()) {
|
|
556
|
-
return (option) => option;
|
|
479
|
+
const options = this.options();
|
|
480
|
+
if (!options.length) {
|
|
481
|
+
return;
|
|
557
482
|
}
|
|
558
|
-
|
|
559
|
-
|
|
560
|
-
|
|
483
|
+
const hasObjectOptions = options.some((option) => typeof option === 'object' && option !== null);
|
|
484
|
+
if (hasObjectOptions) {
|
|
485
|
+
if (!this.optionLabel()) {
|
|
486
|
+
throw new Error('The "optionLabel" input is required when options are objects.');
|
|
487
|
+
}
|
|
561
488
|
}
|
|
562
|
-
return this._getValueExtractor();
|
|
563
489
|
}
|
|
564
490
|
/**
|
|
565
|
-
* Fecha o dropdown
|
|
491
|
+
* Fecha o dropdown de opções do componente select.
|
|
492
|
+
* Este método oculta as opções disponíveis e redefine o índice do item focado para -1,
|
|
493
|
+
* indicando que nenhum item está atualmente focado.
|
|
494
|
+
* @private
|
|
566
495
|
*/
|
|
567
496
|
_closeDropdown() {
|
|
568
497
|
this.showOptions.set(false);
|
|
569
|
-
this._destroyDropdownPortal();
|
|
570
498
|
this.focusedIndex.set(-1);
|
|
571
499
|
}
|
|
572
500
|
/**
|
|
573
|
-
* Adiciona
|
|
574
|
-
*
|
|
575
|
-
*
|
|
501
|
+
* Adiciona um identificador único a cada opção fornecida.
|
|
502
|
+
* Para cada item no array de opções, gera um objeto `InternalDropdownOption` contendo o dado original
|
|
503
|
+
* e um campo `id` único baseado no timestamp atual e no índice do item. Caso a opção seja um grupo
|
|
504
|
+
* (detectado pela presença de um array `items`), adiciona também a propriedade `grouper: true`.
|
|
505
|
+
* @private
|
|
506
|
+
* @param options Array de opções do tipo `T` a serem processadas.
|
|
507
|
+
* @returns Um array de objetos `InternalDropdownOption<T>` com identificadores únicos.
|
|
576
508
|
*/
|
|
577
509
|
_addIdToOptions(options) {
|
|
578
510
|
const timestamp = Date.now();
|
|
@@ -591,9 +523,14 @@ class SelectComponent {
|
|
|
591
523
|
});
|
|
592
524
|
}
|
|
593
525
|
/**
|
|
594
|
-
* Converte uma
|
|
595
|
-
*
|
|
596
|
-
*
|
|
526
|
+
* Converte uma lista de opções possivelmente agrupadas em uma lista plana de opções.
|
|
527
|
+
* Para cada opção que possui um agrupador (`grouper`) e um array de itens em `data.items`,
|
|
528
|
+
* adiciona a opção do agrupador e, em seguida, adiciona cada item do grupo como uma nova opção
|
|
529
|
+
* individual, atribuindo um `id` único para cada item do grupo.
|
|
530
|
+
* Caso a opção não seja um agrupador, ela é adicionada diretamente ao resultado.
|
|
531
|
+
* @private
|
|
532
|
+
* @param options Lista de opções internas do dropdown, podendo conter agrupadores.
|
|
533
|
+
* @returns Lista plana de opções, incluindo agrupadores e seus itens expandidos.
|
|
597
534
|
*/
|
|
598
535
|
_grouperToFlat(options) {
|
|
599
536
|
const result = [];
|
|
@@ -613,8 +550,9 @@ class SelectComponent {
|
|
|
613
550
|
return result;
|
|
614
551
|
}
|
|
615
552
|
/**
|
|
616
|
-
* Move o foco para a próxima opção.
|
|
617
|
-
* @
|
|
553
|
+
* Move o foco para a próxima opção disponível na lista, ignorando opções que sejam agrupadores.
|
|
554
|
+
* @private
|
|
555
|
+
* @param options Lista de opções internas do dropdown.
|
|
618
556
|
*/
|
|
619
557
|
_focusNextOption(options) {
|
|
620
558
|
let nextIndex = this.focusedIndex() + 1;
|
|
@@ -627,8 +565,9 @@ class SelectComponent {
|
|
|
627
565
|
}
|
|
628
566
|
}
|
|
629
567
|
/**
|
|
630
|
-
* Move o foco para a opção anterior.
|
|
631
|
-
* @
|
|
568
|
+
* Move o foco para a opção anterior na lista, ignorando opções do tipo "grouper".
|
|
569
|
+
* @private
|
|
570
|
+
* @param options Lista de opções internas do dropdown.
|
|
632
571
|
*/
|
|
633
572
|
_focusPreviousOption(options) {
|
|
634
573
|
let prevIndex = this.focusedIndex() - 1;
|
|
@@ -641,7 +580,11 @@ class SelectComponent {
|
|
|
641
580
|
}
|
|
642
581
|
}
|
|
643
582
|
/**
|
|
644
|
-
* Rola
|
|
583
|
+
* Rola a lista de opções para garantir que a opção atualmente focada esteja visível.
|
|
584
|
+
* Este método obtém o ID da opção atualmente focada a partir da lista de opções filtradas.
|
|
585
|
+
* Se um ID válido for encontrado, busca o elemento correspondente no DOM e utiliza
|
|
586
|
+
* `scrollIntoView` para rolar até a opção, alinhando-a ao bloco mais próximo.
|
|
587
|
+
* @private
|
|
645
588
|
*/
|
|
646
589
|
_scrollToFocusedOption() {
|
|
647
590
|
const id = this.filteredOptions()[this.focusedIndex()]?.id;
|
|
@@ -651,66 +594,14 @@ class SelectComponent {
|
|
|
651
594
|
const el = document.getElementById(id);
|
|
652
595
|
el?.scrollIntoView({ block: 'nearest' });
|
|
653
596
|
}
|
|
654
|
-
/**
|
|
655
|
-
* Extrai o texto de uma opção, com base em `optionLabel`.
|
|
656
|
-
* @returns Função que retorna o label da opção.
|
|
657
|
-
*/
|
|
658
|
-
_getLabelExtractor() {
|
|
659
|
-
if (this.TIsPrimitive()) {
|
|
660
|
-
return (option) => String(option);
|
|
661
|
-
}
|
|
662
|
-
const labelInput = this.optionLabel();
|
|
663
|
-
if (labelInput) {
|
|
664
|
-
return (option) => String(option[labelInput] ?? '');
|
|
665
|
-
}
|
|
666
|
-
else {
|
|
667
|
-
throw new Error(`optionLabel is required for non-primitive options.`);
|
|
668
|
-
}
|
|
669
|
-
}
|
|
670
|
-
/**
|
|
671
|
-
* Cria e posiciona dinamicamente o dropdown como portal.
|
|
672
|
-
*/
|
|
673
|
-
_createDropdownPortal() {
|
|
674
|
-
if (!isPlatformBrowser(this.platformId)) {
|
|
675
|
-
return;
|
|
676
|
-
}
|
|
677
|
-
const container = this._containerDiv();
|
|
678
|
-
const template = this._dropdownTemplate();
|
|
679
|
-
if (!container || !template) {
|
|
680
|
-
return;
|
|
681
|
-
}
|
|
682
|
-
const dropElementRect = container.nativeElement.getBoundingClientRect();
|
|
683
|
-
this.dropTop = dropElementRect.bottom + window.scrollY;
|
|
684
|
-
this.dropLeft = dropElementRect.left + window.scrollX;
|
|
685
|
-
this.dropWidth = dropElementRect.width;
|
|
686
|
-
this._destroyDropdownPortal();
|
|
687
|
-
this._portalHost = new DomPortalOutlet(document.body);
|
|
688
|
-
const portal = new TemplatePortal(template, this._viewContainerRef);
|
|
689
|
-
this._portalHost.attach(portal);
|
|
690
|
-
const dropdownEl = document.querySelector('.dropdown-body-class');
|
|
691
|
-
if (dropdownEl) {
|
|
692
|
-
dropdownEl.style.position = 'absolute';
|
|
693
|
-
dropdownEl.style.top = `${this.dropTop + 4}px`;
|
|
694
|
-
dropdownEl.style.left = `${this.dropLeft}px`;
|
|
695
|
-
dropdownEl.style.width = `${this.dropWidth}px`;
|
|
696
|
-
}
|
|
697
|
-
}
|
|
698
|
-
/**
|
|
699
|
-
* Remove o portal do dropdown do DOM.
|
|
700
|
-
*/
|
|
701
|
-
_destroyDropdownPortal() {
|
|
702
|
-
if (this._portalHost?.hasAttached()) {
|
|
703
|
-
this._portalHost.detach();
|
|
704
|
-
}
|
|
705
|
-
}
|
|
706
597
|
static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "18.2.14", ngImport: i0, type: SelectComponent, deps: [], target: i0.ɵɵFactoryTarget.Component });
|
|
707
|
-
static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "18.2.14", type: SelectComponent, isStandalone: true, selector: "s-select", inputs: { placeholder: { classPropertyName: "placeholder", publicName: "placeholder", isSignal: true, isRequired: false, transformFunction: null }, multiple: { classPropertyName: "multiple", publicName: "multiple", isSignal: true, isRequired: false, transformFunction: null }, options: { classPropertyName: "options", publicName: "options", isSignal: true, isRequired: true, transformFunction: null }, optionLabel: { classPropertyName: "optionLabel", publicName: "optionLabel", isSignal: true, isRequired: false, transformFunction: null }, optionValue: { classPropertyName: "optionValue", publicName: "optionValue", isSignal: true, isRequired: false, transformFunction: null }, showClear: { classPropertyName: "showClear", publicName: "showClear", isSignal: true, isRequired: false, transformFunction: null }, filter: { classPropertyName: "filter", publicName: "filter", isSignal: true, isRequired: false, transformFunction: null }, checkmark: { classPropertyName: "checkmark", publicName: "checkmark", isSignal: true, isRequired: false, transformFunction: null }, filterBy: { classPropertyName: "filterBy", publicName: "filterBy", isSignal: true, isRequired: false, transformFunction: null }, group: { classPropertyName: "group", publicName: "group", isSignal: true, isRequired: false, transformFunction: null }, virtualScroll: { classPropertyName: "virtualScroll", publicName: "virtualScroll", isSignal: true, isRequired: false, transformFunction: null }, virtualScrollItemSize: { classPropertyName: "virtualScrollItemSize", publicName: "virtualScrollItemSize", isSignal: true, isRequired: false, transformFunction: null }, emptyMessage: { classPropertyName: "emptyMessage", publicName: "emptyMessage", isSignal: true, isRequired: false, transformFunction: null },
|
|
598
|
+
static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "18.2.14", type: SelectComponent, isStandalone: true, selector: "s-select", inputs: { placeholder: { classPropertyName: "placeholder", publicName: "placeholder", isSignal: true, isRequired: false, transformFunction: null }, multiple: { classPropertyName: "multiple", publicName: "multiple", isSignal: true, isRequired: false, transformFunction: null }, options: { classPropertyName: "options", publicName: "options", isSignal: true, isRequired: true, transformFunction: null }, optionLabel: { classPropertyName: "optionLabel", publicName: "optionLabel", isSignal: true, isRequired: false, transformFunction: null }, optionValue: { classPropertyName: "optionValue", publicName: "optionValue", isSignal: true, isRequired: false, transformFunction: null }, showClear: { classPropertyName: "showClear", publicName: "showClear", isSignal: true, isRequired: false, transformFunction: null }, filter: { classPropertyName: "filter", publicName: "filter", isSignal: true, isRequired: false, transformFunction: null }, checkmark: { classPropertyName: "checkmark", publicName: "checkmark", isSignal: true, isRequired: false, transformFunction: null }, filterBy: { classPropertyName: "filterBy", publicName: "filterBy", isSignal: true, isRequired: false, transformFunction: null }, group: { classPropertyName: "group", publicName: "group", isSignal: true, isRequired: false, transformFunction: null }, virtualScroll: { classPropertyName: "virtualScroll", publicName: "virtualScroll", isSignal: true, isRequired: false, transformFunction: null }, virtualScrollItemSize: { classPropertyName: "virtualScrollItemSize", publicName: "virtualScrollItemSize", isSignal: true, isRequired: false, transformFunction: null }, emptyMessage: { classPropertyName: "emptyMessage", publicName: "emptyMessage", isSignal: true, isRequired: false, transformFunction: null }, disabled: { classPropertyName: "disabled", publicName: "disabled", isSignal: true, isRequired: false, transformFunction: null }, showOptions: { classPropertyName: "showOptions", publicName: "showOptions", isSignal: true, isRequired: false, transformFunction: null } }, outputs: { disabled: "disabledChange", showOptions: "showOptionsChange" }, host: { attributes: { "role": "combobox" }, listeners: { "window:resize": "onWindowResize($event)" }, properties: { "attr.aria-expanded": "showOptions()", "attr.aria-haspopup": "\"listbox\"", "attr.aria-owns": "showOptions() ? componentId + \"-listbox\" : null", "attr.aria-activedescendant": "focusedIndex() >= 0 ? filteredOptions()[focusedIndex()]?.id : null", "attr.aria-label": "placeholder() || \"Select option\"", "attr.aria-disabled": "disabled()" } }, providers: [
|
|
708
599
|
{
|
|
709
600
|
provide: NG_VALUE_ACCESSOR,
|
|
710
601
|
useExisting: forwardRef(() => SelectComponent),
|
|
711
602
|
multi: true,
|
|
712
603
|
},
|
|
713
|
-
], viewQueries: [{ propertyName: "
|
|
604
|
+
], viewQueries: [{ propertyName: "_containerDiv", first: true, predicate: ["containerDiv"], descendants: true, isSignal: true }], ngImport: i0, template: "<div\n #containerDiv\n cdkOverlayOrigin\n #trigger=\"cdkOverlayOrigin\"\n class=\"select-container group flex h-[35px] w-full overflow-hidden rounded-[3px] border outline-1 outline-primary focus:outline\"\n [ngClass]=\"{\n 'pointer-events-none border-grayscale-20 bg-grayscale-5': disabled(),\n 'pointer-events-auto border-grayscale-30 bg-grayscale-0': !disabled(),\n }\"\n [attr.aria-disabled]=\"disabled()\"\n [attr.aria-expanded]=\"showOptions()\"\n [attr.aria-haspopup]=\"'listbox'\"\n [attr.aria-owns]=\"'dropdown-container-' + componentId\"\n [attr.aria-labelledby]=\"componentId + '-label'\"\n role=\"combobox\"\n (click)=\"onContainerDivClick()\"\n (keydown)=\"onKeyDown($event)\"\n tabindex=\"0\"\n>\n <span\n class=\"flex flex-grow select-none px-3 py-[7px]\"\n [ngClass]=\"{\n 'text-grayscale-90': !disabled() && !isClean(),\n 'text-grayscale-60': !disabled() && isClean(),\n 'text-grayscale-30': disabled(),\n }\"\n >\n {{ print() || placeholder() }}\n </span>\n\n @if (!disabled() && showClear() && !isClean()) {\n <button\n class=\"mx-3\"\n (click)=\"clear($event)\"\n >\n <i class=\"fas fa-times flex items-center\"></i>\n </button>\n }\n\n <div\n class=\"dropdown-container flex items-center border-l px-3 group-hover:bg-grayscale-10 group-focus:border-primary\"\n [ngClass]=\"{ 'border-grayscale-20': disabled(), 'border-grayscale-30': !disabled() }\"\n >\n <i\n class=\"fas\"\n [ngClass]=\"{\n 'text-grayscale-30': disabled(),\n 'text-grayscale-90': !disabled(),\n 'fa-caret-down': !showOptions(),\n 'fa-caret-up': showOptions(),\n }\"\n ></i>\n </div>\n</div>\n\n<ng-template\n #dropdownTemplate\n cdkConnectedOverlay\n [cdkConnectedOverlayOrigin]=\"trigger\"\n [cdkConnectedOverlayOpen]=\"showOptions()\"\n [cdkConnectedOverlayHasBackdrop]=\"true\"\n (backdropClick)=\"showOptions.set(false)\"\n cdkConnectedOverlayBackdropClass=\"cdk-overlay-transparent-backdrop\"\n (detach)=\"showOptions.set(false)\"\n>\n <div\n [id]=\"'dropdown-container-' + componentId\"\n class=\"dropdown-body-class z-[1000] rounded-[3px] bg-grayscale-0 py-1 shadow-md\"\n (click)=\"$event.stopPropagation()\"\n [style.width.px]=\"containerDiv.offsetWidth\"\n >\n @if (filter()) {\n <div class=\"flex w-full items-center gap-3 px-3 py-1.5\">\n @if (multiple()) {\n <s-checkbox\n #selectAllCheckbox\n [checked]=\"allSelected()\"\n [indeterminate]=\"selectAllIsIndeterminate()\"\n (checkedChange)=\"toggleSelectAll()\"\n ></s-checkbox>\n }\n\n <div class=\"relative flex h-[35px] grow\">\n <form\n class=\"flex grow\"\n [formGroup]=\"filterForm\"\n >\n <input\n class=\"w-full grow rounded-[3px] border border-grayscale-30 pl-2.5 pr-7 outline-1 outline-primary\"\n type=\"text\"\n formControlName=\"filter\"\n (click)=\"$event.stopPropagation()\"\n />\n </form>\n <i class=\"fas fa-search absolute right-2.5 top-2.5 text-grayscale-90\"></i>\n </div>\n <button (click)=\"clearFilter()\">\n <i class=\"fas fa-times flex items-center\"></i>\n </button>\n </div>\n }\n\n <!-- Virtual scroll -->\n @if (virtualScroll() && filteredOptions().length > 10) {\n <cdk-virtual-scroll-viewport\n [itemSize]=\"virtualScrollItemSize()\"\n class=\"h-52 overflow-auto\"\n >\n <ng-container *cdkVirtualFor=\"let option of filteredOptions(); trackBy: trackById\">\n <s-select-option\n [id]=\"option.id\"\n [label]=\"getOptionLabel(option.data)\"\n [multiple]=\"multiple()\"\n [checkmark]=\"checkmark()\"\n [isSelected]=\"isOptionSelected(option)\"\n (selected)=\"selectItem(option)\"\n [isGrouper]=\"option.grouper\"\n [isFocused]=\"option.data === focusedItem()\"\n ></s-select-option>\n </ng-container>\n </cdk-virtual-scroll-viewport>\n }\n\n <!-- Normal list -->\n @if (!virtualScroll() || filteredOptions().length <= 10) {\n <ul class=\"max-h-52 overflow-auto\">\n @for (option of filteredOptions(); track option.id) {\n <s-select-option\n [id]=\"option.id\"\n [label]=\"getOptionLabel(option.data)\"\n [multiple]=\"multiple()\"\n [checkmark]=\"checkmark()\"\n [isSelected]=\"isOptionSelected(option)\"\n (selected)=\"selectItem(option)\"\n [isGrouper]=\"option.grouper ?? false\"\n [isFocused]=\"option.data === focusedItem()\"\n ></s-select-option>\n }\n </ul>\n }\n\n @if (filteredOptions().length === 0) {\n <span class=\"m-3 text-grayscale-60\">{{\n emptyMessage() ?? 'platform.angular_components.no_records_found' | translate\n }}</span>\n }\n </div>\n</ng-template>\n", styles: [":host.ng-dirty.ng-invalid{.dropdown-container,.select-container{border-color:#c13018;outline:none}}\n"], dependencies: [{ kind: "ngmodule", type: CommonModule }, { kind: "directive", type: i1.NgClass, selector: "[ngClass]", inputs: ["class", "ngClass"] }, { kind: "ngmodule", type: ReactiveFormsModule }, { kind: "directive", type: i2.ɵNgNoValidate, selector: "form:not([ngNoForm]):not([ngNativeValidate])" }, { kind: "directive", type: i2.DefaultValueAccessor, selector: "input:not([type=checkbox])[formControlName],textarea[formControlName],input:not([type=checkbox])[formControl],textarea[formControl],input:not([type=checkbox])[ngModel],textarea[ngModel],[ngDefaultControl]" }, { kind: "directive", type: i2.NgControlStatus, selector: "[formControlName],[ngModel],[formControl]" }, { kind: "directive", type: i2.NgControlStatusGroup, selector: "[formGroupName],[formArrayName],[ngModelGroup],[formGroup],form:not([ngNoForm]),[ngForm]" }, { kind: "directive", type: i2.FormGroupDirective, selector: "[formGroup]", inputs: ["formGroup"], outputs: ["ngSubmit"], exportAs: ["ngForm"] }, { kind: "directive", type: i2.FormControlName, selector: "[formControlName]", inputs: ["formControlName", "disabled", "ngModel"], outputs: ["ngModelChange"] }, { kind: "ngmodule", type: ScrollingModule }, { kind: "directive", type: i3.CdkFixedSizeVirtualScroll, selector: "cdk-virtual-scroll-viewport[itemSize]", inputs: ["itemSize", "minBufferPx", "maxBufferPx"] }, { kind: "directive", type: i3.CdkVirtualForOf, selector: "[cdkVirtualFor][cdkVirtualForOf]", inputs: ["cdkVirtualForOf", "cdkVirtualForTrackBy", "cdkVirtualForTemplate", "cdkVirtualForTemplateCacheSize"] }, { kind: "component", type: i3.CdkVirtualScrollViewport, selector: "cdk-virtual-scroll-viewport", inputs: ["orientation", "appendOnly"], outputs: ["scrolledIndexChange"] }, { kind: "component", type: SelectOptionComponent, selector: "s-select-option", inputs: ["id", "label", "multiple", "checkmark", "isGrouper", "isFocused", "isSelected"], outputs: ["isSelectedChange", "selected"] }, { kind: "component", type: CheckboxComponent, selector: "s-checkbox", inputs: ["disabled", "checked", "indeterminate", "label"], outputs: ["disabledChange", "checkedChange", "indeterminateChange"] }, { kind: "ngmodule", type: TranslateModule }, { kind: "pipe", type: i4.TranslatePipe, name: "translate" }, { kind: "ngmodule", type: OverlayModule }, { kind: "directive", type: i5.CdkConnectedOverlay, selector: "[cdk-connected-overlay], [connected-overlay], [cdkConnectedOverlay]", inputs: ["cdkConnectedOverlayOrigin", "cdkConnectedOverlayPositions", "cdkConnectedOverlayPositionStrategy", "cdkConnectedOverlayOffsetX", "cdkConnectedOverlayOffsetY", "cdkConnectedOverlayWidth", "cdkConnectedOverlayHeight", "cdkConnectedOverlayMinWidth", "cdkConnectedOverlayMinHeight", "cdkConnectedOverlayBackdropClass", "cdkConnectedOverlayPanelClass", "cdkConnectedOverlayViewportMargin", "cdkConnectedOverlayScrollStrategy", "cdkConnectedOverlayOpen", "cdkConnectedOverlayDisableClose", "cdkConnectedOverlayTransformOriginOn", "cdkConnectedOverlayHasBackdrop", "cdkConnectedOverlayLockPosition", "cdkConnectedOverlayFlexibleDimensions", "cdkConnectedOverlayGrowAfterOpen", "cdkConnectedOverlayPush", "cdkConnectedOverlayDisposeOnNavigation"], outputs: ["backdropClick", "positionChange", "attach", "detach", "overlayKeydown", "overlayOutsideClick"], exportAs: ["cdkConnectedOverlay"] }, { kind: "directive", type: i5.CdkOverlayOrigin, selector: "[cdk-overlay-origin], [overlay-origin], [cdkOverlayOrigin]", exportAs: ["cdkOverlayOrigin"] }] });
|
|
714
605
|
}
|
|
715
606
|
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "18.2.14", ngImport: i0, type: SelectComponent, decorators: [{
|
|
716
607
|
type: Component,
|
|
@@ -721,17 +612,24 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "18.2.14", ngImpo
|
|
|
721
612
|
SelectOptionComponent,
|
|
722
613
|
CheckboxComponent,
|
|
723
614
|
TranslateModule,
|
|
615
|
+
OverlayModule,
|
|
724
616
|
], host: {
|
|
725
|
-
'(document:click)': 'onDocumentClick($event)',
|
|
726
617
|
'(window:resize)': 'onWindowResize($event)',
|
|
618
|
+
'[attr.aria-expanded]': 'showOptions()',
|
|
619
|
+
'[attr.aria-haspopup]': '"listbox"',
|
|
620
|
+
'[attr.aria-owns]': 'showOptions() ? componentId + "-listbox" : null',
|
|
621
|
+
'[attr.aria-activedescendant]': 'focusedIndex() >= 0 ? filteredOptions()[focusedIndex()]?.id : null',
|
|
622
|
+
'[attr.aria-label]': 'placeholder() || "Select option"',
|
|
623
|
+
'[attr.aria-disabled]': 'disabled()',
|
|
624
|
+
role: 'combobox',
|
|
727
625
|
}, providers: [
|
|
728
626
|
{
|
|
729
627
|
provide: NG_VALUE_ACCESSOR,
|
|
730
628
|
useExisting: forwardRef(() => SelectComponent),
|
|
731
629
|
multi: true,
|
|
732
630
|
},
|
|
733
|
-
], template: "<
|
|
734
|
-
}] });
|
|
631
|
+
], template: "<div\n #containerDiv\n cdkOverlayOrigin\n #trigger=\"cdkOverlayOrigin\"\n class=\"select-container group flex h-[35px] w-full overflow-hidden rounded-[3px] border outline-1 outline-primary focus:outline\"\n [ngClass]=\"{\n 'pointer-events-none border-grayscale-20 bg-grayscale-5': disabled(),\n 'pointer-events-auto border-grayscale-30 bg-grayscale-0': !disabled(),\n }\"\n [attr.aria-disabled]=\"disabled()\"\n [attr.aria-expanded]=\"showOptions()\"\n [attr.aria-haspopup]=\"'listbox'\"\n [attr.aria-owns]=\"'dropdown-container-' + componentId\"\n [attr.aria-labelledby]=\"componentId + '-label'\"\n role=\"combobox\"\n (click)=\"onContainerDivClick()\"\n (keydown)=\"onKeyDown($event)\"\n tabindex=\"0\"\n>\n <span\n class=\"flex flex-grow select-none px-3 py-[7px]\"\n [ngClass]=\"{\n 'text-grayscale-90': !disabled() && !isClean(),\n 'text-grayscale-60': !disabled() && isClean(),\n 'text-grayscale-30': disabled(),\n }\"\n >\n {{ print() || placeholder() }}\n </span>\n\n @if (!disabled() && showClear() && !isClean()) {\n <button\n class=\"mx-3\"\n (click)=\"clear($event)\"\n >\n <i class=\"fas fa-times flex items-center\"></i>\n </button>\n }\n\n <div\n class=\"dropdown-container flex items-center border-l px-3 group-hover:bg-grayscale-10 group-focus:border-primary\"\n [ngClass]=\"{ 'border-grayscale-20': disabled(), 'border-grayscale-30': !disabled() }\"\n >\n <i\n class=\"fas\"\n [ngClass]=\"{\n 'text-grayscale-30': disabled(),\n 'text-grayscale-90': !disabled(),\n 'fa-caret-down': !showOptions(),\n 'fa-caret-up': showOptions(),\n }\"\n ></i>\n </div>\n</div>\n\n<ng-template\n #dropdownTemplate\n cdkConnectedOverlay\n [cdkConnectedOverlayOrigin]=\"trigger\"\n [cdkConnectedOverlayOpen]=\"showOptions()\"\n [cdkConnectedOverlayHasBackdrop]=\"true\"\n (backdropClick)=\"showOptions.set(false)\"\n cdkConnectedOverlayBackdropClass=\"cdk-overlay-transparent-backdrop\"\n (detach)=\"showOptions.set(false)\"\n>\n <div\n [id]=\"'dropdown-container-' + componentId\"\n class=\"dropdown-body-class z-[1000] rounded-[3px] bg-grayscale-0 py-1 shadow-md\"\n (click)=\"$event.stopPropagation()\"\n [style.width.px]=\"containerDiv.offsetWidth\"\n >\n @if (filter()) {\n <div class=\"flex w-full items-center gap-3 px-3 py-1.5\">\n @if (multiple()) {\n <s-checkbox\n #selectAllCheckbox\n [checked]=\"allSelected()\"\n [indeterminate]=\"selectAllIsIndeterminate()\"\n (checkedChange)=\"toggleSelectAll()\"\n ></s-checkbox>\n }\n\n <div class=\"relative flex h-[35px] grow\">\n <form\n class=\"flex grow\"\n [formGroup]=\"filterForm\"\n >\n <input\n class=\"w-full grow rounded-[3px] border border-grayscale-30 pl-2.5 pr-7 outline-1 outline-primary\"\n type=\"text\"\n formControlName=\"filter\"\n (click)=\"$event.stopPropagation()\"\n />\n </form>\n <i class=\"fas fa-search absolute right-2.5 top-2.5 text-grayscale-90\"></i>\n </div>\n <button (click)=\"clearFilter()\">\n <i class=\"fas fa-times flex items-center\"></i>\n </button>\n </div>\n }\n\n <!-- Virtual scroll -->\n @if (virtualScroll() && filteredOptions().length > 10) {\n <cdk-virtual-scroll-viewport\n [itemSize]=\"virtualScrollItemSize()\"\n class=\"h-52 overflow-auto\"\n >\n <ng-container *cdkVirtualFor=\"let option of filteredOptions(); trackBy: trackById\">\n <s-select-option\n [id]=\"option.id\"\n [label]=\"getOptionLabel(option.data)\"\n [multiple]=\"multiple()\"\n [checkmark]=\"checkmark()\"\n [isSelected]=\"isOptionSelected(option)\"\n (selected)=\"selectItem(option)\"\n [isGrouper]=\"option.grouper\"\n [isFocused]=\"option.data === focusedItem()\"\n ></s-select-option>\n </ng-container>\n </cdk-virtual-scroll-viewport>\n }\n\n <!-- Normal list -->\n @if (!virtualScroll() || filteredOptions().length <= 10) {\n <ul class=\"max-h-52 overflow-auto\">\n @for (option of filteredOptions(); track option.id) {\n <s-select-option\n [id]=\"option.id\"\n [label]=\"getOptionLabel(option.data)\"\n [multiple]=\"multiple()\"\n [checkmark]=\"checkmark()\"\n [isSelected]=\"isOptionSelected(option)\"\n (selected)=\"selectItem(option)\"\n [isGrouper]=\"option.grouper ?? false\"\n [isFocused]=\"option.data === focusedItem()\"\n ></s-select-option>\n }\n </ul>\n }\n\n @if (filteredOptions().length === 0) {\n <span class=\"m-3 text-grayscale-60\">{{\n emptyMessage() ?? 'platform.angular_components.no_records_found' | translate\n }}</span>\n }\n </div>\n</ng-template>\n", styles: [":host.ng-dirty.ng-invalid{.dropdown-container,.select-container{border-color:#c13018;outline:none}}\n"] }]
|
|
632
|
+
}], ctorParameters: () => [] });
|
|
735
633
|
|
|
736
634
|
/**
|
|
737
635
|
* Generated bundle index. Do not edit.
|