@nexterajs/ui 0.0.2 → 0.1.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +279 -34
- package/fesm2022/nexterajs-ui-charts.mjs +1096 -0
- package/fesm2022/nexterajs-ui-charts.mjs.map +1 -0
- package/fesm2022/nexterajs-ui-core.mjs +652 -12
- package/fesm2022/nexterajs-ui-core.mjs.map +1 -1
- package/fesm2022/nexterajs-ui-display.mjs +1142 -0
- package/fesm2022/nexterajs-ui-display.mjs.map +1 -0
- package/fesm2022/nexterajs-ui-dropdowns.mjs +321 -33
- package/fesm2022/nexterajs-ui-dropdowns.mjs.map +1 -1
- package/fesm2022/nexterajs-ui-file-uploader.mjs +572 -10
- package/fesm2022/nexterajs-ui-file-uploader.mjs.map +1 -1
- package/fesm2022/nexterajs-ui-forms.mjs +2027 -136
- package/fesm2022/nexterajs-ui-forms.mjs.map +1 -1
- package/fesm2022/nexterajs-ui-grid.mjs +1222 -188
- package/fesm2022/nexterajs-ui-grid.mjs.map +1 -1
- package/fesm2022/nexterajs-ui-intl.mjs +103 -11
- package/fesm2022/nexterajs-ui-intl.mjs.map +1 -1
- package/fesm2022/nexterajs-ui-navigation.mjs +1054 -0
- package/fesm2022/nexterajs-ui-navigation.mjs.map +1 -0
- package/fesm2022/nexterajs-ui-notify.mjs +46 -44
- package/fesm2022/nexterajs-ui-notify.mjs.map +1 -1
- package/fesm2022/nexterajs-ui-overlay.mjs +1671 -0
- package/fesm2022/nexterajs-ui-overlay.mjs.map +1 -0
- package/fesm2022/nexterajs-ui-pivot.mjs +51 -26
- package/fesm2022/nexterajs-ui-pivot.mjs.map +1 -1
- package/fesm2022/nexterajs-ui-shell.mjs +542 -0
- package/fesm2022/nexterajs-ui-shell.mjs.map +1 -0
- package/fesm2022/nexterajs-ui-tree-view.mjs +5 -2
- package/fesm2022/nexterajs-ui-tree-view.mjs.map +1 -1
- package/fesm2022/nexterajs-ui-validation.mjs +42 -11
- package/fesm2022/nexterajs-ui-validation.mjs.map +1 -1
- package/fesm2022/nexterajs-ui.mjs +5 -0
- package/fesm2022/nexterajs-ui.mjs.map +1 -1
- package/package.json +33 -2
- package/styles/_dropdown.scss +5 -5
- package/styles/_editor.scss +52 -17
- package/styles/_mixins.scss +1 -1
- package/styles/_scrollbar.scss +5 -5
- package/styles/_status.scss +21 -0
- package/styles/_toast.scss +14 -14
- package/styles/_tokens.scss +420 -3
- package/styles/_widget.scss +14 -3
- package/styles/index.scss +6 -4
- package/types/nexterajs-ui-charts.d.ts +446 -0
- package/types/nexterajs-ui-core.d.ts +387 -22
- package/types/nexterajs-ui-display.d.ts +720 -0
- package/types/nexterajs-ui-dropdowns.d.ts +191 -48
- package/types/nexterajs-ui-file-uploader.d.ts +236 -7
- package/types/nexterajs-ui-forms.d.ts +675 -30
- package/types/nexterajs-ui-grid.d.ts +448 -93
- package/types/nexterajs-ui-intl.d.ts +39 -4
- package/types/nexterajs-ui-navigation.d.ts +531 -0
- package/types/nexterajs-ui-notify.d.ts +4 -2
- package/types/nexterajs-ui-overlay.d.ts +703 -0
- package/types/nexterajs-ui-pivot.d.ts +56 -48
- package/types/nexterajs-ui-shell.d.ts +294 -0
- package/types/nexterajs-ui-tree-view.d.ts +6 -3
- package/types/nexterajs-ui-validation.d.ts +20 -11
- package/types/nexterajs-ui.d.ts +5 -0
|
@@ -2,12 +2,156 @@ import { Overlay } from '@angular/cdk/overlay';
|
|
|
2
2
|
import { TemplatePortal } from '@angular/cdk/portal';
|
|
3
3
|
import { NgTemplateOutlet } from '@angular/common';
|
|
4
4
|
import * as i0 from '@angular/core';
|
|
5
|
-
import { inject, ViewContainerRef, viewChild, contentChildren, input, computed, booleanAttribute, output,
|
|
5
|
+
import { signal, inject, DestroyRef, ViewContainerRef, viewChild, contentChildren, input, computed, numberAttribute, booleanAttribute, output, forwardRef, ViewEncapsulation, ChangeDetectionStrategy, Component, contentChild, model, Injector, InjectionToken, ElementRef, TemplateRef, Directive } from '@angular/core';
|
|
6
6
|
import { NG_VALUE_ACCESSOR } from '@angular/forms';
|
|
7
|
-
import {
|
|
7
|
+
import { takeUntilDestroyed, toObservable } from '@angular/core/rxjs-interop';
|
|
8
|
+
import { Subject, switchMap, timer, map, firstValueFrom, from, filter, catchError, EMPTY, merge, mergeMap, distinctUntilChanged } from 'rxjs';
|
|
8
9
|
import { NxeFormControlBase, NxeTemplateDirective, nxeOptionalBoolean, nxeResolveText, nxeResolveExpr, NXE_VALIDATION_TARGET } from '@nexterajs/ui/core';
|
|
9
10
|
import { nxePane, trackPaneFlip } from '@nexterajs/ui/styling';
|
|
10
|
-
|
|
11
|
+
|
|
12
|
+
/** True for a store object (anything with a `load` function that is not an array). */
|
|
13
|
+
function nxeIsPickerStore(value) {
|
|
14
|
+
return (!!value &&
|
|
15
|
+
typeof value === 'object' &&
|
|
16
|
+
!Array.isArray(value) &&
|
|
17
|
+
typeof value.load === 'function');
|
|
18
|
+
}
|
|
19
|
+
/**
|
|
20
|
+
* The search plumbing shared by the pickers: debounces typing by `searchTimeout`, emits
|
|
21
|
+
* `searchChange` once the text reaches `minSearchLength` (or is cleared), and, when the
|
|
22
|
+
* `dataSource` is a {@link NxePickerStore}, queries it and keeps only the newest response.
|
|
23
|
+
* Must be created in an injection context. It uses no `effect()`: it reacts only to the explicit
|
|
24
|
+
* {@link typed}, {@link open} and {@link loadMore} calls.
|
|
25
|
+
*/
|
|
26
|
+
class NxePickerSearch {
|
|
27
|
+
cfg;
|
|
28
|
+
/** Rows of the store loaded so far (all pages of the current query). */
|
|
29
|
+
items = signal([], /* @ts-ignore */
|
|
30
|
+
...(ngDevMode ? [{ debugName: "items" }] : /* istanbul ignore next */ []));
|
|
31
|
+
loading = signal(false, /* @ts-ignore */
|
|
32
|
+
...(ngDevMode ? [{ debugName: "loading" }] : /* istanbul ignore next */ []));
|
|
33
|
+
error = signal(null, /* @ts-ignore */
|
|
34
|
+
...(ngDevMode ? [{ debugName: "error" }] : /* istanbul ignore next */ []));
|
|
35
|
+
hasMore = signal(false, /* @ts-ignore */
|
|
36
|
+
...(ngDevMode ? [{ debugName: "hasMore" }] : /* istanbul ignore next */ []));
|
|
37
|
+
typedText = new Subject();
|
|
38
|
+
loadedFor = null;
|
|
39
|
+
seq = 0;
|
|
40
|
+
controller = null;
|
|
41
|
+
constructor(cfg) {
|
|
42
|
+
this.cfg = cfg;
|
|
43
|
+
const destroyRef = inject(DestroyRef);
|
|
44
|
+
this.typedText
|
|
45
|
+
.pipe(switchMap((text) => timer(Math.max(0, cfg.searchTimeout())).pipe(map(() => text))), takeUntilDestroyed(destroyRef))
|
|
46
|
+
.subscribe((text) => this.settled(text));
|
|
47
|
+
destroyRef.onDestroy(() => this.controller?.abort());
|
|
48
|
+
}
|
|
49
|
+
get hasStore() {
|
|
50
|
+
return this.cfg.store() !== null;
|
|
51
|
+
}
|
|
52
|
+
/** True when `text` is long enough to be searched. */
|
|
53
|
+
reachesMinimum(text) {
|
|
54
|
+
return text.length >= this.cfg.minSearchLength();
|
|
55
|
+
}
|
|
56
|
+
/** The user typed; the search settles after `searchTimeout`. */
|
|
57
|
+
typed(text) {
|
|
58
|
+
this.typedText.next(text);
|
|
59
|
+
}
|
|
60
|
+
/** The panel opened with `text` in the field: load the first page unless that query is current. */
|
|
61
|
+
open(text) {
|
|
62
|
+
if (this.hasStore && this.loadedFor !== this.effective(text)) {
|
|
63
|
+
this.query(text);
|
|
64
|
+
}
|
|
65
|
+
}
|
|
66
|
+
/** Loads the next page of the current query (a scroll-to-bottom handler calls this). */
|
|
67
|
+
loadMore() {
|
|
68
|
+
if (this.hasStore && this.hasMore() && !this.loading()) {
|
|
69
|
+
void this.run(this.loadedFor ?? '', true);
|
|
70
|
+
}
|
|
71
|
+
}
|
|
72
|
+
/** Fetches one row by key through `byKey`; `null` when the store cannot or does not know it. */
|
|
73
|
+
async lookup(key) {
|
|
74
|
+
const store = this.cfg.store();
|
|
75
|
+
if (!store?.byKey) {
|
|
76
|
+
return null;
|
|
77
|
+
}
|
|
78
|
+
const controller = new AbortController();
|
|
79
|
+
try {
|
|
80
|
+
return (await firstValueFrom(from(store.byKey(key, { signal: controller.signal })))) ?? null;
|
|
81
|
+
}
|
|
82
|
+
catch {
|
|
83
|
+
return null;
|
|
84
|
+
}
|
|
85
|
+
}
|
|
86
|
+
settled(text) {
|
|
87
|
+
if (text === '' || this.reachesMinimum(text)) {
|
|
88
|
+
this.cfg.searchChange({ searchValue: text });
|
|
89
|
+
}
|
|
90
|
+
if (this.hasStore) {
|
|
91
|
+
this.query(text);
|
|
92
|
+
}
|
|
93
|
+
}
|
|
94
|
+
/** The text actually sent to the store: below the minimum nothing is searched. */
|
|
95
|
+
effective(text) {
|
|
96
|
+
if (this.reachesMinimum(text)) {
|
|
97
|
+
return text;
|
|
98
|
+
}
|
|
99
|
+
return this.cfg.showDataBeforeSearch() ? '' : null;
|
|
100
|
+
}
|
|
101
|
+
query(text) {
|
|
102
|
+
const effective = this.effective(text);
|
|
103
|
+
if (effective === null) {
|
|
104
|
+
this.cancel();
|
|
105
|
+
this.items.set([]);
|
|
106
|
+
this.hasMore.set(false);
|
|
107
|
+
this.loadedFor = null;
|
|
108
|
+
this.cfg.loaded?.();
|
|
109
|
+
return;
|
|
110
|
+
}
|
|
111
|
+
void this.run(effective, false);
|
|
112
|
+
}
|
|
113
|
+
cancel() {
|
|
114
|
+
this.seq++;
|
|
115
|
+
this.controller?.abort();
|
|
116
|
+
this.controller = null;
|
|
117
|
+
this.loading.set(false);
|
|
118
|
+
}
|
|
119
|
+
async run(text, append) {
|
|
120
|
+
const store = this.cfg.store();
|
|
121
|
+
if (!store) {
|
|
122
|
+
return;
|
|
123
|
+
}
|
|
124
|
+
this.cancel();
|
|
125
|
+
const seq = this.seq;
|
|
126
|
+
const controller = new AbortController();
|
|
127
|
+
this.controller = controller;
|
|
128
|
+
this.loading.set(true);
|
|
129
|
+
this.error.set(null);
|
|
130
|
+
const take = Math.max(1, this.cfg.pageSize());
|
|
131
|
+
const skip = append ? this.items().length : 0;
|
|
132
|
+
try {
|
|
133
|
+
const raw = await firstValueFrom(from(store.load({ searchValue: text, searchExpr: this.cfg.searchExpr(), searchOperation: 'contains', skip, take }, { signal: controller.signal })));
|
|
134
|
+
if (seq !== this.seq) {
|
|
135
|
+
return;
|
|
136
|
+
}
|
|
137
|
+
const data = Array.isArray(raw) ? raw : (raw.data ?? []);
|
|
138
|
+
const total = Array.isArray(raw) ? undefined : raw.totalCount;
|
|
139
|
+
const next = append ? [...this.items(), ...data] : data;
|
|
140
|
+
this.items.set(next);
|
|
141
|
+
this.hasMore.set(total !== undefined ? next.length < total : data.length >= take);
|
|
142
|
+
this.loadedFor = text;
|
|
143
|
+
this.loading.set(false);
|
|
144
|
+
this.cfg.loaded?.();
|
|
145
|
+
}
|
|
146
|
+
catch (error) {
|
|
147
|
+
if (seq !== this.seq) {
|
|
148
|
+
return;
|
|
149
|
+
}
|
|
150
|
+
this.error.set(error);
|
|
151
|
+
this.loading.set(false);
|
|
152
|
+
}
|
|
153
|
+
}
|
|
154
|
+
}
|
|
11
155
|
|
|
12
156
|
/**
|
|
13
157
|
* `nxe-select-box` — drop-in replacement for DevExtreme `dx-select-box`.
|
|
@@ -29,7 +173,10 @@ class NxeSelectBoxComponent extends NxeFormControlBase {
|
|
|
29
173
|
...(ngDevMode ? [{ debugName: "inputEl" }] : /* istanbul ignore next */ []));
|
|
30
174
|
templates = contentChildren(NxeTemplateDirective, /* @ts-ignore */
|
|
31
175
|
...(ngDevMode ? [{ debugName: "templates" }] : /* istanbul ignore next */ []));
|
|
32
|
-
/**
|
|
176
|
+
/**
|
|
177
|
+
* The source: a plain array of `Lov`-shaped objects (or primitives), or an {@link NxePickerStore}
|
|
178
|
+
* whose `load({searchValue, skip, take})` the box calls itself (server-side search).
|
|
179
|
+
*/
|
|
33
180
|
dataSource = input([], /* @ts-ignore */
|
|
34
181
|
...(ngDevMode ? [{ debugName: "dataSource" }] : /* istanbul ignore next */ []));
|
|
35
182
|
/** Field shown in the box/list (DevExtreme default `lovName`). Empty => the item itself. */
|
|
@@ -74,9 +221,29 @@ class NxeSelectBoxComponent extends NxeFormControlBase {
|
|
|
74
221
|
/** Named template ('inputField') for the closed field; `$implicit` = the selected item. */
|
|
75
222
|
fieldTemplate = input(/* @ts-ignore */
|
|
76
223
|
...(ngDevMode ? [undefined, { debugName: "fieldTemplate" }] : /* istanbul ignore next */ []));
|
|
224
|
+
/** dx `searchTimeout`: ms of typing pause before `(searchChange)` fires or a store is queried. */
|
|
225
|
+
searchTimeout = input(500, { ...(ngDevMode ? { debugName: "searchTimeout" } : /* istanbul ignore next */ {}), transform: numberAttribute });
|
|
226
|
+
/** dx `minSearchLength`: characters needed before a search is emitted, applied or sent. */
|
|
227
|
+
minSearchLength = input(0, { ...(ngDevMode ? { debugName: "minSearchLength" } : /* istanbul ignore next */ {}), transform: numberAttribute });
|
|
228
|
+
/** dx `showDataBeforeSearch`: list rows while the text is shorter than `minSearchLength`. */
|
|
229
|
+
showDataBeforeSearch = input(false, { ...(ngDevMode ? { debugName: "showDataBeforeSearch" } : /* istanbul ignore next */ {}), transform: booleanAttribute });
|
|
230
|
+
/** Rows requested per page from a store `dataSource` (`take`); more load on scroll to the end. */
|
|
231
|
+
pageSize = input(20, { ...(ngDevMode ? { debugName: "pageSize" } : /* istanbul ignore next */ {}), transform: numberAttribute });
|
|
232
|
+
/**
|
|
233
|
+
* dx `displayValue`: the text shown for the current value while its row is not among the loaded
|
|
234
|
+
* ones (a store `dataSource` with the selection outside the current page, and no `byKey`).
|
|
235
|
+
*/
|
|
236
|
+
displayValue = input(undefined, /* @ts-ignore */
|
|
237
|
+
...(ngDevMode ? [{ debugName: "displayValue" }] : /* istanbul ignore next */ []));
|
|
77
238
|
/** DevExtreme parity, cosmetic. */
|
|
78
239
|
hoverStateEnabled = input(true, { ...(ngDevMode ? { debugName: "hoverStateEnabled" } : /* istanbul ignore next */ {}), transform: booleanAttribute });
|
|
79
240
|
onSelectionChanged = output();
|
|
241
|
+
/**
|
|
242
|
+
* The search text settled: fires `searchTimeout` ms after the last keystroke, once the text has
|
|
243
|
+
* `minSearchLength` characters (or was cleared). Use it to query a server and replace
|
|
244
|
+
* `[dataSource]`, or pass a {@link NxePickerStore} and let the box query for you.
|
|
245
|
+
*/
|
|
246
|
+
searchChange = output();
|
|
80
247
|
focused = signal(false, /* @ts-ignore */
|
|
81
248
|
...(ngDevMode ? [{ debugName: "focused" }] : /* istanbul ignore next */ []));
|
|
82
249
|
open = signal(false, /* @ts-ignore */
|
|
@@ -95,8 +262,39 @@ class NxeSelectBoxComponent extends NxeFormControlBase {
|
|
|
95
262
|
overlayRef;
|
|
96
263
|
closeSub;
|
|
97
264
|
flipSub;
|
|
98
|
-
|
|
265
|
+
store = computed(() => {
|
|
266
|
+
const ds = this.dataSource();
|
|
267
|
+
return nxeIsPickerStore(ds) ? ds : null;
|
|
268
|
+
}, /* @ts-ignore */
|
|
269
|
+
...(ngDevMode ? [{ debugName: "store" }] : /* istanbul ignore next */ []));
|
|
270
|
+
search = new NxePickerSearch({
|
|
271
|
+
store: this.store,
|
|
272
|
+
searchExpr: this.searchExpr,
|
|
273
|
+
searchTimeout: this.searchTimeout,
|
|
274
|
+
minSearchLength: this.minSearchLength,
|
|
275
|
+
showDataBeforeSearch: this.showDataBeforeSearch,
|
|
276
|
+
pageSize: this.pageSize,
|
|
277
|
+
searchChange: (event) => this.searchChange.emit(event),
|
|
278
|
+
loaded: () => this.activeIndex.set(this.filteredItems().length ? 0 : -1),
|
|
279
|
+
});
|
|
280
|
+
/** Rows picked or fetched by key from a store, so the label outlives the page that held them. */
|
|
281
|
+
resolved = signal(new Map(), /* @ts-ignore */
|
|
282
|
+
...(ngDevMode ? [{ debugName: "resolved" }] : /* istanbul ignore next */ []));
|
|
283
|
+
items = computed(() => {
|
|
284
|
+
const ds = this.dataSource();
|
|
285
|
+
return nxeIsPickerStore(ds) ? this.search.items() : (ds ?? []);
|
|
286
|
+
}, /* @ts-ignore */
|
|
99
287
|
...(ngDevMode ? [{ debugName: "items" }] : /* istanbul ignore next */ []));
|
|
288
|
+
/** Fetches the row of an externally set value through `byKey` when no loaded row has it. */
|
|
289
|
+
keyLookup = toObservable(this.value)
|
|
290
|
+
.pipe(filter((v) => v != null && v !== '' && this.search.hasStore && this.findRow(v) === undefined), switchMap((v) => from(this.search.lookup(v)).pipe(catchError(() => EMPTY), filter((row) => row != null), map((row) => [v, row]))), takeUntilDestroyed())
|
|
291
|
+
.subscribe(([key, row]) => this.remember(key, row));
|
|
292
|
+
findRow(key) {
|
|
293
|
+
return this.items().find((it) => this.extractValue(it) === key) ?? this.resolved().get(key);
|
|
294
|
+
}
|
|
295
|
+
remember(key, row) {
|
|
296
|
+
this.resolved.update((m) => new Map(m).set(key, row));
|
|
297
|
+
}
|
|
100
298
|
display(item) {
|
|
101
299
|
return nxeResolveText(this.displayExpr(), item);
|
|
102
300
|
}
|
|
@@ -108,7 +306,7 @@ class NxeSelectBoxComponent extends NxeFormControlBase {
|
|
|
108
306
|
if (v == null) {
|
|
109
307
|
return null;
|
|
110
308
|
}
|
|
111
|
-
return this.
|
|
309
|
+
return this.findRow(v) ?? null;
|
|
112
310
|
}, /* @ts-ignore */
|
|
113
311
|
...(ngDevMode ? [{ debugName: "selectedItem" }] : /* istanbul ignore next */ []));
|
|
114
312
|
hasValue = computed(() => this.value() != null && this.value() !== '', /* @ts-ignore */
|
|
@@ -116,7 +314,10 @@ class NxeSelectBoxComponent extends NxeFormControlBase {
|
|
|
116
314
|
/** Display text when the field is not being searched. */
|
|
117
315
|
displayText = computed(() => {
|
|
118
316
|
const sel = this.selectedItem();
|
|
119
|
-
|
|
317
|
+
if (sel) {
|
|
318
|
+
return this.display(sel);
|
|
319
|
+
}
|
|
320
|
+
return this.hasValue() ? (this.displayValue() ?? '') : '';
|
|
120
321
|
}, /* @ts-ignore */
|
|
121
322
|
...(ngDevMode ? [{ debugName: "displayText" }] : /* istanbul ignore next */ []));
|
|
122
323
|
/** Value bound to the input element. */
|
|
@@ -128,9 +329,15 @@ class NxeSelectBoxComponent extends NxeFormControlBase {
|
|
|
128
329
|
filteredItems = computed(() => {
|
|
129
330
|
const items = this.items();
|
|
130
331
|
const search = this.searchText();
|
|
131
|
-
if (
|
|
332
|
+
if (this.search.hasStore) {
|
|
132
333
|
return items;
|
|
133
334
|
}
|
|
335
|
+
if (!this.searchEnabled() || !search) {
|
|
336
|
+
return this.minSearchLength() > 0 && !this.showDataBeforeSearch() ? [] : items;
|
|
337
|
+
}
|
|
338
|
+
if (!this.search.reachesMinimum(search)) {
|
|
339
|
+
return this.showDataBeforeSearch() ? items : [];
|
|
340
|
+
}
|
|
134
341
|
const expr = this.searchExpr();
|
|
135
342
|
const needle = search.toLowerCase();
|
|
136
343
|
return items.filter((it) => nxeResolveText(expr, it).toLowerCase().includes(needle));
|
|
@@ -163,12 +370,21 @@ class NxeSelectBoxComponent extends NxeFormControlBase {
|
|
|
163
370
|
this.openPanel();
|
|
164
371
|
}
|
|
165
372
|
onSearchInput(event) {
|
|
166
|
-
|
|
373
|
+
const text = event.target.value;
|
|
374
|
+
this.searchText.set(text);
|
|
375
|
+
this.search.typed(text);
|
|
167
376
|
this.activeIndex.set(0);
|
|
168
377
|
if (!this.open()) {
|
|
169
378
|
this.openPanel();
|
|
170
379
|
}
|
|
171
380
|
}
|
|
381
|
+
/** Loads the next page of a store `dataSource` when the list is scrolled to its end. */
|
|
382
|
+
onPanelScroll(event) {
|
|
383
|
+
const el = event.target;
|
|
384
|
+
if (el.scrollTop + el.clientHeight >= el.scrollHeight - 8) {
|
|
385
|
+
this.search.loadMore();
|
|
386
|
+
}
|
|
387
|
+
}
|
|
172
388
|
onBlur() {
|
|
173
389
|
this.focused.set(false);
|
|
174
390
|
this.markAsTouched();
|
|
@@ -179,6 +395,9 @@ class NxeSelectBoxComponent extends NxeFormControlBase {
|
|
|
179
395
|
event.preventDefault();
|
|
180
396
|
const previousValue = this.value();
|
|
181
397
|
const next = this.extractValue(item);
|
|
398
|
+
if (this.search.hasStore) {
|
|
399
|
+
this.remember(next, item);
|
|
400
|
+
}
|
|
182
401
|
this.commitValue(next, event);
|
|
183
402
|
this.onSelectionChanged.emit({ selectedItem: item, previousValue, value: next });
|
|
184
403
|
this.searchText.set(null);
|
|
@@ -230,6 +449,7 @@ class NxeSelectBoxComponent extends NxeFormControlBase {
|
|
|
230
449
|
this.panelWidth.set(this.elementRef.nativeElement.offsetWidth);
|
|
231
450
|
const idx = this.items().findIndex((it) => this.extractValue(it) === this.value());
|
|
232
451
|
this.activeIndex.set(idx >= 0 ? idx : 0);
|
|
452
|
+
this.search.open(this.searchText() ?? '');
|
|
233
453
|
if (!this.overlayRef) {
|
|
234
454
|
this.overlayRef = this.overlay.create({
|
|
235
455
|
positionStrategy: this.overlay
|
|
@@ -268,24 +488,24 @@ class NxeSelectBoxComponent extends NxeFormControlBase {
|
|
|
268
488
|
this.overlayRef?.dispose();
|
|
269
489
|
}
|
|
270
490
|
static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "22.1.5", ngImport: i0, type: NxeSelectBoxComponent, deps: null, target: i0.ɵɵFactoryTarget.Component });
|
|
271
|
-
static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "22.1.5", type: NxeSelectBoxComponent, isStandalone: true, selector: "nxe-select-box", inputs: { dataSource: { classPropertyName: "dataSource", publicName: "dataSource", isSignal: true, isRequired: false, transformFunction: null }, displayExprInput: { classPropertyName: "displayExprInput", publicName: "displayExpr", isSignal: true, isRequired: false, transformFunction: null }, valueExprInput: { classPropertyName: "valueExprInput", publicName: "valueExpr", isSignal: true, isRequired: false, transformFunction: null }, searchExprInput: { classPropertyName: "searchExprInput", publicName: "searchExpr", isSignal: true, isRequired: false, transformFunction: null }, searchEnabledInput: { classPropertyName: "searchEnabledInput", publicName: "searchEnabled", isSignal: true, isRequired: false, transformFunction: null }, showClearButtonInput: { classPropertyName: "showClearButtonInput", publicName: "showClearButton", isSignal: true, isRequired: false, transformFunction: null }, showDropDownButtonInput: { classPropertyName: "showDropDownButtonInput", publicName: "showDropDownButton", isSignal: true, isRequired: false, transformFunction: null }, placeholderInput: { classPropertyName: "placeholderInput", publicName: "placeholder", isSignal: true, isRequired: false, transformFunction: null }, itemTemplate: { classPropertyName: "itemTemplate", publicName: "itemTemplate", isSignal: true, isRequired: false, transformFunction: null }, fieldTemplate: { classPropertyName: "fieldTemplate", publicName: "fieldTemplate", isSignal: true, isRequired: false, transformFunction: null }, hoverStateEnabled: { classPropertyName: "hoverStateEnabled", publicName: "hoverStateEnabled", isSignal: true, isRequired: false, transformFunction: null } }, outputs: { onSelectionChanged: "onSelectionChanged" }, host: { listeners: { "keydown": "onKeydown($event)" }, properties: { "class.nxe-focused": "focused()", "class.nxe-invalid": "
|
|
491
|
+
static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "22.1.5", type: NxeSelectBoxComponent, isStandalone: true, selector: "nxe-select-box", inputs: { dataSource: { classPropertyName: "dataSource", publicName: "dataSource", isSignal: true, isRequired: false, transformFunction: null }, displayExprInput: { classPropertyName: "displayExprInput", publicName: "displayExpr", isSignal: true, isRequired: false, transformFunction: null }, valueExprInput: { classPropertyName: "valueExprInput", publicName: "valueExpr", isSignal: true, isRequired: false, transformFunction: null }, searchExprInput: { classPropertyName: "searchExprInput", publicName: "searchExpr", isSignal: true, isRequired: false, transformFunction: null }, searchEnabledInput: { classPropertyName: "searchEnabledInput", publicName: "searchEnabled", isSignal: true, isRequired: false, transformFunction: null }, showClearButtonInput: { classPropertyName: "showClearButtonInput", publicName: "showClearButton", isSignal: true, isRequired: false, transformFunction: null }, showDropDownButtonInput: { classPropertyName: "showDropDownButtonInput", publicName: "showDropDownButton", isSignal: true, isRequired: false, transformFunction: null }, placeholderInput: { classPropertyName: "placeholderInput", publicName: "placeholder", isSignal: true, isRequired: false, transformFunction: null }, itemTemplate: { classPropertyName: "itemTemplate", publicName: "itemTemplate", isSignal: true, isRequired: false, transformFunction: null }, fieldTemplate: { classPropertyName: "fieldTemplate", publicName: "fieldTemplate", isSignal: true, isRequired: false, transformFunction: null }, searchTimeout: { classPropertyName: "searchTimeout", publicName: "searchTimeout", isSignal: true, isRequired: false, transformFunction: null }, minSearchLength: { classPropertyName: "minSearchLength", publicName: "minSearchLength", isSignal: true, isRequired: false, transformFunction: null }, showDataBeforeSearch: { classPropertyName: "showDataBeforeSearch", publicName: "showDataBeforeSearch", isSignal: true, isRequired: false, transformFunction: null }, pageSize: { classPropertyName: "pageSize", publicName: "pageSize", isSignal: true, isRequired: false, transformFunction: null }, displayValue: { classPropertyName: "displayValue", publicName: "displayValue", isSignal: true, isRequired: false, transformFunction: null }, hoverStateEnabled: { classPropertyName: "hoverStateEnabled", publicName: "hoverStateEnabled", isSignal: true, isRequired: false, transformFunction: null } }, outputs: { onSelectionChanged: "onSelectionChanged", searchChange: "searchChange" }, host: { listeners: { "keydown": "onKeydown($event)" }, properties: { "class.nxe-focused": "focused()", "class.nxe-invalid": "invalidState()", "class.nxe-open": "open()" }, classAttribute: "nxe-widget nxe-editor nxe-selectbox" }, providers: [
|
|
272
492
|
{ provide: NG_VALUE_ACCESSOR, useExisting: forwardRef(() => NxeSelectBoxComponent), multi: true },
|
|
273
493
|
{ provide: NXE_VALIDATION_TARGET, useExisting: forwardRef(() => NxeSelectBoxComponent) },
|
|
274
|
-
], queries: [{ propertyName: "templates", predicate: NxeTemplateDirective, isSignal: true }], viewQueries: [{ propertyName: "dropdownTemplate", first: true, predicate: ["dropdown"], descendants: true, isSignal: true }, { propertyName: "inputEl", first: true, predicate: ["input"], descendants: true, isSignal: true }], usesInheritance: true, ngImport: i0, template: "<div class=\"nxe-editor-container\" (mousedown)=\"onFieldMousedown($event)\">\
|
|
494
|
+
], queries: [{ propertyName: "templates", predicate: NxeTemplateDirective, isSignal: true }], viewQueries: [{ propertyName: "dropdownTemplate", first: true, predicate: ["dropdown"], descendants: true, isSignal: true }, { propertyName: "inputEl", first: true, predicate: ["input"], descendants: true, isSignal: true }], usesInheritance: true, ngImport: i0, template: "<div class=\"nxe-editor-container\" (mousedown)=\"onFieldMousedown($event)\">\n @if (fieldTemplateRef(); as tpl) {\n <div class=\"nxe-select-field\">\n <ng-container *ngTemplateOutlet=\"tpl; context: { $implicit: selectedItem() }\" />\n </div>\n } @else {\n <input\n #input\n class=\"nxe-editor-input nxe-select-input\"\n [attr.tabindex]=\"tabIndex()\"\n role=\"combobox\"\n aria-haspopup=\"listbox\"\n [attr.aria-expanded]=\"open()\"\n [attr.aria-controls]=\"open() ? panelId() : null\"\n [attr.aria-activedescendant]=\"open() && activeIndex() >= 0 ? optionId(activeIndex()) : null\"\n [id]=\"controlId()\"\n [attr.aria-label]=\"ariaLabel() || null\"\n [attr.aria-labelledby]=\"ariaLabelledBy() || null\"\n [attr.aria-invalid]=\"invalidState() ? true : null\"\n [attr.aria-required]=\"required() ? true : null\"\n type=\"text\"\n [value]=\"inputDisplay()\"\n [readOnly]=\"readOnly() || !searchEnabled()\"\n [disabled]=\"disabled()\"\n [attr.placeholder]=\"placeholder() || null\"\n autocomplete=\"off\"\n (input)=\"onSearchInput($event)\"\n (focus)=\"focused.set(true)\"\n (blur)=\"onBlur()\" />\n }\n\n @if (showClearButton() && hasValue() && !readOnly() && !disabled()) {\n <span class=\"nxe-select-clear\" (mousedown)=\"onClear($event)\" aria-hidden=\"true\">\n <!-- A \u00D816 disc with a 2px \u00D7 cut out: two 2px bars, each running corner to corner of the\n 8px square centred on the disc, drawn as a plus and turned 45\u00B0. -->\n <svg viewBox=\"0 0 18 18\" focusable=\"false\">\n <path fill-rule=\"evenodd\" transform=\"rotate(45 9 9)\"\n d=\"M9 1a8 8 0 1 1 0 16A8 8 0 1 1 9 1ZM8 3.343h2V8h4.657v2H10v4.657H8V10H3.343V8H8Z\" />\n </svg>\n </span>\n }\n\n @if (showDropDownButton() && !readOnly()) {\n <span class=\"nxe-select-arrow\" aria-hidden=\"true\">\n <!-- An 8x4 triangle centred in the 18px box. -->\n <svg viewBox=\"0 0 18 18\" focusable=\"false\"><path d=\"M5 7h8l-4 4z\" /></svg>\n </span>\n }\n</div>\n\n<ng-content />\n\n@if (validationError(); as error) {\n @if (focused()) {\n <div class=\"nxe-invalid-message\">{{ error }}</div>\n }\n}\n\n<ng-template #dropdown>\n <div class=\"nxe-select-panel\" [style.width.px]=\"panelWidth()\"\n [id]=\"panelId()\"\n role=\"listbox\"\n (scroll)=\"onPanelScroll($event)\">\n @for (item of filteredItems(); track $index; let i = $index) {\n <div\n class=\"nxe-list-item\"\n [id]=\"optionId(i)\"\n role=\"option\"\n [attr.aria-selected]=\"isSelected(item)\"\n [class.nxe-list-item-selected]=\"isSelected(item)\"\n [class.nxe-list-item-active]=\"i === activeIndex()\"\n (mousedown)=\"selectItem(item, $event)\">\n @if (itemTemplateRef(); as tpl) {\n <ng-container *ngTemplateOutlet=\"tpl; context: { $implicit: item }\" />\n } @else {\n {{ display(item) }}\n }\n </div>\n } @empty {\n <div class=\"nxe-list-empty\">{{ nxeMessages.t('dropdown.noData') }}</div>\n }\n </div>\n</ng-template>\n", styles: ["nxe-select-box{cursor:pointer}nxe-select-box .nxe-select-input{cursor:pointer}nxe-select-box .nxe-select-clear{box-sizing:border-box;flex:0 0 34px;align-self:stretch;display:inline-flex;align-items:center;justify-content:center;width:34px;min-width:34px;padding:0;color:var(--nxe-ui-text-muted, #999);cursor:pointer}nxe-select-box .nxe-select-clear svg{display:block;width:18px;height:18px;fill:currentColor}nxe-select-box .nxe-select-arrow{box-sizing:border-box;position:relative;flex:0 0 34px;align-self:stretch;display:inline-flex;align-items:center;justify-content:center;width:34px;min-width:34px;padding:1px;border-radius:4px;background-clip:content-box;color:var(--nxe-ui-text, #333);cursor:pointer}nxe-select-box .nxe-select-arrow svg{display:block;width:18px;height:18px;fill:currentColor}nxe-select-box:hover:not(.nxe-disabled) .nxe-select-arrow,nxe-select-box:active:not(.nxe-disabled) .nxe-select-arrow{background-color:var(--nxe-ui-neutral-150, #e6e6e6)}nxe-select-box.nxe-open .nxe-select-arrow{background-color:var(--nxe-ui-neutral-350, #b3b3b3)}nxe-select-box .nxe-editor-container:has(>.nxe-select-arrow) .nxe-editor-input{padding-inline-end:0}nxe-select-box .nxe-editor-container:has(>.nxe-select-clear),nxe-select-box .nxe-editor-container:has(>.nxe-select-arrow){--nxe-invalid-badge-inset: 38px}nxe-select-box .nxe-editor-container:has(>.nxe-select-clear):has(>.nxe-select-arrow){--nxe-invalid-badge-inset: 72px}\n"], dependencies: [{ kind: "directive", type: NgTemplateOutlet, selector: "[ngTemplateOutlet]", inputs: ["ngTemplateOutletContext", "ngTemplateOutlet", "ngTemplateOutletInjector"] }], changeDetection: i0.ChangeDetectionStrategy.OnPush, encapsulation: i0.ViewEncapsulation.None });
|
|
275
495
|
}
|
|
276
496
|
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "22.1.5", ngImport: i0, type: NxeSelectBoxComponent, decorators: [{
|
|
277
497
|
type: Component,
|
|
278
498
|
args: [{ selector: 'nxe-select-box', standalone: true, imports: [NgTemplateOutlet], host: {
|
|
279
499
|
class: 'nxe-widget nxe-editor nxe-selectbox',
|
|
280
500
|
'[class.nxe-focused]': 'focused()',
|
|
281
|
-
'[class.nxe-invalid]': '
|
|
501
|
+
'[class.nxe-invalid]': 'invalidState()',
|
|
282
502
|
'[class.nxe-open]': 'open()',
|
|
283
503
|
'(keydown)': 'onKeydown($event)',
|
|
284
504
|
}, providers: [
|
|
285
505
|
{ provide: NG_VALUE_ACCESSOR, useExisting: forwardRef(() => NxeSelectBoxComponent), multi: true },
|
|
286
506
|
{ provide: NXE_VALIDATION_TARGET, useExisting: forwardRef(() => NxeSelectBoxComponent) },
|
|
287
|
-
], changeDetection: ChangeDetectionStrategy.OnPush, encapsulation: ViewEncapsulation.None, template: "<div class=\"nxe-editor-container\" (mousedown)=\"onFieldMousedown($event)\">\
|
|
288
|
-
}], propDecorators: { dropdownTemplate: [{ type: i0.ViewChild, args: ['dropdown', { isSignal: true }] }], inputEl: [{ type: i0.ViewChild, args: ['input', { isSignal: true }] }], templates: [{ type: i0.ContentChildren, args: [i0.forwardRef(() => NxeTemplateDirective), { isSignal: true }] }], dataSource: [{ type: i0.Input, args: [{ isSignal: true, alias: "dataSource", required: false }] }], displayExprInput: [{ type: i0.Input, args: [{ isSignal: true, alias: "displayExpr", required: false }] }], valueExprInput: [{ type: i0.Input, args: [{ isSignal: true, alias: "valueExpr", required: false }] }], searchExprInput: [{ type: i0.Input, args: [{ isSignal: true, alias: "searchExpr", required: false }] }], searchEnabledInput: [{ type: i0.Input, args: [{ isSignal: true, alias: "searchEnabled", required: false }] }], showClearButtonInput: [{ type: i0.Input, args: [{ isSignal: true, alias: "showClearButton", required: false }] }], showDropDownButtonInput: [{ type: i0.Input, args: [{ isSignal: true, alias: "showDropDownButton", required: false }] }], placeholderInput: [{ type: i0.Input, args: [{ isSignal: true, alias: "placeholder", required: false }] }], itemTemplate: [{ type: i0.Input, args: [{ isSignal: true, alias: "itemTemplate", required: false }] }], fieldTemplate: [{ type: i0.Input, args: [{ isSignal: true, alias: "fieldTemplate", required: false }] }], hoverStateEnabled: [{ type: i0.Input, args: [{ isSignal: true, alias: "hoverStateEnabled", required: false }] }], onSelectionChanged: [{ type: i0.Output, args: ["onSelectionChanged"] }] } });
|
|
507
|
+
], changeDetection: ChangeDetectionStrategy.OnPush, encapsulation: ViewEncapsulation.None, template: "<div class=\"nxe-editor-container\" (mousedown)=\"onFieldMousedown($event)\">\n @if (fieldTemplateRef(); as tpl) {\n <div class=\"nxe-select-field\">\n <ng-container *ngTemplateOutlet=\"tpl; context: { $implicit: selectedItem() }\" />\n </div>\n } @else {\n <input\n #input\n class=\"nxe-editor-input nxe-select-input\"\n [attr.tabindex]=\"tabIndex()\"\n role=\"combobox\"\n aria-haspopup=\"listbox\"\n [attr.aria-expanded]=\"open()\"\n [attr.aria-controls]=\"open() ? panelId() : null\"\n [attr.aria-activedescendant]=\"open() && activeIndex() >= 0 ? optionId(activeIndex()) : null\"\n [id]=\"controlId()\"\n [attr.aria-label]=\"ariaLabel() || null\"\n [attr.aria-labelledby]=\"ariaLabelledBy() || null\"\n [attr.aria-invalid]=\"invalidState() ? true : null\"\n [attr.aria-required]=\"required() ? true : null\"\n type=\"text\"\n [value]=\"inputDisplay()\"\n [readOnly]=\"readOnly() || !searchEnabled()\"\n [disabled]=\"disabled()\"\n [attr.placeholder]=\"placeholder() || null\"\n autocomplete=\"off\"\n (input)=\"onSearchInput($event)\"\n (focus)=\"focused.set(true)\"\n (blur)=\"onBlur()\" />\n }\n\n @if (showClearButton() && hasValue() && !readOnly() && !disabled()) {\n <span class=\"nxe-select-clear\" (mousedown)=\"onClear($event)\" aria-hidden=\"true\">\n <!-- A \u00D816 disc with a 2px \u00D7 cut out: two 2px bars, each running corner to corner of the\n 8px square centred on the disc, drawn as a plus and turned 45\u00B0. -->\n <svg viewBox=\"0 0 18 18\" focusable=\"false\">\n <path fill-rule=\"evenodd\" transform=\"rotate(45 9 9)\"\n d=\"M9 1a8 8 0 1 1 0 16A8 8 0 1 1 9 1ZM8 3.343h2V8h4.657v2H10v4.657H8V10H3.343V8H8Z\" />\n </svg>\n </span>\n }\n\n @if (showDropDownButton() && !readOnly()) {\n <span class=\"nxe-select-arrow\" aria-hidden=\"true\">\n <!-- An 8x4 triangle centred in the 18px box. -->\n <svg viewBox=\"0 0 18 18\" focusable=\"false\"><path d=\"M5 7h8l-4 4z\" /></svg>\n </span>\n }\n</div>\n\n<ng-content />\n\n@if (validationError(); as error) {\n @if (focused()) {\n <div class=\"nxe-invalid-message\">{{ error }}</div>\n }\n}\n\n<ng-template #dropdown>\n <div class=\"nxe-select-panel\" [style.width.px]=\"panelWidth()\"\n [id]=\"panelId()\"\n role=\"listbox\"\n (scroll)=\"onPanelScroll($event)\">\n @for (item of filteredItems(); track $index; let i = $index) {\n <div\n class=\"nxe-list-item\"\n [id]=\"optionId(i)\"\n role=\"option\"\n [attr.aria-selected]=\"isSelected(item)\"\n [class.nxe-list-item-selected]=\"isSelected(item)\"\n [class.nxe-list-item-active]=\"i === activeIndex()\"\n (mousedown)=\"selectItem(item, $event)\">\n @if (itemTemplateRef(); as tpl) {\n <ng-container *ngTemplateOutlet=\"tpl; context: { $implicit: item }\" />\n } @else {\n {{ display(item) }}\n }\n </div>\n } @empty {\n <div class=\"nxe-list-empty\">{{ nxeMessages.t('dropdown.noData') }}</div>\n }\n </div>\n</ng-template>\n", styles: ["nxe-select-box{cursor:pointer}nxe-select-box .nxe-select-input{cursor:pointer}nxe-select-box .nxe-select-clear{box-sizing:border-box;flex:0 0 34px;align-self:stretch;display:inline-flex;align-items:center;justify-content:center;width:34px;min-width:34px;padding:0;color:var(--nxe-ui-text-muted, #999);cursor:pointer}nxe-select-box .nxe-select-clear svg{display:block;width:18px;height:18px;fill:currentColor}nxe-select-box .nxe-select-arrow{box-sizing:border-box;position:relative;flex:0 0 34px;align-self:stretch;display:inline-flex;align-items:center;justify-content:center;width:34px;min-width:34px;padding:1px;border-radius:4px;background-clip:content-box;color:var(--nxe-ui-text, #333);cursor:pointer}nxe-select-box .nxe-select-arrow svg{display:block;width:18px;height:18px;fill:currentColor}nxe-select-box:hover:not(.nxe-disabled) .nxe-select-arrow,nxe-select-box:active:not(.nxe-disabled) .nxe-select-arrow{background-color:var(--nxe-ui-neutral-150, #e6e6e6)}nxe-select-box.nxe-open .nxe-select-arrow{background-color:var(--nxe-ui-neutral-350, #b3b3b3)}nxe-select-box .nxe-editor-container:has(>.nxe-select-arrow) .nxe-editor-input{padding-inline-end:0}nxe-select-box .nxe-editor-container:has(>.nxe-select-clear),nxe-select-box .nxe-editor-container:has(>.nxe-select-arrow){--nxe-invalid-badge-inset: 38px}nxe-select-box .nxe-editor-container:has(>.nxe-select-clear):has(>.nxe-select-arrow){--nxe-invalid-badge-inset: 72px}\n"] }]
|
|
508
|
+
}], propDecorators: { dropdownTemplate: [{ type: i0.ViewChild, args: ['dropdown', { isSignal: true }] }], inputEl: [{ type: i0.ViewChild, args: ['input', { isSignal: true }] }], templates: [{ type: i0.ContentChildren, args: [i0.forwardRef(() => NxeTemplateDirective), { isSignal: true }] }], dataSource: [{ type: i0.Input, args: [{ isSignal: true, alias: "dataSource", required: false }] }], displayExprInput: [{ type: i0.Input, args: [{ isSignal: true, alias: "displayExpr", required: false }] }], valueExprInput: [{ type: i0.Input, args: [{ isSignal: true, alias: "valueExpr", required: false }] }], searchExprInput: [{ type: i0.Input, args: [{ isSignal: true, alias: "searchExpr", required: false }] }], searchEnabledInput: [{ type: i0.Input, args: [{ isSignal: true, alias: "searchEnabled", required: false }] }], showClearButtonInput: [{ type: i0.Input, args: [{ isSignal: true, alias: "showClearButton", required: false }] }], showDropDownButtonInput: [{ type: i0.Input, args: [{ isSignal: true, alias: "showDropDownButton", required: false }] }], placeholderInput: [{ type: i0.Input, args: [{ isSignal: true, alias: "placeholder", required: false }] }], itemTemplate: [{ type: i0.Input, args: [{ isSignal: true, alias: "itemTemplate", required: false }] }], fieldTemplate: [{ type: i0.Input, args: [{ isSignal: true, alias: "fieldTemplate", required: false }] }], searchTimeout: [{ type: i0.Input, args: [{ isSignal: true, alias: "searchTimeout", required: false }] }], minSearchLength: [{ type: i0.Input, args: [{ isSignal: true, alias: "minSearchLength", required: false }] }], showDataBeforeSearch: [{ type: i0.Input, args: [{ isSignal: true, alias: "showDataBeforeSearch", required: false }] }], pageSize: [{ type: i0.Input, args: [{ isSignal: true, alias: "pageSize", required: false }] }], displayValue: [{ type: i0.Input, args: [{ isSignal: true, alias: "displayValue", required: false }] }], hoverStateEnabled: [{ type: i0.Input, args: [{ isSignal: true, alias: "hoverStateEnabled", required: false }] }], onSelectionChanged: [{ type: i0.Output, args: ["onSelectionChanged"] }], searchChange: [{ type: i0.Output, args: ["searchChange"] }] } });
|
|
289
509
|
|
|
290
510
|
/**
|
|
291
511
|
* `nxe-tag-box` — drop-in replacement for DevExtreme `dx-tag-box` (multi-select sibling of
|
|
@@ -303,6 +523,7 @@ class NxeTagBoxComponent extends NxeFormControlBase {
|
|
|
303
523
|
...(ngDevMode ? [{ debugName: "dropdownTemplate" }] : /* istanbul ignore next */ []));
|
|
304
524
|
inputEl = viewChild('input', /* @ts-ignore */
|
|
305
525
|
...(ngDevMode ? [{ debugName: "inputEl" }] : /* istanbul ignore next */ []));
|
|
526
|
+
/** A plain array, or an {@link NxePickerStore} the box queries itself (server-side search). */
|
|
306
527
|
dataSource = input([], /* @ts-ignore */
|
|
307
528
|
...(ngDevMode ? [{ debugName: "dataSource" }] : /* istanbul ignore next */ []));
|
|
308
529
|
displayExprInput = input(undefined, { ...(ngDevMode ? { debugName: "displayExprInput" } : /* istanbul ignore next */ {}), alias: 'displayExpr' });
|
|
@@ -341,7 +562,7 @@ class NxeTagBoxComponent extends NxeFormControlBase {
|
|
|
341
562
|
showSelectionControls = computed(() => this.showSelectionControlsInput() ?? this.nxeDefaults.tagBox?.showSelectionControls ?? true, /* @ts-ignore */
|
|
342
563
|
...(ngDevMode ? [{ debugName: "showSelectionControls" }] : /* istanbul ignore next */ []));
|
|
343
564
|
/** dx `selectAllText` — the label of the "Select All" row (dx: `dxList-selectAll`). */
|
|
344
|
-
selectAllText = input(
|
|
565
|
+
selectAllText = input(undefined, /* @ts-ignore */
|
|
345
566
|
...(ngDevMode ? [{ debugName: "selectAllText" }] : /* istanbul ignore next */ []));
|
|
346
567
|
/** dx parity: dx-tag-box does NOT show a drop-down arrow unless showDropDownButton is set. */
|
|
347
568
|
showDropDownButtonInput = input(undefined, { ...(ngDevMode ? { debugName: "showDropDownButtonInput" } : /* istanbul ignore next */ {}), alias: 'showDropDownButton', transform: nxeOptionalBoolean });
|
|
@@ -350,6 +571,16 @@ class NxeTagBoxComponent extends NxeFormControlBase {
|
|
|
350
571
|
placeholderInput = input(undefined, { ...(ngDevMode ? { debugName: "placeholderInput" } : /* istanbul ignore next */ {}), alias: 'placeholder' });
|
|
351
572
|
placeholder = computed(() => this.placeholderInput() ?? this.nxeDefaults.tagBox?.placeholder ?? '', /* @ts-ignore */
|
|
352
573
|
...(ngDevMode ? [{ debugName: "placeholder" }] : /* istanbul ignore next */ []));
|
|
574
|
+
/** dx `searchTimeout`: ms of typing pause before `(searchChange)` fires or a store is queried. */
|
|
575
|
+
searchTimeout = input(500, { ...(ngDevMode ? { debugName: "searchTimeout" } : /* istanbul ignore next */ {}), transform: numberAttribute });
|
|
576
|
+
/** dx `minSearchLength`: characters needed before a search is emitted, applied or sent. */
|
|
577
|
+
minSearchLength = input(0, { ...(ngDevMode ? { debugName: "minSearchLength" } : /* istanbul ignore next */ {}), transform: numberAttribute });
|
|
578
|
+
/** dx `showDataBeforeSearch`: list rows while the text is shorter than `minSearchLength`. */
|
|
579
|
+
showDataBeforeSearch = input(false, { ...(ngDevMode ? { debugName: "showDataBeforeSearch" } : /* istanbul ignore next */ {}), transform: booleanAttribute });
|
|
580
|
+
/** Rows requested per page from a store `dataSource` (`take`); more load on scroll to the end. */
|
|
581
|
+
pageSize = input(20, { ...(ngDevMode ? { debugName: "pageSize" } : /* istanbul ignore next */ {}), transform: numberAttribute });
|
|
582
|
+
/** The search text settled (after `searchTimeout`, once it has `minSearchLength` characters or was cleared). */
|
|
583
|
+
searchChange = output();
|
|
353
584
|
focused = signal(false, /* @ts-ignore */
|
|
354
585
|
...(ngDevMode ? [{ debugName: "focused" }] : /* istanbul ignore next */ []));
|
|
355
586
|
open = signal(false, /* @ts-ignore */
|
|
@@ -361,8 +592,38 @@ class NxeTagBoxComponent extends NxeFormControlBase {
|
|
|
361
592
|
overlayRef;
|
|
362
593
|
closeSub;
|
|
363
594
|
flipSub;
|
|
364
|
-
|
|
595
|
+
store = computed(() => {
|
|
596
|
+
const ds = this.dataSource();
|
|
597
|
+
return nxeIsPickerStore(ds) ? ds : null;
|
|
598
|
+
}, /* @ts-ignore */
|
|
599
|
+
...(ngDevMode ? [{ debugName: "store" }] : /* istanbul ignore next */ []));
|
|
600
|
+
search = new NxePickerSearch({
|
|
601
|
+
store: this.store,
|
|
602
|
+
searchExpr: this.searchExpr,
|
|
603
|
+
searchTimeout: this.searchTimeout,
|
|
604
|
+
minSearchLength: this.minSearchLength,
|
|
605
|
+
showDataBeforeSearch: this.showDataBeforeSearch,
|
|
606
|
+
pageSize: this.pageSize,
|
|
607
|
+
searchChange: (event) => this.searchChange.emit(event),
|
|
608
|
+
});
|
|
609
|
+
/** Rows picked or fetched by key from a store, so a chip keeps its label off the loaded page. */
|
|
610
|
+
resolved = signal(new Map(), /* @ts-ignore */
|
|
611
|
+
...(ngDevMode ? [{ debugName: "resolved" }] : /* istanbul ignore next */ []));
|
|
612
|
+
items = computed(() => {
|
|
613
|
+
const ds = this.dataSource();
|
|
614
|
+
return nxeIsPickerStore(ds) ? this.search.items() : (ds ?? []);
|
|
615
|
+
}, /* @ts-ignore */
|
|
365
616
|
...(ngDevMode ? [{ debugName: "items" }] : /* istanbul ignore next */ []));
|
|
617
|
+
/** Fetches, through `byKey`, the rows of externally set keys that no loaded row has. */
|
|
618
|
+
keyLookup = toObservable(this.value)
|
|
619
|
+
.pipe(mergeMap((v) => (Array.isArray(v) && this.search.hasStore ? v : [])), filter((key) => this.findRow(key) === undefined), mergeMap((key) => from(this.search.lookup(key)).pipe(catchError(() => EMPTY), filter((row) => row != null), map((row) => [key, row]))), takeUntilDestroyed())
|
|
620
|
+
.subscribe(([key, row]) => this.remember(key, row));
|
|
621
|
+
findRow(key) {
|
|
622
|
+
return this.items().find((it) => this.extractValue(it) === key) ?? this.resolved().get(key);
|
|
623
|
+
}
|
|
624
|
+
remember(key, row) {
|
|
625
|
+
this.resolved.update((m) => new Map(m).set(key, row));
|
|
626
|
+
}
|
|
366
627
|
/** The selected keys (always an array). */
|
|
367
628
|
selectedKeys = computed(() => {
|
|
368
629
|
const v = this.value();
|
|
@@ -378,7 +639,7 @@ class NxeTagBoxComponent extends NxeFormControlBase {
|
|
|
378
639
|
/** Selected items resolved from the value keys (for chip rendering). */
|
|
379
640
|
selectedItems = computed(() => {
|
|
380
641
|
const keys = this.selectedKeys();
|
|
381
|
-
return keys.map((k) => this.
|
|
642
|
+
return keys.map((k) => this.findRow(k) ?? k);
|
|
382
643
|
}, /* @ts-ignore */
|
|
383
644
|
...(ngDevMode ? [{ debugName: "selectedItems" }] : /* istanbul ignore next */ []));
|
|
384
645
|
hasValue = computed(() => this.selectedKeys().length > 0, /* @ts-ignore */
|
|
@@ -386,9 +647,15 @@ class NxeTagBoxComponent extends NxeFormControlBase {
|
|
|
386
647
|
filteredItems = computed(() => {
|
|
387
648
|
const items = this.items();
|
|
388
649
|
const search = this.searchText();
|
|
389
|
-
if (
|
|
650
|
+
if (this.search.hasStore) {
|
|
390
651
|
return items;
|
|
391
652
|
}
|
|
653
|
+
if (!this.searchEnabled() || !search) {
|
|
654
|
+
return this.minSearchLength() > 0 && !this.showDataBeforeSearch() ? [] : items;
|
|
655
|
+
}
|
|
656
|
+
if (!this.search.reachesMinimum(search)) {
|
|
657
|
+
return this.showDataBeforeSearch() ? items : [];
|
|
658
|
+
}
|
|
392
659
|
const expr = this.searchExpr();
|
|
393
660
|
const needle = search.toLowerCase();
|
|
394
661
|
return items.filter((it) => nxeResolveText(expr, it).toLowerCase().includes(needle));
|
|
@@ -426,11 +693,20 @@ class NxeTagBoxComponent extends NxeFormControlBase {
|
|
|
426
693
|
this.inputEl()?.nativeElement?.focus();
|
|
427
694
|
}
|
|
428
695
|
onSearchInput(event) {
|
|
429
|
-
|
|
696
|
+
const text = event.target.value;
|
|
697
|
+
this.searchText.set(text);
|
|
698
|
+
this.search.typed(text);
|
|
430
699
|
if (!this.open()) {
|
|
431
700
|
this.openPanel();
|
|
432
701
|
}
|
|
433
702
|
}
|
|
703
|
+
/** Loads the next page of a store `dataSource` when the list is scrolled to its end. */
|
|
704
|
+
onPanelScroll(event) {
|
|
705
|
+
const el = event.target;
|
|
706
|
+
if (el.scrollTop + el.clientHeight >= el.scrollHeight - 8) {
|
|
707
|
+
this.search.loadMore();
|
|
708
|
+
}
|
|
709
|
+
}
|
|
434
710
|
onBlur() {
|
|
435
711
|
this.focused.set(false);
|
|
436
712
|
this.markAsTouched();
|
|
@@ -440,7 +716,13 @@ class NxeTagBoxComponent extends NxeFormControlBase {
|
|
|
440
716
|
const key = this.extractValue(item);
|
|
441
717
|
const keys = this.selectedKeys();
|
|
442
718
|
const next = keys.includes(key) ? keys.filter((k) => k !== key) : [...keys, key];
|
|
719
|
+
if (this.search.hasStore) {
|
|
720
|
+
this.remember(key, item);
|
|
721
|
+
}
|
|
443
722
|
this.commitValue(next, event);
|
|
723
|
+
if (this.searchText()) {
|
|
724
|
+
this.search.typed('');
|
|
725
|
+
}
|
|
444
726
|
this.searchText.set('');
|
|
445
727
|
const input = this.inputEl()?.nativeElement;
|
|
446
728
|
if (input) {
|
|
@@ -454,6 +736,11 @@ class NxeTagBoxComponent extends NxeFormControlBase {
|
|
|
454
736
|
toggleAll(event) {
|
|
455
737
|
event.preventDefault();
|
|
456
738
|
const listed = this.filteredItems().map((it) => this.extractValue(it));
|
|
739
|
+
if (this.search.hasStore) {
|
|
740
|
+
for (const it of this.filteredItems()) {
|
|
741
|
+
this.remember(this.extractValue(it), it);
|
|
742
|
+
}
|
|
743
|
+
}
|
|
457
744
|
const keys = this.selectedKeys();
|
|
458
745
|
const next = this.selectAllState() === true
|
|
459
746
|
? keys.filter((k) => !listed.includes(k))
|
|
@@ -502,6 +789,7 @@ class NxeTagBoxComponent extends NxeFormControlBase {
|
|
|
502
789
|
if (this.overlayRef.hasAttached()) {
|
|
503
790
|
return;
|
|
504
791
|
}
|
|
792
|
+
this.search.open(this.searchText());
|
|
505
793
|
this.overlayRef.attach(new TemplatePortal(this.dropdownTemplate(), this.viewContainerRef));
|
|
506
794
|
this.closeSub = merge(this.overlayRef.backdropClick(), this.overlayRef.keydownEvents().pipe(filter((e) => e.key === 'Escape'))).subscribe(() => this.close());
|
|
507
795
|
this.open.set(true);
|
|
@@ -522,24 +810,24 @@ class NxeTagBoxComponent extends NxeFormControlBase {
|
|
|
522
810
|
this.overlayRef?.dispose();
|
|
523
811
|
}
|
|
524
812
|
static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "22.1.5", ngImport: i0, type: NxeTagBoxComponent, deps: null, target: i0.ɵɵFactoryTarget.Component });
|
|
525
|
-
static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "22.1.5", type: NxeTagBoxComponent, isStandalone: true, selector: "nxe-tag-box", inputs: { dataSource: { classPropertyName: "dataSource", publicName: "dataSource", isSignal: true, isRequired: false, transformFunction: null }, displayExprInput: { classPropertyName: "displayExprInput", publicName: "displayExpr", isSignal: true, isRequired: false, transformFunction: null }, valueExprInput: { classPropertyName: "valueExprInput", publicName: "valueExpr", isSignal: true, isRequired: false, transformFunction: null }, searchExprInput: { classPropertyName: "searchExprInput", publicName: "searchExpr", isSignal: true, isRequired: false, transformFunction: null }, searchEnabledInput: { classPropertyName: "searchEnabledInput", publicName: "searchEnabled", isSignal: true, isRequired: false, transformFunction: null }, showClearButtonInput: { classPropertyName: "showClearButtonInput", publicName: "showClearButton", isSignal: true, isRequired: false, transformFunction: null }, showSelectionControlsInput: { classPropertyName: "showSelectionControlsInput", publicName: "showSelectionControls", isSignal: true, isRequired: false, transformFunction: null }, selectAllText: { classPropertyName: "selectAllText", publicName: "selectAllText", isSignal: true, isRequired: false, transformFunction: null }, showDropDownButtonInput: { classPropertyName: "showDropDownButtonInput", publicName: "showDropDownButton", isSignal: true, isRequired: false, transformFunction: null }, placeholderInput: { classPropertyName: "placeholderInput", publicName: "placeholder", isSignal: true, isRequired: false, transformFunction: null } }, host: { listeners: { "keydown": "onKeydown($event)" }, properties: { "class.nxe-focused": "focused()", "class.nxe-invalid": "
|
|
813
|
+
static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "22.1.5", type: NxeTagBoxComponent, isStandalone: true, selector: "nxe-tag-box", inputs: { dataSource: { classPropertyName: "dataSource", publicName: "dataSource", isSignal: true, isRequired: false, transformFunction: null }, displayExprInput: { classPropertyName: "displayExprInput", publicName: "displayExpr", isSignal: true, isRequired: false, transformFunction: null }, valueExprInput: { classPropertyName: "valueExprInput", publicName: "valueExpr", isSignal: true, isRequired: false, transformFunction: null }, searchExprInput: { classPropertyName: "searchExprInput", publicName: "searchExpr", isSignal: true, isRequired: false, transformFunction: null }, searchEnabledInput: { classPropertyName: "searchEnabledInput", publicName: "searchEnabled", isSignal: true, isRequired: false, transformFunction: null }, showClearButtonInput: { classPropertyName: "showClearButtonInput", publicName: "showClearButton", isSignal: true, isRequired: false, transformFunction: null }, showSelectionControlsInput: { classPropertyName: "showSelectionControlsInput", publicName: "showSelectionControls", isSignal: true, isRequired: false, transformFunction: null }, selectAllText: { classPropertyName: "selectAllText", publicName: "selectAllText", isSignal: true, isRequired: false, transformFunction: null }, showDropDownButtonInput: { classPropertyName: "showDropDownButtonInput", publicName: "showDropDownButton", isSignal: true, isRequired: false, transformFunction: null }, placeholderInput: { classPropertyName: "placeholderInput", publicName: "placeholder", isSignal: true, isRequired: false, transformFunction: null }, searchTimeout: { classPropertyName: "searchTimeout", publicName: "searchTimeout", isSignal: true, isRequired: false, transformFunction: null }, minSearchLength: { classPropertyName: "minSearchLength", publicName: "minSearchLength", isSignal: true, isRequired: false, transformFunction: null }, showDataBeforeSearch: { classPropertyName: "showDataBeforeSearch", publicName: "showDataBeforeSearch", isSignal: true, isRequired: false, transformFunction: null }, pageSize: { classPropertyName: "pageSize", publicName: "pageSize", isSignal: true, isRequired: false, transformFunction: null } }, outputs: { searchChange: "searchChange" }, host: { listeners: { "keydown": "onKeydown($event)" }, properties: { "class.nxe-focused": "focused()", "class.nxe-invalid": "invalidState()", "class.nxe-open": "open()" }, classAttribute: "nxe-widget nxe-editor nxe-tagbox" }, providers: [
|
|
526
814
|
{ provide: NG_VALUE_ACCESSOR, useExisting: forwardRef(() => NxeTagBoxComponent), multi: true },
|
|
527
815
|
{ provide: NXE_VALIDATION_TARGET, useExisting: forwardRef(() => NxeTagBoxComponent) },
|
|
528
|
-
], viewQueries: [{ propertyName: "dropdownTemplate", first: true, predicate: ["dropdown"], descendants: true, isSignal: true }, { propertyName: "inputEl", first: true, predicate: ["input"], descendants: true, isSignal: true }], usesInheritance: true, ngImport: i0, template: "<!--\r\n Two columns, as dx-tag-box renders them: the wrapping tag container (dx turns\r\n `.dx-texteditor-input-container` into `.dx-tag-container`) and, beside it, the buttons \u2014 never\r\n inside it, so they cannot wrap onto a tag row and they centre on the whole editor height.\r\n-->\r\n<div class=\"nxe-editor-container\" (mousedown)=\"onFieldMousedown($event)\">\r\n <div class=\"nxe-tag-container\">\r\n @for (item of selectedItems(); track $index) {\r\n <span class=\"nxe-tag\">\r\n <span class=\"nxe-tag-text\">{{ display(item) }}</span>\r\n <!-- Rendered in every state, as dx does (m_tag_box.js appends it unconditionally);\r\n readOnly/disabled make it inert rather than removing it. -->\r\n <span class=\"nxe-tag-remove\" (mousedown)=\"removeTag(item, $event)\" aria-hidden=\"true\"></span>\r\n </span>\r\n }\r\n\r\n <input\r\n #input\r\n class=\"nxe-editor-input nxe-tag-input\"\r\n [attr.tabindex]=\"tabIndex()\"\r\n role=\"combobox\"\r\n aria-haspopup=\"listbox\"\r\n [attr.aria-expanded]=\"open()\"\r\n [attr.aria-controls]=\"open() ? panelId() : null\"\r\n\r\n [id]=\"controlId()\"\r\n [attr.aria-label]=\"ariaLabel() || null\"\r\n [attr.aria-labelledby]=\"ariaLabelledBy() || null\"\r\n [attr.aria-invalid]=\"validationError() ? true : null\"\r\n [attr.aria-required]=\"required() ? true : null\"\r\n type=\"text\"\r\n [readOnly]=\"readOnly() || !searchEnabled()\"\r\n [disabled]=\"disabled()\"\r\n [attr.placeholder]=\"selectedItems().length ? null : (placeholder() || null)\"\r\n autocomplete=\"off\"\r\n (input)=\"onSearchInput($event)\"\r\n (focus)=\"focused.set(true)\"\r\n (blur)=\"onBlur()\" />\r\n </div>\r\n\r\n @if (showClearButton() && hasValue() && !readOnly() && !disabled()) {\r\n <span class=\"nxe-select-clear\" (mousedown)=\"onClear($event)\" aria-hidden=\"true\">\r\n <!-- A \u00D816 disc with a 2px \u00D7 cut out: two 2px bars, each running corner to corner of the\r\n 8px square centred on the disc, drawn as a plus and turned 45\u00B0. -->\r\n <svg viewBox=\"0 0 18 18\" focusable=\"false\">\r\n <path fill-rule=\"evenodd\" transform=\"rotate(45 9 9)\"\r\n d=\"M9 1a8 8 0 1 1 0 16A8 8 0 1 1 9 1ZM8 3.343h2V8h4.657v2H10v4.657H8V10H3.343V8H8Z\" />\r\n </svg>\r\n </span>\r\n }\r\n @if (showDropDownButton() && !readOnly()) {\r\n <span class=\"nxe-select-arrow\" aria-hidden=\"true\">\r\n <!-- An 8x4 triangle centred in the 18px box. -->\r\n <svg viewBox=\"0 0 18 18\" focusable=\"false\"><path d=\"M5 7h8l-4 4z\" /></svg>\r\n </span>\r\n }\r\n</div>\r\n\r\n<ng-content />\r\n\r\n@if (validationError(); as error) {\r\n @if (focused()) {\r\n <div class=\"nxe-invalid-message\">{{ error }}</div>\r\n }\r\n}\r\n\r\n<ng-template #dropdown>\r\n <div class=\"nxe-select-panel\" [style.width.px]=\"panelWidth()\"\r\n [id]=\"panelId()\"\r\n role=\"listbox\"\r\n aria-multiselectable=\"true\">\r\n @if (showSelectionControls()) {\r\n <!-- dx `selectionMode: 'all'`, which showSelectionControls switches on\r\n (m_tag_box.js _listConfig): a tri-state \"Select All\" over the rows shown. Hidden\r\n while the list is empty, as `.dx-empty-collection .dx-list-select-all` is. -->\r\n @if (filteredItems().length) {\r\n <div\r\n class=\"nxe-tag-select-all\"\r\n [id]=\"panelId() + '-select-all'\"\r\n role=\"option\"\r\n [attr.aria-selected]=\"selectAllState() === true\"\r\n [attr.aria-checked]=\"selectAllState() === undefined ? 'mixed' : selectAllState()\"\r\n (mousedown)=\"toggleAll($event)\">\r\n <span\r\n class=\"nxe-tag-check\"\r\n [class.nxe-tag-checked]=\"selectAllState() === true\"\r\n [class.nxe-tag-indeterminate]=\"selectAllState() === undefined\"\r\n aria-hidden=\"true\"></span>\r\n <span class=\"nxe-tag-select-all-label\">{{ selectAllText() }}</span>\r\n </div>\r\n }\r\n @for (item of filteredItems(); track $index; let i = $index) {\r\n <div\r\n class=\"nxe-list-item nxe-tag-item\"\r\n [id]=\"optionId(i)\"\r\n role=\"option\"\r\n [attr.aria-selected]=\"isSelected(item)\"\r\n [class.nxe-list-item-selected]=\"isSelected(item)\"\r\n (mousedown)=\"toggle(item, $event)\">\r\n <span class=\"nxe-tag-check\" [class.nxe-tag-checked]=\"isSelected(item)\" aria-hidden=\"true\"></span>\r\n <span class=\"nxe-tag-item-text\">{{ display(item) }}</span>\r\n </div>\r\n } @empty {\r\n <div class=\"nxe-list-empty\">No data to display</div>\r\n }\r\n } @else {\r\n <!-- dx `selectionMode: 'multiple'`: plain rows, selection shown by the row fill. -->\r\n @for (item of filteredItems(); track $index; let i = $index) {\r\n <div\r\n class=\"nxe-list-item\"\r\n [id]=\"optionId(i)\"\r\n role=\"option\"\r\n [attr.aria-selected]=\"isSelected(item)\"\r\n [class.nxe-list-item-selected]=\"isSelected(item)\"\r\n (mousedown)=\"toggle(item, $event)\">\r\n {{ display(item) }}\r\n </div>\r\n } @empty {\r\n <div class=\"nxe-list-empty\">No data to display</div>\r\n }\r\n }\r\n </div>\r\n</ng-template>\r\n", styles: ["nxe-tag-box{cursor:pointer}nxe-tag-box .nxe-tag-container{box-sizing:border-box;position:relative;display:flex;flex:1 1 auto;flex-wrap:wrap;align-items:stretch;align-self:stretch;min-width:0;padding-bottom:4px}nxe-tag-box .nxe-tag-input{flex:1 1 60px;min-width:60px;width:auto;height:auto;min-height:30px;padding-bottom:4px}nxe-tag-box .nxe-tag-container:has(>.nxe-tag)>.nxe-tag-input{padding-inline-start:0;margin-inline-start:5px}nxe-tag-box.nxe-invalid>.nxe-editor-container:not(:has(>.nxe-select-clear,>.nxe-select-arrow))>.nxe-tag-container:not(:has(>.nxe-tag))>.nxe-tag-input{padding-inline-end:34px}nxe-tag-box .nxe-tag{box-sizing:border-box;position:relative;display:inline-flex;align-self:flex-start;justify-content:center;max-width:calc(100% - 5px);min-width:40px;margin-top:4px;margin-inline-start:4px;padding-block:3px 4px;padding-inline:6px 25px;background-color:#ddd;border-radius:2px;color:#333}nxe-tag-box .nxe-tag-text{overflow:hidden;text-overflow:ellipsis;white-space:nowrap}nxe-tag-box .nxe-tag-remove{position:absolute;inset-inline-end:0;top:0;width:25px;height:100%;cursor:pointer}nxe-tag-box .nxe-tag-remove:before,nxe-tag-box .nxe-tag-remove:after{position:absolute;top:50%;content:\"\";transform:rotate(45deg);inset-inline-end:9px;margin-top:-5px;width:3px;height:11px;background:#aaa}nxe-tag-box .nxe-tag-remove:after{inset-inline-end:5px;margin-top:-1px;width:11px;height:3px}nxe-tag-box:not(.nxe-disabled) .nxe-tag-remove:active:before,nxe-tag-box:not(.nxe-disabled) .nxe-tag-remove:active:after{background:#ddd}nxe-tag-box.nxe-disabled .nxe-tag,nxe-tag-box.nxe-disabled .nxe-tag-remove{cursor:default}nxe-tag-box .nxe-select-clear{box-sizing:border-box;flex:0 0 34px;align-self:stretch;display:inline-flex;align-items:center;justify-content:center;width:34px;min-width:34px;padding:0;color:#999;cursor:pointer}nxe-tag-box .nxe-select-clear svg{display:block;width:18px;height:18px;fill:currentColor}nxe-tag-box .nxe-select-arrow{box-sizing:border-box;position:relative;flex:0 0 34px;align-self:stretch;display:inline-flex;align-items:center;justify-content:center;width:34px;min-width:34px;padding:1px;border-radius:4px;background-clip:content-box;color:#333;cursor:pointer}nxe-tag-box .nxe-select-arrow svg{display:block;width:18px;height:18px;fill:currentColor}nxe-tag-box:hover:not(.nxe-disabled) .nxe-select-arrow,nxe-tag-box:active:not(.nxe-disabled) .nxe-select-arrow{background-color:#e6e6e6}nxe-tag-box.nxe-open .nxe-select-arrow{background-color:#b3b3b3}nxe-tag-box .nxe-editor-container:has(>.nxe-select-arrow) .nxe-editor-input{padding-inline-end:0}nxe-tag-box .nxe-editor-container:has(>.nxe-select-clear),nxe-tag-box .nxe-editor-container:has(>.nxe-select-arrow){--nxe-invalid-badge-inset: 38px}nxe-tag-box .nxe-editor-container:has(>.nxe-select-clear):has(>.nxe-select-arrow){--nxe-invalid-badge-inset: 72px}.nxe-select-panel .nxe-list-item.nxe-tag-item{display:block;position:relative;padding-block:10px;padding-inline:41px 10px}.nxe-select-panel .nxe-list-item.nxe-tag-item:hover,.nxe-select-panel .nxe-list-item.nxe-tag-item:active,.nxe-select-panel .nxe-list-item.nxe-tag-item.nxe-list-item-selected,.nxe-select-panel .nxe-list-item.nxe-tag-item.nxe-list-item-selected:hover:not(.nxe-list-item-active){background-color:transparent;color:var(--nxe-ui-text)}.nxe-tag-check{box-sizing:border-box;position:relative;display:block;width:22px;height:22px;border:1px solid var(--nxe-ui-border);border-radius:2px;background:var(--nxe-ui-surface)}.nxe-tag-check.nxe-tag-checked:after{content:\"\";position:absolute;box-sizing:border-box;top:5px;inset-inline-start:2.5px;width:15px;height:11px;background-color:var(--nxe-ui-accent);clip-path:polygon(0 5.586px,5.414px 11px,15px 1.414px,13.586px 0,5.414px 8.172px,1.414px 4.172px)}@media(forced-colors:active){.nxe-tag-check.nxe-tag-checked:after{forced-color-adjust:none;background-color:CanvasText}}.nxe-tag-check.nxe-tag-indeterminate:after{content:\"\";position:absolute;box-sizing:border-box;top:50%;inset-inline-start:50%;width:12px;height:12px;margin-top:-6px;margin-inline-start:-6px;border-radius:2px;background-color:var(--nxe-ui-accent)}@media(forced-colors:active){.nxe-tag-check.nxe-tag-indeterminate:after{forced-color-adjust:none;background-color:CanvasText}}.nxe-tag-item .nxe-tag-check{position:absolute;top:50%;inset-inline-start:10px;margin-top:-10px}.nxe-tag-item:hover .nxe-tag-check,.nxe-tag-select-all:hover .nxe-tag-check{border-color:var(--nxe-ui-checkbox-hover-border, #265a87)}.nxe-tag-select-all{box-sizing:border-box;padding-block:12px 11px;padding-inline:0;border-bottom:1px solid var(--nxe-ui-border);margin-bottom:3px;white-space:nowrap;cursor:pointer}.nxe-tag-select-all .nxe-tag-check{float:inline-start;margin-top:-1px;margin-bottom:-3px;margin-inline-start:10px}.nxe-tag-select-all-label{display:inline-block;overflow:hidden;text-overflow:ellipsis;white-space:nowrap;line-height:17px;padding:0 10px;margin-top:1px}\n"], changeDetection: i0.ChangeDetectionStrategy.OnPush, encapsulation: i0.ViewEncapsulation.None });
|
|
816
|
+
], viewQueries: [{ propertyName: "dropdownTemplate", first: true, predicate: ["dropdown"], descendants: true, isSignal: true }, { propertyName: "inputEl", first: true, predicate: ["input"], descendants: true, isSignal: true }], usesInheritance: true, ngImport: i0, template: "<!--\n Two columns, as dx-tag-box renders them: the wrapping tag container (dx turns\n `.dx-texteditor-input-container` into `.dx-tag-container`) and, beside it, the buttons \u2014 never\n inside it, so they cannot wrap onto a tag row and they centre on the whole editor height.\n-->\n<div class=\"nxe-editor-container\" (mousedown)=\"onFieldMousedown($event)\">\n <div class=\"nxe-tag-container\">\n @for (item of selectedItems(); track $index) {\n <span class=\"nxe-tag\">\n <span class=\"nxe-tag-text\">{{ display(item) }}</span>\n <!-- Rendered in every state, as dx does (m_tag_box.js appends it unconditionally);\n readOnly/disabled make it inert rather than removing it. -->\n <span class=\"nxe-tag-remove\" (mousedown)=\"removeTag(item, $event)\" aria-hidden=\"true\"></span>\n </span>\n }\n\n <input\n #input\n class=\"nxe-editor-input nxe-tag-input\"\n [attr.tabindex]=\"tabIndex()\"\n role=\"combobox\"\n aria-haspopup=\"listbox\"\n [attr.aria-expanded]=\"open()\"\n [attr.aria-controls]=\"open() ? panelId() : null\"\n\n [id]=\"controlId()\"\n [attr.aria-label]=\"ariaLabel() || null\"\n [attr.aria-labelledby]=\"ariaLabelledBy() || null\"\n [attr.aria-invalid]=\"invalidState() ? true : null\"\n [attr.aria-required]=\"required() ? true : null\"\n type=\"text\"\n [readOnly]=\"readOnly() || !searchEnabled()\"\n [disabled]=\"disabled()\"\n [attr.placeholder]=\"selectedItems().length ? null : (placeholder() || null)\"\n autocomplete=\"off\"\n (input)=\"onSearchInput($event)\"\n (focus)=\"focused.set(true)\"\n (blur)=\"onBlur()\" />\n </div>\n\n @if (showClearButton() && hasValue() && !readOnly() && !disabled()) {\n <span class=\"nxe-select-clear\" (mousedown)=\"onClear($event)\" aria-hidden=\"true\">\n <!-- A \u00D816 disc with a 2px \u00D7 cut out: two 2px bars, each running corner to corner of the\n 8px square centred on the disc, drawn as a plus and turned 45\u00B0. -->\n <svg viewBox=\"0 0 18 18\" focusable=\"false\">\n <path fill-rule=\"evenodd\" transform=\"rotate(45 9 9)\"\n d=\"M9 1a8 8 0 1 1 0 16A8 8 0 1 1 9 1ZM8 3.343h2V8h4.657v2H10v4.657H8V10H3.343V8H8Z\" />\n </svg>\n </span>\n }\n @if (showDropDownButton() && !readOnly()) {\n <span class=\"nxe-select-arrow\" aria-hidden=\"true\">\n <!-- An 8x4 triangle centred in the 18px box. -->\n <svg viewBox=\"0 0 18 18\" focusable=\"false\"><path d=\"M5 7h8l-4 4z\" /></svg>\n </span>\n }\n</div>\n\n<ng-content />\n\n@if (validationError(); as error) {\n @if (focused()) {\n <div class=\"nxe-invalid-message\">{{ error }}</div>\n }\n}\n\n<ng-template #dropdown>\n <div class=\"nxe-select-panel\" [style.width.px]=\"panelWidth()\"\n [id]=\"panelId()\"\n role=\"listbox\"\n aria-multiselectable=\"true\"\n (scroll)=\"onPanelScroll($event)\">\n @if (showSelectionControls()) {\n <!-- dx `selectionMode: 'all'`, which showSelectionControls switches on\n (m_tag_box.js _listConfig): a tri-state \"Select All\" over the rows shown. Hidden\n while the list is empty, as `.dx-empty-collection .dx-list-select-all` is. -->\n @if (filteredItems().length) {\n <div\n class=\"nxe-tag-select-all\"\n [id]=\"panelId() + '-select-all'\"\n role=\"option\"\n [attr.aria-selected]=\"selectAllState() === true\"\n [attr.aria-checked]=\"selectAllState() === undefined ? 'mixed' : selectAllState()\"\n (mousedown)=\"toggleAll($event)\">\n <span\n class=\"nxe-tag-check\"\n [class.nxe-tag-checked]=\"selectAllState() === true\"\n [class.nxe-tag-indeterminate]=\"selectAllState() === undefined\"\n aria-hidden=\"true\"></span>\n <span class=\"nxe-tag-select-all-label\">{{ selectAllText() ?? nxeMessages.t('dropdown.selectAll') }}</span>\n </div>\n }\n @for (item of filteredItems(); track $index; let i = $index) {\n <div\n class=\"nxe-list-item nxe-tag-item\"\n [id]=\"optionId(i)\"\n role=\"option\"\n [attr.aria-selected]=\"isSelected(item)\"\n [class.nxe-list-item-selected]=\"isSelected(item)\"\n (mousedown)=\"toggle(item, $event)\">\n <span class=\"nxe-tag-check\" [class.nxe-tag-checked]=\"isSelected(item)\" aria-hidden=\"true\"></span>\n <span class=\"nxe-tag-item-text\">{{ display(item) }}</span>\n </div>\n } @empty {\n <div class=\"nxe-list-empty\">{{ nxeMessages.t('dropdown.noData') }}</div>\n }\n } @else {\n <!-- dx `selectionMode: 'multiple'`: plain rows, selection shown by the row fill. -->\n @for (item of filteredItems(); track $index; let i = $index) {\n <div\n class=\"nxe-list-item\"\n [id]=\"optionId(i)\"\n role=\"option\"\n [attr.aria-selected]=\"isSelected(item)\"\n [class.nxe-list-item-selected]=\"isSelected(item)\"\n (mousedown)=\"toggle(item, $event)\">\n {{ display(item) }}\n </div>\n } @empty {\n <div class=\"nxe-list-empty\">{{ nxeMessages.t('dropdown.noData') }}</div>\n }\n }\n </div>\n</ng-template>\n", styles: ["nxe-tag-box{cursor:pointer}nxe-tag-box .nxe-tag-container{box-sizing:border-box;position:relative;display:flex;flex:1 1 auto;flex-wrap:wrap;align-items:stretch;align-self:stretch;min-width:0;padding-bottom:4px}nxe-tag-box .nxe-tag-input{flex:1 1 60px;min-width:60px;width:auto;height:auto;min-height:30px;padding-bottom:4px}nxe-tag-box .nxe-tag-container:has(>.nxe-tag)>.nxe-tag-input{padding-inline-start:0;margin-inline-start:5px}nxe-tag-box.nxe-invalid>.nxe-editor-container:not(:has(>.nxe-select-clear,>.nxe-select-arrow))>.nxe-tag-container:not(:has(>.nxe-tag))>.nxe-tag-input{padding-inline-end:34px}nxe-tag-box .nxe-tag{box-sizing:border-box;position:relative;display:inline-flex;align-self:flex-start;justify-content:center;max-width:calc(100% - 5px);min-width:40px;margin-top:4px;margin-inline-start:4px;padding-block:3px 4px;padding-inline:6px 25px;background-color:var(--nxe-ui-border, #ddd);border-radius:2px;color:var(--nxe-ui-text, #333)}nxe-tag-box .nxe-tag-text{overflow:hidden;text-overflow:ellipsis;white-space:nowrap}nxe-tag-box .nxe-tag-remove{position:absolute;inset-inline-end:0;top:0;width:25px;height:100%;cursor:pointer}nxe-tag-box .nxe-tag-remove:before,nxe-tag-box .nxe-tag-remove:after{position:absolute;top:50%;content:\"\";transform:rotate(45deg);inset-inline-end:9px;margin-top:-5px;width:3px;height:11px;background:var(--nxe-ui-neutral-400, #aaa)}nxe-tag-box .nxe-tag-remove:after{inset-inline-end:5px;margin-top:-1px;width:11px;height:3px}nxe-tag-box:not(.nxe-disabled) .nxe-tag-remove:active:before,nxe-tag-box:not(.nxe-disabled) .nxe-tag-remove:active:after{background:var(--nxe-ui-border, #ddd)}nxe-tag-box.nxe-disabled .nxe-tag,nxe-tag-box.nxe-disabled .nxe-tag-remove{cursor:default}nxe-tag-box .nxe-select-clear{box-sizing:border-box;flex:0 0 34px;align-self:stretch;display:inline-flex;align-items:center;justify-content:center;width:34px;min-width:34px;padding:0;color:var(--nxe-ui-text-muted, #999);cursor:pointer}nxe-tag-box .nxe-select-clear svg{display:block;width:18px;height:18px;fill:currentColor}nxe-tag-box .nxe-select-arrow{box-sizing:border-box;position:relative;flex:0 0 34px;align-self:stretch;display:inline-flex;align-items:center;justify-content:center;width:34px;min-width:34px;padding:1px;border-radius:4px;background-clip:content-box;color:var(--nxe-ui-text, #333);cursor:pointer}nxe-tag-box .nxe-select-arrow svg{display:block;width:18px;height:18px;fill:currentColor}nxe-tag-box:hover:not(.nxe-disabled) .nxe-select-arrow,nxe-tag-box:active:not(.nxe-disabled) .nxe-select-arrow{background-color:var(--nxe-ui-neutral-150, #e6e6e6)}nxe-tag-box.nxe-open .nxe-select-arrow{background-color:var(--nxe-ui-neutral-350, #b3b3b3)}nxe-tag-box .nxe-editor-container:has(>.nxe-select-arrow) .nxe-editor-input{padding-inline-end:0}nxe-tag-box .nxe-editor-container:has(>.nxe-select-clear),nxe-tag-box .nxe-editor-container:has(>.nxe-select-arrow){--nxe-invalid-badge-inset: 38px}nxe-tag-box .nxe-editor-container:has(>.nxe-select-clear):has(>.nxe-select-arrow){--nxe-invalid-badge-inset: 72px}.nxe-select-panel .nxe-list-item.nxe-tag-item{display:block;position:relative;padding-block:10px;padding-inline:41px 10px}.nxe-select-panel .nxe-list-item.nxe-tag-item:hover,.nxe-select-panel .nxe-list-item.nxe-tag-item:active,.nxe-select-panel .nxe-list-item.nxe-tag-item.nxe-list-item-selected,.nxe-select-panel .nxe-list-item.nxe-tag-item.nxe-list-item-selected:hover:not(.nxe-list-item-active){background-color:transparent;color:var(--nxe-ui-text)}.nxe-tag-check{box-sizing:border-box;position:relative;display:block;width:22px;height:22px;border:1px solid var(--nxe-ui-border);border-radius:2px;background:var(--nxe-ui-surface)}.nxe-tag-check.nxe-tag-checked:after{content:\"\";position:absolute;box-sizing:border-box;top:5px;inset-inline-start:2.5px;width:15px;height:11px;background-color:var(--nxe-ui-accent);clip-path:polygon(0 5.586px,5.414px 11px,15px 1.414px,13.586px 0,5.414px 8.172px,1.414px 4.172px)}@media(forced-colors:active){.nxe-tag-check.nxe-tag-checked:after{forced-color-adjust:none;background-color:CanvasText}}.nxe-tag-check.nxe-tag-indeterminate:after{content:\"\";position:absolute;box-sizing:border-box;top:50%;inset-inline-start:50%;width:12px;height:12px;margin-top:-6px;margin-inline-start:-6px;border-radius:2px;background-color:var(--nxe-ui-accent)}@media(forced-colors:active){.nxe-tag-check.nxe-tag-indeterminate:after{forced-color-adjust:none;background-color:CanvasText}}.nxe-tag-item .nxe-tag-check{position:absolute;top:50%;inset-inline-start:10px;margin-top:-10px}.nxe-tag-item:hover .nxe-tag-check,.nxe-tag-select-all:hover .nxe-tag-check{border-color:var(--nxe-ui-checkbox-hover-border, #265a87)}.nxe-tag-select-all{box-sizing:border-box;padding-block:12px 11px;padding-inline:0;border-bottom:1px solid var(--nxe-ui-border);margin-bottom:3px;white-space:nowrap;cursor:pointer}.nxe-tag-select-all .nxe-tag-check{float:inline-start;margin-top:-1px;margin-bottom:-3px;margin-inline-start:10px}.nxe-tag-select-all-label{display:inline-block;overflow:hidden;text-overflow:ellipsis;white-space:nowrap;line-height:17px;padding:0 10px;margin-top:1px}\n"], changeDetection: i0.ChangeDetectionStrategy.OnPush, encapsulation: i0.ViewEncapsulation.None });
|
|
529
817
|
}
|
|
530
818
|
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "22.1.5", ngImport: i0, type: NxeTagBoxComponent, decorators: [{
|
|
531
819
|
type: Component,
|
|
532
820
|
args: [{ selector: 'nxe-tag-box', standalone: true, host: {
|
|
533
821
|
class: 'nxe-widget nxe-editor nxe-tagbox',
|
|
534
822
|
'[class.nxe-focused]': 'focused()',
|
|
535
|
-
'[class.nxe-invalid]': '
|
|
823
|
+
'[class.nxe-invalid]': 'invalidState()',
|
|
536
824
|
'[class.nxe-open]': 'open()',
|
|
537
825
|
'(keydown)': 'onKeydown($event)',
|
|
538
826
|
}, providers: [
|
|
539
827
|
{ provide: NG_VALUE_ACCESSOR, useExisting: forwardRef(() => NxeTagBoxComponent), multi: true },
|
|
540
828
|
{ provide: NXE_VALIDATION_TARGET, useExisting: forwardRef(() => NxeTagBoxComponent) },
|
|
541
|
-
], changeDetection: ChangeDetectionStrategy.OnPush, encapsulation: ViewEncapsulation.None, template: "<!--\r\n Two columns, as dx-tag-box renders them: the wrapping tag container (dx turns\r\n `.dx-texteditor-input-container` into `.dx-tag-container`) and, beside it, the buttons \u2014 never\r\n inside it, so they cannot wrap onto a tag row and they centre on the whole editor height.\r\n-->\r\n<div class=\"nxe-editor-container\" (mousedown)=\"onFieldMousedown($event)\">\r\n <div class=\"nxe-tag-container\">\r\n @for (item of selectedItems(); track $index) {\r\n <span class=\"nxe-tag\">\r\n <span class=\"nxe-tag-text\">{{ display(item) }}</span>\r\n <!-- Rendered in every state, as dx does (m_tag_box.js appends it unconditionally);\r\n readOnly/disabled make it inert rather than removing it. -->\r\n <span class=\"nxe-tag-remove\" (mousedown)=\"removeTag(item, $event)\" aria-hidden=\"true\"></span>\r\n </span>\r\n }\r\n\r\n <input\r\n #input\r\n class=\"nxe-editor-input nxe-tag-input\"\r\n [attr.tabindex]=\"tabIndex()\"\r\n role=\"combobox\"\r\n aria-haspopup=\"listbox\"\r\n [attr.aria-expanded]=\"open()\"\r\n [attr.aria-controls]=\"open() ? panelId() : null\"\r\n\r\n [id]=\"controlId()\"\r\n [attr.aria-label]=\"ariaLabel() || null\"\r\n [attr.aria-labelledby]=\"ariaLabelledBy() || null\"\r\n [attr.aria-invalid]=\"validationError() ? true : null\"\r\n [attr.aria-required]=\"required() ? true : null\"\r\n type=\"text\"\r\n [readOnly]=\"readOnly() || !searchEnabled()\"\r\n [disabled]=\"disabled()\"\r\n [attr.placeholder]=\"selectedItems().length ? null : (placeholder() || null)\"\r\n autocomplete=\"off\"\r\n (input)=\"onSearchInput($event)\"\r\n (focus)=\"focused.set(true)\"\r\n (blur)=\"onBlur()\" />\r\n </div>\r\n\r\n @if (showClearButton() && hasValue() && !readOnly() && !disabled()) {\r\n <span class=\"nxe-select-clear\" (mousedown)=\"onClear($event)\" aria-hidden=\"true\">\r\n <!-- A \u00D816 disc with a 2px \u00D7 cut out: two 2px bars, each running corner to corner of the\r\n 8px square centred on the disc, drawn as a plus and turned 45\u00B0. -->\r\n <svg viewBox=\"0 0 18 18\" focusable=\"false\">\r\n <path fill-rule=\"evenodd\" transform=\"rotate(45 9 9)\"\r\n d=\"M9 1a8 8 0 1 1 0 16A8 8 0 1 1 9 1ZM8 3.343h2V8h4.657v2H10v4.657H8V10H3.343V8H8Z\" />\r\n </svg>\r\n </span>\r\n }\r\n @if (showDropDownButton() && !readOnly()) {\r\n <span class=\"nxe-select-arrow\" aria-hidden=\"true\">\r\n <!-- An 8x4 triangle centred in the 18px box. -->\r\n <svg viewBox=\"0 0 18 18\" focusable=\"false\"><path d=\"M5 7h8l-4 4z\" /></svg>\r\n </span>\r\n }\r\n</div>\r\n\r\n<ng-content />\r\n\r\n@if (validationError(); as error) {\r\n @if (focused()) {\r\n <div class=\"nxe-invalid-message\">{{ error }}</div>\r\n }\r\n}\r\n\r\n<ng-template #dropdown>\r\n <div class=\"nxe-select-panel\" [style.width.px]=\"panelWidth()\"\r\n [id]=\"panelId()\"\r\n role=\"listbox\"\r\n aria-multiselectable=\"true\">\r\n @if (showSelectionControls()) {\r\n <!-- dx `selectionMode: 'all'`, which showSelectionControls switches on\r\n (m_tag_box.js _listConfig): a tri-state \"Select All\" over the rows shown. Hidden\r\n while the list is empty, as `.dx-empty-collection .dx-list-select-all` is. -->\r\n @if (filteredItems().length) {\r\n <div\r\n class=\"nxe-tag-select-all\"\r\n [id]=\"panelId() + '-select-all'\"\r\n role=\"option\"\r\n [attr.aria-selected]=\"selectAllState() === true\"\r\n [attr.aria-checked]=\"selectAllState() === undefined ? 'mixed' : selectAllState()\"\r\n (mousedown)=\"toggleAll($event)\">\r\n <span\r\n class=\"nxe-tag-check\"\r\n [class.nxe-tag-checked]=\"selectAllState() === true\"\r\n [class.nxe-tag-indeterminate]=\"selectAllState() === undefined\"\r\n aria-hidden=\"true\"></span>\r\n <span class=\"nxe-tag-select-all-label\">{{ selectAllText() }}</span>\r\n </div>\r\n }\r\n @for (item of filteredItems(); track $index; let i = $index) {\r\n <div\r\n class=\"nxe-list-item nxe-tag-item\"\r\n [id]=\"optionId(i)\"\r\n role=\"option\"\r\n [attr.aria-selected]=\"isSelected(item)\"\r\n [class.nxe-list-item-selected]=\"isSelected(item)\"\r\n (mousedown)=\"toggle(item, $event)\">\r\n <span class=\"nxe-tag-check\" [class.nxe-tag-checked]=\"isSelected(item)\" aria-hidden=\"true\"></span>\r\n <span class=\"nxe-tag-item-text\">{{ display(item) }}</span>\r\n </div>\r\n } @empty {\r\n <div class=\"nxe-list-empty\">No data to display</div>\r\n }\r\n } @else {\r\n <!-- dx `selectionMode: 'multiple'`: plain rows, selection shown by the row fill. -->\r\n @for (item of filteredItems(); track $index; let i = $index) {\r\n <div\r\n class=\"nxe-list-item\"\r\n [id]=\"optionId(i)\"\r\n role=\"option\"\r\n [attr.aria-selected]=\"isSelected(item)\"\r\n [class.nxe-list-item-selected]=\"isSelected(item)\"\r\n (mousedown)=\"toggle(item, $event)\">\r\n {{ display(item) }}\r\n </div>\r\n } @empty {\r\n <div class=\"nxe-list-empty\">No data to display</div>\r\n }\r\n }\r\n </div>\r\n</ng-template>\r\n", styles: ["nxe-tag-box{cursor:pointer}nxe-tag-box .nxe-tag-container{box-sizing:border-box;position:relative;display:flex;flex:1 1 auto;flex-wrap:wrap;align-items:stretch;align-self:stretch;min-width:0;padding-bottom:4px}nxe-tag-box .nxe-tag-input{flex:1 1 60px;min-width:60px;width:auto;height:auto;min-height:30px;padding-bottom:4px}nxe-tag-box .nxe-tag-container:has(>.nxe-tag)>.nxe-tag-input{padding-inline-start:0;margin-inline-start:5px}nxe-tag-box.nxe-invalid>.nxe-editor-container:not(:has(>.nxe-select-clear,>.nxe-select-arrow))>.nxe-tag-container:not(:has(>.nxe-tag))>.nxe-tag-input{padding-inline-end:34px}nxe-tag-box .nxe-tag{box-sizing:border-box;position:relative;display:inline-flex;align-self:flex-start;justify-content:center;max-width:calc(100% - 5px);min-width:40px;margin-top:4px;margin-inline-start:4px;padding-block:3px 4px;padding-inline:6px 25px;background-color:#ddd;border-radius:2px;color:#333}nxe-tag-box .nxe-tag-text{overflow:hidden;text-overflow:ellipsis;white-space:nowrap}nxe-tag-box .nxe-tag-remove{position:absolute;inset-inline-end:0;top:0;width:25px;height:100%;cursor:pointer}nxe-tag-box .nxe-tag-remove:before,nxe-tag-box .nxe-tag-remove:after{position:absolute;top:50%;content:\"\";transform:rotate(45deg);inset-inline-end:9px;margin-top:-5px;width:3px;height:11px;background:#aaa}nxe-tag-box .nxe-tag-remove:after{inset-inline-end:5px;margin-top:-1px;width:11px;height:3px}nxe-tag-box:not(.nxe-disabled) .nxe-tag-remove:active:before,nxe-tag-box:not(.nxe-disabled) .nxe-tag-remove:active:after{background:#ddd}nxe-tag-box.nxe-disabled .nxe-tag,nxe-tag-box.nxe-disabled .nxe-tag-remove{cursor:default}nxe-tag-box .nxe-select-clear{box-sizing:border-box;flex:0 0 34px;align-self:stretch;display:inline-flex;align-items:center;justify-content:center;width:34px;min-width:34px;padding:0;color:#999;cursor:pointer}nxe-tag-box .nxe-select-clear svg{display:block;width:18px;height:18px;fill:currentColor}nxe-tag-box .nxe-select-arrow{box-sizing:border-box;position:relative;flex:0 0 34px;align-self:stretch;display:inline-flex;align-items:center;justify-content:center;width:34px;min-width:34px;padding:1px;border-radius:4px;background-clip:content-box;color:#333;cursor:pointer}nxe-tag-box .nxe-select-arrow svg{display:block;width:18px;height:18px;fill:currentColor}nxe-tag-box:hover:not(.nxe-disabled) .nxe-select-arrow,nxe-tag-box:active:not(.nxe-disabled) .nxe-select-arrow{background-color:#e6e6e6}nxe-tag-box.nxe-open .nxe-select-arrow{background-color:#b3b3b3}nxe-tag-box .nxe-editor-container:has(>.nxe-select-arrow) .nxe-editor-input{padding-inline-end:0}nxe-tag-box .nxe-editor-container:has(>.nxe-select-clear),nxe-tag-box .nxe-editor-container:has(>.nxe-select-arrow){--nxe-invalid-badge-inset: 38px}nxe-tag-box .nxe-editor-container:has(>.nxe-select-clear):has(>.nxe-select-arrow){--nxe-invalid-badge-inset: 72px}.nxe-select-panel .nxe-list-item.nxe-tag-item{display:block;position:relative;padding-block:10px;padding-inline:41px 10px}.nxe-select-panel .nxe-list-item.nxe-tag-item:hover,.nxe-select-panel .nxe-list-item.nxe-tag-item:active,.nxe-select-panel .nxe-list-item.nxe-tag-item.nxe-list-item-selected,.nxe-select-panel .nxe-list-item.nxe-tag-item.nxe-list-item-selected:hover:not(.nxe-list-item-active){background-color:transparent;color:var(--nxe-ui-text)}.nxe-tag-check{box-sizing:border-box;position:relative;display:block;width:22px;height:22px;border:1px solid var(--nxe-ui-border);border-radius:2px;background:var(--nxe-ui-surface)}.nxe-tag-check.nxe-tag-checked:after{content:\"\";position:absolute;box-sizing:border-box;top:5px;inset-inline-start:2.5px;width:15px;height:11px;background-color:var(--nxe-ui-accent);clip-path:polygon(0 5.586px,5.414px 11px,15px 1.414px,13.586px 0,5.414px 8.172px,1.414px 4.172px)}@media(forced-colors:active){.nxe-tag-check.nxe-tag-checked:after{forced-color-adjust:none;background-color:CanvasText}}.nxe-tag-check.nxe-tag-indeterminate:after{content:\"\";position:absolute;box-sizing:border-box;top:50%;inset-inline-start:50%;width:12px;height:12px;margin-top:-6px;margin-inline-start:-6px;border-radius:2px;background-color:var(--nxe-ui-accent)}@media(forced-colors:active){.nxe-tag-check.nxe-tag-indeterminate:after{forced-color-adjust:none;background-color:CanvasText}}.nxe-tag-item .nxe-tag-check{position:absolute;top:50%;inset-inline-start:10px;margin-top:-10px}.nxe-tag-item:hover .nxe-tag-check,.nxe-tag-select-all:hover .nxe-tag-check{border-color:var(--nxe-ui-checkbox-hover-border, #265a87)}.nxe-tag-select-all{box-sizing:border-box;padding-block:12px 11px;padding-inline:0;border-bottom:1px solid var(--nxe-ui-border);margin-bottom:3px;white-space:nowrap;cursor:pointer}.nxe-tag-select-all .nxe-tag-check{float:inline-start;margin-top:-1px;margin-bottom:-3px;margin-inline-start:10px}.nxe-tag-select-all-label{display:inline-block;overflow:hidden;text-overflow:ellipsis;white-space:nowrap;line-height:17px;padding:0 10px;margin-top:1px}\n"] }]
|
|
542
|
-
}], propDecorators: { dropdownTemplate: [{ type: i0.ViewChild, args: ['dropdown', { isSignal: true }] }], inputEl: [{ type: i0.ViewChild, args: ['input', { isSignal: true }] }], dataSource: [{ type: i0.Input, args: [{ isSignal: true, alias: "dataSource", required: false }] }], displayExprInput: [{ type: i0.Input, args: [{ isSignal: true, alias: "displayExpr", required: false }] }], valueExprInput: [{ type: i0.Input, args: [{ isSignal: true, alias: "valueExpr", required: false }] }], searchExprInput: [{ type: i0.Input, args: [{ isSignal: true, alias: "searchExpr", required: false }] }], searchEnabledInput: [{ type: i0.Input, args: [{ isSignal: true, alias: "searchEnabled", required: false }] }], showClearButtonInput: [{ type: i0.Input, args: [{ isSignal: true, alias: "showClearButton", required: false }] }], showSelectionControlsInput: [{ type: i0.Input, args: [{ isSignal: true, alias: "showSelectionControls", required: false }] }], selectAllText: [{ type: i0.Input, args: [{ isSignal: true, alias: "selectAllText", required: false }] }], showDropDownButtonInput: [{ type: i0.Input, args: [{ isSignal: true, alias: "showDropDownButton", required: false }] }], placeholderInput: [{ type: i0.Input, args: [{ isSignal: true, alias: "placeholder", required: false }] }] } });
|
|
829
|
+
], changeDetection: ChangeDetectionStrategy.OnPush, encapsulation: ViewEncapsulation.None, template: "<!--\n Two columns, as dx-tag-box renders them: the wrapping tag container (dx turns\n `.dx-texteditor-input-container` into `.dx-tag-container`) and, beside it, the buttons \u2014 never\n inside it, so they cannot wrap onto a tag row and they centre on the whole editor height.\n-->\n<div class=\"nxe-editor-container\" (mousedown)=\"onFieldMousedown($event)\">\n <div class=\"nxe-tag-container\">\n @for (item of selectedItems(); track $index) {\n <span class=\"nxe-tag\">\n <span class=\"nxe-tag-text\">{{ display(item) }}</span>\n <!-- Rendered in every state, as dx does (m_tag_box.js appends it unconditionally);\n readOnly/disabled make it inert rather than removing it. -->\n <span class=\"nxe-tag-remove\" (mousedown)=\"removeTag(item, $event)\" aria-hidden=\"true\"></span>\n </span>\n }\n\n <input\n #input\n class=\"nxe-editor-input nxe-tag-input\"\n [attr.tabindex]=\"tabIndex()\"\n role=\"combobox\"\n aria-haspopup=\"listbox\"\n [attr.aria-expanded]=\"open()\"\n [attr.aria-controls]=\"open() ? panelId() : null\"\n\n [id]=\"controlId()\"\n [attr.aria-label]=\"ariaLabel() || null\"\n [attr.aria-labelledby]=\"ariaLabelledBy() || null\"\n [attr.aria-invalid]=\"invalidState() ? true : null\"\n [attr.aria-required]=\"required() ? true : null\"\n type=\"text\"\n [readOnly]=\"readOnly() || !searchEnabled()\"\n [disabled]=\"disabled()\"\n [attr.placeholder]=\"selectedItems().length ? null : (placeholder() || null)\"\n autocomplete=\"off\"\n (input)=\"onSearchInput($event)\"\n (focus)=\"focused.set(true)\"\n (blur)=\"onBlur()\" />\n </div>\n\n @if (showClearButton() && hasValue() && !readOnly() && !disabled()) {\n <span class=\"nxe-select-clear\" (mousedown)=\"onClear($event)\" aria-hidden=\"true\">\n <!-- A \u00D816 disc with a 2px \u00D7 cut out: two 2px bars, each running corner to corner of the\n 8px square centred on the disc, drawn as a plus and turned 45\u00B0. -->\n <svg viewBox=\"0 0 18 18\" focusable=\"false\">\n <path fill-rule=\"evenodd\" transform=\"rotate(45 9 9)\"\n d=\"M9 1a8 8 0 1 1 0 16A8 8 0 1 1 9 1ZM8 3.343h2V8h4.657v2H10v4.657H8V10H3.343V8H8Z\" />\n </svg>\n </span>\n }\n @if (showDropDownButton() && !readOnly()) {\n <span class=\"nxe-select-arrow\" aria-hidden=\"true\">\n <!-- An 8x4 triangle centred in the 18px box. -->\n <svg viewBox=\"0 0 18 18\" focusable=\"false\"><path d=\"M5 7h8l-4 4z\" /></svg>\n </span>\n }\n</div>\n\n<ng-content />\n\n@if (validationError(); as error) {\n @if (focused()) {\n <div class=\"nxe-invalid-message\">{{ error }}</div>\n }\n}\n\n<ng-template #dropdown>\n <div class=\"nxe-select-panel\" [style.width.px]=\"panelWidth()\"\n [id]=\"panelId()\"\n role=\"listbox\"\n aria-multiselectable=\"true\"\n (scroll)=\"onPanelScroll($event)\">\n @if (showSelectionControls()) {\n <!-- dx `selectionMode: 'all'`, which showSelectionControls switches on\n (m_tag_box.js _listConfig): a tri-state \"Select All\" over the rows shown. Hidden\n while the list is empty, as `.dx-empty-collection .dx-list-select-all` is. -->\n @if (filteredItems().length) {\n <div\n class=\"nxe-tag-select-all\"\n [id]=\"panelId() + '-select-all'\"\n role=\"option\"\n [attr.aria-selected]=\"selectAllState() === true\"\n [attr.aria-checked]=\"selectAllState() === undefined ? 'mixed' : selectAllState()\"\n (mousedown)=\"toggleAll($event)\">\n <span\n class=\"nxe-tag-check\"\n [class.nxe-tag-checked]=\"selectAllState() === true\"\n [class.nxe-tag-indeterminate]=\"selectAllState() === undefined\"\n aria-hidden=\"true\"></span>\n <span class=\"nxe-tag-select-all-label\">{{ selectAllText() ?? nxeMessages.t('dropdown.selectAll') }}</span>\n </div>\n }\n @for (item of filteredItems(); track $index; let i = $index) {\n <div\n class=\"nxe-list-item nxe-tag-item\"\n [id]=\"optionId(i)\"\n role=\"option\"\n [attr.aria-selected]=\"isSelected(item)\"\n [class.nxe-list-item-selected]=\"isSelected(item)\"\n (mousedown)=\"toggle(item, $event)\">\n <span class=\"nxe-tag-check\" [class.nxe-tag-checked]=\"isSelected(item)\" aria-hidden=\"true\"></span>\n <span class=\"nxe-tag-item-text\">{{ display(item) }}</span>\n </div>\n } @empty {\n <div class=\"nxe-list-empty\">{{ nxeMessages.t('dropdown.noData') }}</div>\n }\n } @else {\n <!-- dx `selectionMode: 'multiple'`: plain rows, selection shown by the row fill. -->\n @for (item of filteredItems(); track $index; let i = $index) {\n <div\n class=\"nxe-list-item\"\n [id]=\"optionId(i)\"\n role=\"option\"\n [attr.aria-selected]=\"isSelected(item)\"\n [class.nxe-list-item-selected]=\"isSelected(item)\"\n (mousedown)=\"toggle(item, $event)\">\n {{ display(item) }}\n </div>\n } @empty {\n <div class=\"nxe-list-empty\">{{ nxeMessages.t('dropdown.noData') }}</div>\n }\n }\n </div>\n</ng-template>\n", styles: ["nxe-tag-box{cursor:pointer}nxe-tag-box .nxe-tag-container{box-sizing:border-box;position:relative;display:flex;flex:1 1 auto;flex-wrap:wrap;align-items:stretch;align-self:stretch;min-width:0;padding-bottom:4px}nxe-tag-box .nxe-tag-input{flex:1 1 60px;min-width:60px;width:auto;height:auto;min-height:30px;padding-bottom:4px}nxe-tag-box .nxe-tag-container:has(>.nxe-tag)>.nxe-tag-input{padding-inline-start:0;margin-inline-start:5px}nxe-tag-box.nxe-invalid>.nxe-editor-container:not(:has(>.nxe-select-clear,>.nxe-select-arrow))>.nxe-tag-container:not(:has(>.nxe-tag))>.nxe-tag-input{padding-inline-end:34px}nxe-tag-box .nxe-tag{box-sizing:border-box;position:relative;display:inline-flex;align-self:flex-start;justify-content:center;max-width:calc(100% - 5px);min-width:40px;margin-top:4px;margin-inline-start:4px;padding-block:3px 4px;padding-inline:6px 25px;background-color:var(--nxe-ui-border, #ddd);border-radius:2px;color:var(--nxe-ui-text, #333)}nxe-tag-box .nxe-tag-text{overflow:hidden;text-overflow:ellipsis;white-space:nowrap}nxe-tag-box .nxe-tag-remove{position:absolute;inset-inline-end:0;top:0;width:25px;height:100%;cursor:pointer}nxe-tag-box .nxe-tag-remove:before,nxe-tag-box .nxe-tag-remove:after{position:absolute;top:50%;content:\"\";transform:rotate(45deg);inset-inline-end:9px;margin-top:-5px;width:3px;height:11px;background:var(--nxe-ui-neutral-400, #aaa)}nxe-tag-box .nxe-tag-remove:after{inset-inline-end:5px;margin-top:-1px;width:11px;height:3px}nxe-tag-box:not(.nxe-disabled) .nxe-tag-remove:active:before,nxe-tag-box:not(.nxe-disabled) .nxe-tag-remove:active:after{background:var(--nxe-ui-border, #ddd)}nxe-tag-box.nxe-disabled .nxe-tag,nxe-tag-box.nxe-disabled .nxe-tag-remove{cursor:default}nxe-tag-box .nxe-select-clear{box-sizing:border-box;flex:0 0 34px;align-self:stretch;display:inline-flex;align-items:center;justify-content:center;width:34px;min-width:34px;padding:0;color:var(--nxe-ui-text-muted, #999);cursor:pointer}nxe-tag-box .nxe-select-clear svg{display:block;width:18px;height:18px;fill:currentColor}nxe-tag-box .nxe-select-arrow{box-sizing:border-box;position:relative;flex:0 0 34px;align-self:stretch;display:inline-flex;align-items:center;justify-content:center;width:34px;min-width:34px;padding:1px;border-radius:4px;background-clip:content-box;color:var(--nxe-ui-text, #333);cursor:pointer}nxe-tag-box .nxe-select-arrow svg{display:block;width:18px;height:18px;fill:currentColor}nxe-tag-box:hover:not(.nxe-disabled) .nxe-select-arrow,nxe-tag-box:active:not(.nxe-disabled) .nxe-select-arrow{background-color:var(--nxe-ui-neutral-150, #e6e6e6)}nxe-tag-box.nxe-open .nxe-select-arrow{background-color:var(--nxe-ui-neutral-350, #b3b3b3)}nxe-tag-box .nxe-editor-container:has(>.nxe-select-arrow) .nxe-editor-input{padding-inline-end:0}nxe-tag-box .nxe-editor-container:has(>.nxe-select-clear),nxe-tag-box .nxe-editor-container:has(>.nxe-select-arrow){--nxe-invalid-badge-inset: 38px}nxe-tag-box .nxe-editor-container:has(>.nxe-select-clear):has(>.nxe-select-arrow){--nxe-invalid-badge-inset: 72px}.nxe-select-panel .nxe-list-item.nxe-tag-item{display:block;position:relative;padding-block:10px;padding-inline:41px 10px}.nxe-select-panel .nxe-list-item.nxe-tag-item:hover,.nxe-select-panel .nxe-list-item.nxe-tag-item:active,.nxe-select-panel .nxe-list-item.nxe-tag-item.nxe-list-item-selected,.nxe-select-panel .nxe-list-item.nxe-tag-item.nxe-list-item-selected:hover:not(.nxe-list-item-active){background-color:transparent;color:var(--nxe-ui-text)}.nxe-tag-check{box-sizing:border-box;position:relative;display:block;width:22px;height:22px;border:1px solid var(--nxe-ui-border);border-radius:2px;background:var(--nxe-ui-surface)}.nxe-tag-check.nxe-tag-checked:after{content:\"\";position:absolute;box-sizing:border-box;top:5px;inset-inline-start:2.5px;width:15px;height:11px;background-color:var(--nxe-ui-accent);clip-path:polygon(0 5.586px,5.414px 11px,15px 1.414px,13.586px 0,5.414px 8.172px,1.414px 4.172px)}@media(forced-colors:active){.nxe-tag-check.nxe-tag-checked:after{forced-color-adjust:none;background-color:CanvasText}}.nxe-tag-check.nxe-tag-indeterminate:after{content:\"\";position:absolute;box-sizing:border-box;top:50%;inset-inline-start:50%;width:12px;height:12px;margin-top:-6px;margin-inline-start:-6px;border-radius:2px;background-color:var(--nxe-ui-accent)}@media(forced-colors:active){.nxe-tag-check.nxe-tag-indeterminate:after{forced-color-adjust:none;background-color:CanvasText}}.nxe-tag-item .nxe-tag-check{position:absolute;top:50%;inset-inline-start:10px;margin-top:-10px}.nxe-tag-item:hover .nxe-tag-check,.nxe-tag-select-all:hover .nxe-tag-check{border-color:var(--nxe-ui-checkbox-hover-border, #265a87)}.nxe-tag-select-all{box-sizing:border-box;padding-block:12px 11px;padding-inline:0;border-bottom:1px solid var(--nxe-ui-border);margin-bottom:3px;white-space:nowrap;cursor:pointer}.nxe-tag-select-all .nxe-tag-check{float:inline-start;margin-top:-1px;margin-bottom:-3px;margin-inline-start:10px}.nxe-tag-select-all-label{display:inline-block;overflow:hidden;text-overflow:ellipsis;white-space:nowrap;line-height:17px;padding:0 10px;margin-top:1px}\n"] }]
|
|
830
|
+
}], propDecorators: { dropdownTemplate: [{ type: i0.ViewChild, args: ['dropdown', { isSignal: true }] }], inputEl: [{ type: i0.ViewChild, args: ['input', { isSignal: true }] }], dataSource: [{ type: i0.Input, args: [{ isSignal: true, alias: "dataSource", required: false }] }], displayExprInput: [{ type: i0.Input, args: [{ isSignal: true, alias: "displayExpr", required: false }] }], valueExprInput: [{ type: i0.Input, args: [{ isSignal: true, alias: "valueExpr", required: false }] }], searchExprInput: [{ type: i0.Input, args: [{ isSignal: true, alias: "searchExpr", required: false }] }], searchEnabledInput: [{ type: i0.Input, args: [{ isSignal: true, alias: "searchEnabled", required: false }] }], showClearButtonInput: [{ type: i0.Input, args: [{ isSignal: true, alias: "showClearButton", required: false }] }], showSelectionControlsInput: [{ type: i0.Input, args: [{ isSignal: true, alias: "showSelectionControls", required: false }] }], selectAllText: [{ type: i0.Input, args: [{ isSignal: true, alias: "selectAllText", required: false }] }], showDropDownButtonInput: [{ type: i0.Input, args: [{ isSignal: true, alias: "showDropDownButton", required: false }] }], placeholderInput: [{ type: i0.Input, args: [{ isSignal: true, alias: "placeholder", required: false }] }], searchTimeout: [{ type: i0.Input, args: [{ isSignal: true, alias: "searchTimeout", required: false }] }], minSearchLength: [{ type: i0.Input, args: [{ isSignal: true, alias: "minSearchLength", required: false }] }], showDataBeforeSearch: [{ type: i0.Input, args: [{ isSignal: true, alias: "showDataBeforeSearch", required: false }] }], pageSize: [{ type: i0.Input, args: [{ isSignal: true, alias: "pageSize", required: false }] }], searchChange: [{ type: i0.Output, args: ["searchChange"] }] } });
|
|
543
831
|
|
|
544
832
|
/**
|
|
545
833
|
* `nxe-drop-down-options` — drop-in for DevExtreme `dxo-drop-down-options`, a no-template config
|
|
@@ -744,22 +1032,22 @@ class NxeDropDownBoxComponent extends NxeFormControlBase {
|
|
|
744
1032
|
this.overlayRef?.dispose();
|
|
745
1033
|
}
|
|
746
1034
|
static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "22.1.5", ngImport: i0, type: NxeDropDownBoxComponent, deps: [], target: i0.ɵɵFactoryTarget.Component });
|
|
747
|
-
static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "22.1.5", type: NxeDropDownBoxComponent, isStandalone: true, selector: "nxe-drop-down-box", inputs: { dataSource: { classPropertyName: "dataSource", publicName: "dataSource", isSignal: true, isRequired: false, transformFunction: null }, displayExprInput: { classPropertyName: "displayExprInput", publicName: "displayExpr", isSignal: true, isRequired: false, transformFunction: null }, valueExprInput: { classPropertyName: "valueExprInput", publicName: "valueExpr", isSignal: true, isRequired: false, transformFunction: null }, placeholderInput: { classPropertyName: "placeholderInput", publicName: "placeholder", isSignal: true, isRequired: false, transformFunction: null }, dropDownOptions: { classPropertyName: "dropDownOptions", publicName: "dropDownOptions", isSignal: true, isRequired: false, transformFunction: null }, showClearButtonInput: { classPropertyName: "showClearButtonInput", publicName: "showClearButton", isSignal: true, isRequired: false, transformFunction: null }, opened: { classPropertyName: "opened", publicName: "opened", isSignal: true, isRequired: false, transformFunction: null } }, outputs: { opened: "openedChange", onClosed: "onClosed" }, host: { properties: { "class.nxe-focused": "focused()", "class.nxe-invalid": "
|
|
1035
|
+
static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "22.1.5", type: NxeDropDownBoxComponent, isStandalone: true, selector: "nxe-drop-down-box", inputs: { dataSource: { classPropertyName: "dataSource", publicName: "dataSource", isSignal: true, isRequired: false, transformFunction: null }, displayExprInput: { classPropertyName: "displayExprInput", publicName: "displayExpr", isSignal: true, isRequired: false, transformFunction: null }, valueExprInput: { classPropertyName: "valueExprInput", publicName: "valueExpr", isSignal: true, isRequired: false, transformFunction: null }, placeholderInput: { classPropertyName: "placeholderInput", publicName: "placeholder", isSignal: true, isRequired: false, transformFunction: null }, dropDownOptions: { classPropertyName: "dropDownOptions", publicName: "dropDownOptions", isSignal: true, isRequired: false, transformFunction: null }, showClearButtonInput: { classPropertyName: "showClearButtonInput", publicName: "showClearButton", isSignal: true, isRequired: false, transformFunction: null }, opened: { classPropertyName: "opened", publicName: "opened", isSignal: true, isRequired: false, transformFunction: null } }, outputs: { opened: "openedChange", onClosed: "onClosed" }, host: { properties: { "class.nxe-focused": "focused()", "class.nxe-invalid": "invalidState()", "class.nxe-open": "open()" }, classAttribute: "nxe-widget nxe-editor nxe-dropdownbox" }, providers: [
|
|
748
1036
|
{ provide: NG_VALUE_ACCESSOR, useExisting: forwardRef(() => NxeDropDownBoxComponent), multi: true },
|
|
749
1037
|
{ provide: NXE_VALIDATION_TARGET, useExisting: forwardRef(() => NxeDropDownBoxComponent) },
|
|
750
|
-
], queries: [{ propertyName: "templates", predicate: NxeTemplateDirective, isSignal: true }, { propertyName: "options", first: true, predicate: NxeDropDownOptionsComponent, descendants: true, isSignal: true }], viewQueries: [{ propertyName: "panelTemplate", first: true, predicate: ["panel"], descendants: true, isSignal: true }], usesInheritance: true, ngImport: i0, template: "<div class=\"nxe-editor-container\" (mousedown)=\"onFieldMousedown($event)\">\
|
|
1038
|
+
], queries: [{ propertyName: "templates", predicate: NxeTemplateDirective, isSignal: true }, { propertyName: "options", first: true, predicate: NxeDropDownOptionsComponent, descendants: true, isSignal: true }], viewQueries: [{ propertyName: "panelTemplate", first: true, predicate: ["panel"], descendants: true, isSignal: true }], usesInheritance: true, ngImport: i0, template: "<div class=\"nxe-editor-container\" (mousedown)=\"onFieldMousedown($event)\">\n <input\n class=\"nxe-editor-input nxe-dropdownbox-input\"\n [attr.tabindex]=\"tabIndex()\"\n role=\"combobox\"\n aria-haspopup=\"dialog\"\n [attr.aria-expanded]=\"opened()\"\n [attr.aria-controls]=\"opened() ? panelId() : null\"\n [id]=\"controlId()\"\n [attr.aria-label]=\"ariaLabel() || null\"\n [attr.aria-labelledby]=\"ariaLabelledBy() || null\"\n [attr.aria-invalid]=\"invalidState() ? true : null\"\n [attr.aria-required]=\"required() ? true : null\"\n type=\"text\"\n readonly\n [value]=\"displayText()\"\n [disabled]=\"disabled()\"\n [attr.placeholder]=\"placeholder() || null\"\n (focus)=\"focused.set(true)\"\n (blur)=\"onBlur()\" />\n @if (showClearButton() && hasValue() && !readOnly() && !disabled()) {\n <span class=\"nxe-select-clear\" (mousedown)=\"onClear($event)\" aria-hidden=\"true\">\n <!-- A \u00D816 disc with a 2px \u00D7 cut out: two 2px bars, each running corner to corner of the\n 8px square centred on the disc, drawn as a plus and turned 45\u00B0. -->\n <svg viewBox=\"0 0 18 18\" focusable=\"false\">\n <path fill-rule=\"evenodd\" transform=\"rotate(45 9 9)\"\n d=\"M9 1a8 8 0 1 1 0 16A8 8 0 1 1 9 1ZM8 3.343h2V8h4.657v2H10v4.657H8V10H3.343V8H8Z\" />\n </svg>\n </span>\n }\n\n @if (!readOnly()) {\n <span class=\"nxe-select-arrow\" aria-hidden=\"true\">\n <!-- An 8x4 triangle centred in the 18px box. -->\n <svg viewBox=\"0 0 18 18\" focusable=\"false\"><path d=\"M5 7h8l-4 4z\" /></svg>\n </span>\n }\n</div>\n\n<ng-content />\n\n@if (validationError(); as error) {\n @if (focused()) {\n <div class=\"nxe-invalid-message\">{{ error }}</div>\n }\n}\n\n<ng-template #panel>\n <div class=\"nxe-dropdownbox-panel\" [id]=\"panelId()\" role=\"dialog\" [style.width]=\"panelStyleWidth()\">\n @if (contentTemplateRef(); as tpl) {\n <ng-container *ngTemplateOutlet=\"tpl; context: { $implicit: value() }\" />\n }\n </div>\n</ng-template>\n", styles: ["nxe-drop-down-box{cursor:pointer}nxe-drop-down-box .nxe-dropdownbox-input{cursor:pointer}nxe-drop-down-box .nxe-select-clear{box-sizing:border-box;flex:0 0 34px;align-self:stretch;display:inline-flex;align-items:center;justify-content:center;width:34px;min-width:34px;padding:0;color:var(--nxe-ui-text-muted, #999);cursor:pointer}nxe-drop-down-box .nxe-select-clear svg{display:block;width:18px;height:18px;fill:currentColor}nxe-drop-down-box .nxe-select-arrow{box-sizing:border-box;position:relative;flex:0 0 34px;align-self:stretch;display:inline-flex;align-items:center;justify-content:center;width:34px;min-width:34px;padding:1px;border-radius:4px;background-clip:content-box;color:var(--nxe-ui-text, #333);cursor:pointer}nxe-drop-down-box .nxe-select-arrow svg{display:block;width:18px;height:18px;fill:currentColor}nxe-drop-down-box:hover:not(.nxe-disabled) .nxe-select-arrow,nxe-drop-down-box:active:not(.nxe-disabled) .nxe-select-arrow{background-color:var(--nxe-ui-neutral-150, #e6e6e6)}nxe-drop-down-box.nxe-open .nxe-select-arrow{background-color:var(--nxe-ui-neutral-350, #b3b3b3)}nxe-drop-down-box .nxe-editor-container:has(>.nxe-select-arrow) .nxe-editor-input{padding-inline-end:0}nxe-drop-down-box .nxe-editor-container:has(>.nxe-select-clear),nxe-drop-down-box .nxe-editor-container:has(>.nxe-select-arrow){--nxe-invalid-badge-inset: 38px}nxe-drop-down-box .nxe-editor-container:has(>.nxe-select-clear):has(>.nxe-select-arrow){--nxe-invalid-badge-inset: 72px}.nxe-dropdownbox-panel{box-sizing:border-box;background:var(--nxe-ui-surface, #fff);border:1px solid var(--nxe-ui-border, #ddd);border-radius:6px;box-shadow:var(--nxe-ui-popup-shadow, 0 6px 12px rgba(0, 0, 0, .175));overflow:auto;max-height:420px}\n"], dependencies: [{ kind: "directive", type: NgTemplateOutlet, selector: "[ngTemplateOutlet]", inputs: ["ngTemplateOutletContext", "ngTemplateOutlet", "ngTemplateOutletInjector"] }], changeDetection: i0.ChangeDetectionStrategy.OnPush, encapsulation: i0.ViewEncapsulation.None });
|
|
751
1039
|
}
|
|
752
1040
|
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "22.1.5", ngImport: i0, type: NxeDropDownBoxComponent, decorators: [{
|
|
753
1041
|
type: Component,
|
|
754
1042
|
args: [{ selector: 'nxe-drop-down-box', standalone: true, imports: [NgTemplateOutlet], host: {
|
|
755
1043
|
class: 'nxe-widget nxe-editor nxe-dropdownbox',
|
|
756
1044
|
'[class.nxe-focused]': 'focused()',
|
|
757
|
-
'[class.nxe-invalid]': '
|
|
1045
|
+
'[class.nxe-invalid]': 'invalidState()',
|
|
758
1046
|
'[class.nxe-open]': 'open()',
|
|
759
1047
|
}, providers: [
|
|
760
1048
|
{ provide: NG_VALUE_ACCESSOR, useExisting: forwardRef(() => NxeDropDownBoxComponent), multi: true },
|
|
761
1049
|
{ provide: NXE_VALIDATION_TARGET, useExisting: forwardRef(() => NxeDropDownBoxComponent) },
|
|
762
|
-
], changeDetection: ChangeDetectionStrategy.OnPush, encapsulation: ViewEncapsulation.None, template: "<div class=\"nxe-editor-container\" (mousedown)=\"onFieldMousedown($event)\">\
|
|
1050
|
+
], changeDetection: ChangeDetectionStrategy.OnPush, encapsulation: ViewEncapsulation.None, template: "<div class=\"nxe-editor-container\" (mousedown)=\"onFieldMousedown($event)\">\n <input\n class=\"nxe-editor-input nxe-dropdownbox-input\"\n [attr.tabindex]=\"tabIndex()\"\n role=\"combobox\"\n aria-haspopup=\"dialog\"\n [attr.aria-expanded]=\"opened()\"\n [attr.aria-controls]=\"opened() ? panelId() : null\"\n [id]=\"controlId()\"\n [attr.aria-label]=\"ariaLabel() || null\"\n [attr.aria-labelledby]=\"ariaLabelledBy() || null\"\n [attr.aria-invalid]=\"invalidState() ? true : null\"\n [attr.aria-required]=\"required() ? true : null\"\n type=\"text\"\n readonly\n [value]=\"displayText()\"\n [disabled]=\"disabled()\"\n [attr.placeholder]=\"placeholder() || null\"\n (focus)=\"focused.set(true)\"\n (blur)=\"onBlur()\" />\n @if (showClearButton() && hasValue() && !readOnly() && !disabled()) {\n <span class=\"nxe-select-clear\" (mousedown)=\"onClear($event)\" aria-hidden=\"true\">\n <!-- A \u00D816 disc with a 2px \u00D7 cut out: two 2px bars, each running corner to corner of the\n 8px square centred on the disc, drawn as a plus and turned 45\u00B0. -->\n <svg viewBox=\"0 0 18 18\" focusable=\"false\">\n <path fill-rule=\"evenodd\" transform=\"rotate(45 9 9)\"\n d=\"M9 1a8 8 0 1 1 0 16A8 8 0 1 1 9 1ZM8 3.343h2V8h4.657v2H10v4.657H8V10H3.343V8H8Z\" />\n </svg>\n </span>\n }\n\n @if (!readOnly()) {\n <span class=\"nxe-select-arrow\" aria-hidden=\"true\">\n <!-- An 8x4 triangle centred in the 18px box. -->\n <svg viewBox=\"0 0 18 18\" focusable=\"false\"><path d=\"M5 7h8l-4 4z\" /></svg>\n </span>\n }\n</div>\n\n<ng-content />\n\n@if (validationError(); as error) {\n @if (focused()) {\n <div class=\"nxe-invalid-message\">{{ error }}</div>\n }\n}\n\n<ng-template #panel>\n <div class=\"nxe-dropdownbox-panel\" [id]=\"panelId()\" role=\"dialog\" [style.width]=\"panelStyleWidth()\">\n @if (contentTemplateRef(); as tpl) {\n <ng-container *ngTemplateOutlet=\"tpl; context: { $implicit: value() }\" />\n }\n </div>\n</ng-template>\n", styles: ["nxe-drop-down-box{cursor:pointer}nxe-drop-down-box .nxe-dropdownbox-input{cursor:pointer}nxe-drop-down-box .nxe-select-clear{box-sizing:border-box;flex:0 0 34px;align-self:stretch;display:inline-flex;align-items:center;justify-content:center;width:34px;min-width:34px;padding:0;color:var(--nxe-ui-text-muted, #999);cursor:pointer}nxe-drop-down-box .nxe-select-clear svg{display:block;width:18px;height:18px;fill:currentColor}nxe-drop-down-box .nxe-select-arrow{box-sizing:border-box;position:relative;flex:0 0 34px;align-self:stretch;display:inline-flex;align-items:center;justify-content:center;width:34px;min-width:34px;padding:1px;border-radius:4px;background-clip:content-box;color:var(--nxe-ui-text, #333);cursor:pointer}nxe-drop-down-box .nxe-select-arrow svg{display:block;width:18px;height:18px;fill:currentColor}nxe-drop-down-box:hover:not(.nxe-disabled) .nxe-select-arrow,nxe-drop-down-box:active:not(.nxe-disabled) .nxe-select-arrow{background-color:var(--nxe-ui-neutral-150, #e6e6e6)}nxe-drop-down-box.nxe-open .nxe-select-arrow{background-color:var(--nxe-ui-neutral-350, #b3b3b3)}nxe-drop-down-box .nxe-editor-container:has(>.nxe-select-arrow) .nxe-editor-input{padding-inline-end:0}nxe-drop-down-box .nxe-editor-container:has(>.nxe-select-clear),nxe-drop-down-box .nxe-editor-container:has(>.nxe-select-arrow){--nxe-invalid-badge-inset: 38px}nxe-drop-down-box .nxe-editor-container:has(>.nxe-select-clear):has(>.nxe-select-arrow){--nxe-invalid-badge-inset: 72px}.nxe-dropdownbox-panel{box-sizing:border-box;background:var(--nxe-ui-surface, #fff);border:1px solid var(--nxe-ui-border, #ddd);border-radius:6px;box-shadow:var(--nxe-ui-popup-shadow, 0 6px 12px rgba(0, 0, 0, .175));overflow:auto;max-height:420px}\n"] }]
|
|
763
1051
|
}], ctorParameters: () => [], propDecorators: { panelTemplate: [{ type: i0.ViewChild, args: ['panel', { isSignal: true }] }], templates: [{ type: i0.ContentChildren, args: [i0.forwardRef(() => NxeTemplateDirective), { isSignal: true }] }], options: [{ type: i0.ContentChild, args: [i0.forwardRef(() => NxeDropDownOptionsComponent), { isSignal: true }] }], dataSource: [{ type: i0.Input, args: [{ isSignal: true, alias: "dataSource", required: false }] }], displayExprInput: [{ type: i0.Input, args: [{ isSignal: true, alias: "displayExpr", required: false }] }], valueExprInput: [{ type: i0.Input, args: [{ isSignal: true, alias: "valueExpr", required: false }] }], placeholderInput: [{ type: i0.Input, args: [{ isSignal: true, alias: "placeholder", required: false }] }], dropDownOptions: [{ type: i0.Input, args: [{ isSignal: true, alias: "dropDownOptions", required: false }] }], showClearButtonInput: [{ type: i0.Input, args: [{ isSignal: true, alias: "showClearButton", required: false }] }], opened: [{ type: i0.Input, args: [{ isSignal: true, alias: "opened", required: false }] }, { type: i0.Output, args: ["openedChange"] }], onClosed: [{ type: i0.Output, args: ["onClosed"] }] } });
|
|
764
1052
|
|
|
765
1053
|
/** DI token the menu provides so projected `nxe-menu-item`s can close it on click. */
|
|
@@ -1030,21 +1318,21 @@ class NxeAutoCompleteComponent extends NxeFormControlBase {
|
|
|
1030
1318
|
this.closePanel();
|
|
1031
1319
|
}
|
|
1032
1320
|
static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "22.1.5", ngImport: i0, type: NxeAutoCompleteComponent, deps: null, target: i0.ɵɵFactoryTarget.Component });
|
|
1033
|
-
static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "22.1.5", type: NxeAutoCompleteComponent, isStandalone: true, selector: "nxe-auto-complete", inputs: { dataSource: { classPropertyName: "dataSource", publicName: "dataSource", isSignal: true, isRequired: false, transformFunction: null }, valueExpr: { classPropertyName: "valueExpr", publicName: "valueExpr", isSignal: true, isRequired: false, transformFunction: null }, searchExprInput: { classPropertyName: "searchExprInput", publicName: "searchExpr", isSignal: true, isRequired: false, transformFunction: null }, searchMode: { classPropertyName: "searchMode", publicName: "searchMode", isSignal: true, isRequired: false, transformFunction: null }, minSearchLength: { classPropertyName: "minSearchLength", publicName: "minSearchLength", isSignal: true, isRequired: false, transformFunction: null }, maxItemCount: { classPropertyName: "maxItemCount", publicName: "maxItemCount", isSignal: true, isRequired: false, transformFunction: null }, placeholder: { classPropertyName: "placeholder", publicName: "placeholder", isSignal: true, isRequired: false, transformFunction: null }, showClearButton: { classPropertyName: "showClearButton", publicName: "showClearButton", isSignal: true, isRequired: false, transformFunction: null } }, outputs: { onSelectionChanged: "onSelectionChanged" }, host: { listeners: { "keydown": "onKeydown($event)" }, properties: { "class.nxe-focused": "focused()", "class.nxe-invalid": "
|
|
1321
|
+
static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "22.1.5", type: NxeAutoCompleteComponent, isStandalone: true, selector: "nxe-auto-complete", inputs: { dataSource: { classPropertyName: "dataSource", publicName: "dataSource", isSignal: true, isRequired: false, transformFunction: null }, valueExpr: { classPropertyName: "valueExpr", publicName: "valueExpr", isSignal: true, isRequired: false, transformFunction: null }, searchExprInput: { classPropertyName: "searchExprInput", publicName: "searchExpr", isSignal: true, isRequired: false, transformFunction: null }, searchMode: { classPropertyName: "searchMode", publicName: "searchMode", isSignal: true, isRequired: false, transformFunction: null }, minSearchLength: { classPropertyName: "minSearchLength", publicName: "minSearchLength", isSignal: true, isRequired: false, transformFunction: null }, maxItemCount: { classPropertyName: "maxItemCount", publicName: "maxItemCount", isSignal: true, isRequired: false, transformFunction: null }, placeholder: { classPropertyName: "placeholder", publicName: "placeholder", isSignal: true, isRequired: false, transformFunction: null }, showClearButton: { classPropertyName: "showClearButton", publicName: "showClearButton", isSignal: true, isRequired: false, transformFunction: null } }, outputs: { onSelectionChanged: "onSelectionChanged" }, host: { listeners: { "keydown": "onKeydown($event)" }, properties: { "class.nxe-focused": "focused()", "class.nxe-invalid": "invalidState()", "class.nxe-open": "open()" }, classAttribute: "nxe-widget nxe-editor nxe-autocomplete-box" }, providers: [
|
|
1034
1322
|
{
|
|
1035
1323
|
provide: NG_VALUE_ACCESSOR,
|
|
1036
1324
|
useExisting: forwardRef(() => NxeAutoCompleteComponent),
|
|
1037
1325
|
multi: true,
|
|
1038
1326
|
},
|
|
1039
1327
|
{ provide: NXE_VALIDATION_TARGET, useExisting: forwardRef(() => NxeAutoCompleteComponent) },
|
|
1040
|
-
], viewQueries: [{ propertyName: "dropdownTemplate", first: true, predicate: ["dropdown"], descendants: true, isSignal: true }, { propertyName: "inputEl", first: true, predicate: ["input"], descendants: true, isSignal: true }], usesInheritance: true, ngImport: i0, template: "<div class=\"nxe-editor-container\">\
|
|
1328
|
+
], viewQueries: [{ propertyName: "dropdownTemplate", first: true, predicate: ["dropdown"], descendants: true, isSignal: true }, { propertyName: "inputEl", first: true, predicate: ["input"], descendants: true, isSignal: true }], usesInheritance: true, ngImport: i0, template: "<div class=\"nxe-editor-container\">\n <input\n #input\n class=\"nxe-editor-input nxe-autocomplete-input\"\n [attr.tabindex]=\"tabIndex()\"\n role=\"combobox\"\n aria-haspopup=\"listbox\"\n [attr.aria-expanded]=\"open()\"\n [attr.aria-controls]=\"open() ? panelId() : null\"\n [attr.aria-activedescendant]=\"open() && activeIndex() >= 0 ? optionId(activeIndex()) : null\"\n [id]=\"controlId()\"\n [attr.aria-label]=\"ariaLabel() || null\"\n [attr.aria-labelledby]=\"ariaLabelledBy() || null\"\n [attr.aria-invalid]=\"invalidState() ? true : null\"\n [attr.aria-required]=\"required() ? true : null\"\n type=\"text\"\n [value]=\"text()\"\n [readOnly]=\"readOnly()\"\n [disabled]=\"disabled()\"\n [attr.placeholder]=\"placeholder() || null\"\n autocomplete=\"off\"\n (input)=\"onFieldInput($event)\"\n (focus)=\"onFocus()\"\n (blur)=\"onBlur()\" />\n\n @if (showClearButton() && text() && !readOnly() && !disabled()) {\n <span class=\"nxe-select-clear\" (mousedown)=\"onClear($event)\" aria-hidden=\"true\">\n <!-- A \u00D816 disc with a 2px \u00D7 cut out: two 2px bars, each running corner to corner of the\n 8px square centred on the disc, drawn as a plus and turned 45\u00B0. -->\n <svg viewBox=\"0 0 18 18\" focusable=\"false\">\n <path fill-rule=\"evenodd\" transform=\"rotate(45 9 9)\"\n d=\"M9 1a8 8 0 1 1 0 16A8 8 0 1 1 9 1ZM8 3.343h2V8h4.657v2H10v4.657H8V10H3.343V8H8Z\" />\n </svg>\n </span>\n }\n</div>\n\n<ng-content />\n\n@if (validationError(); as error) {\n @if (focused()) {\n <div class=\"nxe-invalid-message\">{{ error }}</div>\n }\n}\n\n<ng-template #dropdown>\n <div class=\"nxe-autocomplete-box-panel\" [style.width.px]=\"panelWidth()\"\n [id]=\"panelId()\"\n role=\"listbox\">\n @for (item of suggestions(); track $index; let i = $index) {\n <div\n class=\"nxe-list-item\"\n [id]=\"optionId(i)\"\n role=\"option\"\n [attr.aria-selected]=\"i === activeIndex()\"\n [class.nxe-list-item-active]=\"i === activeIndex()\"\n (mousedown)=\"pick(item, $event)\">\n {{ itemText(item) }}\n </div>\n }\n </div>\n</ng-template>\n", styles: ["nxe-auto-complete .nxe-select-clear{box-sizing:border-box;flex:0 0 34px;align-self:stretch;display:inline-flex;align-items:center;justify-content:center;width:34px;min-width:34px;padding:0;color:var(--nxe-ui-text-muted, #999);cursor:pointer}nxe-auto-complete .nxe-select-clear svg{display:block;width:18px;height:18px;fill:currentColor}nxe-auto-complete .nxe-select-arrow{box-sizing:border-box;position:relative;flex:0 0 34px;align-self:stretch;display:inline-flex;align-items:center;justify-content:center;width:34px;min-width:34px;padding:1px;border-radius:4px;background-clip:content-box;color:var(--nxe-ui-text, #333);cursor:pointer}nxe-auto-complete .nxe-select-arrow svg{display:block;width:18px;height:18px;fill:currentColor}nxe-auto-complete:hover:not(.nxe-disabled) .nxe-select-arrow,nxe-auto-complete:active:not(.nxe-disabled) .nxe-select-arrow{background-color:var(--nxe-ui-neutral-150, #e6e6e6)}nxe-auto-complete.nxe-open .nxe-select-arrow{background-color:var(--nxe-ui-neutral-350, #b3b3b3)}nxe-auto-complete .nxe-editor-container:has(>.nxe-select-arrow) .nxe-editor-input{padding-inline-end:0}nxe-auto-complete .nxe-editor-container:has(>.nxe-select-clear),nxe-auto-complete .nxe-editor-container:has(>.nxe-select-arrow){--nxe-invalid-badge-inset: 38px}nxe-auto-complete .nxe-editor-container:has(>.nxe-select-clear):has(>.nxe-select-arrow){--nxe-invalid-badge-inset: 72px}.nxe-autocomplete-box-panel{max-height:300px;overflow-y:auto;background:var(--nxe-ui-surface, #fff);border:1px solid var(--nxe-ui-border, #ddd);box-sizing:border-box}\n"], changeDetection: i0.ChangeDetectionStrategy.OnPush, encapsulation: i0.ViewEncapsulation.None });
|
|
1041
1329
|
}
|
|
1042
1330
|
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "22.1.5", ngImport: i0, type: NxeAutoCompleteComponent, decorators: [{
|
|
1043
1331
|
type: Component,
|
|
1044
1332
|
args: [{ selector: 'nxe-auto-complete', standalone: true, host: {
|
|
1045
1333
|
class: 'nxe-widget nxe-editor nxe-autocomplete-box',
|
|
1046
1334
|
'[class.nxe-focused]': 'focused()',
|
|
1047
|
-
'[class.nxe-invalid]': '
|
|
1335
|
+
'[class.nxe-invalid]': 'invalidState()',
|
|
1048
1336
|
'[class.nxe-open]': 'open()',
|
|
1049
1337
|
'(keydown)': 'onKeydown($event)',
|
|
1050
1338
|
}, providers: [
|
|
@@ -1054,7 +1342,7 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "22.1.5", ngImpor
|
|
|
1054
1342
|
multi: true,
|
|
1055
1343
|
},
|
|
1056
1344
|
{ provide: NXE_VALIDATION_TARGET, useExisting: forwardRef(() => NxeAutoCompleteComponent) },
|
|
1057
|
-
], changeDetection: ChangeDetectionStrategy.OnPush, encapsulation: ViewEncapsulation.None, template: "<div class=\"nxe-editor-container\">\
|
|
1345
|
+
], changeDetection: ChangeDetectionStrategy.OnPush, encapsulation: ViewEncapsulation.None, template: "<div class=\"nxe-editor-container\">\n <input\n #input\n class=\"nxe-editor-input nxe-autocomplete-input\"\n [attr.tabindex]=\"tabIndex()\"\n role=\"combobox\"\n aria-haspopup=\"listbox\"\n [attr.aria-expanded]=\"open()\"\n [attr.aria-controls]=\"open() ? panelId() : null\"\n [attr.aria-activedescendant]=\"open() && activeIndex() >= 0 ? optionId(activeIndex()) : null\"\n [id]=\"controlId()\"\n [attr.aria-label]=\"ariaLabel() || null\"\n [attr.aria-labelledby]=\"ariaLabelledBy() || null\"\n [attr.aria-invalid]=\"invalidState() ? true : null\"\n [attr.aria-required]=\"required() ? true : null\"\n type=\"text\"\n [value]=\"text()\"\n [readOnly]=\"readOnly()\"\n [disabled]=\"disabled()\"\n [attr.placeholder]=\"placeholder() || null\"\n autocomplete=\"off\"\n (input)=\"onFieldInput($event)\"\n (focus)=\"onFocus()\"\n (blur)=\"onBlur()\" />\n\n @if (showClearButton() && text() && !readOnly() && !disabled()) {\n <span class=\"nxe-select-clear\" (mousedown)=\"onClear($event)\" aria-hidden=\"true\">\n <!-- A \u00D816 disc with a 2px \u00D7 cut out: two 2px bars, each running corner to corner of the\n 8px square centred on the disc, drawn as a plus and turned 45\u00B0. -->\n <svg viewBox=\"0 0 18 18\" focusable=\"false\">\n <path fill-rule=\"evenodd\" transform=\"rotate(45 9 9)\"\n d=\"M9 1a8 8 0 1 1 0 16A8 8 0 1 1 9 1ZM8 3.343h2V8h4.657v2H10v4.657H8V10H3.343V8H8Z\" />\n </svg>\n </span>\n }\n</div>\n\n<ng-content />\n\n@if (validationError(); as error) {\n @if (focused()) {\n <div class=\"nxe-invalid-message\">{{ error }}</div>\n }\n}\n\n<ng-template #dropdown>\n <div class=\"nxe-autocomplete-box-panel\" [style.width.px]=\"panelWidth()\"\n [id]=\"panelId()\"\n role=\"listbox\">\n @for (item of suggestions(); track $index; let i = $index) {\n <div\n class=\"nxe-list-item\"\n [id]=\"optionId(i)\"\n role=\"option\"\n [attr.aria-selected]=\"i === activeIndex()\"\n [class.nxe-list-item-active]=\"i === activeIndex()\"\n (mousedown)=\"pick(item, $event)\">\n {{ itemText(item) }}\n </div>\n }\n </div>\n</ng-template>\n", styles: ["nxe-auto-complete .nxe-select-clear{box-sizing:border-box;flex:0 0 34px;align-self:stretch;display:inline-flex;align-items:center;justify-content:center;width:34px;min-width:34px;padding:0;color:var(--nxe-ui-text-muted, #999);cursor:pointer}nxe-auto-complete .nxe-select-clear svg{display:block;width:18px;height:18px;fill:currentColor}nxe-auto-complete .nxe-select-arrow{box-sizing:border-box;position:relative;flex:0 0 34px;align-self:stretch;display:inline-flex;align-items:center;justify-content:center;width:34px;min-width:34px;padding:1px;border-radius:4px;background-clip:content-box;color:var(--nxe-ui-text, #333);cursor:pointer}nxe-auto-complete .nxe-select-arrow svg{display:block;width:18px;height:18px;fill:currentColor}nxe-auto-complete:hover:not(.nxe-disabled) .nxe-select-arrow,nxe-auto-complete:active:not(.nxe-disabled) .nxe-select-arrow{background-color:var(--nxe-ui-neutral-150, #e6e6e6)}nxe-auto-complete.nxe-open .nxe-select-arrow{background-color:var(--nxe-ui-neutral-350, #b3b3b3)}nxe-auto-complete .nxe-editor-container:has(>.nxe-select-arrow) .nxe-editor-input{padding-inline-end:0}nxe-auto-complete .nxe-editor-container:has(>.nxe-select-clear),nxe-auto-complete .nxe-editor-container:has(>.nxe-select-arrow){--nxe-invalid-badge-inset: 38px}nxe-auto-complete .nxe-editor-container:has(>.nxe-select-clear):has(>.nxe-select-arrow){--nxe-invalid-badge-inset: 72px}.nxe-autocomplete-box-panel{max-height:300px;overflow-y:auto;background:var(--nxe-ui-surface, #fff);border:1px solid var(--nxe-ui-border, #ddd);box-sizing:border-box}\n"] }]
|
|
1058
1346
|
}], propDecorators: { dropdownTemplate: [{ type: i0.ViewChild, args: ['dropdown', { isSignal: true }] }], inputEl: [{ type: i0.ViewChild, args: ['input', { isSignal: true }] }], dataSource: [{ type: i0.Input, args: [{ isSignal: true, alias: "dataSource", required: false }] }], valueExpr: [{ type: i0.Input, args: [{ isSignal: true, alias: "valueExpr", required: false }] }], searchExprInput: [{ type: i0.Input, args: [{ isSignal: true, alias: "searchExpr", required: false }] }], searchMode: [{ type: i0.Input, args: [{ isSignal: true, alias: "searchMode", required: false }] }], minSearchLength: [{ type: i0.Input, args: [{ isSignal: true, alias: "minSearchLength", required: false }] }], maxItemCount: [{ type: i0.Input, args: [{ isSignal: true, alias: "maxItemCount", required: false }] }], placeholder: [{ type: i0.Input, args: [{ isSignal: true, alias: "placeholder", required: false }] }], showClearButton: [{ type: i0.Input, args: [{ isSignal: true, alias: "showClearButton", required: false }] }], onSelectionChanged: [{ type: i0.Output, args: ["onSelectionChanged"] }] } });
|
|
1059
1347
|
|
|
1060
1348
|
/** DI token the autocomplete provides so projected `nxe-option`s can close it on click. */
|
|
@@ -1213,5 +1501,5 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "22.1.5", ngImpor
|
|
|
1213
1501
|
* Generated bundle index. Do not edit.
|
|
1214
1502
|
*/
|
|
1215
1503
|
|
|
1216
|
-
export { NXE_AUTOCOMPLETE, NxeAutoCompleteComponent, NxeAutocompleteComponent, NxeAutocompleteTriggerDirective, NxeDropDownBoxComponent, NxeDropDownOptionsComponent, NxeListComponent, NxeOptionComponent, NxeSelectBoxComponent, NxeTagBoxComponent };
|
|
1504
|
+
export { NXE_AUTOCOMPLETE, NXE_MENU, NxeAutoCompleteComponent, NxeAutocompleteComponent, NxeAutocompleteTriggerDirective, NxeDropDownBoxComponent, NxeDropDownOptionsComponent, NxeListComponent, NxeOptionComponent, NxePickerSearch, NxeSelectBoxComponent, NxeTagBoxComponent, nxeIsPickerStore };
|
|
1217
1505
|
//# sourceMappingURL=nexterajs-ui-dropdowns.mjs.map
|