@spartan-ng/brain 0.0.1-alpha.411 → 0.0.1-alpha.413
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/esm2022/select/index.mjs +15 -5
- package/esm2022/select/lib/brn-select-content.component.mjs +64 -45
- package/esm2022/select/lib/brn-select-content.token.mjs +9 -0
- package/esm2022/select/lib/brn-select-option.directive.mjs +49 -45
- package/esm2022/select/lib/brn-select-placeholder.directive.mjs +16 -0
- package/esm2022/select/lib/brn-select-trigger.directive.mjs +67 -0
- package/esm2022/select/lib/brn-select-value.component.mjs +58 -36
- package/esm2022/select/lib/brn-select-value.directive.mjs +16 -0
- package/esm2022/select/lib/brn-select.component.mjs +104 -178
- package/esm2022/select/lib/brn-select.token.mjs +9 -0
- package/fesm2022/spartan-ng-brain-select.mjs +378 -497
- package/fesm2022/spartan-ng-brain-select.mjs.map +1 -1
- package/package.json +7 -7
- package/select/index.d.ts +11 -5
- package/select/lib/brn-select-content.component.d.ts +17 -19
- package/select/lib/brn-select-content.token.d.ts +4 -0
- package/select/lib/brn-select-option.directive.d.ts +19 -19
- package/select/lib/brn-select-placeholder.directive.d.ts +8 -0
- package/select/lib/brn-select-trigger.directive.d.ts +20 -0
- package/select/lib/brn-select-value.component.d.ts +13 -6
- package/select/lib/brn-select-value.directive.d.ts +11 -0
- package/select/lib/brn-select.component.d.ts +38 -49
- package/select/lib/brn-select.token.d.ts +4 -0
- package/esm2022/select/lib/brn-select.service.mjs +0 -207
- package/select/lib/brn-select.service.d.ts +0 -71
|
@@ -1,279 +1,100 @@
|
|
|
1
1
|
import * as i0 from '@angular/core';
|
|
2
|
-
import { inject, ElementRef,
|
|
3
|
-
import
|
|
4
|
-
import {
|
|
5
|
-
import {
|
|
6
|
-
import {
|
|
7
|
-
import {
|
|
8
|
-
import
|
|
9
|
-
import { skip, takeUntil, map, switchMap, delay } from 'rxjs/operators';
|
|
10
|
-
import * as i1$1 from '@spartan-ng/brain/label';
|
|
2
|
+
import { InjectionToken, inject, ElementRef, input, booleanAttribute, computed, signal, Directive, DestroyRef, Injector, viewChild, contentChild, contentChildren, effect, afterNextRender, untracked, Component, ChangeDetectionStrategy, TemplateRef, PLATFORM_ID, numberAttribute, model, NgModule } from '@angular/core';
|
|
3
|
+
import { NgTemplateOutlet, isPlatformBrowser } from '@angular/common';
|
|
4
|
+
import { takeUntilDestroyed, toSignal, toObservable } from '@angular/core/rxjs-interop';
|
|
5
|
+
import { ActiveDescendantKeyManager } from '@angular/cdk/a11y';
|
|
6
|
+
import { Subject, fromEvent, interval, of } from 'rxjs';
|
|
7
|
+
import { takeUntil, switchMap, delay, map } from 'rxjs/operators';
|
|
8
|
+
import * as i1 from '@spartan-ng/brain/label';
|
|
11
9
|
import { BrnLabelDirective } from '@spartan-ng/brain/label';
|
|
12
|
-
import
|
|
10
|
+
import { NgControl, NgForm, FormGroupDirective } from '@angular/forms';
|
|
11
|
+
import { CdkListboxModule } from '@angular/cdk/listbox';
|
|
12
|
+
import * as i1$1 from '@angular/cdk/overlay';
|
|
13
13
|
import { CdkConnectedOverlay, OverlayModule } from '@angular/cdk/overlay';
|
|
14
14
|
import { provideExposedSideProviderExisting, provideExposesStateProviderExisting } from '@spartan-ng/brain/core';
|
|
15
15
|
import { BrnFormFieldControl } from '@spartan-ng/brain/form-field';
|
|
16
16
|
import { ErrorStateMatcher, ErrorStateTracker } from '@spartan-ng/brain/forms';
|
|
17
17
|
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
_ngControl = inject(NgControl, { optional: true });
|
|
22
|
-
_platform = inject(PLATFORM_ID);
|
|
23
|
-
isExpanded = this._selectService.isExpanded;
|
|
24
|
-
selectTriggerId = computed(() => `${this._selectService.id()}--trigger`);
|
|
25
|
-
selectContentId = computed(() => `${this._selectService.id()}--content`);
|
|
26
|
-
selectDisable = computed(() => this._selectService.disabled());
|
|
27
|
-
selectTriggerLabelledBy = computed(() => {
|
|
28
|
-
if (this._selectService.value() && this._selectService.value().length > 0) {
|
|
29
|
-
return `${this._selectService.labelId()} ${this._selectService.id()}--value`;
|
|
30
|
-
}
|
|
31
|
-
return this._selectService.labelId();
|
|
32
|
-
});
|
|
33
|
-
_resizeObserver;
|
|
34
|
-
constructor() {
|
|
35
|
-
if (!this._selectService)
|
|
36
|
-
return;
|
|
37
|
-
this._selectService._setSelectTrigger(this);
|
|
38
|
-
}
|
|
39
|
-
ngAfterViewInit() {
|
|
40
|
-
this._selectService.setTriggerWidth(this._el.nativeElement.offsetWidth);
|
|
41
|
-
// if we are on the client, listen for element resize events
|
|
42
|
-
if (isPlatformBrowser(this._platform)) {
|
|
43
|
-
this._resizeObserver = new ResizeObserver(() => this._selectService.setTriggerWidth(this._el.nativeElement.offsetWidth));
|
|
44
|
-
this._resizeObserver.observe(this._el.nativeElement);
|
|
45
|
-
}
|
|
46
|
-
}
|
|
47
|
-
ngOnDestroy() {
|
|
48
|
-
this._resizeObserver?.disconnect();
|
|
49
|
-
}
|
|
50
|
-
focus() {
|
|
51
|
-
this._el.nativeElement.focus();
|
|
52
|
-
}
|
|
53
|
-
/** @nocollapse */ static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "18.2.5", ngImport: i0, type: BrnSelectTriggerDirective, deps: [], target: i0.ɵɵFactoryTarget.Directive });
|
|
54
|
-
/** @nocollapse */ static ɵdir = i0.ɵɵngDeclareDirective({ minVersion: "14.0.0", version: "18.2.5", type: BrnSelectTriggerDirective, isStandalone: true, selector: "[brnSelectTrigger]", host: { attributes: { "role": "combobox", "aria-autocomplete": "none", "type": "button" }, properties: { "attr.id": "selectTriggerId()", "disabled": "selectDisable()", "attr.aria-expanded": "isExpanded()", "attr.aria-controls": "selectContentId() + ''", "attr.aria-labelledBy": "selectTriggerLabelledBy()", "attr.dir": "_selectService.dir()", "class.ng-invalid": "this._ngControl?.invalid || null", "class.ng-dirty": "this._ngControl?.dirty || null", "class.ng-valid": "this._ngControl?.valid || null", "class.ng-touched": "this._ngControl?.touched || null", "class.ng-untouched": "this._ngControl?.untouched || null", "class.ng-pristine": "this._ngControl?.pristine || null" } }, ngImport: i0 });
|
|
18
|
+
const BrnSelectContentToken = new InjectionToken('BrnSelectContentToken');
|
|
19
|
+
function injectBrnSelectContent() {
|
|
20
|
+
return inject(BrnSelectContentToken);
|
|
55
21
|
}
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
'[attr.aria-controls]': "selectContentId() + ''",
|
|
67
|
-
'[attr.aria-labelledBy]': 'selectTriggerLabelledBy()',
|
|
68
|
-
'aria-autocomplete': 'none',
|
|
69
|
-
'[attr.dir]': '_selectService.dir()',
|
|
70
|
-
'[class.ng-invalid]': 'this._ngControl?.invalid || null',
|
|
71
|
-
'[class.ng-dirty]': 'this._ngControl?.dirty || null',
|
|
72
|
-
'[class.ng-valid]': 'this._ngControl?.valid || null',
|
|
73
|
-
'[class.ng-touched]': 'this._ngControl?.touched || null',
|
|
74
|
-
'[class.ng-untouched]': 'this._ngControl?.untouched || null',
|
|
75
|
-
'[class.ng-pristine]': 'this._ngControl?.pristine || null',
|
|
76
|
-
type: 'button',
|
|
77
|
-
},
|
|
78
|
-
}]
|
|
79
|
-
}], ctorParameters: () => [] });
|
|
80
|
-
class BrnSelectService {
|
|
81
|
-
state = signal({
|
|
82
|
-
id: '',
|
|
83
|
-
labelId: '',
|
|
84
|
-
panelId: '',
|
|
85
|
-
isExpanded: false,
|
|
86
|
-
placeholder: signal(''),
|
|
87
|
-
multiple: signal(false),
|
|
88
|
-
disabled: signal(false),
|
|
89
|
-
disabledBySetDisabled: signal(false),
|
|
90
|
-
dir: signal('ltr'),
|
|
91
|
-
selectedOptions: [],
|
|
92
|
-
possibleOptions: [],
|
|
93
|
-
value: '',
|
|
94
|
-
triggerWidth: 0,
|
|
95
|
-
});
|
|
96
|
-
id = computed(() => this.state().id);
|
|
97
|
-
labelId = computed(() => this.state().labelId);
|
|
98
|
-
panelId = computed(() => this.state().panelId);
|
|
99
|
-
placeholder = computed(() => this.state().placeholder());
|
|
100
|
-
disabled = computed(() => this.state().disabled() || this.state().disabledBySetDisabled());
|
|
101
|
-
isExpanded = computed(() => this.state().isExpanded);
|
|
102
|
-
multiple = computed(() => this.state().multiple());
|
|
103
|
-
dir = computed(() => this.state().dir());
|
|
104
|
-
selectedOptions = computed(() => this.state().selectedOptions);
|
|
105
|
-
value = computed(() => this.state().value);
|
|
106
|
-
triggerWidth = computed(() => this.state().triggerWidth);
|
|
107
|
-
possibleOptions = computed(() => this.state().possibleOptions);
|
|
108
|
-
_multiple$ = toObservable(this.multiple);
|
|
109
|
-
listBoxValueChangeEvent$ = new Subject();
|
|
110
|
-
_selectTrigger;
|
|
111
|
-
get selectTrigger() {
|
|
112
|
-
return this._selectTrigger;
|
|
113
|
-
}
|
|
114
|
-
constructor() {
|
|
115
|
-
this.listBoxValueChangeEvent$.pipe(takeUntilDestroyed()).subscribe((listBoxChange) => {
|
|
116
|
-
const updatedSelections = this.multiple() ? this.getUpdatedOptions(listBoxChange) : [listBoxChange.option];
|
|
117
|
-
const value = this.multiple() ? listBoxChange.value : listBoxChange.value[0];
|
|
118
|
-
this.state.update((state) => ({
|
|
119
|
-
...state,
|
|
120
|
-
selectedOptions: [...updatedSelections],
|
|
121
|
-
value: value,
|
|
122
|
-
}));
|
|
123
|
-
});
|
|
124
|
-
// We need to skip the first value because we don't want to deselect all options when the component is initialized with a preselected value e.g. by the form control
|
|
125
|
-
this._multiple$.pipe(skip(1), takeUntilDestroyed()).subscribe((multiple) => {
|
|
126
|
-
if (!multiple && this.value().length > 1) {
|
|
127
|
-
this.deselectAllOptions();
|
|
128
|
-
}
|
|
129
|
-
});
|
|
130
|
-
}
|
|
131
|
-
setTriggerWidth(triggerWidth) {
|
|
132
|
-
this.state.update((s) => ({ ...s, triggerWidth }));
|
|
133
|
-
}
|
|
134
|
-
getUpdatedOptions(latestListboxChange) {
|
|
135
|
-
const isNewSelection = latestListboxChange.value.findIndex((value) => value === latestListboxChange.option?.value);
|
|
136
|
-
if (isNewSelection === -1) {
|
|
137
|
-
const removedOptionIndex = this.selectedOptions().findIndex((option) => latestListboxChange.option === option);
|
|
138
|
-
const options = this.selectedOptions();
|
|
139
|
-
options.splice(removedOptionIndex, 1);
|
|
140
|
-
return options;
|
|
141
|
-
}
|
|
142
|
-
return [...this.selectedOptions(), latestListboxChange.option];
|
|
143
|
-
}
|
|
144
|
-
deselectAllOptions() {
|
|
145
|
-
this.state.update((state) => ({
|
|
146
|
-
...state,
|
|
147
|
-
selectedOptions: [],
|
|
148
|
-
value: [],
|
|
149
|
-
}));
|
|
150
|
-
}
|
|
151
|
-
// Needed due to https://github.com/angular/angular/issues/20810
|
|
152
|
-
_setSelectTrigger(trigger) {
|
|
153
|
-
this._selectTrigger = trigger;
|
|
154
|
-
}
|
|
155
|
-
setInitialSelectedOptions(value) {
|
|
156
|
-
this.selectOptionByValue(value);
|
|
157
|
-
this.state.update((state) => ({
|
|
158
|
-
...state,
|
|
159
|
-
value: value,
|
|
160
|
-
initialSelectedOptions: this.selectedOptions(),
|
|
161
|
-
selectedOptions: this.selectedOptions(),
|
|
162
|
-
}));
|
|
163
|
-
}
|
|
164
|
-
/**
|
|
165
|
-
* Sync the updated options with "possibleOptions" in the select service
|
|
166
|
-
*/
|
|
167
|
-
updatePossibleOptions(options) {
|
|
168
|
-
this.state.update((state) => ({
|
|
169
|
-
...state,
|
|
170
|
-
possibleOptions: options,
|
|
171
|
-
}));
|
|
172
|
-
}
|
|
173
|
-
selectOptionByValue(value) {
|
|
174
|
-
const options = this.possibleOptions();
|
|
175
|
-
if (value === null || value === undefined) {
|
|
176
|
-
const nullOrUndefinedOption = options.find((o) => o && o.value === value);
|
|
177
|
-
if (!nullOrUndefinedOption) {
|
|
178
|
-
this.state.update((state) => ({
|
|
179
|
-
...state,
|
|
180
|
-
selectedOptions: [],
|
|
181
|
-
value: this.multiple() ? [] : '',
|
|
182
|
-
}));
|
|
183
|
-
return;
|
|
184
|
-
}
|
|
185
|
-
}
|
|
186
|
-
if (this.multiple()) {
|
|
187
|
-
const selectedOptions = options.filter((option) => {
|
|
188
|
-
if (Array.isArray(value)) {
|
|
189
|
-
return value.includes(option?.value);
|
|
190
|
-
}
|
|
191
|
-
return value === option?.value;
|
|
192
|
-
});
|
|
193
|
-
this.state.update((state) => ({
|
|
194
|
-
...state,
|
|
195
|
-
selectedOptions,
|
|
196
|
-
value: value,
|
|
197
|
-
}));
|
|
198
|
-
}
|
|
199
|
-
else {
|
|
200
|
-
const selectedOption = options.find((option) => option?.value === value);
|
|
201
|
-
if (!selectedOption) {
|
|
202
|
-
return;
|
|
203
|
-
}
|
|
204
|
-
this.state.update((state) => ({
|
|
205
|
-
...state,
|
|
206
|
-
selectedOptions: [selectedOption],
|
|
207
|
-
value: selectedOption.value,
|
|
208
|
-
}));
|
|
209
|
-
}
|
|
210
|
-
}
|
|
211
|
-
/** @nocollapse */ static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "18.2.5", ngImport: i0, type: BrnSelectService, deps: [], target: i0.ɵɵFactoryTarget.Injectable });
|
|
212
|
-
/** @nocollapse */ static ɵprov = i0.ɵɵngDeclareInjectable({ minVersion: "12.0.0", version: "18.2.5", ngImport: i0, type: BrnSelectService });
|
|
22
|
+
function provideBrnSelectContent(select) {
|
|
23
|
+
return { provide: BrnSelectContentToken, useExisting: select };
|
|
24
|
+
}
|
|
25
|
+
|
|
26
|
+
const BrnSelectToken = new InjectionToken('BrnSelectToken');
|
|
27
|
+
function injectBrnSelect() {
|
|
28
|
+
return inject(BrnSelectToken);
|
|
29
|
+
}
|
|
30
|
+
function provideBrnSelect(select) {
|
|
31
|
+
return { provide: BrnSelectToken, useExisting: select };
|
|
213
32
|
}
|
|
214
|
-
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "18.2.5", ngImport: i0, type: BrnSelectService, decorators: [{
|
|
215
|
-
type: Injectable
|
|
216
|
-
}], ctorParameters: () => [] });
|
|
217
33
|
|
|
34
|
+
let nextId$1 = 0;
|
|
218
35
|
class BrnSelectOptionDirective {
|
|
219
|
-
|
|
220
|
-
|
|
221
|
-
_focused = signal(false);
|
|
36
|
+
_select = injectBrnSelect();
|
|
37
|
+
_content = injectBrnSelectContent();
|
|
222
38
|
elementRef = inject(ElementRef);
|
|
223
|
-
|
|
224
|
-
|
|
225
|
-
|
|
226
|
-
|
|
227
|
-
|
|
228
|
-
|
|
39
|
+
id = input(`brn-option-${nextId$1++}`);
|
|
40
|
+
value = input();
|
|
41
|
+
// we use "_disabled" here because disabled is already defined in the Highlightable interface
|
|
42
|
+
_disabled = input(false, {
|
|
43
|
+
alias: 'disabled',
|
|
44
|
+
transform: booleanAttribute,
|
|
229
45
|
});
|
|
230
|
-
|
|
46
|
+
get disabled() {
|
|
47
|
+
return this._disabled();
|
|
48
|
+
}
|
|
49
|
+
selected = computed(() => this.value() !== undefined && this._select.isSelected(this.value()));
|
|
50
|
+
_active = signal(false);
|
|
231
51
|
checkedState = computed(() => (this.selected() ? 'checked' : 'unchecked'));
|
|
232
|
-
dir =
|
|
233
|
-
|
|
234
|
-
|
|
235
|
-
|
|
236
|
-
}
|
|
237
|
-
|
|
238
|
-
this._cdkSelectOption.disabled = this.disabledSignal();
|
|
239
|
-
});
|
|
52
|
+
dir = this._select.dir;
|
|
53
|
+
select() {
|
|
54
|
+
if (this._disabled()) {
|
|
55
|
+
return;
|
|
56
|
+
}
|
|
57
|
+
this._select.selectOption(this.value());
|
|
240
58
|
}
|
|
241
|
-
|
|
242
|
-
|
|
59
|
+
/** Get the label for this element which is required by the FocusableOption interface. */
|
|
60
|
+
getLabel() {
|
|
61
|
+
return this.elementRef.nativeElement.textContent?.trim() ?? '';
|
|
243
62
|
}
|
|
244
|
-
|
|
245
|
-
|
|
246
|
-
|
|
247
|
-
|
|
248
|
-
transform: booleanAttribute,
|
|
249
|
-
});
|
|
250
|
-
hover() {
|
|
251
|
-
this.focus();
|
|
63
|
+
setActiveStyles() {
|
|
64
|
+
this._active.set(true);
|
|
65
|
+
// scroll the option into view if it is not visible
|
|
66
|
+
this.elementRef.nativeElement.scrollIntoView({ block: 'nearest' });
|
|
252
67
|
}
|
|
253
|
-
|
|
254
|
-
this.
|
|
255
|
-
this._focused.set(true);
|
|
68
|
+
setInactiveStyles() {
|
|
69
|
+
this._active.set(false);
|
|
256
70
|
}
|
|
257
|
-
|
|
258
|
-
this.
|
|
71
|
+
activate() {
|
|
72
|
+
if (this._disabled()) {
|
|
73
|
+
return;
|
|
74
|
+
}
|
|
75
|
+
this._content.setActiveOption(this);
|
|
259
76
|
}
|
|
260
77
|
/** @nocollapse */ static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "18.2.5", ngImport: i0, type: BrnSelectOptionDirective, deps: [], target: i0.ɵɵFactoryTarget.Directive });
|
|
261
|
-
/** @nocollapse */ static ɵdir = i0.ɵɵngDeclareDirective({ minVersion: "17.1.0", version: "18.2.5", type: BrnSelectOptionDirective, isStandalone: true, selector: "[brnOption]", inputs: { value: { classPropertyName: "value", publicName: "value", isSignal: true, isRequired: false, transformFunction: null },
|
|
78
|
+
/** @nocollapse */ static ɵdir = i0.ɵɵngDeclareDirective({ minVersion: "17.1.0", version: "18.2.5", type: BrnSelectOptionDirective, isStandalone: true, selector: "[brnOption]", inputs: { id: { classPropertyName: "id", publicName: "id", isSignal: true, isRequired: false, transformFunction: null }, value: { classPropertyName: "value", publicName: "value", isSignal: true, isRequired: false, transformFunction: null }, _disabled: { classPropertyName: "_disabled", publicName: "disabled", isSignal: true, isRequired: false, transformFunction: null } }, host: { attributes: { "role": "option" }, listeners: { "click": "select()", "mouseenter": "activate()" }, properties: { "id": "id()", "attr.aria-selected": "selected()", "attr.aria-disabled": "_disabled()", "attr.dir": "_select.dir()", "attr.data-active": "_active() ? '' : undefined", "attr.data-disabled": "_disabled() ? '' : undefined" } }, ngImport: i0 });
|
|
262
79
|
}
|
|
263
80
|
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "18.2.5", ngImport: i0, type: BrnSelectOptionDirective, decorators: [{
|
|
264
81
|
type: Directive,
|
|
265
82
|
args: [{
|
|
266
83
|
selector: '[brnOption]',
|
|
267
84
|
standalone: true,
|
|
268
|
-
hostDirectives: [CdkOption],
|
|
269
85
|
host: {
|
|
270
|
-
|
|
271
|
-
'
|
|
272
|
-
'[attr.
|
|
273
|
-
'[attr.
|
|
86
|
+
role: 'option',
|
|
87
|
+
'[id]': 'id()',
|
|
88
|
+
'[attr.aria-selected]': 'selected()',
|
|
89
|
+
'[attr.aria-disabled]': '_disabled()',
|
|
90
|
+
'(click)': 'select()',
|
|
91
|
+
'[attr.dir]': '_select.dir()',
|
|
92
|
+
'[attr.data-active]': "_active() ? '' : undefined",
|
|
93
|
+
'[attr.data-disabled]': "_disabled() ? '' : undefined",
|
|
94
|
+
'(mouseenter)': 'activate()',
|
|
274
95
|
},
|
|
275
96
|
}]
|
|
276
|
-
}]
|
|
97
|
+
}] });
|
|
277
98
|
|
|
278
99
|
const SCROLLBY_PIXELS = 100;
|
|
279
100
|
class BrnSelectScrollUpDirective {
|
|
@@ -333,51 +154,47 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "18.2.5", ngImpor
|
|
|
333
154
|
}]
|
|
334
155
|
}] });
|
|
335
156
|
class BrnSelectContentComponent {
|
|
336
|
-
|
|
337
|
-
|
|
338
|
-
|
|
339
|
-
_selectService = inject(BrnSelectService);
|
|
340
|
-
labelledBy = this._selectService.labelId;
|
|
341
|
-
id = this._selectService.id;
|
|
157
|
+
_elementRef = inject(ElementRef);
|
|
158
|
+
_injector = inject(Injector);
|
|
159
|
+
_select = injectBrnSelect();
|
|
342
160
|
canScrollUp = signal(false);
|
|
343
161
|
canScrollDown = signal(false);
|
|
344
|
-
initialSelectedOptions$ = toObservable(this._selectService.selectedOptions);
|
|
345
162
|
viewport = viewChild.required('viewport');
|
|
346
163
|
scrollUpBtn = contentChild(BrnSelectScrollUpDirective);
|
|
347
164
|
scrollDownBtn = contentChild(BrnSelectScrollDownDirective);
|
|
348
165
|
_options = contentChildren(BrnSelectOptionDirective, { descendants: true });
|
|
166
|
+
/** @internal */
|
|
167
|
+
keyManager = null;
|
|
349
168
|
constructor() {
|
|
350
|
-
this._cdkListbox.valueChange
|
|
351
|
-
.asObservable()
|
|
352
|
-
.pipe(takeUntilDestroyed())
|
|
353
|
-
.subscribe((val) => this._selectService.listBoxValueChangeEvent$.next(val));
|
|
354
169
|
effect(() => {
|
|
355
|
-
this.
|
|
356
|
-
this._selectService.isExpanded() && setTimeout(() => this.updateArrowDisplay());
|
|
170
|
+
this._select.open() && afterNextRender(() => this.updateArrowDisplay(), { injector: this._injector });
|
|
357
171
|
});
|
|
358
172
|
}
|
|
359
|
-
|
|
360
|
-
this.
|
|
361
|
-
|
|
362
|
-
|
|
363
|
-
|
|
364
|
-
|
|
365
|
-
|
|
366
|
-
|
|
367
|
-
|
|
173
|
+
ngAfterContentInit() {
|
|
174
|
+
this.keyManager = new ActiveDescendantKeyManager(this._options, this._injector)
|
|
175
|
+
.withHomeAndEnd()
|
|
176
|
+
.withVerticalOrientation()
|
|
177
|
+
.withTypeAhead()
|
|
178
|
+
.withAllowedModifierKeys(['shiftKey'])
|
|
179
|
+
.withWrap()
|
|
180
|
+
.skipPredicate((option) => option._disabled());
|
|
181
|
+
effect(() => {
|
|
182
|
+
// any time the select is opened, we need to focus the first selected option or the first option
|
|
183
|
+
const open = this._select.open();
|
|
184
|
+
const options = this._options();
|
|
185
|
+
if (!open || !options.length) {
|
|
186
|
+
return;
|
|
368
187
|
}
|
|
369
|
-
|
|
370
|
-
|
|
371
|
-
|
|
188
|
+
untracked(() => {
|
|
189
|
+
const selectedOption = options.find((option) => option.selected());
|
|
190
|
+
if (selectedOption) {
|
|
191
|
+
this.keyManager?.setActiveItem(selectedOption);
|
|
372
192
|
}
|
|
373
193
|
else {
|
|
374
|
-
|
|
194
|
+
this.keyManager?.setFirstItemActive();
|
|
375
195
|
}
|
|
376
|
-
}
|
|
377
|
-
|
|
378
|
-
cdkOption?.select();
|
|
379
|
-
}
|
|
380
|
-
});
|
|
196
|
+
});
|
|
197
|
+
}, { injector: this._injector });
|
|
381
198
|
}
|
|
382
199
|
updateArrowDisplay() {
|
|
383
200
|
const { scrollTop, scrollHeight, clientHeight } = this.viewport().nativeElement;
|
|
@@ -389,7 +206,7 @@ class BrnSelectContentComponent {
|
|
|
389
206
|
this.updateArrowDisplay();
|
|
390
207
|
}
|
|
391
208
|
focusList() {
|
|
392
|
-
this.
|
|
209
|
+
this._elementRef.nativeElement.focus();
|
|
393
210
|
}
|
|
394
211
|
moveFocusUp() {
|
|
395
212
|
this.viewport().nativeElement.scrollBy({ top: -SCROLLBY_PIXELS, behavior: 'smooth' });
|
|
@@ -399,15 +216,29 @@ class BrnSelectContentComponent {
|
|
|
399
216
|
}
|
|
400
217
|
moveFocusDown() {
|
|
401
218
|
this.viewport().nativeElement.scrollBy({ top: SCROLLBY_PIXELS, behavior: 'smooth' });
|
|
402
|
-
const viewportSize = this.
|
|
219
|
+
const viewportSize = this._elementRef.nativeElement.scrollHeight;
|
|
403
220
|
const viewportScrollPosition = this.viewport().nativeElement.scrollTop;
|
|
404
221
|
if (viewportSize + viewportScrollPosition + SCROLLBY_PIXELS >
|
|
405
222
|
this.viewport().nativeElement.scrollHeight + SCROLLBY_PIXELS / 2) {
|
|
406
223
|
this.scrollDownBtn()?.stopEmittingEvents();
|
|
407
224
|
}
|
|
408
225
|
}
|
|
226
|
+
setActiveOption(option) {
|
|
227
|
+
const index = this._options().findIndex((o) => o === option);
|
|
228
|
+
if (index === -1) {
|
|
229
|
+
return;
|
|
230
|
+
}
|
|
231
|
+
this.keyManager?.setActiveItem(index);
|
|
232
|
+
}
|
|
233
|
+
selectActiveItem(event) {
|
|
234
|
+
event.preventDefault();
|
|
235
|
+
const activeOption = this.keyManager?.activeItem;
|
|
236
|
+
if (activeOption) {
|
|
237
|
+
this._select.selectOption(activeOption.value());
|
|
238
|
+
}
|
|
239
|
+
}
|
|
409
240
|
/** @nocollapse */ static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "18.2.5", ngImport: i0, type: BrnSelectContentComponent, deps: [], target: i0.ɵɵFactoryTarget.Component });
|
|
410
|
-
/** @nocollapse */ static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.2.0", version: "18.2.5", type: BrnSelectContentComponent, isStandalone: true, selector: "brn-select-content, hlm-select-content:not(noHlm)", host: { properties: { "attr.aria-labelledBy": "
|
|
241
|
+
/** @nocollapse */ static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.2.0", version: "18.2.5", type: BrnSelectContentComponent, isStandalone: true, selector: "brn-select-content, hlm-select-content:not(noHlm)", host: { attributes: { "role": "listbox", "tabindex": "0", "aria-orientation": "vertical" }, listeners: { "keydown": "keyManager?.onKeydown($event)", "keydown.enter": "selectActiveItem($event)", "keydown.space": "selectActiveItem($event)" }, properties: { "attr.aria-multiselectable": "_select.multiple()", "attr.aria-disabled": "_select.disabled() || _select._formDisabled()", "attr.aria-activedescendant": "keyManager?.activeItem?.id()", "attr.aria-labelledBy": "_select.labelId()", "attr.aria-controlledBy": "_select.id() +'--trigger'", "id": "_select.id() + '--content'", "attr.dir": "_select.dir()" } }, providers: [provideBrnSelectContent(BrnSelectContentComponent)], queries: [{ propertyName: "scrollUpBtn", first: true, predicate: BrnSelectScrollUpDirective, descendants: true, isSignal: true }, { propertyName: "scrollDownBtn", first: true, predicate: BrnSelectScrollDownDirective, descendants: true, isSignal: true }, { propertyName: "_options", predicate: BrnSelectOptionDirective, descendants: true, isSignal: true }], viewQueries: [{ propertyName: "viewport", first: true, predicate: ["viewport"], descendants: true, isSignal: true }], ngImport: i0, template: `
|
|
411
242
|
<ng-template #scrollUp>
|
|
412
243
|
<ng-content select="hlm-select-scroll-up" />
|
|
413
244
|
<ng-content select="brnSelectScrollUp" />
|
|
@@ -436,11 +267,20 @@ class BrnSelectContentComponent {
|
|
|
436
267
|
}
|
|
437
268
|
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "18.2.5", ngImport: i0, type: BrnSelectContentComponent, decorators: [{
|
|
438
269
|
type: Component,
|
|
439
|
-
args: [{ selector: 'brn-select-content, hlm-select-content:not(noHlm)',
|
|
440
|
-
|
|
441
|
-
|
|
442
|
-
'[
|
|
443
|
-
'[attr.
|
|
270
|
+
args: [{ standalone: true, selector: 'brn-select-content, hlm-select-content:not(noHlm)', imports: [NgTemplateOutlet], providers: [provideBrnSelectContent(BrnSelectContentComponent)], changeDetection: ChangeDetectionStrategy.OnPush, host: {
|
|
271
|
+
role: 'listbox',
|
|
272
|
+
tabindex: '0',
|
|
273
|
+
'[attr.aria-multiselectable]': '_select.multiple()',
|
|
274
|
+
'[attr.aria-disabled]': '_select.disabled() || _select._formDisabled()',
|
|
275
|
+
'aria-orientation': 'vertical',
|
|
276
|
+
'[attr.aria-activedescendant]': 'keyManager?.activeItem?.id()',
|
|
277
|
+
'[attr.aria-labelledBy]': '_select.labelId()',
|
|
278
|
+
'[attr.aria-controlledBy]': "_select.id() +'--trigger'",
|
|
279
|
+
'[id]': "_select.id() + '--content'",
|
|
280
|
+
'[attr.dir]': '_select.dir()',
|
|
281
|
+
'(keydown)': 'keyManager?.onKeydown($event)',
|
|
282
|
+
'(keydown.enter)': 'selectActiveItem($event)',
|
|
283
|
+
'(keydown.space)': 'selectActiveItem($event)',
|
|
444
284
|
}, template: `
|
|
445
285
|
<ng-template #scrollUp>
|
|
446
286
|
<ng-content select="hlm-select-scroll-up" />
|
|
@@ -493,7 +333,7 @@ class BrnSelectLabelDirective {
|
|
|
493
333
|
this._group?.labelledBy.set(this._label.id());
|
|
494
334
|
}
|
|
495
335
|
/** @nocollapse */ static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "18.2.5", ngImport: i0, type: BrnSelectLabelDirective, deps: [], target: i0.ɵɵFactoryTarget.Directive });
|
|
496
|
-
/** @nocollapse */ static ɵdir = i0.ɵɵngDeclareDirective({ minVersion: "14.0.0", version: "18.2.5", type: BrnSelectLabelDirective, isStandalone: true, selector: "[brnSelectLabel]", hostDirectives: [{ directive: i1
|
|
336
|
+
/** @nocollapse */ static ɵdir = i0.ɵɵngDeclareDirective({ minVersion: "14.0.0", version: "18.2.5", type: BrnSelectLabelDirective, isStandalone: true, selector: "[brnSelectLabel]", hostDirectives: [{ directive: i1.BrnLabelDirective }], ngImport: i0 });
|
|
497
337
|
}
|
|
498
338
|
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "18.2.5", ngImport: i0, type: BrnSelectLabelDirective, decorators: [{
|
|
499
339
|
type: Directive,
|
|
@@ -504,71 +344,195 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "18.2.5", ngImpor
|
|
|
504
344
|
}]
|
|
505
345
|
}], ctorParameters: () => [] });
|
|
506
346
|
|
|
507
|
-
class
|
|
508
|
-
|
|
509
|
-
|
|
510
|
-
|
|
511
|
-
|
|
512
|
-
|
|
347
|
+
class BrnSelectPlaceholderDirective {
|
|
348
|
+
/** @internale */
|
|
349
|
+
templateRef = inject(TemplateRef);
|
|
350
|
+
/** @nocollapse */ static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "18.2.5", ngImport: i0, type: BrnSelectPlaceholderDirective, deps: [], target: i0.ɵɵFactoryTarget.Directive });
|
|
351
|
+
/** @nocollapse */ static ɵdir = i0.ɵɵngDeclareDirective({ minVersion: "14.0.0", version: "18.2.5", type: BrnSelectPlaceholderDirective, isStandalone: true, selector: "[brnSelectPlaceholder], [hlmSelectPlaceholder]", ngImport: i0 });
|
|
352
|
+
}
|
|
353
|
+
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "18.2.5", ngImport: i0, type: BrnSelectPlaceholderDirective, decorators: [{
|
|
354
|
+
type: Directive,
|
|
355
|
+
args: [{
|
|
356
|
+
standalone: true,
|
|
357
|
+
selector: '[brnSelectPlaceholder], [hlmSelectPlaceholder]',
|
|
358
|
+
}]
|
|
359
|
+
}] });
|
|
360
|
+
|
|
361
|
+
class BrnSelectTriggerDirective {
|
|
362
|
+
_elementRef = inject(ElementRef);
|
|
363
|
+
_select = injectBrnSelect();
|
|
364
|
+
_ngControl = inject(NgControl, { optional: true });
|
|
365
|
+
_platform = inject(PLATFORM_ID);
|
|
366
|
+
_triggerId = computed(() => `${this._select.id()}--trigger`);
|
|
367
|
+
_contentId = computed(() => `${this._select.id()}--content`);
|
|
368
|
+
_disabled = computed(() => this._select.disabled() || this._select._formDisabled());
|
|
369
|
+
_labelledBy = computed(() => {
|
|
370
|
+
const value = this._select.value();
|
|
371
|
+
if (Array.isArray(value) && value.length > 0) {
|
|
372
|
+
return `${this._select.labelId()} ${this._select.id()}--value`;
|
|
373
|
+
}
|
|
374
|
+
return this._select.labelId();
|
|
375
|
+
});
|
|
376
|
+
_resizeObserver;
|
|
513
377
|
constructor() {
|
|
514
|
-
|
|
515
|
-
|
|
516
|
-
|
|
517
|
-
|
|
518
|
-
|
|
519
|
-
|
|
520
|
-
.
|
|
521
|
-
|
|
522
|
-
|
|
523
|
-
cdr.detectChanges();
|
|
524
|
-
return;
|
|
525
|
-
}
|
|
526
|
-
const selectedLabels = value.map((selectedOption) => selectedOption?.getLabel());
|
|
527
|
-
if (this._selectService.dir() === 'rtl') {
|
|
528
|
-
selectedLabels.reverse();
|
|
529
|
-
}
|
|
530
|
-
const result = this.transformFn()(selectedLabels);
|
|
531
|
-
this.value = result;
|
|
532
|
-
cdr.detectChanges();
|
|
533
|
-
});
|
|
378
|
+
this._select.trigger.set(this);
|
|
379
|
+
}
|
|
380
|
+
ngAfterViewInit() {
|
|
381
|
+
this._select.triggerWidth.set(this._elementRef.nativeElement.offsetWidth);
|
|
382
|
+
// if we are on the client, listen for element resize events
|
|
383
|
+
if (isPlatformBrowser(this._platform)) {
|
|
384
|
+
this._resizeObserver = new ResizeObserver(() => this._select.triggerWidth.set(this._elementRef.nativeElement.offsetWidth));
|
|
385
|
+
this._resizeObserver.observe(this._elementRef.nativeElement);
|
|
386
|
+
}
|
|
534
387
|
}
|
|
388
|
+
ngOnDestroy() {
|
|
389
|
+
this._resizeObserver?.disconnect();
|
|
390
|
+
}
|
|
391
|
+
focus() {
|
|
392
|
+
this._elementRef.nativeElement.focus();
|
|
393
|
+
}
|
|
394
|
+
/** @nocollapse */ static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "18.2.5", ngImport: i0, type: BrnSelectTriggerDirective, deps: [], target: i0.ɵɵFactoryTarget.Directive });
|
|
395
|
+
/** @nocollapse */ static ɵdir = i0.ɵɵngDeclareDirective({ minVersion: "14.0.0", version: "18.2.5", type: BrnSelectTriggerDirective, isStandalone: true, selector: "[brnSelectTrigger]", host: { attributes: { "type": "button", "role": "combobox", "aria-autocomplete": "none" }, listeners: { "keydown.ArrowDown": "_select.show()" }, properties: { "attr.id": "_triggerId()", "disabled": "_disabled()", "attr.aria-expanded": "_select.open()", "attr.aria-controls": "_contentId()", "attr.aria-labelledBy": "_labelledBy()", "attr.dir": "_select.dir()", "class.ng-invalid": "_ngControl?.invalid || null", "class.ng-dirty": "_ngControl?.dirty || null", "class.ng-valid": "_ngControl?.valid || null", "class.ng-touched": "_ngControl?.touched || null", "class.ng-untouched": "_ngControl?.untouched || null", "class.ng-pristine": "_ngControl?.pristine || null" } }, ngImport: i0 });
|
|
396
|
+
}
|
|
397
|
+
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "18.2.5", ngImport: i0, type: BrnSelectTriggerDirective, decorators: [{
|
|
398
|
+
type: Directive,
|
|
399
|
+
args: [{
|
|
400
|
+
selector: '[brnSelectTrigger]',
|
|
401
|
+
standalone: true,
|
|
402
|
+
host: {
|
|
403
|
+
type: 'button',
|
|
404
|
+
role: 'combobox',
|
|
405
|
+
'[attr.id]': '_triggerId()',
|
|
406
|
+
'[disabled]': '_disabled()',
|
|
407
|
+
'[attr.aria-expanded]': '_select.open()',
|
|
408
|
+
'[attr.aria-controls]': '_contentId()',
|
|
409
|
+
'[attr.aria-labelledBy]': '_labelledBy()',
|
|
410
|
+
'aria-autocomplete': 'none',
|
|
411
|
+
'[attr.dir]': '_select.dir()',
|
|
412
|
+
'[class.ng-invalid]': '_ngControl?.invalid || null',
|
|
413
|
+
'[class.ng-dirty]': '_ngControl?.dirty || null',
|
|
414
|
+
'[class.ng-valid]': '_ngControl?.valid || null',
|
|
415
|
+
'[class.ng-touched]': '_ngControl?.touched || null',
|
|
416
|
+
'[class.ng-untouched]': '_ngControl?.untouched || null',
|
|
417
|
+
'[class.ng-pristine]': '_ngControl?.pristine || null',
|
|
418
|
+
'(keydown.ArrowDown)': '_select.show()',
|
|
419
|
+
},
|
|
420
|
+
}]
|
|
421
|
+
}], ctorParameters: () => [] });
|
|
422
|
+
|
|
423
|
+
class BrnSelectValueDirective {
|
|
424
|
+
/** @internale */
|
|
425
|
+
templateRef = inject(TemplateRef);
|
|
426
|
+
/** @nocollapse */ static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "18.2.5", ngImport: i0, type: BrnSelectValueDirective, deps: [], target: i0.ɵɵFactoryTarget.Directive });
|
|
427
|
+
/** @nocollapse */ static ɵdir = i0.ɵɵngDeclareDirective({ minVersion: "14.0.0", version: "18.2.5", type: BrnSelectValueDirective, isStandalone: true, selector: "[brnSelectValue], [hlmSelectValue]", ngImport: i0 });
|
|
428
|
+
}
|
|
429
|
+
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "18.2.5", ngImport: i0, type: BrnSelectValueDirective, decorators: [{
|
|
430
|
+
type: Directive,
|
|
431
|
+
args: [{
|
|
432
|
+
standalone: true,
|
|
433
|
+
selector: '[brnSelectValue], [hlmSelectValue]',
|
|
434
|
+
}]
|
|
435
|
+
}] });
|
|
436
|
+
|
|
437
|
+
class BrnSelectValueComponent {
|
|
438
|
+
_select = injectBrnSelect();
|
|
439
|
+
id = computed(() => `${this._select.id()}--value`);
|
|
440
|
+
placeholder = computed(() => this._select.placeholder());
|
|
441
|
+
_showPlaceholder = computed(() => this.value() === null || this.value() === undefined || this.value() === '');
|
|
442
|
+
/** Allow a custom value template */
|
|
443
|
+
customValueTemplate = contentChild(BrnSelectValueDirective, { descendants: true });
|
|
444
|
+
customPlaceholderTemplate = contentChild(BrnSelectPlaceholderDirective, { descendants: true });
|
|
445
|
+
value = computed(() => {
|
|
446
|
+
const value = this._values();
|
|
447
|
+
if (value.length === 0) {
|
|
448
|
+
return null;
|
|
449
|
+
}
|
|
450
|
+
// remove any selected values that are not in the options list
|
|
451
|
+
const existingOptions = value.filter((val) => this._select.options().some((option) => option.value() === val));
|
|
452
|
+
const selectedOption = existingOptions.map((val) => this._select.options().find((option) => option.value() === val));
|
|
453
|
+
if (selectedOption.length === 0) {
|
|
454
|
+
return null;
|
|
455
|
+
}
|
|
456
|
+
const selectedLabels = selectedOption.map((option) => option?.getLabel());
|
|
457
|
+
if (this._select.dir() === 'rtl') {
|
|
458
|
+
selectedLabels.reverse();
|
|
459
|
+
}
|
|
460
|
+
return this.transformFn()(selectedLabels);
|
|
461
|
+
});
|
|
462
|
+
/** Normalize the values as an array */
|
|
463
|
+
_values = computed(() => Array.isArray(this._select.value()) ? this._select.value() : [this._select.value()]);
|
|
464
|
+
transformFn = input((values) => (values ?? []).join(', '));
|
|
535
465
|
/** @nocollapse */ static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "18.2.5", ngImport: i0, type: BrnSelectValueComponent, deps: [], target: i0.ɵɵFactoryTarget.Component });
|
|
536
|
-
/** @nocollapse */ static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.
|
|
537
|
-
|
|
538
|
-
|
|
466
|
+
/** @nocollapse */ static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "18.2.5", type: BrnSelectValueComponent, isStandalone: true, selector: "brn-select-value, hlm-select-value", inputs: { transformFn: { classPropertyName: "transformFn", publicName: "transformFn", isSignal: true, isRequired: false, transformFunction: null } }, host: { properties: { "id": "id()" } }, queries: [{ propertyName: "customValueTemplate", first: true, predicate: BrnSelectValueDirective, descendants: true, isSignal: true }, { propertyName: "customPlaceholderTemplate", first: true, predicate: BrnSelectPlaceholderDirective, descendants: true, isSignal: true }], ngImport: i0, template: `
|
|
467
|
+
@if (_showPlaceholder()) {
|
|
468
|
+
<ng-container [ngTemplateOutlet]="customPlaceholderTemplate()?.templateRef ?? defaultPlaceholderTemplate" />
|
|
469
|
+
} @else {
|
|
470
|
+
<ng-container
|
|
471
|
+
[ngTemplateOutlet]="customValueTemplate()?.templateRef ?? defaultValueTemplate"
|
|
472
|
+
[ngTemplateOutletContext]="{ $implicit: _select.value() }"
|
|
473
|
+
/>
|
|
474
|
+
}
|
|
475
|
+
|
|
476
|
+
<ng-template #defaultValueTemplate>{{ value() }}</ng-template>
|
|
477
|
+
<ng-template #defaultPlaceholderTemplate>{{ placeholder() }}</ng-template>
|
|
478
|
+
`, isInline: true, styles: [":host{display:-webkit-box;-webkit-box-orient:vertical;-webkit-line-clamp:1;white-space:nowrap;pointer-events:none}\n"], dependencies: [{ kind: "directive", type: NgTemplateOutlet, selector: "[ngTemplateOutlet]", inputs: ["ngTemplateOutletContext", "ngTemplateOutlet", "ngTemplateOutletInjector"] }], changeDetection: i0.ChangeDetectionStrategy.OnPush });
|
|
539
479
|
}
|
|
540
480
|
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "18.2.5", ngImport: i0, type: BrnSelectValueComponent, decorators: [{
|
|
541
481
|
type: Component,
|
|
542
|
-
args: [{ selector: 'brn-select-value, hlm-select-value', template: `
|
|
543
|
-
|
|
482
|
+
args: [{ selector: 'brn-select-value, hlm-select-value', imports: [NgTemplateOutlet], template: `
|
|
483
|
+
@if (_showPlaceholder()) {
|
|
484
|
+
<ng-container [ngTemplateOutlet]="customPlaceholderTemplate()?.templateRef ?? defaultPlaceholderTemplate" />
|
|
485
|
+
} @else {
|
|
486
|
+
<ng-container
|
|
487
|
+
[ngTemplateOutlet]="customValueTemplate()?.templateRef ?? defaultValueTemplate"
|
|
488
|
+
[ngTemplateOutletContext]="{ $implicit: _select.value() }"
|
|
489
|
+
/>
|
|
490
|
+
}
|
|
491
|
+
|
|
492
|
+
<ng-template #defaultValueTemplate>{{ value() }}</ng-template>
|
|
493
|
+
<ng-template #defaultPlaceholderTemplate>{{ placeholder() }}</ng-template>
|
|
544
494
|
`, host: {
|
|
545
495
|
'[id]': 'id()',
|
|
546
496
|
}, standalone: true, changeDetection: ChangeDetectionStrategy.OnPush, styles: [":host{display:-webkit-box;-webkit-box-orient:vertical;-webkit-line-clamp:1;white-space:nowrap;pointer-events:none}\n"] }]
|
|
547
|
-
}]
|
|
497
|
+
}] });
|
|
548
498
|
|
|
549
499
|
let nextId = 0;
|
|
550
500
|
class BrnSelectComponent {
|
|
551
|
-
|
|
552
|
-
|
|
553
|
-
|
|
501
|
+
_defaultErrorStateMatcher = inject(ErrorStateMatcher);
|
|
502
|
+
_parentForm = inject(NgForm, { optional: true });
|
|
503
|
+
_injector = inject(Injector);
|
|
504
|
+
_parentFormGroup = inject(FormGroupDirective, { optional: true });
|
|
505
|
+
ngControl = inject(NgControl, { optional: true, self: true });
|
|
506
|
+
id = input(`brn-select-${nextId++}`);
|
|
507
|
+
multiple = input(false, {
|
|
508
|
+
transform: booleanAttribute,
|
|
509
|
+
});
|
|
554
510
|
placeholder = input('');
|
|
555
|
-
disabled = input(false
|
|
511
|
+
disabled = input(false, {
|
|
512
|
+
transform: booleanAttribute,
|
|
513
|
+
});
|
|
556
514
|
dir = input('ltr');
|
|
557
|
-
|
|
515
|
+
closeDelay = input(100, {
|
|
516
|
+
transform: numberAttribute,
|
|
517
|
+
});
|
|
518
|
+
open = model(false);
|
|
519
|
+
value = model();
|
|
520
|
+
compareWith = input((o1, o2) => o1 === o2);
|
|
521
|
+
_formDisabled = signal(false);
|
|
522
|
+
/** Label provided by the consumer. */
|
|
558
523
|
selectLabel = contentChild(BrnLabelDirective, { descendants: false });
|
|
559
524
|
/** Overlay pane containing the options. */
|
|
560
525
|
selectContent = contentChild.required(BrnSelectContentComponent);
|
|
561
|
-
|
|
562
|
-
options
|
|
563
|
-
|
|
526
|
+
/** @internal */
|
|
527
|
+
options = contentChildren(BrnSelectOptionDirective, { descendants: true });
|
|
528
|
+
/** @internal Derive the selected options to filter out the unselected options */
|
|
529
|
+
selectedOptions = computed(() => this.options().filter((option) => option.selected()));
|
|
564
530
|
/** Overlay pane containing the options. */
|
|
565
|
-
_overlayDir = viewChild(CdkConnectedOverlay);
|
|
566
|
-
|
|
567
|
-
|
|
568
|
-
_delayedExpanded = toSignal(toObservable(this.
|
|
569
|
-
state = computed(() => (this.
|
|
570
|
-
openedChange = output();
|
|
571
|
-
valueChange = output();
|
|
531
|
+
_overlayDir = viewChild.required(CdkConnectedOverlay);
|
|
532
|
+
trigger = signal(null);
|
|
533
|
+
triggerWidth = signal(0);
|
|
534
|
+
_delayedExpanded = toSignal(toObservable(this.open).pipe(switchMap((expanded) => (!expanded ? of(expanded).pipe(delay(this.closeDelay())) : of(expanded))), takeUntilDestroyed()), { initialValue: false });
|
|
535
|
+
state = computed(() => (this.open() ? 'open' : 'closed'));
|
|
572
536
|
_positionChanges$ = new Subject();
|
|
573
537
|
side = toSignal(this._positionChanges$.pipe(map((change) =>
|
|
574
538
|
// todo: better translation or adjusting hlm to take that into account
|
|
@@ -577,14 +541,11 @@ class BrnSelectComponent {
|
|
|
577
541
|
? 'left'
|
|
578
542
|
: 'right'
|
|
579
543
|
: change.connectionPair.originY)), { initialValue: 'bottom' });
|
|
580
|
-
|
|
581
|
-
labelProvided = signal(false);
|
|
582
|
-
ngControl = inject(NgControl, { optional: true, self: true });
|
|
544
|
+
labelId = computed(() => this.selectLabel()?.id ?? `${this.id()}--label`);
|
|
583
545
|
// eslint-disable-next-line @typescript-eslint/no-empty-function
|
|
584
546
|
_onChange = () => { };
|
|
585
547
|
// eslint-disable-next-line @typescript-eslint/no-empty-function
|
|
586
548
|
_onTouched = () => { };
|
|
587
|
-
_shouldEmitValueChange = signal(false);
|
|
588
549
|
/*
|
|
589
550
|
* This position config ensures that the top "start" corner of the overlay
|
|
590
551
|
* is aligned with with the top "start" of the origin by default (overlapping
|
|
@@ -618,113 +579,41 @@ class BrnSelectComponent {
|
|
|
618
579
|
},
|
|
619
580
|
];
|
|
620
581
|
errorStateTracker;
|
|
621
|
-
_defaultErrorStateMatcher = inject(ErrorStateMatcher);
|
|
622
|
-
_parentForm = inject(NgForm, { optional: true });
|
|
623
|
-
_parentFormGroup = inject(FormGroupDirective, { optional: true });
|
|
624
582
|
errorState = computed(() => this.errorStateTracker.errorState());
|
|
625
|
-
writeValue$ = new Subject();
|
|
626
583
|
constructor() {
|
|
627
|
-
this._selectService.state.update((state) => ({
|
|
628
|
-
...state,
|
|
629
|
-
multiple: this.multiple,
|
|
630
|
-
placeholder: this.placeholder,
|
|
631
|
-
disabled: this.disabled,
|
|
632
|
-
disabledBySetDisabled: this._disabledFromSetDisabledState,
|
|
633
|
-
dir: this.dir,
|
|
634
|
-
}));
|
|
635
|
-
this.handleOptionChanges();
|
|
636
|
-
this.handleInitialOptionSelect();
|
|
637
|
-
this._selectService.state.update((state) => ({
|
|
638
|
-
...state,
|
|
639
|
-
id: `brn-select-${nextId++}`,
|
|
640
|
-
}));
|
|
641
584
|
if (this.ngControl !== null) {
|
|
642
585
|
this.ngControl.valueAccessor = this;
|
|
643
586
|
}
|
|
644
|
-
// Watch for Listbox Selection Changes to trigger Collapse and Value Change
|
|
645
|
-
this._selectService.listBoxValueChangeEvent$.pipe(takeUntilDestroyed()).subscribe(() => {
|
|
646
|
-
if (!this.multiple()) {
|
|
647
|
-
this.close();
|
|
648
|
-
}
|
|
649
|
-
// we set shouldEmitValueChange to true because we want to propagate the value change
|
|
650
|
-
// as a result of user interaction
|
|
651
|
-
this._shouldEmitValueChange.set(true);
|
|
652
|
-
});
|
|
653
|
-
/**
|
|
654
|
-
* Listening to value changes in order to trigger forms api on change
|
|
655
|
-
* ShouldEmitValueChange simply ensures we only propagate value change when a user makes a selection
|
|
656
|
-
* we don't propagate changes made from outside the component (ex. patch value or initial value from form control)
|
|
657
|
-
*/
|
|
658
|
-
toObservable(this._selectService.value).subscribe((value) => {
|
|
659
|
-
if (this._shouldEmitValueChange()) {
|
|
660
|
-
this._onChange((value ?? null));
|
|
661
|
-
this.valueChange.emit((value ?? null));
|
|
662
|
-
}
|
|
663
|
-
this._shouldEmitValueChange.set(true);
|
|
664
|
-
});
|
|
665
587
|
this.errorStateTracker = new ErrorStateTracker(this._defaultErrorStateMatcher, this.ngControl, this._parentFormGroup, this._parentForm);
|
|
666
588
|
}
|
|
667
|
-
ngAfterContentInit() {
|
|
668
|
-
// Check if Label Directive Provided and pass to service
|
|
669
|
-
const label = this.selectLabel();
|
|
670
|
-
if (label) {
|
|
671
|
-
this.labelProvided.set(true);
|
|
672
|
-
this._selectService.state.update((state) => ({
|
|
673
|
-
...state,
|
|
674
|
-
labelId: label.id(),
|
|
675
|
-
}));
|
|
676
|
-
}
|
|
677
|
-
else if (this.placeholder()) {
|
|
678
|
-
this._selectService.state.update((state) => ({
|
|
679
|
-
...state,
|
|
680
|
-
labelId: `${state.id}--label`,
|
|
681
|
-
}));
|
|
682
|
-
}
|
|
683
|
-
}
|
|
684
589
|
ngDoCheck() {
|
|
685
590
|
this.errorStateTracker.updateErrorState();
|
|
686
591
|
}
|
|
687
592
|
toggle() {
|
|
688
|
-
if (this.
|
|
689
|
-
this.
|
|
593
|
+
if (this.open()) {
|
|
594
|
+
this.hide();
|
|
690
595
|
}
|
|
691
596
|
else {
|
|
692
|
-
this.
|
|
597
|
+
this.show();
|
|
693
598
|
}
|
|
694
599
|
}
|
|
695
|
-
|
|
696
|
-
if (
|
|
600
|
+
show() {
|
|
601
|
+
if (this.open() || this.disabled() || this._formDisabled() || this.options()?.length == 0) {
|
|
697
602
|
return;
|
|
698
|
-
this._selectService.state.update((state) => ({
|
|
699
|
-
...state,
|
|
700
|
-
isExpanded: true,
|
|
701
|
-
}));
|
|
702
|
-
this.openedChange.emit(true);
|
|
703
|
-
this._moveFocusToCDKList();
|
|
704
|
-
}
|
|
705
|
-
close() {
|
|
706
|
-
if (!this.isExpanded())
|
|
707
|
-
return;
|
|
708
|
-
if (this._selectService.selectTrigger) {
|
|
709
|
-
this._selectService.selectTrigger.focus();
|
|
710
603
|
}
|
|
711
|
-
this.
|
|
712
|
-
|
|
713
|
-
...state,
|
|
714
|
-
isExpanded: false,
|
|
715
|
-
}));
|
|
716
|
-
this._onTouched();
|
|
717
|
-
}
|
|
718
|
-
_canOpen() {
|
|
719
|
-
return !this.isExpanded() && !this.disabled() && this.options()?.length > 0;
|
|
604
|
+
this.open.set(true);
|
|
605
|
+
afterNextRender(() => this.selectContent().focusList(), { injector: this._injector });
|
|
720
606
|
}
|
|
721
|
-
|
|
722
|
-
|
|
723
|
-
|
|
724
|
-
|
|
607
|
+
hide() {
|
|
608
|
+
if (!this.open())
|
|
609
|
+
return;
|
|
610
|
+
this.open.set(false);
|
|
611
|
+
this._onTouched();
|
|
612
|
+
// restore focus to the trigger
|
|
613
|
+
this.trigger()?.focus();
|
|
725
614
|
}
|
|
726
615
|
writeValue(value) {
|
|
727
|
-
this.
|
|
616
|
+
this.value.set(value);
|
|
728
617
|
}
|
|
729
618
|
registerOnChange(fn) {
|
|
730
619
|
this._onChange = fn;
|
|
@@ -733,80 +622,65 @@ class BrnSelectComponent {
|
|
|
733
622
|
this._onTouched = fn;
|
|
734
623
|
}
|
|
735
624
|
setDisabledState(isDisabled) {
|
|
736
|
-
this.
|
|
625
|
+
this._formDisabled.set(isDisabled);
|
|
737
626
|
}
|
|
738
|
-
|
|
739
|
-
|
|
740
|
-
|
|
741
|
-
|
|
742
|
-
|
|
743
|
-
|
|
744
|
-
|
|
745
|
-
|
|
746
|
-
.
|
|
747
|
-
|
|
748
|
-
|
|
749
|
-
|
|
750
|
-
|
|
751
|
-
|
|
752
|
-
|
|
753
|
-
}
|
|
754
|
-
});
|
|
627
|
+
selectOption(value) {
|
|
628
|
+
// if this is a multiple select we need to add the value to the array
|
|
629
|
+
if (this.multiple()) {
|
|
630
|
+
const currentValue = this.value();
|
|
631
|
+
const newValue = currentValue ? [...currentValue, value] : [value];
|
|
632
|
+
this.value.set(newValue);
|
|
633
|
+
}
|
|
634
|
+
else {
|
|
635
|
+
this.value.set(value);
|
|
636
|
+
}
|
|
637
|
+
this._onChange?.(this.value());
|
|
638
|
+
// if this is single select close the dropdown
|
|
639
|
+
if (!this.multiple()) {
|
|
640
|
+
this.hide();
|
|
641
|
+
}
|
|
755
642
|
}
|
|
756
|
-
|
|
757
|
-
|
|
758
|
-
|
|
759
|
-
|
|
760
|
-
|
|
761
|
-
|
|
762
|
-
|
|
763
|
-
|
|
764
|
-
|
|
765
|
-
|
|
766
|
-
this._selectService.updatePossibleOptions(options);
|
|
767
|
-
});
|
|
643
|
+
deselectOption(value) {
|
|
644
|
+
if (this.multiple()) {
|
|
645
|
+
const currentValue = this.value();
|
|
646
|
+
const newValue = currentValue.filter((val) => val !== value);
|
|
647
|
+
this.value.set(newValue);
|
|
648
|
+
}
|
|
649
|
+
else {
|
|
650
|
+
this.value.set(null);
|
|
651
|
+
}
|
|
652
|
+
this._onChange?.(this.value());
|
|
768
653
|
}
|
|
769
|
-
|
|
770
|
-
|
|
771
|
-
|
|
772
|
-
handleInvalidOptions(options) {
|
|
773
|
-
const selectedOptions = this._selectService.selectedOptions();
|
|
774
|
-
const availableOptionSet = new Set(options);
|
|
775
|
-
if (this._selectService.multiple()) {
|
|
776
|
-
const filteredOptions = selectedOptions.filter((o) => availableOptionSet.has(o));
|
|
777
|
-
if (selectedOptions.length !== filteredOptions.length) {
|
|
778
|
-
const value = filteredOptions.map((o) => o?.value ?? '');
|
|
779
|
-
this._selectService.state.update((state) => ({
|
|
780
|
-
...state,
|
|
781
|
-
selectedOptions: filteredOptions,
|
|
782
|
-
value: value,
|
|
783
|
-
}));
|
|
784
|
-
}
|
|
654
|
+
toggleSelect(value) {
|
|
655
|
+
if (this.isSelected(value)) {
|
|
656
|
+
this.deselectOption(value);
|
|
785
657
|
}
|
|
786
658
|
else {
|
|
787
|
-
|
|
788
|
-
|
|
789
|
-
|
|
790
|
-
|
|
791
|
-
|
|
792
|
-
|
|
793
|
-
|
|
794
|
-
}
|
|
659
|
+
this.selectOption(value);
|
|
660
|
+
}
|
|
661
|
+
}
|
|
662
|
+
isSelected(value) {
|
|
663
|
+
const selection = this.value();
|
|
664
|
+
if (Array.isArray(selection)) {
|
|
665
|
+
return selection.some((val) => this.compareWith()(val, value));
|
|
795
666
|
}
|
|
667
|
+
else if (value !== undefined) {
|
|
668
|
+
return this.compareWith()(selection, value);
|
|
669
|
+
}
|
|
670
|
+
return false;
|
|
796
671
|
}
|
|
797
672
|
/** @nocollapse */ static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "18.2.5", ngImport: i0, type: BrnSelectComponent, deps: [], target: i0.ɵɵFactoryTarget.Component });
|
|
798
|
-
/** @nocollapse */ static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "18.2.5", type: BrnSelectComponent, isStandalone: true, selector: "brn-select, hlm-select", inputs: { multiple: { classPropertyName: "multiple", publicName: "multiple", isSignal: true, isRequired: false, transformFunction: null }, placeholder: { classPropertyName: "placeholder", publicName: "placeholder", isSignal: true, isRequired: false, transformFunction: null }, disabled: { classPropertyName: "disabled", publicName: "disabled", isSignal: true, isRequired: false, transformFunction: null }, dir: { classPropertyName: "dir", publicName: "dir", isSignal: true, isRequired: false, transformFunction: null }, closeDelay: { classPropertyName: "closeDelay", publicName: "closeDelay", isSignal: true, isRequired: false, transformFunction: null } }, outputs: {
|
|
799
|
-
BrnSelectService,
|
|
800
|
-
CdkListbox,
|
|
673
|
+
/** @nocollapse */ static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "18.2.5", type: BrnSelectComponent, isStandalone: true, selector: "brn-select, hlm-select", inputs: { id: { classPropertyName: "id", publicName: "id", isSignal: true, isRequired: false, transformFunction: null }, multiple: { classPropertyName: "multiple", publicName: "multiple", isSignal: true, isRequired: false, transformFunction: null }, placeholder: { classPropertyName: "placeholder", publicName: "placeholder", isSignal: true, isRequired: false, transformFunction: null }, disabled: { classPropertyName: "disabled", publicName: "disabled", isSignal: true, isRequired: false, transformFunction: null }, dir: { classPropertyName: "dir", publicName: "dir", isSignal: true, isRequired: false, transformFunction: null }, closeDelay: { classPropertyName: "closeDelay", publicName: "closeDelay", isSignal: true, isRequired: false, transformFunction: null }, open: { classPropertyName: "open", publicName: "open", isSignal: true, isRequired: false, transformFunction: null }, value: { classPropertyName: "value", publicName: "value", isSignal: true, isRequired: false, transformFunction: null }, compareWith: { classPropertyName: "compareWith", publicName: "compareWith", isSignal: true, isRequired: false, transformFunction: null } }, outputs: { open: "openChange", value: "valueChange" }, providers: [
|
|
801
674
|
provideExposedSideProviderExisting((() => BrnSelectComponent)),
|
|
802
675
|
provideExposesStateProviderExisting((() => BrnSelectComponent)),
|
|
676
|
+
provideBrnSelect(BrnSelectComponent),
|
|
803
677
|
{
|
|
804
678
|
provide: BrnFormFieldControl,
|
|
805
679
|
useExisting: BrnSelectComponent,
|
|
806
680
|
},
|
|
807
|
-
], queries: [{ propertyName: "selectLabel", first: true, predicate: BrnLabelDirective, isSignal: true }, { propertyName: "selectContent", first: true, predicate: BrnSelectContentComponent, descendants: true, isSignal: true }, { propertyName: "options", predicate:
|
|
808
|
-
@if (!
|
|
809
|
-
<label class="hidden" [attr.id]="
|
|
681
|
+
], queries: [{ propertyName: "selectLabel", first: true, predicate: BrnLabelDirective, isSignal: true }, { propertyName: "selectContent", first: true, predicate: BrnSelectContentComponent, descendants: true, isSignal: true }, { propertyName: "options", predicate: BrnSelectOptionDirective, descendants: true, isSignal: true }], viewQueries: [{ propertyName: "_overlayDir", first: true, predicate: CdkConnectedOverlay, descendants: true, isSignal: true }], ngImport: i0, template: `
|
|
682
|
+
@if (!selectLabel() && placeholder()) {
|
|
683
|
+
<label class="hidden" [attr.id]="labelId()">{{ placeholder() }}</label>
|
|
810
684
|
} @else {
|
|
811
685
|
<ng-content select="label[hlmLabel],label[brnLabel]" />
|
|
812
686
|
}
|
|
@@ -814,6 +688,7 @@ class BrnSelectComponent {
|
|
|
814
688
|
<div cdk-overlay-origin (click)="toggle()" #trigger="cdkOverlayOrigin">
|
|
815
689
|
<ng-content select="hlm-select-trigger,[brnSelectTrigger]" />
|
|
816
690
|
</div>
|
|
691
|
+
|
|
817
692
|
<ng-template
|
|
818
693
|
cdk-connected-overlay
|
|
819
694
|
cdkConnectedOverlayLockPosition
|
|
@@ -823,13 +698,13 @@ class BrnSelectComponent {
|
|
|
823
698
|
[cdkConnectedOverlayOpen]="_delayedExpanded()"
|
|
824
699
|
[cdkConnectedOverlayPositions]="_positions"
|
|
825
700
|
[cdkConnectedOverlayWidth]="triggerWidth() > 0 ? triggerWidth() : 'auto'"
|
|
826
|
-
(backdropClick)="
|
|
827
|
-
(detach)="
|
|
701
|
+
(backdropClick)="hide()"
|
|
702
|
+
(detach)="hide()"
|
|
828
703
|
(positionChange)="_positionChanges$.next($event)"
|
|
829
704
|
>
|
|
830
705
|
<ng-content />
|
|
831
706
|
</ng-template>
|
|
832
|
-
`, isInline: true, dependencies: [{ kind: "ngmodule", type: OverlayModule }, { kind: "directive", type: i1$
|
|
707
|
+
`, isInline: true, dependencies: [{ kind: "ngmodule", type: OverlayModule }, { kind: "directive", type: i1$1.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: i1$1.CdkOverlayOrigin, selector: "[cdk-overlay-origin], [overlay-origin], [cdkOverlayOrigin]", exportAs: ["cdkOverlayOrigin"] }, { kind: "ngmodule", type: CdkListboxModule }], changeDetection: i0.ChangeDetectionStrategy.OnPush });
|
|
833
708
|
}
|
|
834
709
|
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "18.2.5", ngImport: i0, type: BrnSelectComponent, decorators: [{
|
|
835
710
|
type: Component,
|
|
@@ -839,18 +714,17 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "18.2.5", ngImpor
|
|
|
839
714
|
imports: [OverlayModule, CdkListboxModule],
|
|
840
715
|
changeDetection: ChangeDetectionStrategy.OnPush,
|
|
841
716
|
providers: [
|
|
842
|
-
BrnSelectService,
|
|
843
|
-
CdkListbox,
|
|
844
717
|
provideExposedSideProviderExisting((() => BrnSelectComponent)),
|
|
845
718
|
provideExposesStateProviderExisting((() => BrnSelectComponent)),
|
|
719
|
+
provideBrnSelect(BrnSelectComponent),
|
|
846
720
|
{
|
|
847
721
|
provide: BrnFormFieldControl,
|
|
848
722
|
useExisting: BrnSelectComponent,
|
|
849
723
|
},
|
|
850
724
|
],
|
|
851
725
|
template: `
|
|
852
|
-
@if (!
|
|
853
|
-
<label class="hidden" [attr.id]="
|
|
726
|
+
@if (!selectLabel() && placeholder()) {
|
|
727
|
+
<label class="hidden" [attr.id]="labelId()">{{ placeholder() }}</label>
|
|
854
728
|
} @else {
|
|
855
729
|
<ng-content select="label[hlmLabel],label[brnLabel]" />
|
|
856
730
|
}
|
|
@@ -858,6 +732,7 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "18.2.5", ngImpor
|
|
|
858
732
|
<div cdk-overlay-origin (click)="toggle()" #trigger="cdkOverlayOrigin">
|
|
859
733
|
<ng-content select="hlm-select-trigger,[brnSelectTrigger]" />
|
|
860
734
|
</div>
|
|
735
|
+
|
|
861
736
|
<ng-template
|
|
862
737
|
cdk-connected-overlay
|
|
863
738
|
cdkConnectedOverlayLockPosition
|
|
@@ -867,8 +742,8 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "18.2.5", ngImpor
|
|
|
867
742
|
[cdkConnectedOverlayOpen]="_delayedExpanded()"
|
|
868
743
|
[cdkConnectedOverlayPositions]="_positions"
|
|
869
744
|
[cdkConnectedOverlayWidth]="triggerWidth() > 0 ? triggerWidth() : 'auto'"
|
|
870
|
-
(backdropClick)="
|
|
871
|
-
(detach)="
|
|
745
|
+
(backdropClick)="hide()"
|
|
746
|
+
(detach)="hide()"
|
|
872
747
|
(positionChange)="_positionChanges$.next($event)"
|
|
873
748
|
>
|
|
874
749
|
<ng-content />
|
|
@@ -887,6 +762,8 @@ const BrnSelectImports = [
|
|
|
887
762
|
BrnSelectScrollUpDirective,
|
|
888
763
|
BrnSelectGroupDirective,
|
|
889
764
|
BrnSelectLabelDirective,
|
|
765
|
+
BrnSelectValueDirective,
|
|
766
|
+
BrnSelectPlaceholderDirective,
|
|
890
767
|
];
|
|
891
768
|
class BrnSelectModule {
|
|
892
769
|
/** @nocollapse */ static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "18.2.5", ngImport: i0, type: BrnSelectModule, deps: [], target: i0.ɵɵFactoryTarget.NgModule });
|
|
@@ -898,7 +775,9 @@ class BrnSelectModule {
|
|
|
898
775
|
BrnSelectScrollDownDirective,
|
|
899
776
|
BrnSelectScrollUpDirective,
|
|
900
777
|
BrnSelectGroupDirective,
|
|
901
|
-
BrnSelectLabelDirective
|
|
778
|
+
BrnSelectLabelDirective,
|
|
779
|
+
BrnSelectValueDirective,
|
|
780
|
+
BrnSelectPlaceholderDirective], exports: [BrnSelectComponent,
|
|
902
781
|
BrnSelectContentComponent,
|
|
903
782
|
BrnSelectTriggerDirective,
|
|
904
783
|
BrnSelectOptionDirective,
|
|
@@ -906,7 +785,9 @@ class BrnSelectModule {
|
|
|
906
785
|
BrnSelectScrollDownDirective,
|
|
907
786
|
BrnSelectScrollUpDirective,
|
|
908
787
|
BrnSelectGroupDirective,
|
|
909
|
-
BrnSelectLabelDirective
|
|
788
|
+
BrnSelectLabelDirective,
|
|
789
|
+
BrnSelectValueDirective,
|
|
790
|
+
BrnSelectPlaceholderDirective] });
|
|
910
791
|
/** @nocollapse */ static ɵinj = i0.ɵɵngDeclareInjector({ minVersion: "12.0.0", version: "18.2.5", ngImport: i0, type: BrnSelectModule, imports: [BrnSelectComponent] });
|
|
911
792
|
}
|
|
912
793
|
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "18.2.5", ngImport: i0, type: BrnSelectModule, decorators: [{
|
|
@@ -921,5 +802,5 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "18.2.5", ngImpor
|
|
|
921
802
|
* Generated bundle index. Do not edit.
|
|
922
803
|
*/
|
|
923
804
|
|
|
924
|
-
export { BrnSelectComponent, BrnSelectContentComponent, BrnSelectGroupDirective, BrnSelectImports, BrnSelectLabelDirective, BrnSelectModule, BrnSelectOptionDirective, BrnSelectScrollDownDirective, BrnSelectScrollUpDirective,
|
|
805
|
+
export { BrnSelectComponent, BrnSelectContentComponent, BrnSelectGroupDirective, BrnSelectImports, BrnSelectLabelDirective, BrnSelectModule, BrnSelectOptionDirective, BrnSelectPlaceholderDirective, BrnSelectScrollDownDirective, BrnSelectScrollUpDirective, BrnSelectTriggerDirective, BrnSelectValueComponent, BrnSelectValueDirective };
|
|
925
806
|
//# sourceMappingURL=spartan-ng-brain-select.mjs.map
|