@acorex/components 22.0.0-next.9 → 22.0.1
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/combo-box/README.md +35 -0
- package/fesm2022/acorex-components-accordion.mjs +2 -2
- package/fesm2022/acorex-components-accordion.mjs.map +1 -1
- package/fesm2022/acorex-components-action-sheet.mjs +1 -0
- package/fesm2022/acorex-components-action-sheet.mjs.map +1 -1
- package/fesm2022/acorex-components-alert.mjs +2 -2
- package/fesm2022/acorex-components-alert.mjs.map +1 -1
- package/fesm2022/acorex-components-button.mjs +4 -4
- package/fesm2022/acorex-components-button.mjs.map +1 -1
- package/fesm2022/acorex-components-calendar.mjs +10 -12
- package/fesm2022/acorex-components-calendar.mjs.map +1 -1
- package/fesm2022/acorex-components-check-box.mjs +2 -2
- package/fesm2022/acorex-components-check-box.mjs.map +1 -1
- package/fesm2022/acorex-components-combo-box.mjs +783 -0
- package/fesm2022/acorex-components-combo-box.mjs.map +1 -0
- package/fesm2022/acorex-components-conversation-composer-action-choice-dialog.component-DCcRJYfF.mjs +50 -0
- package/fesm2022/acorex-components-conversation-composer-action-choice-dialog.component-DCcRJYfF.mjs.map +1 -0
- package/fesm2022/{acorex-components-conversation-open-composer-picker-for-files-Hh5Oyp3p.mjs → acorex-components-conversation-open-composer-picker-for-files-DnSW908R.mjs} +7 -20
- package/fesm2022/acorex-components-conversation-open-composer-picker-for-files-DnSW908R.mjs.map +1 -0
- package/fesm2022/acorex-components-conversation.mjs +8966 -16359
- package/fesm2022/acorex-components-conversation.mjs.map +1 -1
- package/fesm2022/acorex-components-data-table.mjs +188 -64
- package/fesm2022/acorex-components-data-table.mjs.map +1 -1
- package/fesm2022/acorex-components-datetime-box.mjs +14 -16
- package/fesm2022/acorex-components-datetime-box.mjs.map +1 -1
- package/fesm2022/acorex-components-datetime-input.mjs +61 -32
- package/fesm2022/acorex-components-datetime-input.mjs.map +1 -1
- package/fesm2022/acorex-components-decorators.mjs +21 -5
- package/fesm2022/acorex-components-decorators.mjs.map +1 -1
- package/fesm2022/acorex-components-dialog.mjs +7 -4
- package/fesm2022/acorex-components-dialog.mjs.map +1 -1
- package/fesm2022/acorex-components-drawer.mjs +2 -2
- package/fesm2022/acorex-components-drawer.mjs.map +1 -1
- package/fesm2022/acorex-components-dropdown.mjs +4 -4
- package/fesm2022/acorex-components-dropdown.mjs.map +1 -1
- package/fesm2022/acorex-components-fab.mjs +5 -5
- package/fesm2022/acorex-components-fab.mjs.map +1 -1
- package/fesm2022/acorex-components-file-viewer.mjs +27 -27
- package/fesm2022/acorex-components-file-viewer.mjs.map +1 -1
- package/fesm2022/acorex-components-form.mjs +21 -5
- package/fesm2022/acorex-components-form.mjs.map +1 -1
- package/fesm2022/acorex-components-grid-layout-builder.mjs +238 -36
- package/fesm2022/acorex-components-grid-layout-builder.mjs.map +1 -1
- package/fesm2022/acorex-components-label.mjs +2 -2
- package/fesm2022/acorex-components-label.mjs.map +1 -1
- package/fesm2022/acorex-components-list.mjs +2 -2
- package/fesm2022/acorex-components-list.mjs.map +1 -1
- package/fesm2022/acorex-components-loading-dialog.mjs +59 -42
- package/fesm2022/acorex-components-loading-dialog.mjs.map +1 -1
- package/fesm2022/acorex-components-lookup.mjs +2897 -0
- package/fesm2022/acorex-components-lookup.mjs.map +1 -0
- package/fesm2022/acorex-components-map.mjs +2 -2
- package/fesm2022/acorex-components-map.mjs.map +1 -1
- package/fesm2022/acorex-components-menu.mjs +238 -75
- package/fesm2022/acorex-components-menu.mjs.map +1 -1
- package/fesm2022/acorex-components-notification.mjs +13 -6
- package/fesm2022/acorex-components-notification.mjs.map +1 -1
- package/fesm2022/acorex-components-number-box.mjs +30 -29
- package/fesm2022/acorex-components-number-box.mjs.map +1 -1
- package/fesm2022/acorex-components-password-box.mjs +3 -3
- package/fesm2022/acorex-components-password-box.mjs.map +1 -1
- package/fesm2022/acorex-components-popover.mjs +40 -6
- package/fesm2022/acorex-components-popover.mjs.map +1 -1
- package/fesm2022/acorex-components-popup.mjs +4 -2
- package/fesm2022/acorex-components-popup.mjs.map +1 -1
- package/fesm2022/acorex-components-radio.mjs +2 -2
- package/fesm2022/acorex-components-radio.mjs.map +1 -1
- package/fesm2022/acorex-components-range-slider.mjs +2 -2
- package/fesm2022/acorex-components-range-slider.mjs.map +1 -1
- package/fesm2022/acorex-components-scheduler.mjs +12 -22
- package/fesm2022/acorex-components-scheduler.mjs.map +1 -1
- package/fesm2022/acorex-components-select-box.mjs +55 -18
- package/fesm2022/acorex-components-select-box.mjs.map +1 -1
- package/fesm2022/acorex-components-selection-list.mjs +2 -2
- package/fesm2022/acorex-components-selection-list.mjs.map +1 -1
- package/fesm2022/acorex-components-switch.mjs +2 -2
- package/fesm2022/acorex-components-switch.mjs.map +1 -1
- package/fesm2022/acorex-components-tabs.mjs +2 -2
- package/fesm2022/acorex-components-tabs.mjs.map +1 -1
- package/fesm2022/acorex-components-tag-box.mjs +2 -2
- package/fesm2022/acorex-components-tag-box.mjs.map +1 -1
- package/fesm2022/acorex-components-text-area.mjs +2 -2
- package/fesm2022/acorex-components-text-area.mjs.map +1 -1
- package/fesm2022/acorex-components-toast.mjs +9 -2
- package/fesm2022/acorex-components-toast.mjs.map +1 -1
- package/fesm2022/acorex-components-tooltip.mjs +2 -2
- package/fesm2022/acorex-components-tooltip.mjs.map +1 -1
- package/fesm2022/acorex-components-tree-view.mjs +40 -3
- package/fesm2022/acorex-components-tree-view.mjs.map +1 -1
- package/lookup/README.md +74 -0
- package/package.json +12 -7
- package/select-box/README.md +5 -0
- package/types/acorex-components-action-sheet.d.ts +9 -1
- package/types/acorex-components-combo-box.d.ts +280 -0
- package/types/acorex-components-conversation.d.ts +947 -1354
- package/types/acorex-components-data-table.d.ts +47 -5
- package/types/acorex-components-datetime-box.d.ts +2 -0
- package/types/acorex-components-datetime-input.d.ts +24 -5
- package/types/acorex-components-decorators.d.ts +1 -0
- package/types/acorex-components-dialog.d.ts +9 -0
- package/types/acorex-components-grid-layout-builder.d.ts +34 -2
- package/types/acorex-components-loading-dialog.d.ts +12 -4
- package/types/acorex-components-lookup.d.ts +831 -0
- package/types/acorex-components-menu.d.ts +28 -4
- package/types/acorex-components-notification.d.ts +11 -1
- package/types/acorex-components-number-box.d.ts +3 -1
- package/types/acorex-components-popover.d.ts +12 -1
- package/types/acorex-components-popup.d.ts +9 -1
- package/types/acorex-components-scheduler.d.ts +2 -4
- package/types/acorex-components-select-box.d.ts +21 -4
- package/types/acorex-components-toast.d.ts +10 -1
- package/types/acorex-components-tree-view.d.ts +9 -1
- package/fesm2022/acorex-components-conversation-composer-action-choice-dialog.component-CNHiM1Sp.mjs +0 -106
- package/fesm2022/acorex-components-conversation-composer-action-choice-dialog.component-CNHiM1Sp.mjs.map +0 -1
- package/fesm2022/acorex-components-conversation-open-composer-picker-for-files-Hh5Oyp3p.mjs.map +0 -1
- package/fesm2022/acorex-components-selection-list-2.mjs +0 -168
- package/fesm2022/acorex-components-selection-list-2.mjs.map +0 -1
- package/selection-list-2/README.md +0 -3
- package/types/acorex-components-selection-list-2.d.ts +0 -52
|
@@ -0,0 +1,2897 @@
|
|
|
1
|
+
import { AXDataSource, AXListDataSource, NXValueComponent, convertArrayToDataSource, AXComponent, AXClearableComponent, AXClosableComponent, AXValuableComponent } from '@acorex/cdk/common';
|
|
2
|
+
import { AXButtonComponent } from '@acorex/components/button';
|
|
3
|
+
import { AXChipsComponent } from '@acorex/components/chips';
|
|
4
|
+
import * as i1$1 from '@acorex/components/decorators';
|
|
5
|
+
import { AXDecoratorModule } from '@acorex/components/decorators';
|
|
6
|
+
import { AXPopoverComponent } from '@acorex/components/popover';
|
|
7
|
+
import { AXSearchBoxComponent } from '@acorex/components/search-box';
|
|
8
|
+
import { AXPlatform } from '@acorex/core/platform';
|
|
9
|
+
import { AXTranslatorPipe } from '@acorex/core/translation';
|
|
10
|
+
import { NgTemplateOutlet, AsyncPipe, DOCUMENT } from '@angular/common';
|
|
11
|
+
import * as i0 from '@angular/core';
|
|
12
|
+
import { input, output, signal, computed, viewChild, viewChildren, inject, NgZone, effect, untracked, Directive, ViewEncapsulation, ChangeDetectionStrategy, Component, ElementRef, DestroyRef, model, linkedSignal, afterRenderEffect, NgModule } from '@angular/core';
|
|
13
|
+
import { takeUntilDestroyed } from '@angular/core/rxjs-interop';
|
|
14
|
+
import * as i2 from '@acorex/cdk/list-navigation';
|
|
15
|
+
import { AXListNavigationDirective, AXListNavigationItemDirective, AXListNavigationModule } from '@acorex/cdk/list-navigation';
|
|
16
|
+
import * as i1 from '@angular/cdk/scrolling';
|
|
17
|
+
import { CdkVirtualScrollViewport, ScrollingModule } from '@angular/cdk/scrolling';
|
|
18
|
+
import { AXTreeViewComponent } from '@acorex/components/tree-view';
|
|
19
|
+
import { AXDataTableComponent, AXDataTableTextColumnComponent } from '@acorex/components/data-table';
|
|
20
|
+
import { fromEvent, auditTime } from 'rxjs';
|
|
21
|
+
import { AXCheckBoxComponent } from '@acorex/components/check-box';
|
|
22
|
+
|
|
23
|
+
/**
|
|
24
|
+
* Converts a drop-down-tree datasource (nested array or lazy callback) into an
|
|
25
|
+
* `AXDataSource` that a multi-column data table can load and expand.
|
|
26
|
+
*/
|
|
27
|
+
function createLookupTreeTableDataSource(source, options) {
|
|
28
|
+
const isCallback = typeof source === 'function';
|
|
29
|
+
return new AXDataSource({
|
|
30
|
+
pageSize: 8,
|
|
31
|
+
key: options.valueField,
|
|
32
|
+
load: (query) => loadTreeTableRows(source, options, query, isCallback),
|
|
33
|
+
byKey: (key) => findTreeTableItem(source, options.valueField, key),
|
|
34
|
+
});
|
|
35
|
+
}
|
|
36
|
+
async function loadTreeTableRows(source, options, query, isCallback) {
|
|
37
|
+
const parentFilter = query.filter?.field === options.parentField ? query.filter : undefined;
|
|
38
|
+
const textFilter = query.filter && query.filter.field !== options.parentField ? query.filter : undefined;
|
|
39
|
+
if (parentFilter) {
|
|
40
|
+
const children = await loadChildren(source, options, parentFilter.value, isCallback);
|
|
41
|
+
return { items: children, total: children.length };
|
|
42
|
+
}
|
|
43
|
+
const roots = mapTreeNodes(await loadRoots(source, isCallback), options);
|
|
44
|
+
const items = textFilter ? filterTreeNodes(roots, options.textField, String(textFilter.value ?? '')) : roots;
|
|
45
|
+
return { items, total: items.length };
|
|
46
|
+
}
|
|
47
|
+
async function loadRoots(source, isCallback) {
|
|
48
|
+
if (!isCallback) {
|
|
49
|
+
return source ?? [];
|
|
50
|
+
}
|
|
51
|
+
return (await source()) ?? [];
|
|
52
|
+
}
|
|
53
|
+
async function loadChildren(source, options, parentId, isCallback) {
|
|
54
|
+
if (isCallback) {
|
|
55
|
+
const nodes = (await source(String(parentId))) ?? [];
|
|
56
|
+
return mapTreeNodes(nodes, options);
|
|
57
|
+
}
|
|
58
|
+
const parent = findTreeNode(source, options.valueField, parentId);
|
|
59
|
+
const children = Array.isArray(parent?.['children']) ? parent['children'] : [];
|
|
60
|
+
return mapTreeNodes(children, options);
|
|
61
|
+
}
|
|
62
|
+
function mapTreeNodes(nodes, options) {
|
|
63
|
+
return nodes.map((node) => mapTreeNode(node, options));
|
|
64
|
+
}
|
|
65
|
+
function mapTreeNode(node, options) {
|
|
66
|
+
const rawChildren = node['children'];
|
|
67
|
+
const children = Array.isArray(rawChildren) ? mapTreeNodes(rawChildren, options) : undefined;
|
|
68
|
+
const childrenCount = node['childrenCount'];
|
|
69
|
+
const hasChildren = (children?.length ?? 0) > 0 ||
|
|
70
|
+
(typeof childrenCount === 'number' && childrenCount > 0) ||
|
|
71
|
+
node['hasChild'] === true ||
|
|
72
|
+
node['hasChildren'] === true;
|
|
73
|
+
return {
|
|
74
|
+
...node,
|
|
75
|
+
[options.hasChildrenField]: hasChildren,
|
|
76
|
+
...(children && children.length > 0 ? { children } : {}),
|
|
77
|
+
};
|
|
78
|
+
}
|
|
79
|
+
/**
|
|
80
|
+
* Recursively filters a nested tree by `textField` (case-insensitive contains).
|
|
81
|
+
* A node is kept if it matches or any descendant matches. Matching parents keep
|
|
82
|
+
* all children. Every kept ancestor is a new object with `expanded: true` so
|
|
83
|
+
* nested hits are visible without mutating the original tree.
|
|
84
|
+
*/
|
|
85
|
+
function filterTreeNodes(nodes, textField, query) {
|
|
86
|
+
const needle = query.trim().toLowerCase();
|
|
87
|
+
if (!needle) {
|
|
88
|
+
return nodes;
|
|
89
|
+
}
|
|
90
|
+
const result = [];
|
|
91
|
+
for (const node of nodes) {
|
|
92
|
+
const rawChildren = node['children'];
|
|
93
|
+
const nested = Array.isArray(rawChildren) ? rawChildren : undefined;
|
|
94
|
+
const children = nested ? filterTreeNodes(nested, textField, needle) : undefined;
|
|
95
|
+
const selfMatch = String(node[textField] ?? '')
|
|
96
|
+
.toLowerCase()
|
|
97
|
+
.includes(needle);
|
|
98
|
+
if (selfMatch) {
|
|
99
|
+
result.push({
|
|
100
|
+
...node,
|
|
101
|
+
...(nested && nested.length > 0 ? { children: cloneTreeNodes(nested), expanded: true } : {}),
|
|
102
|
+
});
|
|
103
|
+
}
|
|
104
|
+
else if (children && children.length > 0) {
|
|
105
|
+
result.push({
|
|
106
|
+
...node,
|
|
107
|
+
children,
|
|
108
|
+
expanded: true,
|
|
109
|
+
});
|
|
110
|
+
}
|
|
111
|
+
}
|
|
112
|
+
return result;
|
|
113
|
+
}
|
|
114
|
+
function cloneTreeNodes(nodes) {
|
|
115
|
+
return nodes.map((node) => {
|
|
116
|
+
const raw = node['children'];
|
|
117
|
+
const children = Array.isArray(raw) && raw.length > 0 ? cloneTreeNodes(raw) : undefined;
|
|
118
|
+
return children ? { ...node, children } : { ...node };
|
|
119
|
+
});
|
|
120
|
+
}
|
|
121
|
+
/** Immutable copy of a nested tree so tree-view mutations cannot poison the source. */
|
|
122
|
+
function cloneLookupTreeNodes(nodes) {
|
|
123
|
+
return cloneTreeNodes(nodes);
|
|
124
|
+
}
|
|
125
|
+
/** Depth-first flattening of nested `children` arrays. */
|
|
126
|
+
function flattenTreeNodes(nodes) {
|
|
127
|
+
const result = [];
|
|
128
|
+
for (const node of nodes) {
|
|
129
|
+
result.push(node);
|
|
130
|
+
const children = node['children'];
|
|
131
|
+
if (Array.isArray(children)) {
|
|
132
|
+
result.push(...flattenTreeNodes(children));
|
|
133
|
+
}
|
|
134
|
+
}
|
|
135
|
+
return result;
|
|
136
|
+
}
|
|
137
|
+
function findTreeTableItem(source, valueField, key) {
|
|
138
|
+
if (typeof source === 'function' || !Array.isArray(source)) {
|
|
139
|
+
return undefined;
|
|
140
|
+
}
|
|
141
|
+
return findTreeNode(source, valueField, key) ?? undefined;
|
|
142
|
+
}
|
|
143
|
+
function findTreeNode(nodes, valueField, key) {
|
|
144
|
+
for (const node of nodes) {
|
|
145
|
+
if (String(node[valueField]) === String(key)) {
|
|
146
|
+
return node;
|
|
147
|
+
}
|
|
148
|
+
const children = node['children'];
|
|
149
|
+
if (Array.isArray(children)) {
|
|
150
|
+
const found = findTreeNode(children, valueField, key);
|
|
151
|
+
if (found) {
|
|
152
|
+
return found;
|
|
153
|
+
}
|
|
154
|
+
}
|
|
155
|
+
}
|
|
156
|
+
return null;
|
|
157
|
+
}
|
|
158
|
+
|
|
159
|
+
/**
|
|
160
|
+
* Shared `AXDataSource` + CDK virtual scroll plumbing for the list-based lookup views
|
|
161
|
+
* (`ax-lookup-drop-down-list`, `ax-lookup-multi-select`).
|
|
162
|
+
*/
|
|
163
|
+
class AXLookupListViewBase {
|
|
164
|
+
/** Whether the filtered datasource currently has no items. */
|
|
165
|
+
hasNoMatches() {
|
|
166
|
+
return this.isEmpty();
|
|
167
|
+
}
|
|
168
|
+
/** Number of items in the current filtered result set. */
|
|
169
|
+
matchCount() {
|
|
170
|
+
return this.totalCount();
|
|
171
|
+
}
|
|
172
|
+
#ngZone;
|
|
173
|
+
constructor() {
|
|
174
|
+
/**
|
|
175
|
+
* The datasource providing the items (paged, remote-capable).
|
|
176
|
+
*/
|
|
177
|
+
this.dataSource = input.required(/* @ts-ignore */
|
|
178
|
+
...(ngDevMode ? [{ debugName: "dataSource" }] : /* istanbul ignore next */ []));
|
|
179
|
+
/**
|
|
180
|
+
* The item property used as the selection value.
|
|
181
|
+
*/
|
|
182
|
+
this.valueField = input('id', /* @ts-ignore */
|
|
183
|
+
...(ngDevMode ? [{ debugName: "valueField" }] : /* istanbul ignore next */ []));
|
|
184
|
+
/**
|
|
185
|
+
* The item property used as the display text.
|
|
186
|
+
*/
|
|
187
|
+
this.textField = input('text', /* @ts-ignore */
|
|
188
|
+
...(ngDevMode ? [{ debugName: "textField" }] : /* istanbul ignore next */ []));
|
|
189
|
+
/**
|
|
190
|
+
* The item property marking an item as disabled.
|
|
191
|
+
*/
|
|
192
|
+
this.disabledField = input('disabled', /* @ts-ignore */
|
|
193
|
+
...(ngDevMode ? [{ debugName: "disabledField" }] : /* istanbul ignore next */ []));
|
|
194
|
+
/**
|
|
195
|
+
* Currently selected values (always an array, even for single selection).
|
|
196
|
+
*/
|
|
197
|
+
this.selectedValues = input([], /* @ts-ignore */
|
|
198
|
+
...(ngDevMode ? [{ debugName: "selectedValues" }] : /* istanbul ignore next */ []));
|
|
199
|
+
/**
|
|
200
|
+
* The fixed row height in pixels used by the virtual scroll viewport.
|
|
201
|
+
*/
|
|
202
|
+
this.itemHeight = input(40, /* @ts-ignore */
|
|
203
|
+
...(ngDevMode ? [{ debugName: "itemHeight" }] : /* istanbul ignore next */ []));
|
|
204
|
+
/**
|
|
205
|
+
* The maximum number of rows visible before the popup scrolls.
|
|
206
|
+
*/
|
|
207
|
+
this.maxVisibleItems = input(8, /* @ts-ignore */
|
|
208
|
+
...(ngDevMode ? [{ debugName: "maxVisibleItems" }] : /* istanbul ignore next */ []));
|
|
209
|
+
/**
|
|
210
|
+
* Custom template rendered for each item. Context: `$implicit` is the item.
|
|
211
|
+
* Default option chrome is not applied on top of the template.
|
|
212
|
+
*/
|
|
213
|
+
this.itemTemplate = input(undefined, /* @ts-ignore */
|
|
214
|
+
...(ngDevMode ? [{ debugName: "itemTemplate" }] : /* istanbul ignore next */ []));
|
|
215
|
+
/**
|
|
216
|
+
* Custom template rendered when the datasource has no items.
|
|
217
|
+
*/
|
|
218
|
+
this.emptyTemplate = input(undefined, /* @ts-ignore */
|
|
219
|
+
...(ngDevMode ? [{ debugName: "emptyTemplate" }] : /* istanbul ignore next */ []));
|
|
220
|
+
/**
|
|
221
|
+
* Custom template rendered for rows whose page is still loading.
|
|
222
|
+
*/
|
|
223
|
+
this.loadingTemplate = input(undefined, /* @ts-ignore */
|
|
224
|
+
...(ngDevMode ? [{ debugName: "loadingTemplate" }] : /* istanbul ignore next */ []));
|
|
225
|
+
/**
|
|
226
|
+
* When `true`, list rows use alternating background colors for easier scanning.
|
|
227
|
+
*/
|
|
228
|
+
this.alternate = input(false, /* @ts-ignore */
|
|
229
|
+
...(ngDevMode ? [{ debugName: "alternate" }] : /* istanbul ignore next */ []));
|
|
230
|
+
/**
|
|
231
|
+
* Emitted when the user picks (or toggles) an item.
|
|
232
|
+
*/
|
|
233
|
+
this.itemClick = output();
|
|
234
|
+
/**
|
|
235
|
+
* Emitted when keyboard navigation should leave the list (e.g. ArrowUp on the first
|
|
236
|
+
* item, or a printable key that should return focus to the trigger search input).
|
|
237
|
+
*/
|
|
238
|
+
this.navigateOut = output();
|
|
239
|
+
/** CDK virtual scroll adapter over the datasource. */
|
|
240
|
+
this.listDataSource = signal(null, /* @ts-ignore */
|
|
241
|
+
...(ngDevMode ? [{ debugName: "listDataSource" }] : /* istanbul ignore next */ []));
|
|
242
|
+
this.totalCount = signal(0, /* @ts-ignore */
|
|
243
|
+
...(ngDevMode ? [{ debugName: "totalCount" }] : /* istanbul ignore next */ []));
|
|
244
|
+
this.isLoading = signal(true, /* @ts-ignore */
|
|
245
|
+
...(ngDevMode ? [{ debugName: "isLoading" }] : /* istanbul ignore next */ []));
|
|
246
|
+
this.isEmpty = computed(() => this.totalCount() === 0 && !this.isLoading(), /* @ts-ignore */
|
|
247
|
+
...(ngDevMode ? [{ debugName: "isEmpty" }] : /* istanbul ignore next */ []));
|
|
248
|
+
/** Viewport height so the popup grows with the items up to `maxVisibleItems`. */
|
|
249
|
+
this.viewportHeight = computed(() => {
|
|
250
|
+
const count = this.totalCount() || (this.isLoading() ? 3 : 1);
|
|
251
|
+
return Math.min(count, this.maxVisibleItems()) * this.itemHeight();
|
|
252
|
+
}, /* @ts-ignore */
|
|
253
|
+
...(ngDevMode ? [{ debugName: "viewportHeight" }] : /* istanbul ignore next */ []));
|
|
254
|
+
this.viewportRef = viewChild(CdkVirtualScrollViewport, /* @ts-ignore */
|
|
255
|
+
...(ngDevMode ? [{ debugName: "viewportRef" }] : /* istanbul ignore next */ []));
|
|
256
|
+
this.listNavigation = viewChild(AXListNavigationDirective, /* @ts-ignore */
|
|
257
|
+
...(ngDevMode ? [{ debugName: "listNavigation" }] : /* istanbul ignore next */ []));
|
|
258
|
+
this.navItems = viewChildren(AXListNavigationItemDirective, /* @ts-ignore */
|
|
259
|
+
...(ngDevMode ? [{ debugName: "navItems" }] : /* istanbul ignore next */ []));
|
|
260
|
+
this.#ngZone = inject(NgZone);
|
|
261
|
+
this.trackByIndex = (index) => index;
|
|
262
|
+
// CDK measures the viewport size only once, when it initializes. Inside the popover the
|
|
263
|
+
// panel is still animating/positioning at that moment (and the height also changes when
|
|
264
|
+
// the loading placeholder is replaced by the real item count), so the measurement is stale
|
|
265
|
+
// and CDK renders too few rows, leaving empty space. A ResizeObserver on the viewport
|
|
266
|
+
// element re-measures on every actual size change, covering all of these cases.
|
|
267
|
+
effect((onCleanup) => {
|
|
268
|
+
const viewport = this.viewportRef();
|
|
269
|
+
if (!viewport || typeof ResizeObserver === 'undefined') {
|
|
270
|
+
return;
|
|
271
|
+
}
|
|
272
|
+
const observer = new ResizeObserver(() => {
|
|
273
|
+
this.#ngZone.run(() => viewport.checkViewportSize());
|
|
274
|
+
});
|
|
275
|
+
observer.observe(viewport.elementRef.nativeElement);
|
|
276
|
+
onCleanup(() => observer.disconnect());
|
|
277
|
+
});
|
|
278
|
+
effect((onCleanup) => {
|
|
279
|
+
const source = this.dataSource();
|
|
280
|
+
const list = new AXListDataSource({ source });
|
|
281
|
+
untracked(() => {
|
|
282
|
+
this.totalCount.set(source.totalCount);
|
|
283
|
+
this.isLoading.set(source.totalCount > 0 ? source.isLoading : true);
|
|
284
|
+
this.listDataSource.set(list);
|
|
285
|
+
});
|
|
286
|
+
const loadingSub = source.onLoadingChanged.subscribe((value) => this.isLoading.set(value));
|
|
287
|
+
const changedSub = source.onChanged.subscribe((e) => this.totalCount.set(e.totalCount));
|
|
288
|
+
onCleanup(() => {
|
|
289
|
+
loadingSub.unsubscribe();
|
|
290
|
+
changedSub.unsubscribe();
|
|
291
|
+
});
|
|
292
|
+
});
|
|
293
|
+
}
|
|
294
|
+
/** Moves keyboard focus to the first rendered list option. */
|
|
295
|
+
focusFirst() {
|
|
296
|
+
this.listNavigation()?.focusOnIndex(0);
|
|
297
|
+
}
|
|
298
|
+
getValue(item) {
|
|
299
|
+
return item?.[this.valueField()];
|
|
300
|
+
}
|
|
301
|
+
getText(item) {
|
|
302
|
+
return String(item?.[this.textField()] ?? '');
|
|
303
|
+
}
|
|
304
|
+
isSelected(item) {
|
|
305
|
+
const value = this.getValue(item);
|
|
306
|
+
return this.selectedValues().some((v) => v == value);
|
|
307
|
+
}
|
|
308
|
+
isDisabled(item) {
|
|
309
|
+
return Boolean(item?.[this.disabledField()]);
|
|
310
|
+
}
|
|
311
|
+
handleItemClick(item) {
|
|
312
|
+
if (!item || this.isDisabled(item)) {
|
|
313
|
+
return;
|
|
314
|
+
}
|
|
315
|
+
this.itemClick.emit({ item, value: this.getValue(item) });
|
|
316
|
+
}
|
|
317
|
+
/**
|
|
318
|
+
* Commit on mousedown (not click) so a searchable trigger blur cannot destroy the
|
|
319
|
+
* list before the pick is applied.
|
|
320
|
+
*/
|
|
321
|
+
handleItemMouseDown(event, item) {
|
|
322
|
+
event.preventDefault();
|
|
323
|
+
event.stopPropagation();
|
|
324
|
+
this.handleItemClick(item);
|
|
325
|
+
}
|
|
326
|
+
handleItemKeypress(e, item) {
|
|
327
|
+
if (e.nativeEvent.key === 'Enter' || e.nativeEvent.code === 'Space') {
|
|
328
|
+
e.nativeEvent.stopPropagation();
|
|
329
|
+
e.nativeEvent.preventDefault();
|
|
330
|
+
this.handleItemClick(item);
|
|
331
|
+
}
|
|
332
|
+
}
|
|
333
|
+
handleListKeypress(e) {
|
|
334
|
+
const key = e.nativeEvent.key;
|
|
335
|
+
const nav = this.listNavigation();
|
|
336
|
+
const viewport = this.viewportRef();
|
|
337
|
+
if (key === 'ArrowUp' && nav && nav.activeIndex() === 0) {
|
|
338
|
+
const offset = viewport?.measureScrollOffset() ?? 0;
|
|
339
|
+
if (offset > 0) {
|
|
340
|
+
e.nativeEvent.preventDefault();
|
|
341
|
+
viewport.scrollToOffset(Math.max(0, offset - this.itemHeight()));
|
|
342
|
+
queueMicrotask(() => nav.focusOnIndex(0));
|
|
343
|
+
return;
|
|
344
|
+
}
|
|
345
|
+
e.nativeEvent.preventDefault();
|
|
346
|
+
this.navigateOut.emit('up');
|
|
347
|
+
return;
|
|
348
|
+
}
|
|
349
|
+
if (key === 'ArrowDown' && nav && viewport) {
|
|
350
|
+
const items = this.navItems();
|
|
351
|
+
if (items.length > 0 && nav.activeIndex() >= items.length - 1) {
|
|
352
|
+
const maxOffset = Math.max(0, this.totalCount() * this.itemHeight() - viewport.getViewportSize());
|
|
353
|
+
const nextOffset = Math.min(maxOffset, viewport.measureScrollOffset() + this.itemHeight());
|
|
354
|
+
if (nextOffset > viewport.measureScrollOffset()) {
|
|
355
|
+
e.nativeEvent.preventDefault();
|
|
356
|
+
viewport.scrollToOffset(nextOffset);
|
|
357
|
+
queueMicrotask(() => nav.focusOnIndex(this.navItems().length - 1));
|
|
358
|
+
}
|
|
359
|
+
return;
|
|
360
|
+
}
|
|
361
|
+
}
|
|
362
|
+
if (key === 'ArrowUp' ||
|
|
363
|
+
key === 'ArrowDown' ||
|
|
364
|
+
key === 'Tab' ||
|
|
365
|
+
key === 'Shift' ||
|
|
366
|
+
key === 'Enter' ||
|
|
367
|
+
key === 'Escape' ||
|
|
368
|
+
key === ' ') {
|
|
369
|
+
return;
|
|
370
|
+
}
|
|
371
|
+
this.navigateOut.emit('typeahead');
|
|
372
|
+
}
|
|
373
|
+
activateNavItem(nav, item) {
|
|
374
|
+
nav?.navigateTo(item);
|
|
375
|
+
}
|
|
376
|
+
static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "22.0.8", ngImport: i0, type: AXLookupListViewBase, deps: [], target: i0.ɵɵFactoryTarget.Directive }); }
|
|
377
|
+
static { this.ɵdir = i0.ɵɵngDeclareDirective({ minVersion: "17.2.0", version: "22.0.8", type: AXLookupListViewBase, isStandalone: true, inputs: { dataSource: { classPropertyName: "dataSource", publicName: "dataSource", isSignal: true, isRequired: true, transformFunction: null }, valueField: { classPropertyName: "valueField", publicName: "valueField", isSignal: true, isRequired: false, transformFunction: null }, textField: { classPropertyName: "textField", publicName: "textField", isSignal: true, isRequired: false, transformFunction: null }, disabledField: { classPropertyName: "disabledField", publicName: "disabledField", isSignal: true, isRequired: false, transformFunction: null }, selectedValues: { classPropertyName: "selectedValues", publicName: "selectedValues", isSignal: true, isRequired: false, transformFunction: null }, itemHeight: { classPropertyName: "itemHeight", publicName: "itemHeight", isSignal: true, isRequired: false, transformFunction: null }, maxVisibleItems: { classPropertyName: "maxVisibleItems", publicName: "maxVisibleItems", isSignal: true, isRequired: false, transformFunction: null }, itemTemplate: { classPropertyName: "itemTemplate", publicName: "itemTemplate", isSignal: true, isRequired: false, transformFunction: null }, emptyTemplate: { classPropertyName: "emptyTemplate", publicName: "emptyTemplate", isSignal: true, isRequired: false, transformFunction: null }, loadingTemplate: { classPropertyName: "loadingTemplate", publicName: "loadingTemplate", isSignal: true, isRequired: false, transformFunction: null }, alternate: { classPropertyName: "alternate", publicName: "alternate", isSignal: true, isRequired: false, transformFunction: null } }, outputs: { itemClick: "itemClick", navigateOut: "navigateOut" }, viewQueries: [{ propertyName: "viewportRef", first: true, predicate: CdkVirtualScrollViewport, descendants: true, isSignal: true }, { propertyName: "listNavigation", first: true, predicate: AXListNavigationDirective, descendants: true, isSignal: true }, { propertyName: "navItems", predicate: AXListNavigationItemDirective, descendants: true, isSignal: true }], ngImport: i0 }); }
|
|
378
|
+
}
|
|
379
|
+
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "22.0.8", ngImport: i0, type: AXLookupListViewBase, decorators: [{
|
|
380
|
+
type: Directive
|
|
381
|
+
}], ctorParameters: () => [], propDecorators: { dataSource: [{ type: i0.Input, args: [{ isSignal: true, alias: "dataSource", required: true }] }], valueField: [{ type: i0.Input, args: [{ isSignal: true, alias: "valueField", required: false }] }], textField: [{ type: i0.Input, args: [{ isSignal: true, alias: "textField", required: false }] }], disabledField: [{ type: i0.Input, args: [{ isSignal: true, alias: "disabledField", required: false }] }], selectedValues: [{ type: i0.Input, args: [{ isSignal: true, alias: "selectedValues", required: false }] }], itemHeight: [{ type: i0.Input, args: [{ isSignal: true, alias: "itemHeight", required: false }] }], maxVisibleItems: [{ type: i0.Input, args: [{ isSignal: true, alias: "maxVisibleItems", required: false }] }], itemTemplate: [{ type: i0.Input, args: [{ isSignal: true, alias: "itemTemplate", required: false }] }], emptyTemplate: [{ type: i0.Input, args: [{ isSignal: true, alias: "emptyTemplate", required: false }] }], loadingTemplate: [{ type: i0.Input, args: [{ isSignal: true, alias: "loadingTemplate", required: false }] }], alternate: [{ type: i0.Input, args: [{ isSignal: true, alias: "alternate", required: false }] }], itemClick: [{ type: i0.Output, args: ["itemClick"] }], navigateOut: [{ type: i0.Output, args: ["navigateOut"] }], viewportRef: [{ type: i0.ViewChild, args: [i0.forwardRef(() => CdkVirtualScrollViewport), { isSignal: true }] }], listNavigation: [{ type: i0.ViewChild, args: [i0.forwardRef(() => AXListNavigationDirective), { isSignal: true }] }], navItems: [{ type: i0.ViewChildren, args: [i0.forwardRef(() => AXListNavigationItemDirective), { isSignal: true }] }] } });
|
|
382
|
+
|
|
383
|
+
/**
|
|
384
|
+
* Internal mini component for the `drop-down-list` lookup mode:
|
|
385
|
+
* a predefined, virtualized list of options for picking single values.
|
|
386
|
+
*
|
|
387
|
+
* @category Components
|
|
388
|
+
*/
|
|
389
|
+
class AXLookupDropDownListComponent extends AXLookupListViewBase {
|
|
390
|
+
static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "22.0.8", ngImport: i0, type: AXLookupDropDownListComponent, deps: null, target: i0.ɵɵFactoryTarget.Component }); }
|
|
391
|
+
static { this.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "22.0.8", type: AXLookupDropDownListComponent, isStandalone: true, selector: "ax-lookup-drop-down-list", providers: [{ provide: AXLookupListViewBase, useExisting: AXLookupDropDownListComponent }], usesInheritance: true, ngImport: i0, template: `
|
|
392
|
+
@if (isEmpty()) {
|
|
393
|
+
@if (emptyTemplate()) {
|
|
394
|
+
<ng-container [ngTemplateOutlet]="emptyTemplate()!" />
|
|
395
|
+
} @else {
|
|
396
|
+
<div class="ax-lookup-empty">
|
|
397
|
+
{{ '@acorex:common.general.no-result-found' | translate | async }}
|
|
398
|
+
</div>
|
|
399
|
+
}
|
|
400
|
+
} @else {
|
|
401
|
+
<cdk-virtual-scroll-viewport
|
|
402
|
+
class="ax-lookup-viewport"
|
|
403
|
+
role="listbox"
|
|
404
|
+
axListNavigation
|
|
405
|
+
#nav="axListNavigation"
|
|
406
|
+
[itemSize]="itemHeight()"
|
|
407
|
+
[style.height.px]="viewportHeight()"
|
|
408
|
+
(onKeypress)="handleListKeypress($event)"
|
|
409
|
+
>
|
|
410
|
+
<div
|
|
411
|
+
*cdkVirtualFor="let item of listDataSource(); let i = index; trackBy: trackByIndex"
|
|
412
|
+
role="option"
|
|
413
|
+
class="ax-lookup-option-host"
|
|
414
|
+
axListNavigationItem
|
|
415
|
+
#navItem="axListNavigationItem"
|
|
416
|
+
[style.height.px]="itemHeight()"
|
|
417
|
+
[class.ax-lookup-option]="!itemTemplate()"
|
|
418
|
+
[class.ax-state-alternate]="alternate() && i % 2 === 1"
|
|
419
|
+
[class.ax-state-selected]="item != null && isSelected(item)"
|
|
420
|
+
[class.ax-state-disabled]="item != null && isDisabled(item)"
|
|
421
|
+
[class.ax-state-active]="navItem.isActive()"
|
|
422
|
+
[attr.aria-selected]="item != null ? isSelected(item) : null"
|
|
423
|
+
(mouseenter)="activateNavItem(nav, navItem)"
|
|
424
|
+
(mousedown)="handleItemMouseDown($event, item)"
|
|
425
|
+
(onKeypress)="handleItemKeypress($event, item)"
|
|
426
|
+
>
|
|
427
|
+
@if (item != null) {
|
|
428
|
+
@if (itemTemplate()) {
|
|
429
|
+
<ng-container [ngTemplateOutlet]="itemTemplate()!" [ngTemplateOutletContext]="{ $implicit: item }" />
|
|
430
|
+
} @else {
|
|
431
|
+
<span class="ax-lookup-option-text">{{ getText(item) }}</span>
|
|
432
|
+
@if (isSelected(item)) {
|
|
433
|
+
<span class="ax-lookup-option-check ax-icon ax-icon-check" aria-hidden="true"></span>
|
|
434
|
+
}
|
|
435
|
+
}
|
|
436
|
+
} @else {
|
|
437
|
+
<ng-container [ngTemplateOutlet]="loadingRow" />
|
|
438
|
+
}
|
|
439
|
+
</div>
|
|
440
|
+
</cdk-virtual-scroll-viewport>
|
|
441
|
+
}
|
|
442
|
+
|
|
443
|
+
<ng-template #loadingRow>
|
|
444
|
+
@if (loadingTemplate()) {
|
|
445
|
+
<ng-container [ngTemplateOutlet]="loadingTemplate()!" />
|
|
446
|
+
} @else {
|
|
447
|
+
<span class="ax-lookup-option-loading">{{ '@acorex:common.status.loading' | translate | async }}</span>
|
|
448
|
+
}
|
|
449
|
+
</ng-template>
|
|
450
|
+
`, isInline: true, dependencies: [{ kind: "ngmodule", type: ScrollingModule }, { kind: "directive", type: i1.CdkFixedSizeVirtualScroll, selector: "cdk-virtual-scroll-viewport[itemSize]", inputs: ["itemSize", "minBufferPx", "maxBufferPx"] }, { kind: "directive", type: i1.CdkVirtualForOf, selector: "[cdkVirtualFor][cdkVirtualForOf]", inputs: ["cdkVirtualForOf", "cdkVirtualForTrackBy", "cdkVirtualForTemplate", "cdkVirtualForTemplateCacheSize"] }, { kind: "component", type: i1.CdkVirtualScrollViewport, selector: "cdk-virtual-scroll-viewport", inputs: ["orientation", "appendOnly"], outputs: ["scrolledIndexChange"] }, { kind: "directive", type: NgTemplateOutlet, selector: "[ngTemplateOutlet]", inputs: ["ngTemplateOutletContext", "ngTemplateOutlet", "ngTemplateOutletInjector"] }, { kind: "ngmodule", type: AXListNavigationModule }, { kind: "directive", type: i2.AXListNavigationDirective, selector: "[axListNavigation]", inputs: ["orientation"], outputs: ["onNavigationChanged", "onKeypress"], exportAs: ["axListNavigation"] }, { kind: "directive", type: i2.AXListNavigationItemDirective, selector: "[axListNavigationItem]", outputs: ["onKeypress"], exportAs: ["axListNavigationItem"] }, { kind: "pipe", type: AXTranslatorPipe, name: "translate" }, { kind: "pipe", type: AsyncPipe, name: "async" }], changeDetection: i0.ChangeDetectionStrategy.OnPush, encapsulation: i0.ViewEncapsulation.None }); }
|
|
451
|
+
}
|
|
452
|
+
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "22.0.8", ngImport: i0, type: AXLookupDropDownListComponent, decorators: [{
|
|
453
|
+
type: Component,
|
|
454
|
+
args: [{
|
|
455
|
+
selector: 'ax-lookup-drop-down-list',
|
|
456
|
+
changeDetection: ChangeDetectionStrategy.OnPush,
|
|
457
|
+
encapsulation: ViewEncapsulation.None,
|
|
458
|
+
imports: [ScrollingModule, NgTemplateOutlet, AXTranslatorPipe, AsyncPipe, AXListNavigationModule],
|
|
459
|
+
providers: [{ provide: AXLookupListViewBase, useExisting: AXLookupDropDownListComponent }],
|
|
460
|
+
template: `
|
|
461
|
+
@if (isEmpty()) {
|
|
462
|
+
@if (emptyTemplate()) {
|
|
463
|
+
<ng-container [ngTemplateOutlet]="emptyTemplate()!" />
|
|
464
|
+
} @else {
|
|
465
|
+
<div class="ax-lookup-empty">
|
|
466
|
+
{{ '@acorex:common.general.no-result-found' | translate | async }}
|
|
467
|
+
</div>
|
|
468
|
+
}
|
|
469
|
+
} @else {
|
|
470
|
+
<cdk-virtual-scroll-viewport
|
|
471
|
+
class="ax-lookup-viewport"
|
|
472
|
+
role="listbox"
|
|
473
|
+
axListNavigation
|
|
474
|
+
#nav="axListNavigation"
|
|
475
|
+
[itemSize]="itemHeight()"
|
|
476
|
+
[style.height.px]="viewportHeight()"
|
|
477
|
+
(onKeypress)="handleListKeypress($event)"
|
|
478
|
+
>
|
|
479
|
+
<div
|
|
480
|
+
*cdkVirtualFor="let item of listDataSource(); let i = index; trackBy: trackByIndex"
|
|
481
|
+
role="option"
|
|
482
|
+
class="ax-lookup-option-host"
|
|
483
|
+
axListNavigationItem
|
|
484
|
+
#navItem="axListNavigationItem"
|
|
485
|
+
[style.height.px]="itemHeight()"
|
|
486
|
+
[class.ax-lookup-option]="!itemTemplate()"
|
|
487
|
+
[class.ax-state-alternate]="alternate() && i % 2 === 1"
|
|
488
|
+
[class.ax-state-selected]="item != null && isSelected(item)"
|
|
489
|
+
[class.ax-state-disabled]="item != null && isDisabled(item)"
|
|
490
|
+
[class.ax-state-active]="navItem.isActive()"
|
|
491
|
+
[attr.aria-selected]="item != null ? isSelected(item) : null"
|
|
492
|
+
(mouseenter)="activateNavItem(nav, navItem)"
|
|
493
|
+
(mousedown)="handleItemMouseDown($event, item)"
|
|
494
|
+
(onKeypress)="handleItemKeypress($event, item)"
|
|
495
|
+
>
|
|
496
|
+
@if (item != null) {
|
|
497
|
+
@if (itemTemplate()) {
|
|
498
|
+
<ng-container [ngTemplateOutlet]="itemTemplate()!" [ngTemplateOutletContext]="{ $implicit: item }" />
|
|
499
|
+
} @else {
|
|
500
|
+
<span class="ax-lookup-option-text">{{ getText(item) }}</span>
|
|
501
|
+
@if (isSelected(item)) {
|
|
502
|
+
<span class="ax-lookup-option-check ax-icon ax-icon-check" aria-hidden="true"></span>
|
|
503
|
+
}
|
|
504
|
+
}
|
|
505
|
+
} @else {
|
|
506
|
+
<ng-container [ngTemplateOutlet]="loadingRow" />
|
|
507
|
+
}
|
|
508
|
+
</div>
|
|
509
|
+
</cdk-virtual-scroll-viewport>
|
|
510
|
+
}
|
|
511
|
+
|
|
512
|
+
<ng-template #loadingRow>
|
|
513
|
+
@if (loadingTemplate()) {
|
|
514
|
+
<ng-container [ngTemplateOutlet]="loadingTemplate()!" />
|
|
515
|
+
} @else {
|
|
516
|
+
<span class="ax-lookup-option-loading">{{ '@acorex:common.status.loading' | translate | async }}</span>
|
|
517
|
+
}
|
|
518
|
+
</ng-template>
|
|
519
|
+
`,
|
|
520
|
+
}]
|
|
521
|
+
}] });
|
|
522
|
+
|
|
523
|
+
/**
|
|
524
|
+
* Internal mini component for the `drop-down-tree` lookup mode:
|
|
525
|
+
* a predefined list rendered in a tree-like structure for single item selection.
|
|
526
|
+
*
|
|
527
|
+
* @category Components
|
|
528
|
+
*/
|
|
529
|
+
class AXLookupDropDownTreeComponent {
|
|
530
|
+
constructor() {
|
|
531
|
+
/**
|
|
532
|
+
* The tree datasource: an array of nodes or a lazy children callback.
|
|
533
|
+
*/
|
|
534
|
+
this.dataSource = input.required(/* @ts-ignore */
|
|
535
|
+
...(ngDevMode ? [{ debugName: "dataSource" }] : /* istanbul ignore next */ []));
|
|
536
|
+
/**
|
|
537
|
+
* The node property used as the selection value (tree `idField`).
|
|
538
|
+
*/
|
|
539
|
+
this.valueField = input('id', /* @ts-ignore */
|
|
540
|
+
...(ngDevMode ? [{ debugName: "valueField" }] : /* istanbul ignore next */ []));
|
|
541
|
+
/**
|
|
542
|
+
* The node property used as the display text (tree `titleField`).
|
|
543
|
+
*/
|
|
544
|
+
this.textField = input('title', /* @ts-ignore */
|
|
545
|
+
...(ngDevMode ? [{ debugName: "textField" }] : /* istanbul ignore next */ []));
|
|
546
|
+
/**
|
|
547
|
+
* The node property marking a node as disabled.
|
|
548
|
+
*/
|
|
549
|
+
this.disabledField = input('disabled', /* @ts-ignore */
|
|
550
|
+
...(ngDevMode ? [{ debugName: "disabledField" }] : /* istanbul ignore next */ []));
|
|
551
|
+
/**
|
|
552
|
+
* Currently selected values (at most one for single selection).
|
|
553
|
+
*/
|
|
554
|
+
this.selectedValues = input([], /* @ts-ignore */
|
|
555
|
+
...(ngDevMode ? [{ debugName: "selectedValues" }] : /* istanbul ignore next */ []));
|
|
556
|
+
/**
|
|
557
|
+
* Custom template rendered for each tree node.
|
|
558
|
+
*/
|
|
559
|
+
this.nodeTemplate = input(undefined, /* @ts-ignore */
|
|
560
|
+
...(ngDevMode ? [{ debugName: "nodeTemplate" }] : /* istanbul ignore next */ []));
|
|
561
|
+
/**
|
|
562
|
+
* Custom template rendered when the filtered tree has no nodes.
|
|
563
|
+
*/
|
|
564
|
+
this.emptyTemplate = input(undefined, /* @ts-ignore */
|
|
565
|
+
...(ngDevMode ? [{ debugName: "emptyTemplate" }] : /* istanbul ignore next */ []));
|
|
566
|
+
/**
|
|
567
|
+
* When `true`, visible tree nodes use alternating background colors.
|
|
568
|
+
*/
|
|
569
|
+
this.alternate = input(false, /* @ts-ignore */
|
|
570
|
+
...(ngDevMode ? [{ debugName: "alternate" }] : /* istanbul ignore next */ []));
|
|
571
|
+
/**
|
|
572
|
+
* Unique id that changes on every search apply so a new tree instance is created.
|
|
573
|
+
*/
|
|
574
|
+
this.filterKey = input('0', /* @ts-ignore */
|
|
575
|
+
...(ngDevMode ? [{ debugName: "filterKey" }] : /* istanbul ignore next */ []));
|
|
576
|
+
/**
|
|
577
|
+
* Emitted when the user selects a node.
|
|
578
|
+
*/
|
|
579
|
+
this.itemClick = output();
|
|
580
|
+
this.selectedIds = computed(() => this.selectedValues().map((v) => String(v)), /* @ts-ignore */
|
|
581
|
+
...(ngDevMode ? [{ debugName: "selectedIds" }] : /* istanbul ignore next */ []));
|
|
582
|
+
this.isEmpty = computed(() => {
|
|
583
|
+
const source = this.dataSource();
|
|
584
|
+
return Array.isArray(source) && source.length === 0;
|
|
585
|
+
}, /* @ts-ignore */
|
|
586
|
+
...(ngDevMode ? [{ debugName: "isEmpty" }] : /* istanbul ignore next */ []));
|
|
587
|
+
this.treeInstances = computed(() => [{ id: this.filterKey(), source: this.dataSource() }], /* @ts-ignore */
|
|
588
|
+
...(ngDevMode ? [{ debugName: "treeInstances" }] : /* istanbul ignore next */ []));
|
|
589
|
+
}
|
|
590
|
+
/** Whether the filtered tree currently has no nodes. */
|
|
591
|
+
hasNoMatches() {
|
|
592
|
+
return this.isEmpty();
|
|
593
|
+
}
|
|
594
|
+
handleSelectionChange(e) {
|
|
595
|
+
if (e.source !== 'user') {
|
|
596
|
+
return;
|
|
597
|
+
}
|
|
598
|
+
const node = e.selectedNodes[0];
|
|
599
|
+
if (!node) {
|
|
600
|
+
return;
|
|
601
|
+
}
|
|
602
|
+
this.itemClick.emit({ item: node, value: node[this.valueField()] });
|
|
603
|
+
}
|
|
604
|
+
static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "22.0.8", ngImport: i0, type: AXLookupDropDownTreeComponent, deps: [], target: i0.ɵɵFactoryTarget.Component }); }
|
|
605
|
+
static { this.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "22.0.8", type: AXLookupDropDownTreeComponent, isStandalone: true, selector: "ax-lookup-drop-down-tree", inputs: { dataSource: { classPropertyName: "dataSource", publicName: "dataSource", isSignal: true, isRequired: true, transformFunction: null }, valueField: { classPropertyName: "valueField", publicName: "valueField", isSignal: true, isRequired: false, transformFunction: null }, textField: { classPropertyName: "textField", publicName: "textField", isSignal: true, isRequired: false, transformFunction: null }, disabledField: { classPropertyName: "disabledField", publicName: "disabledField", isSignal: true, isRequired: false, transformFunction: null }, selectedValues: { classPropertyName: "selectedValues", publicName: "selectedValues", isSignal: true, isRequired: false, transformFunction: null }, nodeTemplate: { classPropertyName: "nodeTemplate", publicName: "nodeTemplate", isSignal: true, isRequired: false, transformFunction: null }, emptyTemplate: { classPropertyName: "emptyTemplate", publicName: "emptyTemplate", isSignal: true, isRequired: false, transformFunction: null }, alternate: { classPropertyName: "alternate", publicName: "alternate", isSignal: true, isRequired: false, transformFunction: null }, filterKey: { classPropertyName: "filterKey", publicName: "filterKey", isSignal: true, isRequired: false, transformFunction: null } }, outputs: { itemClick: "itemClick" }, ngImport: i0, template: `
|
|
606
|
+
@if (isEmpty()) {
|
|
607
|
+
@if (emptyTemplate()) {
|
|
608
|
+
<ng-container [ngTemplateOutlet]="emptyTemplate()!" />
|
|
609
|
+
} @else {
|
|
610
|
+
<div class="ax-lookup-empty">
|
|
611
|
+
{{ '@acorex:common.general.no-result-found' | translate | async }}
|
|
612
|
+
</div>
|
|
613
|
+
}
|
|
614
|
+
} @else {
|
|
615
|
+
<div class="ax-lookup-tree">
|
|
616
|
+
@for (instance of treeInstances(); track instance.id) {
|
|
617
|
+
<ax-tree-view
|
|
618
|
+
[datasource]="instance.source"
|
|
619
|
+
selectMode="single"
|
|
620
|
+
selectionBehavior="all"
|
|
621
|
+
[controlledSelection]="true"
|
|
622
|
+
[selectedIds]="selectedIds()"
|
|
623
|
+
[idField]="valueField()"
|
|
624
|
+
[titleField]="textField()"
|
|
625
|
+
[disabledField]="disabledField()"
|
|
626
|
+
[nodeTemplate]="nodeTemplate()"
|
|
627
|
+
[alternate]="alternate()"
|
|
628
|
+
(onSelectionChange)="handleSelectionChange($event)"
|
|
629
|
+
/>
|
|
630
|
+
}
|
|
631
|
+
</div>
|
|
632
|
+
}
|
|
633
|
+
`, isInline: true, dependencies: [{ kind: "component", type: AXTreeViewComponent, selector: "ax-tree-view", inputs: ["datasource", "selectMode", "selectionBehavior", "dragArea", "dragBehavior", "showIcons", "showChildrenBadge", "expandedIcon", "collapsedIcon", "indentSize", "look", "alternate", "nodeTemplate", "idField", "titleField", "tooltipField", "iconField", "expandedField", "selectedField", "indeterminateField", "disabledField", "hiddenField", "childrenField", "childrenCountField", "dataField", "inheritDisabled", "expandOnDoubleClick", "doubleClickDuration", "tooltipDelay", "controlledSelection", "selectedIds"], outputs: ["datasourceChange", "selectedIdsChange", "onBeforeDrop", "onNodeToggle", "onNodeSelect", "onNodeDoubleClick", "onNodeClick", "onSelectionChange", "onOrderChange", "onMoveChange", "onItemsChange"] }, { kind: "directive", type: NgTemplateOutlet, selector: "[ngTemplateOutlet]", inputs: ["ngTemplateOutletContext", "ngTemplateOutlet", "ngTemplateOutletInjector"] }, { kind: "pipe", type: AXTranslatorPipe, name: "translate" }, { kind: "pipe", type: AsyncPipe, name: "async" }], changeDetection: i0.ChangeDetectionStrategy.OnPush, encapsulation: i0.ViewEncapsulation.None }); }
|
|
634
|
+
}
|
|
635
|
+
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "22.0.8", ngImport: i0, type: AXLookupDropDownTreeComponent, decorators: [{
|
|
636
|
+
type: Component,
|
|
637
|
+
args: [{
|
|
638
|
+
selector: 'ax-lookup-drop-down-tree',
|
|
639
|
+
changeDetection: ChangeDetectionStrategy.OnPush,
|
|
640
|
+
encapsulation: ViewEncapsulation.None,
|
|
641
|
+
imports: [AXTreeViewComponent, NgTemplateOutlet, AXTranslatorPipe, AsyncPipe],
|
|
642
|
+
template: `
|
|
643
|
+
@if (isEmpty()) {
|
|
644
|
+
@if (emptyTemplate()) {
|
|
645
|
+
<ng-container [ngTemplateOutlet]="emptyTemplate()!" />
|
|
646
|
+
} @else {
|
|
647
|
+
<div class="ax-lookup-empty">
|
|
648
|
+
{{ '@acorex:common.general.no-result-found' | translate | async }}
|
|
649
|
+
</div>
|
|
650
|
+
}
|
|
651
|
+
} @else {
|
|
652
|
+
<div class="ax-lookup-tree">
|
|
653
|
+
@for (instance of treeInstances(); track instance.id) {
|
|
654
|
+
<ax-tree-view
|
|
655
|
+
[datasource]="instance.source"
|
|
656
|
+
selectMode="single"
|
|
657
|
+
selectionBehavior="all"
|
|
658
|
+
[controlledSelection]="true"
|
|
659
|
+
[selectedIds]="selectedIds()"
|
|
660
|
+
[idField]="valueField()"
|
|
661
|
+
[titleField]="textField()"
|
|
662
|
+
[disabledField]="disabledField()"
|
|
663
|
+
[nodeTemplate]="nodeTemplate()"
|
|
664
|
+
[alternate]="alternate()"
|
|
665
|
+
(onSelectionChange)="handleSelectionChange($event)"
|
|
666
|
+
/>
|
|
667
|
+
}
|
|
668
|
+
</div>
|
|
669
|
+
}
|
|
670
|
+
`,
|
|
671
|
+
}]
|
|
672
|
+
}], propDecorators: { dataSource: [{ type: i0.Input, args: [{ isSignal: true, alias: "dataSource", required: true }] }], valueField: [{ type: i0.Input, args: [{ isSignal: true, alias: "valueField", required: false }] }], textField: [{ type: i0.Input, args: [{ isSignal: true, alias: "textField", required: false }] }], disabledField: [{ type: i0.Input, args: [{ isSignal: true, alias: "disabledField", required: false }] }], selectedValues: [{ type: i0.Input, args: [{ isSignal: true, alias: "selectedValues", required: false }] }], nodeTemplate: [{ type: i0.Input, args: [{ isSignal: true, alias: "nodeTemplate", required: false }] }], emptyTemplate: [{ type: i0.Input, args: [{ isSignal: true, alias: "emptyTemplate", required: false }] }], alternate: [{ type: i0.Input, args: [{ isSignal: true, alias: "alternate", required: false }] }], filterKey: [{ type: i0.Input, args: [{ isSignal: true, alias: "filterKey", required: false }] }], itemClick: [{ type: i0.Output, args: ["itemClick"] }] } });
|
|
673
|
+
|
|
674
|
+
/**
|
|
675
|
+
* Internal mini component for the `multi-column-tree` lookup mode:
|
|
676
|
+
* a multi-column `ax-data-table` with a drop-down tree inside it.
|
|
677
|
+
* Rows expand/collapse via the data-table hierarchy (`parentField` / nested `children`).
|
|
678
|
+
*
|
|
679
|
+
* @category Components
|
|
680
|
+
*/
|
|
681
|
+
class AXLookupMultiColumnTreeComponent {
|
|
682
|
+
constructor() {
|
|
683
|
+
/**
|
|
684
|
+
* The datasource providing hierarchical rows (roots on load, children via `parentField`).
|
|
685
|
+
*/
|
|
686
|
+
this.dataSource = input.required(/* @ts-ignore */
|
|
687
|
+
...(ngDevMode ? [{ debugName: "dataSource" }] : /* istanbul ignore next */ []));
|
|
688
|
+
/**
|
|
689
|
+
* The item property used as the selection value (also the data-table row key).
|
|
690
|
+
*/
|
|
691
|
+
this.valueField = input('id', /* @ts-ignore */
|
|
692
|
+
...(ngDevMode ? [{ debugName: "valueField" }] : /* istanbul ignore next */ []));
|
|
693
|
+
/**
|
|
694
|
+
* The item property used as the display text. The matching column shows the expand control
|
|
695
|
+
* unless another column sets `expandHandler`.
|
|
696
|
+
*/
|
|
697
|
+
this.textField = input('text', /* @ts-ignore */
|
|
698
|
+
...(ngDevMode ? [{ debugName: "textField" }] : /* istanbul ignore next */ []));
|
|
699
|
+
/**
|
|
700
|
+
* The item property marking an item as disabled.
|
|
701
|
+
*/
|
|
702
|
+
this.disabledField = input('disabled', /* @ts-ignore */
|
|
703
|
+
...(ngDevMode ? [{ debugName: "disabledField" }] : /* istanbul ignore next */ []));
|
|
704
|
+
/**
|
|
705
|
+
* Field used by the data table to fetch children (`AXDataSource` filter on expand).
|
|
706
|
+
*/
|
|
707
|
+
this.parentField = input('parentId', /* @ts-ignore */
|
|
708
|
+
...(ngDevMode ? [{ debugName: "parentField" }] : /* istanbul ignore next */ []));
|
|
709
|
+
/**
|
|
710
|
+
* Field used by the data table to decide whether a row can expand.
|
|
711
|
+
*/
|
|
712
|
+
this.hasChildrenField = input('hasChild', /* @ts-ignore */
|
|
713
|
+
...(ngDevMode ? [{ debugName: "hasChildrenField" }] : /* istanbul ignore next */ []));
|
|
714
|
+
/**
|
|
715
|
+
* Currently selected values (always an array, even for single selection).
|
|
716
|
+
*/
|
|
717
|
+
this.selectedValues = input([], /* @ts-ignore */
|
|
718
|
+
...(ngDevMode ? [{ debugName: "selectedValues" }] : /* istanbul ignore next */ []));
|
|
719
|
+
/**
|
|
720
|
+
* The fixed row height in pixels passed to the data table.
|
|
721
|
+
*/
|
|
722
|
+
this.itemHeight = input(40, /* @ts-ignore */
|
|
723
|
+
...(ngDevMode ? [{ debugName: "itemHeight" }] : /* istanbul ignore next */ []));
|
|
724
|
+
/**
|
|
725
|
+
* The maximum number of body rows visible before the table scrolls.
|
|
726
|
+
*/
|
|
727
|
+
this.maxVisibleItems = input(8, /* @ts-ignore */
|
|
728
|
+
...(ngDevMode ? [{ debugName: "maxVisibleItems" }] : /* istanbul ignore next */ []));
|
|
729
|
+
/**
|
|
730
|
+
* Column definitions rendered as `ax-text-column` instances.
|
|
731
|
+
*/
|
|
732
|
+
this.columns = input([], /* @ts-ignore */
|
|
733
|
+
...(ngDevMode ? [{ debugName: "columns" }] : /* istanbul ignore next */ []));
|
|
734
|
+
/**
|
|
735
|
+
* Optional custom row content. Context: `$implicit` is the row item.
|
|
736
|
+
* When set, replaces the default multi-column cell layout.
|
|
737
|
+
*/
|
|
738
|
+
this.itemTemplate = input(undefined, /* @ts-ignore */
|
|
739
|
+
...(ngDevMode ? [{ debugName: "itemTemplate" }] : /* istanbul ignore next */ []));
|
|
740
|
+
/**
|
|
741
|
+
* Custom template rendered when the datasource has no items.
|
|
742
|
+
*/
|
|
743
|
+
this.emptyTemplate = input(undefined, /* @ts-ignore */
|
|
744
|
+
...(ngDevMode ? [{ debugName: "emptyTemplate" }] : /* istanbul ignore next */ []));
|
|
745
|
+
/**
|
|
746
|
+
* Custom template rendered while the table is loading.
|
|
747
|
+
*/
|
|
748
|
+
this.loadingTemplate = input(undefined, /* @ts-ignore */
|
|
749
|
+
...(ngDevMode ? [{ debugName: "loadingTemplate" }] : /* istanbul ignore next */ []));
|
|
750
|
+
/**
|
|
751
|
+
* When `true`, table rows use alternating background colors for easier scanning.
|
|
752
|
+
*/
|
|
753
|
+
this.alternate = input(false, /* @ts-ignore */
|
|
754
|
+
...(ngDevMode ? [{ debugName: "alternate" }] : /* istanbul ignore next */ []));
|
|
755
|
+
/**
|
|
756
|
+
* Emitted when the user picks a row (not when expanding/collapsing).
|
|
757
|
+
*/
|
|
758
|
+
this.itemClick = output();
|
|
759
|
+
/**
|
|
760
|
+
* Header (~40px) + up to `maxVisibleItems` body rows. Expanded children scroll inside.
|
|
761
|
+
*/
|
|
762
|
+
this.tableHeight = computed(() => 40 + this.maxVisibleItems() * this.itemHeight(), /* @ts-ignore */
|
|
763
|
+
...(ngDevMode ? [{ debugName: "tableHeight" }] : /* istanbul ignore next */ []));
|
|
764
|
+
this.loadingConfig = computed(() => ({
|
|
765
|
+
enabled: true,
|
|
766
|
+
animation: true,
|
|
767
|
+
loadingTemplate: this.loadingTemplate(),
|
|
768
|
+
}), /* @ts-ignore */
|
|
769
|
+
...(ngDevMode ? [{ debugName: "loadingConfig" }] : /* istanbul ignore next */ []));
|
|
770
|
+
this.resolveRowCssClass = (row) => {
|
|
771
|
+
const item = row;
|
|
772
|
+
if (!item) {
|
|
773
|
+
return '';
|
|
774
|
+
}
|
|
775
|
+
const classes = [];
|
|
776
|
+
if (this.isSelected(item)) {
|
|
777
|
+
classes.push('ax-state-selected');
|
|
778
|
+
}
|
|
779
|
+
if (this.isDisabled(item)) {
|
|
780
|
+
classes.push('ax-state-disabled');
|
|
781
|
+
}
|
|
782
|
+
return classes.join(' ');
|
|
783
|
+
};
|
|
784
|
+
}
|
|
785
|
+
/** Stable unique key for `@for` — avoids NG0955 when `field` is missing or duplicated. */
|
|
786
|
+
trackColumnKey(index, column) {
|
|
787
|
+
return `${column?.field ?? ''}::${index}`;
|
|
788
|
+
}
|
|
789
|
+
resolveColumnWidth(column) {
|
|
790
|
+
const width = column.width?.trim();
|
|
791
|
+
if (!width || width.includes('fr')) {
|
|
792
|
+
return 'auto';
|
|
793
|
+
}
|
|
794
|
+
return width;
|
|
795
|
+
}
|
|
796
|
+
isExpandColumn(index, column) {
|
|
797
|
+
if (column.expandHandler === true) {
|
|
798
|
+
return true;
|
|
799
|
+
}
|
|
800
|
+
if (this.columns().some((item) => item.expandHandler === true)) {
|
|
801
|
+
return false;
|
|
802
|
+
}
|
|
803
|
+
const textIndex = this.columns().findIndex((item) => item.field === this.textField());
|
|
804
|
+
return (textIndex === -1 ? 0 : textIndex) === index;
|
|
805
|
+
}
|
|
806
|
+
handleRowClick(event) {
|
|
807
|
+
this.handleItemClick(event.data);
|
|
808
|
+
}
|
|
809
|
+
handleItemClick(item) {
|
|
810
|
+
if (!item || this.isDisabled(item)) {
|
|
811
|
+
return;
|
|
812
|
+
}
|
|
813
|
+
this.itemClick.emit({ item, value: this.getValue(item) });
|
|
814
|
+
}
|
|
815
|
+
handleItemMouseDown(event, item) {
|
|
816
|
+
event.preventDefault();
|
|
817
|
+
event.stopPropagation();
|
|
818
|
+
this.handleItemClick(item);
|
|
819
|
+
}
|
|
820
|
+
isSelected(item) {
|
|
821
|
+
const value = this.getValue(item);
|
|
822
|
+
return this.selectedValues().some((v) => v == value);
|
|
823
|
+
}
|
|
824
|
+
isDisabled(item) {
|
|
825
|
+
return Boolean(item?.[this.disabledField()]);
|
|
826
|
+
}
|
|
827
|
+
getValue(item) {
|
|
828
|
+
return item?.[this.valueField()];
|
|
829
|
+
}
|
|
830
|
+
static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "22.0.8", ngImport: i0, type: AXLookupMultiColumnTreeComponent, deps: [], target: i0.ɵɵFactoryTarget.Component }); }
|
|
831
|
+
static { this.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "22.0.8", type: AXLookupMultiColumnTreeComponent, isStandalone: true, selector: "ax-lookup-multi-column-tree", inputs: { dataSource: { classPropertyName: "dataSource", publicName: "dataSource", isSignal: true, isRequired: true, transformFunction: null }, valueField: { classPropertyName: "valueField", publicName: "valueField", isSignal: true, isRequired: false, transformFunction: null }, textField: { classPropertyName: "textField", publicName: "textField", isSignal: true, isRequired: false, transformFunction: null }, disabledField: { classPropertyName: "disabledField", publicName: "disabledField", isSignal: true, isRequired: false, transformFunction: null }, parentField: { classPropertyName: "parentField", publicName: "parentField", isSignal: true, isRequired: false, transformFunction: null }, hasChildrenField: { classPropertyName: "hasChildrenField", publicName: "hasChildrenField", isSignal: true, isRequired: false, transformFunction: null }, selectedValues: { classPropertyName: "selectedValues", publicName: "selectedValues", isSignal: true, isRequired: false, transformFunction: null }, itemHeight: { classPropertyName: "itemHeight", publicName: "itemHeight", isSignal: true, isRequired: false, transformFunction: null }, maxVisibleItems: { classPropertyName: "maxVisibleItems", publicName: "maxVisibleItems", isSignal: true, isRequired: false, transformFunction: null }, columns: { classPropertyName: "columns", publicName: "columns", isSignal: true, isRequired: false, transformFunction: null }, itemTemplate: { classPropertyName: "itemTemplate", publicName: "itemTemplate", isSignal: true, isRequired: false, transformFunction: null }, emptyTemplate: { classPropertyName: "emptyTemplate", publicName: "emptyTemplate", isSignal: true, isRequired: false, transformFunction: null }, loadingTemplate: { classPropertyName: "loadingTemplate", publicName: "loadingTemplate", isSignal: true, isRequired: false, transformFunction: null }, alternate: { classPropertyName: "alternate", publicName: "alternate", isSignal: true, isRequired: false, transformFunction: null } }, outputs: { itemClick: "itemClick" }, host: { properties: { "style.height.px": "tableHeight()" }, classAttribute: "ax-lookup-multi-column ax-lookup-multi-column-tree" }, ngImport: i0, template: `
|
|
832
|
+
<ax-data-table
|
|
833
|
+
class="ax-lookup-multi-column-table"
|
|
834
|
+
look="minimal"
|
|
835
|
+
[dataSource]="dataSource()"
|
|
836
|
+
[parentField]="parentField()"
|
|
837
|
+
[hasChildrenField]="hasChildrenField()"
|
|
838
|
+
[itemHeight]="itemHeight()"
|
|
839
|
+
[alternative]="alternate()"
|
|
840
|
+
[emptyTemplate]="emptyTemplate()"
|
|
841
|
+
[loading]="loadingConfig()"
|
|
842
|
+
[paging]="false"
|
|
843
|
+
[showHeader]="true"
|
|
844
|
+
[fixedHeader]="true"
|
|
845
|
+
[showFooter]="false"
|
|
846
|
+
[allowReordering]="false"
|
|
847
|
+
[rowTemplate]="itemTemplate() ? customRowTemplate : undefined"
|
|
848
|
+
[rowCssClass]="resolveRowCssClass"
|
|
849
|
+
(onRowClick)="handleRowClick($event)"
|
|
850
|
+
>
|
|
851
|
+
@for (column of columns(); track trackColumnKey($index, column)) {
|
|
852
|
+
<ax-text-column
|
|
853
|
+
[dataField]="column.field"
|
|
854
|
+
[caption]="column.title"
|
|
855
|
+
[width]="resolveColumnWidth(column)"
|
|
856
|
+
[expandHandler]="isExpandColumn($index, column)"
|
|
857
|
+
[allowSorting]="false"
|
|
858
|
+
[allowResizing]="false"
|
|
859
|
+
/>
|
|
860
|
+
}
|
|
861
|
+
</ax-data-table>
|
|
862
|
+
|
|
863
|
+
<ng-template #customRowTemplate let-ctx>
|
|
864
|
+
<tr
|
|
865
|
+
[class.ax-state-selected]="ctx.data != null && isSelected(ctx.data)"
|
|
866
|
+
[class.ax-state-disabled]="ctx.data != null && isDisabled(ctx.data)"
|
|
867
|
+
[style.height.px]="itemHeight()"
|
|
868
|
+
[style.max-height.px]="itemHeight()"
|
|
869
|
+
(mousedown)="handleItemMouseDown($event, ctx.data)"
|
|
870
|
+
>
|
|
871
|
+
<td [attr.colspan]="columns().length || 1">
|
|
872
|
+
@if (ctx.data != null && itemTemplate()) {
|
|
873
|
+
<ng-container
|
|
874
|
+
[ngTemplateOutlet]="itemTemplate()!"
|
|
875
|
+
[ngTemplateOutletContext]="{ $implicit: ctx.data }"
|
|
876
|
+
/>
|
|
877
|
+
}
|
|
878
|
+
</td>
|
|
879
|
+
</tr>
|
|
880
|
+
</ng-template>
|
|
881
|
+
`, isInline: true, dependencies: [{ kind: "directive", type: NgTemplateOutlet, selector: "[ngTemplateOutlet]", inputs: ["ngTemplateOutletContext", "ngTemplateOutlet", "ngTemplateOutletInjector"] }, { kind: "component", type: AXDataTableComponent, selector: "ax-data-table", inputs: ["dataSource", "selectedRows", "parentField", "hasChildrenField", "rowDetailsTemplate", "rowCssClass", "cellCssClass", "highlightText", "look", "rowTemplate", "emptyTemplate", "noDataTemplate", "alternative", "showHeader", "fixedHeader", "showFooter", "fixedFooter", "itemHeight", "allowReordering", "paging", "fetchDataMode", "loading", "focusedRow"], outputs: ["selectedRowsChange", "focusedRowChange", "onRowClick", "onRowDbClick", "onColumnsOrderChanged", "onColumnSizeChanged", "onPageChanged"] }, { kind: "component", type: AXDataTableTextColumnComponent, selector: "ax-text-column", inputs: ["width", "caption", "allowSorting", "allowResizing", "fixed", "hasTitle", "customExpandIcon", "customCollapseIcon", "dataField", "expandHandler", "wrapText", "cellTemplate", "footerTemplate", "headerTemplate", "format", "formatOptions"] }], changeDetection: i0.ChangeDetectionStrategy.OnPush, encapsulation: i0.ViewEncapsulation.None }); }
|
|
882
|
+
}
|
|
883
|
+
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "22.0.8", ngImport: i0, type: AXLookupMultiColumnTreeComponent, decorators: [{
|
|
884
|
+
type: Component,
|
|
885
|
+
args: [{
|
|
886
|
+
selector: 'ax-lookup-multi-column-tree',
|
|
887
|
+
changeDetection: ChangeDetectionStrategy.OnPush,
|
|
888
|
+
encapsulation: ViewEncapsulation.None,
|
|
889
|
+
imports: [NgTemplateOutlet, AXDataTableComponent, AXDataTableTextColumnComponent],
|
|
890
|
+
host: {
|
|
891
|
+
class: 'ax-lookup-multi-column ax-lookup-multi-column-tree',
|
|
892
|
+
'[style.height.px]': 'tableHeight()',
|
|
893
|
+
},
|
|
894
|
+
template: `
|
|
895
|
+
<ax-data-table
|
|
896
|
+
class="ax-lookup-multi-column-table"
|
|
897
|
+
look="minimal"
|
|
898
|
+
[dataSource]="dataSource()"
|
|
899
|
+
[parentField]="parentField()"
|
|
900
|
+
[hasChildrenField]="hasChildrenField()"
|
|
901
|
+
[itemHeight]="itemHeight()"
|
|
902
|
+
[alternative]="alternate()"
|
|
903
|
+
[emptyTemplate]="emptyTemplate()"
|
|
904
|
+
[loading]="loadingConfig()"
|
|
905
|
+
[paging]="false"
|
|
906
|
+
[showHeader]="true"
|
|
907
|
+
[fixedHeader]="true"
|
|
908
|
+
[showFooter]="false"
|
|
909
|
+
[allowReordering]="false"
|
|
910
|
+
[rowTemplate]="itemTemplate() ? customRowTemplate : undefined"
|
|
911
|
+
[rowCssClass]="resolveRowCssClass"
|
|
912
|
+
(onRowClick)="handleRowClick($event)"
|
|
913
|
+
>
|
|
914
|
+
@for (column of columns(); track trackColumnKey($index, column)) {
|
|
915
|
+
<ax-text-column
|
|
916
|
+
[dataField]="column.field"
|
|
917
|
+
[caption]="column.title"
|
|
918
|
+
[width]="resolveColumnWidth(column)"
|
|
919
|
+
[expandHandler]="isExpandColumn($index, column)"
|
|
920
|
+
[allowSorting]="false"
|
|
921
|
+
[allowResizing]="false"
|
|
922
|
+
/>
|
|
923
|
+
}
|
|
924
|
+
</ax-data-table>
|
|
925
|
+
|
|
926
|
+
<ng-template #customRowTemplate let-ctx>
|
|
927
|
+
<tr
|
|
928
|
+
[class.ax-state-selected]="ctx.data != null && isSelected(ctx.data)"
|
|
929
|
+
[class.ax-state-disabled]="ctx.data != null && isDisabled(ctx.data)"
|
|
930
|
+
[style.height.px]="itemHeight()"
|
|
931
|
+
[style.max-height.px]="itemHeight()"
|
|
932
|
+
(mousedown)="handleItemMouseDown($event, ctx.data)"
|
|
933
|
+
>
|
|
934
|
+
<td [attr.colspan]="columns().length || 1">
|
|
935
|
+
@if (ctx.data != null && itemTemplate()) {
|
|
936
|
+
<ng-container
|
|
937
|
+
[ngTemplateOutlet]="itemTemplate()!"
|
|
938
|
+
[ngTemplateOutletContext]="{ $implicit: ctx.data }"
|
|
939
|
+
/>
|
|
940
|
+
}
|
|
941
|
+
</td>
|
|
942
|
+
</tr>
|
|
943
|
+
</ng-template>
|
|
944
|
+
`,
|
|
945
|
+
}]
|
|
946
|
+
}], propDecorators: { dataSource: [{ type: i0.Input, args: [{ isSignal: true, alias: "dataSource", required: true }] }], valueField: [{ type: i0.Input, args: [{ isSignal: true, alias: "valueField", required: false }] }], textField: [{ type: i0.Input, args: [{ isSignal: true, alias: "textField", required: false }] }], disabledField: [{ type: i0.Input, args: [{ isSignal: true, alias: "disabledField", required: false }] }], parentField: [{ type: i0.Input, args: [{ isSignal: true, alias: "parentField", required: false }] }], hasChildrenField: [{ type: i0.Input, args: [{ isSignal: true, alias: "hasChildrenField", required: false }] }], selectedValues: [{ type: i0.Input, args: [{ isSignal: true, alias: "selectedValues", required: false }] }], itemHeight: [{ type: i0.Input, args: [{ isSignal: true, alias: "itemHeight", required: false }] }], maxVisibleItems: [{ type: i0.Input, args: [{ isSignal: true, alias: "maxVisibleItems", required: false }] }], columns: [{ type: i0.Input, args: [{ isSignal: true, alias: "columns", required: false }] }], itemTemplate: [{ type: i0.Input, args: [{ isSignal: true, alias: "itemTemplate", required: false }] }], emptyTemplate: [{ type: i0.Input, args: [{ isSignal: true, alias: "emptyTemplate", required: false }] }], loadingTemplate: [{ type: i0.Input, args: [{ isSignal: true, alias: "loadingTemplate", required: false }] }], alternate: [{ type: i0.Input, args: [{ isSignal: true, alias: "alternate", required: false }] }], itemClick: [{ type: i0.Output, args: ["itemClick"] }] } });
|
|
947
|
+
|
|
948
|
+
/**
|
|
949
|
+
* Internal mini component for the `multi-column` lookup mode:
|
|
950
|
+
* renders selectable rows in an `ax-data-table` grid and loads further
|
|
951
|
+
* pages as the user scrolls (no pager UI).
|
|
952
|
+
*
|
|
953
|
+
* @category Components
|
|
954
|
+
*/
|
|
955
|
+
class AXLookupMultiColumnComponent {
|
|
956
|
+
/** Accumulated rows fed to the table (grows as pages are scrolled in). */
|
|
957
|
+
#loadedItems;
|
|
958
|
+
/** Total matching rows from the source (used to size the popup). */
|
|
959
|
+
#totalCount;
|
|
960
|
+
#host;
|
|
961
|
+
constructor() {
|
|
962
|
+
/**
|
|
963
|
+
* The datasource providing the grid rows (paged, remote-capable).
|
|
964
|
+
* Pages are fetched on demand as the user scrolls the table body.
|
|
965
|
+
*/
|
|
966
|
+
this.dataSource = input.required(/* @ts-ignore */
|
|
967
|
+
...(ngDevMode ? [{ debugName: "dataSource" }] : /* istanbul ignore next */ []));
|
|
968
|
+
/**
|
|
969
|
+
* The item property used as the selection value.
|
|
970
|
+
*/
|
|
971
|
+
this.valueField = input('id', /* @ts-ignore */
|
|
972
|
+
...(ngDevMode ? [{ debugName: "valueField" }] : /* istanbul ignore next */ []));
|
|
973
|
+
/**
|
|
974
|
+
* The item property used as the display text.
|
|
975
|
+
*/
|
|
976
|
+
this.textField = input('text', /* @ts-ignore */
|
|
977
|
+
...(ngDevMode ? [{ debugName: "textField" }] : /* istanbul ignore next */ []));
|
|
978
|
+
/**
|
|
979
|
+
* The item property marking an item as disabled.
|
|
980
|
+
*/
|
|
981
|
+
this.disabledField = input('disabled', /* @ts-ignore */
|
|
982
|
+
...(ngDevMode ? [{ debugName: "disabledField" }] : /* istanbul ignore next */ []));
|
|
983
|
+
/**
|
|
984
|
+
* Currently selected values (always an array, even for single selection).
|
|
985
|
+
*/
|
|
986
|
+
this.selectedValues = input([], /* @ts-ignore */
|
|
987
|
+
...(ngDevMode ? [{ debugName: "selectedValues" }] : /* istanbul ignore next */ []));
|
|
988
|
+
/**
|
|
989
|
+
* The fixed row height in pixels passed to the data table.
|
|
990
|
+
*/
|
|
991
|
+
this.itemHeight = input(40, /* @ts-ignore */
|
|
992
|
+
...(ngDevMode ? [{ debugName: "itemHeight" }] : /* istanbul ignore next */ []));
|
|
993
|
+
/**
|
|
994
|
+
* The maximum number of body rows visible before the table scrolls.
|
|
995
|
+
*/
|
|
996
|
+
this.maxVisibleItems = input(8, /* @ts-ignore */
|
|
997
|
+
...(ngDevMode ? [{ debugName: "maxVisibleItems" }] : /* istanbul ignore next */ []));
|
|
998
|
+
/**
|
|
999
|
+
* Column definitions rendered as `ax-text-column` instances.
|
|
1000
|
+
*/
|
|
1001
|
+
this.columns = input([], /* @ts-ignore */
|
|
1002
|
+
...(ngDevMode ? [{ debugName: "columns" }] : /* istanbul ignore next */ []));
|
|
1003
|
+
/**
|
|
1004
|
+
* Optional custom row content. Context: `$implicit` is the row item.
|
|
1005
|
+
* When set, replaces the default multi-column cell layout.
|
|
1006
|
+
*/
|
|
1007
|
+
this.itemTemplate = input(undefined, /* @ts-ignore */
|
|
1008
|
+
...(ngDevMode ? [{ debugName: "itemTemplate" }] : /* istanbul ignore next */ []));
|
|
1009
|
+
/**
|
|
1010
|
+
* Custom template rendered when the datasource has no items.
|
|
1011
|
+
*/
|
|
1012
|
+
this.emptyTemplate = input(undefined, /* @ts-ignore */
|
|
1013
|
+
...(ngDevMode ? [{ debugName: "emptyTemplate" }] : /* istanbul ignore next */ []));
|
|
1014
|
+
/**
|
|
1015
|
+
* Custom template rendered while the table is loading.
|
|
1016
|
+
*/
|
|
1017
|
+
this.loadingTemplate = input(undefined, /* @ts-ignore */
|
|
1018
|
+
...(ngDevMode ? [{ debugName: "loadingTemplate" }] : /* istanbul ignore next */ []));
|
|
1019
|
+
/**
|
|
1020
|
+
* When `true`, table rows use alternating background colors for easier scanning.
|
|
1021
|
+
*/
|
|
1022
|
+
this.alternate = input(false, /* @ts-ignore */
|
|
1023
|
+
...(ngDevMode ? [{ debugName: "alternate" }] : /* istanbul ignore next */ []));
|
|
1024
|
+
/**
|
|
1025
|
+
* Emitted when the user picks a row.
|
|
1026
|
+
*/
|
|
1027
|
+
this.itemClick = output();
|
|
1028
|
+
this.tableRef = viewChild(AXDataTableComponent, /* @ts-ignore */
|
|
1029
|
+
...(ngDevMode ? [{ debugName: "tableRef" }] : /* istanbul ignore next */ []));
|
|
1030
|
+
/** Accumulated rows fed to the table (grows as pages are scrolled in). */
|
|
1031
|
+
this.#loadedItems = [];
|
|
1032
|
+
/** Total matching rows from the source (used to size the popup). */
|
|
1033
|
+
this.#totalCount = signal(0, /* @ts-ignore */
|
|
1034
|
+
...(ngDevMode ? [{ debugName: "#totalCount" }] : /* istanbul ignore next */ []));
|
|
1035
|
+
/**
|
|
1036
|
+
* Local table source: one page of whatever has been scrolled in so far.
|
|
1037
|
+
* Kept as a stable instance so the table host is not recreated on each page load.
|
|
1038
|
+
* `pageSize` grows with `#loadedItems` — never seed with a huge empty array (data-table
|
|
1039
|
+
* initializes `displayedRows` as `new Array(pageSize)`, which caused NG0955-level jank).
|
|
1040
|
+
*/
|
|
1041
|
+
this.tableDataSource = new AXDataSource({
|
|
1042
|
+
pageSize: 1,
|
|
1043
|
+
key: 'id',
|
|
1044
|
+
load: async () => ({
|
|
1045
|
+
items: this.#loadedItems,
|
|
1046
|
+
total: this.#loadedItems.length,
|
|
1047
|
+
}),
|
|
1048
|
+
});
|
|
1049
|
+
/**
|
|
1050
|
+
* Header (~40px) + body rows. Grows with results up to `maxVisibleItems`,
|
|
1051
|
+
* then the table body scrolls for the rest.
|
|
1052
|
+
*/
|
|
1053
|
+
this.tableHeight = computed(() => {
|
|
1054
|
+
const header = 40;
|
|
1055
|
+
const total = this.#totalCount();
|
|
1056
|
+
const rows = total > 0 ? total : Math.min(3, this.maxVisibleItems());
|
|
1057
|
+
return header + Math.min(rows, this.maxVisibleItems()) * this.itemHeight();
|
|
1058
|
+
}, /* @ts-ignore */
|
|
1059
|
+
...(ngDevMode ? [{ debugName: "tableHeight" }] : /* istanbul ignore next */ []));
|
|
1060
|
+
this.loadingConfig = computed(() => ({
|
|
1061
|
+
enabled: true,
|
|
1062
|
+
animation: true,
|
|
1063
|
+
loadingTemplate: this.loadingTemplate(),
|
|
1064
|
+
}), /* @ts-ignore */
|
|
1065
|
+
...(ngDevMode ? [{ debugName: "loadingConfig" }] : /* istanbul ignore next */ []));
|
|
1066
|
+
this.#host = inject((ElementRef));
|
|
1067
|
+
this.resolveRowCssClass = (row) => {
|
|
1068
|
+
const item = row;
|
|
1069
|
+
if (!item) {
|
|
1070
|
+
return '';
|
|
1071
|
+
}
|
|
1072
|
+
const classes = [];
|
|
1073
|
+
if (this.isSelected(item)) {
|
|
1074
|
+
classes.push('ax-state-selected');
|
|
1075
|
+
}
|
|
1076
|
+
if (this.isDisabled(item)) {
|
|
1077
|
+
classes.push('ax-state-disabled');
|
|
1078
|
+
}
|
|
1079
|
+
return classes.join(' ');
|
|
1080
|
+
};
|
|
1081
|
+
effect((onCleanup) => {
|
|
1082
|
+
const source = this.dataSource();
|
|
1083
|
+
this.tableDataSource.config.key = source.config.key || this.valueField();
|
|
1084
|
+
untracked(() => {
|
|
1085
|
+
this.#applyLoadedItems(source.cachedItems, source.totalCount);
|
|
1086
|
+
});
|
|
1087
|
+
const changedSub = source.onChanged.subscribe((event) => {
|
|
1088
|
+
this.#applyLoadedItems(event.cachedItems, event.totalCount);
|
|
1089
|
+
});
|
|
1090
|
+
// Fetch page 0 only when the source has never loaded. Reopen remounts this
|
|
1091
|
+
// view; setPage(0) is a no-op on a warm source and must not force a new API call.
|
|
1092
|
+
queueMicrotask(() => {
|
|
1093
|
+
if (!source.cachedItems.some((item) => item != null)) {
|
|
1094
|
+
source.setPage(0);
|
|
1095
|
+
}
|
|
1096
|
+
});
|
|
1097
|
+
onCleanup(() => changedSub.unsubscribe());
|
|
1098
|
+
});
|
|
1099
|
+
effect((onCleanup) => {
|
|
1100
|
+
// Rebind when the table instance appears / source changes.
|
|
1101
|
+
this.tableRef();
|
|
1102
|
+
this.dataSource();
|
|
1103
|
+
let scrollSub;
|
|
1104
|
+
const timer = setTimeout(() => {
|
|
1105
|
+
const wrapper = this.tableRef()?.getHostElement()?.querySelector('.ax-data-table-wrapper') ??
|
|
1106
|
+
this.#host.nativeElement.querySelector('.ax-data-table-wrapper');
|
|
1107
|
+
if (!wrapper) {
|
|
1108
|
+
return;
|
|
1109
|
+
}
|
|
1110
|
+
scrollSub = fromEvent(wrapper, 'scroll')
|
|
1111
|
+
.pipe(auditTime(80))
|
|
1112
|
+
.subscribe(() => this.#tryLoadMore(wrapper));
|
|
1113
|
+
}, 0);
|
|
1114
|
+
onCleanup(() => {
|
|
1115
|
+
clearTimeout(timer);
|
|
1116
|
+
scrollSub?.unsubscribe();
|
|
1117
|
+
});
|
|
1118
|
+
});
|
|
1119
|
+
}
|
|
1120
|
+
/** Stable unique key for `@for` — avoids NG0955 when `field` is missing or duplicated. */
|
|
1121
|
+
trackColumnKey(index, column) {
|
|
1122
|
+
return `${column?.field ?? ''}::${index}`;
|
|
1123
|
+
}
|
|
1124
|
+
resolveColumnWidth(column) {
|
|
1125
|
+
const width = column.width?.trim();
|
|
1126
|
+
if (!width || width.includes('fr')) {
|
|
1127
|
+
return 'auto';
|
|
1128
|
+
}
|
|
1129
|
+
return width;
|
|
1130
|
+
}
|
|
1131
|
+
#applyLoadedItems(cachedItems, totalCount) {
|
|
1132
|
+
this.#loadedItems = cachedItems.filter((item) => item != null);
|
|
1133
|
+
this.#totalCount.set(totalCount);
|
|
1134
|
+
this.#syncTablePageSize();
|
|
1135
|
+
this.tableDataSource.refresh({ reset: true });
|
|
1136
|
+
}
|
|
1137
|
+
#syncTablePageSize() {
|
|
1138
|
+
this.tableDataSource.config.pageSize = Math.max(this.#loadedItems.length, 1);
|
|
1139
|
+
}
|
|
1140
|
+
handleRowClick(event) {
|
|
1141
|
+
this.handleItemClick(event.data);
|
|
1142
|
+
}
|
|
1143
|
+
handleItemClick(item) {
|
|
1144
|
+
if (!item || this.isDisabled(item)) {
|
|
1145
|
+
return;
|
|
1146
|
+
}
|
|
1147
|
+
this.itemClick.emit({ item, value: this.getValue(item) });
|
|
1148
|
+
}
|
|
1149
|
+
handleItemMouseDown(event, item) {
|
|
1150
|
+
event.preventDefault();
|
|
1151
|
+
event.stopPropagation();
|
|
1152
|
+
this.handleItemClick(item);
|
|
1153
|
+
}
|
|
1154
|
+
isSelected(item) {
|
|
1155
|
+
const value = this.getValue(item);
|
|
1156
|
+
return this.selectedValues().some((v) => v == value);
|
|
1157
|
+
}
|
|
1158
|
+
isDisabled(item) {
|
|
1159
|
+
return Boolean(item?.[this.disabledField()]);
|
|
1160
|
+
}
|
|
1161
|
+
#tryLoadMore(wrapper) {
|
|
1162
|
+
const nearBottom = wrapper.scrollTop + wrapper.clientHeight >= wrapper.scrollHeight - 48;
|
|
1163
|
+
if (!nearBottom) {
|
|
1164
|
+
return;
|
|
1165
|
+
}
|
|
1166
|
+
const source = this.dataSource();
|
|
1167
|
+
if (source.isLoading || source.totalCount === 0) {
|
|
1168
|
+
return;
|
|
1169
|
+
}
|
|
1170
|
+
const loadedCount = source.cachedItems.filter((item) => item != null).length;
|
|
1171
|
+
if (loadedCount >= source.totalCount) {
|
|
1172
|
+
return;
|
|
1173
|
+
}
|
|
1174
|
+
const nextPage = Math.floor(loadedCount / source.pageSize);
|
|
1175
|
+
source.setPage(nextPage);
|
|
1176
|
+
}
|
|
1177
|
+
getValue(item) {
|
|
1178
|
+
return item?.[this.valueField()];
|
|
1179
|
+
}
|
|
1180
|
+
static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "22.0.8", ngImport: i0, type: AXLookupMultiColumnComponent, deps: [], target: i0.ɵɵFactoryTarget.Component }); }
|
|
1181
|
+
static { this.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "22.0.8", type: AXLookupMultiColumnComponent, isStandalone: true, selector: "ax-lookup-multi-column", inputs: { dataSource: { classPropertyName: "dataSource", publicName: "dataSource", isSignal: true, isRequired: true, transformFunction: null }, valueField: { classPropertyName: "valueField", publicName: "valueField", isSignal: true, isRequired: false, transformFunction: null }, textField: { classPropertyName: "textField", publicName: "textField", isSignal: true, isRequired: false, transformFunction: null }, disabledField: { classPropertyName: "disabledField", publicName: "disabledField", isSignal: true, isRequired: false, transformFunction: null }, selectedValues: { classPropertyName: "selectedValues", publicName: "selectedValues", isSignal: true, isRequired: false, transformFunction: null }, itemHeight: { classPropertyName: "itemHeight", publicName: "itemHeight", isSignal: true, isRequired: false, transformFunction: null }, maxVisibleItems: { classPropertyName: "maxVisibleItems", publicName: "maxVisibleItems", isSignal: true, isRequired: false, transformFunction: null }, columns: { classPropertyName: "columns", publicName: "columns", isSignal: true, isRequired: false, transformFunction: null }, itemTemplate: { classPropertyName: "itemTemplate", publicName: "itemTemplate", isSignal: true, isRequired: false, transformFunction: null }, emptyTemplate: { classPropertyName: "emptyTemplate", publicName: "emptyTemplate", isSignal: true, isRequired: false, transformFunction: null }, loadingTemplate: { classPropertyName: "loadingTemplate", publicName: "loadingTemplate", isSignal: true, isRequired: false, transformFunction: null }, alternate: { classPropertyName: "alternate", publicName: "alternate", isSignal: true, isRequired: false, transformFunction: null } }, outputs: { itemClick: "itemClick" }, host: { properties: { "style.height.px": "tableHeight()" }, classAttribute: "ax-lookup-multi-column" }, viewQueries: [{ propertyName: "tableRef", first: true, predicate: AXDataTableComponent, descendants: true, isSignal: true }], ngImport: i0, template: `
|
|
1182
|
+
<ax-data-table
|
|
1183
|
+
class="ax-lookup-multi-column-table"
|
|
1184
|
+
look="minimal"
|
|
1185
|
+
[dataSource]="tableDataSource"
|
|
1186
|
+
[itemHeight]="itemHeight()"
|
|
1187
|
+
[alternative]="alternate()"
|
|
1188
|
+
[emptyTemplate]="emptyTemplate()"
|
|
1189
|
+
[loading]="loadingConfig()"
|
|
1190
|
+
[paging]="false"
|
|
1191
|
+
[showHeader]="true"
|
|
1192
|
+
[fixedHeader]="true"
|
|
1193
|
+
[showFooter]="false"
|
|
1194
|
+
[allowReordering]="false"
|
|
1195
|
+
[rowTemplate]="itemTemplate() ? customRowTemplate : undefined"
|
|
1196
|
+
[rowCssClass]="resolveRowCssClass"
|
|
1197
|
+
(onRowClick)="handleRowClick($event)"
|
|
1198
|
+
>
|
|
1199
|
+
@for (column of columns(); track trackColumnKey($index, column)) {
|
|
1200
|
+
<ax-text-column
|
|
1201
|
+
[dataField]="column.field"
|
|
1202
|
+
[caption]="column.title"
|
|
1203
|
+
[width]="resolveColumnWidth(column)"
|
|
1204
|
+
[allowSorting]="false"
|
|
1205
|
+
[allowResizing]="false"
|
|
1206
|
+
/>
|
|
1207
|
+
}
|
|
1208
|
+
</ax-data-table>
|
|
1209
|
+
|
|
1210
|
+
<ng-template #customRowTemplate let-ctx>
|
|
1211
|
+
<tr
|
|
1212
|
+
[class.ax-state-selected]="ctx.data != null && isSelected(ctx.data)"
|
|
1213
|
+
[class.ax-state-disabled]="ctx.data != null && isDisabled(ctx.data)"
|
|
1214
|
+
[style.height.px]="itemHeight()"
|
|
1215
|
+
[style.max-height.px]="itemHeight()"
|
|
1216
|
+
(mousedown)="handleItemMouseDown($event, ctx.data)"
|
|
1217
|
+
>
|
|
1218
|
+
<td [attr.colspan]="columns().length || 1">
|
|
1219
|
+
@if (ctx.data != null && itemTemplate()) {
|
|
1220
|
+
<ng-container
|
|
1221
|
+
[ngTemplateOutlet]="itemTemplate()!"
|
|
1222
|
+
[ngTemplateOutletContext]="{ $implicit: ctx.data }"
|
|
1223
|
+
/>
|
|
1224
|
+
}
|
|
1225
|
+
</td>
|
|
1226
|
+
</tr>
|
|
1227
|
+
</ng-template>
|
|
1228
|
+
`, isInline: true, dependencies: [{ kind: "directive", type: NgTemplateOutlet, selector: "[ngTemplateOutlet]", inputs: ["ngTemplateOutletContext", "ngTemplateOutlet", "ngTemplateOutletInjector"] }, { kind: "component", type: AXDataTableComponent, selector: "ax-data-table", inputs: ["dataSource", "selectedRows", "parentField", "hasChildrenField", "rowDetailsTemplate", "rowCssClass", "cellCssClass", "highlightText", "look", "rowTemplate", "emptyTemplate", "noDataTemplate", "alternative", "showHeader", "fixedHeader", "showFooter", "fixedFooter", "itemHeight", "allowReordering", "paging", "fetchDataMode", "loading", "focusedRow"], outputs: ["selectedRowsChange", "focusedRowChange", "onRowClick", "onRowDbClick", "onColumnsOrderChanged", "onColumnSizeChanged", "onPageChanged"] }, { kind: "component", type: AXDataTableTextColumnComponent, selector: "ax-text-column", inputs: ["width", "caption", "allowSorting", "allowResizing", "fixed", "hasTitle", "customExpandIcon", "customCollapseIcon", "dataField", "expandHandler", "wrapText", "cellTemplate", "footerTemplate", "headerTemplate", "format", "formatOptions"] }], changeDetection: i0.ChangeDetectionStrategy.OnPush, encapsulation: i0.ViewEncapsulation.None }); }
|
|
1229
|
+
}
|
|
1230
|
+
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "22.0.8", ngImport: i0, type: AXLookupMultiColumnComponent, decorators: [{
|
|
1231
|
+
type: Component,
|
|
1232
|
+
args: [{
|
|
1233
|
+
selector: 'ax-lookup-multi-column',
|
|
1234
|
+
changeDetection: ChangeDetectionStrategy.OnPush,
|
|
1235
|
+
encapsulation: ViewEncapsulation.None,
|
|
1236
|
+
imports: [NgTemplateOutlet, AXDataTableComponent, AXDataTableTextColumnComponent],
|
|
1237
|
+
host: {
|
|
1238
|
+
class: 'ax-lookup-multi-column',
|
|
1239
|
+
'[style.height.px]': 'tableHeight()',
|
|
1240
|
+
},
|
|
1241
|
+
template: `
|
|
1242
|
+
<ax-data-table
|
|
1243
|
+
class="ax-lookup-multi-column-table"
|
|
1244
|
+
look="minimal"
|
|
1245
|
+
[dataSource]="tableDataSource"
|
|
1246
|
+
[itemHeight]="itemHeight()"
|
|
1247
|
+
[alternative]="alternate()"
|
|
1248
|
+
[emptyTemplate]="emptyTemplate()"
|
|
1249
|
+
[loading]="loadingConfig()"
|
|
1250
|
+
[paging]="false"
|
|
1251
|
+
[showHeader]="true"
|
|
1252
|
+
[fixedHeader]="true"
|
|
1253
|
+
[showFooter]="false"
|
|
1254
|
+
[allowReordering]="false"
|
|
1255
|
+
[rowTemplate]="itemTemplate() ? customRowTemplate : undefined"
|
|
1256
|
+
[rowCssClass]="resolveRowCssClass"
|
|
1257
|
+
(onRowClick)="handleRowClick($event)"
|
|
1258
|
+
>
|
|
1259
|
+
@for (column of columns(); track trackColumnKey($index, column)) {
|
|
1260
|
+
<ax-text-column
|
|
1261
|
+
[dataField]="column.field"
|
|
1262
|
+
[caption]="column.title"
|
|
1263
|
+
[width]="resolveColumnWidth(column)"
|
|
1264
|
+
[allowSorting]="false"
|
|
1265
|
+
[allowResizing]="false"
|
|
1266
|
+
/>
|
|
1267
|
+
}
|
|
1268
|
+
</ax-data-table>
|
|
1269
|
+
|
|
1270
|
+
<ng-template #customRowTemplate let-ctx>
|
|
1271
|
+
<tr
|
|
1272
|
+
[class.ax-state-selected]="ctx.data != null && isSelected(ctx.data)"
|
|
1273
|
+
[class.ax-state-disabled]="ctx.data != null && isDisabled(ctx.data)"
|
|
1274
|
+
[style.height.px]="itemHeight()"
|
|
1275
|
+
[style.max-height.px]="itemHeight()"
|
|
1276
|
+
(mousedown)="handleItemMouseDown($event, ctx.data)"
|
|
1277
|
+
>
|
|
1278
|
+
<td [attr.colspan]="columns().length || 1">
|
|
1279
|
+
@if (ctx.data != null && itemTemplate()) {
|
|
1280
|
+
<ng-container
|
|
1281
|
+
[ngTemplateOutlet]="itemTemplate()!"
|
|
1282
|
+
[ngTemplateOutletContext]="{ $implicit: ctx.data }"
|
|
1283
|
+
/>
|
|
1284
|
+
}
|
|
1285
|
+
</td>
|
|
1286
|
+
</tr>
|
|
1287
|
+
</ng-template>
|
|
1288
|
+
`,
|
|
1289
|
+
}]
|
|
1290
|
+
}], ctorParameters: () => [], propDecorators: { dataSource: [{ type: i0.Input, args: [{ isSignal: true, alias: "dataSource", required: true }] }], valueField: [{ type: i0.Input, args: [{ isSignal: true, alias: "valueField", required: false }] }], textField: [{ type: i0.Input, args: [{ isSignal: true, alias: "textField", required: false }] }], disabledField: [{ type: i0.Input, args: [{ isSignal: true, alias: "disabledField", required: false }] }], selectedValues: [{ type: i0.Input, args: [{ isSignal: true, alias: "selectedValues", required: false }] }], itemHeight: [{ type: i0.Input, args: [{ isSignal: true, alias: "itemHeight", required: false }] }], maxVisibleItems: [{ type: i0.Input, args: [{ isSignal: true, alias: "maxVisibleItems", required: false }] }], columns: [{ type: i0.Input, args: [{ isSignal: true, alias: "columns", required: false }] }], itemTemplate: [{ type: i0.Input, args: [{ isSignal: true, alias: "itemTemplate", required: false }] }], emptyTemplate: [{ type: i0.Input, args: [{ isSignal: true, alias: "emptyTemplate", required: false }] }], loadingTemplate: [{ type: i0.Input, args: [{ isSignal: true, alias: "loadingTemplate", required: false }] }], alternate: [{ type: i0.Input, args: [{ isSignal: true, alias: "alternate", required: false }] }], itemClick: [{ type: i0.Output, args: ["itemClick"] }], tableRef: [{ type: i0.ViewChild, args: [i0.forwardRef(() => AXDataTableComponent), { isSignal: true }] }] } });
|
|
1291
|
+
|
|
1292
|
+
/**
|
|
1293
|
+
* Internal mini component for the `multi-select-tree` lookup mode:
|
|
1294
|
+
* a predefined list rendered in a tree-like structure for multiple item selection.
|
|
1295
|
+
*
|
|
1296
|
+
* @category Components
|
|
1297
|
+
*/
|
|
1298
|
+
class AXLookupMultiSelectTreeComponent {
|
|
1299
|
+
constructor() {
|
|
1300
|
+
/**
|
|
1301
|
+
* The tree datasource: an array of nodes or a lazy children callback.
|
|
1302
|
+
*/
|
|
1303
|
+
this.dataSource = input.required(/* @ts-ignore */
|
|
1304
|
+
...(ngDevMode ? [{ debugName: "dataSource" }] : /* istanbul ignore next */ []));
|
|
1305
|
+
/**
|
|
1306
|
+
* The node property used as the selection value (tree `idField`).
|
|
1307
|
+
*/
|
|
1308
|
+
this.valueField = input('id', /* @ts-ignore */
|
|
1309
|
+
...(ngDevMode ? [{ debugName: "valueField" }] : /* istanbul ignore next */ []));
|
|
1310
|
+
/**
|
|
1311
|
+
* The node property used as the display text (tree `titleField`).
|
|
1312
|
+
*/
|
|
1313
|
+
this.textField = input('title', /* @ts-ignore */
|
|
1314
|
+
...(ngDevMode ? [{ debugName: "textField" }] : /* istanbul ignore next */ []));
|
|
1315
|
+
/**
|
|
1316
|
+
* The node property marking a node as disabled.
|
|
1317
|
+
*/
|
|
1318
|
+
this.disabledField = input('disabled', /* @ts-ignore */
|
|
1319
|
+
...(ngDevMode ? [{ debugName: "disabledField" }] : /* istanbul ignore next */ []));
|
|
1320
|
+
/**
|
|
1321
|
+
* Currently selected values.
|
|
1322
|
+
*/
|
|
1323
|
+
this.selectedValues = input([], /* @ts-ignore */
|
|
1324
|
+
...(ngDevMode ? [{ debugName: "selectedValues" }] : /* istanbul ignore next */ []));
|
|
1325
|
+
/**
|
|
1326
|
+
* How selecting parent/child nodes affects each other. Passed through to the tree-view.
|
|
1327
|
+
*/
|
|
1328
|
+
this.selectionBehavior = input('all', /* @ts-ignore */
|
|
1329
|
+
...(ngDevMode ? [{ debugName: "selectionBehavior" }] : /* istanbul ignore next */ []));
|
|
1330
|
+
/**
|
|
1331
|
+
* Custom template rendered for each tree node.
|
|
1332
|
+
*/
|
|
1333
|
+
this.nodeTemplate = input(undefined, /* @ts-ignore */
|
|
1334
|
+
...(ngDevMode ? [{ debugName: "nodeTemplate" }] : /* istanbul ignore next */ []));
|
|
1335
|
+
/**
|
|
1336
|
+
* Custom template rendered when the filtered tree has no nodes.
|
|
1337
|
+
*/
|
|
1338
|
+
this.emptyTemplate = input(undefined, /* @ts-ignore */
|
|
1339
|
+
...(ngDevMode ? [{ debugName: "emptyTemplate" }] : /* istanbul ignore next */ []));
|
|
1340
|
+
/**
|
|
1341
|
+
* When `true`, visible tree nodes use alternating background colors.
|
|
1342
|
+
*/
|
|
1343
|
+
this.alternate = input(false, /* @ts-ignore */
|
|
1344
|
+
...(ngDevMode ? [{ debugName: "alternate" }] : /* istanbul ignore next */ []));
|
|
1345
|
+
/**
|
|
1346
|
+
* Unique id that changes on every search apply so a new tree instance is created.
|
|
1347
|
+
*/
|
|
1348
|
+
this.filterKey = input('0', /* @ts-ignore */
|
|
1349
|
+
...(ngDevMode ? [{ debugName: "filterKey" }] : /* istanbul ignore next */ []));
|
|
1350
|
+
/**
|
|
1351
|
+
* Emitted when the user changes the tree selection.
|
|
1352
|
+
*/
|
|
1353
|
+
this.selectionChange = output();
|
|
1354
|
+
this.selectedIds = computed(() => this.selectedValues().map((v) => String(v)), /* @ts-ignore */
|
|
1355
|
+
...(ngDevMode ? [{ debugName: "selectedIds" }] : /* istanbul ignore next */ []));
|
|
1356
|
+
this.isEmpty = computed(() => {
|
|
1357
|
+
const source = this.dataSource();
|
|
1358
|
+
return Array.isArray(source) && source.length === 0;
|
|
1359
|
+
}, /* @ts-ignore */
|
|
1360
|
+
...(ngDevMode ? [{ debugName: "isEmpty" }] : /* istanbul ignore next */ []));
|
|
1361
|
+
this.treeInstances = computed(() => [{ id: this.filterKey(), source: this.dataSource() }], /* @ts-ignore */
|
|
1362
|
+
...(ngDevMode ? [{ debugName: "treeInstances" }] : /* istanbul ignore next */ []));
|
|
1363
|
+
}
|
|
1364
|
+
/** Whether the filtered tree currently has no nodes. */
|
|
1365
|
+
hasNoMatches() {
|
|
1366
|
+
return this.isEmpty();
|
|
1367
|
+
}
|
|
1368
|
+
handleSelectionChange(e) {
|
|
1369
|
+
if (e.source !== 'user') {
|
|
1370
|
+
return;
|
|
1371
|
+
}
|
|
1372
|
+
this.selectionChange.emit({ ids: e.selectedIds, nodes: e.selectedNodes });
|
|
1373
|
+
}
|
|
1374
|
+
static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "22.0.8", ngImport: i0, type: AXLookupMultiSelectTreeComponent, deps: [], target: i0.ɵɵFactoryTarget.Component }); }
|
|
1375
|
+
static { this.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "22.0.8", type: AXLookupMultiSelectTreeComponent, isStandalone: true, selector: "ax-lookup-multi-select-tree", inputs: { dataSource: { classPropertyName: "dataSource", publicName: "dataSource", isSignal: true, isRequired: true, transformFunction: null }, valueField: { classPropertyName: "valueField", publicName: "valueField", isSignal: true, isRequired: false, transformFunction: null }, textField: { classPropertyName: "textField", publicName: "textField", isSignal: true, isRequired: false, transformFunction: null }, disabledField: { classPropertyName: "disabledField", publicName: "disabledField", isSignal: true, isRequired: false, transformFunction: null }, selectedValues: { classPropertyName: "selectedValues", publicName: "selectedValues", isSignal: true, isRequired: false, transformFunction: null }, selectionBehavior: { classPropertyName: "selectionBehavior", publicName: "selectionBehavior", isSignal: true, isRequired: false, transformFunction: null }, nodeTemplate: { classPropertyName: "nodeTemplate", publicName: "nodeTemplate", isSignal: true, isRequired: false, transformFunction: null }, emptyTemplate: { classPropertyName: "emptyTemplate", publicName: "emptyTemplate", isSignal: true, isRequired: false, transformFunction: null }, alternate: { classPropertyName: "alternate", publicName: "alternate", isSignal: true, isRequired: false, transformFunction: null }, filterKey: { classPropertyName: "filterKey", publicName: "filterKey", isSignal: true, isRequired: false, transformFunction: null } }, outputs: { selectionChange: "selectionChange" }, ngImport: i0, template: `
|
|
1376
|
+
@if (isEmpty()) {
|
|
1377
|
+
@if (emptyTemplate()) {
|
|
1378
|
+
<ng-container [ngTemplateOutlet]="emptyTemplate()!" />
|
|
1379
|
+
} @else {
|
|
1380
|
+
<div class="ax-lookup-empty">
|
|
1381
|
+
{{ '@acorex:common.general.no-result-found' | translate | async }}
|
|
1382
|
+
</div>
|
|
1383
|
+
}
|
|
1384
|
+
} @else {
|
|
1385
|
+
<div class="ax-lookup-tree">
|
|
1386
|
+
@for (instance of treeInstances(); track instance.id) {
|
|
1387
|
+
<ax-tree-view
|
|
1388
|
+
[datasource]="instance.source"
|
|
1389
|
+
selectMode="multiple"
|
|
1390
|
+
[selectionBehavior]="selectionBehavior()"
|
|
1391
|
+
[controlledSelection]="true"
|
|
1392
|
+
[selectedIds]="selectedIds()"
|
|
1393
|
+
[idField]="valueField()"
|
|
1394
|
+
[titleField]="textField()"
|
|
1395
|
+
[disabledField]="disabledField()"
|
|
1396
|
+
[nodeTemplate]="nodeTemplate()"
|
|
1397
|
+
[alternate]="alternate()"
|
|
1398
|
+
(onSelectionChange)="handleSelectionChange($event)"
|
|
1399
|
+
/>
|
|
1400
|
+
}
|
|
1401
|
+
</div>
|
|
1402
|
+
}
|
|
1403
|
+
`, isInline: true, dependencies: [{ kind: "component", type: AXTreeViewComponent, selector: "ax-tree-view", inputs: ["datasource", "selectMode", "selectionBehavior", "dragArea", "dragBehavior", "showIcons", "showChildrenBadge", "expandedIcon", "collapsedIcon", "indentSize", "look", "alternate", "nodeTemplate", "idField", "titleField", "tooltipField", "iconField", "expandedField", "selectedField", "indeterminateField", "disabledField", "hiddenField", "childrenField", "childrenCountField", "dataField", "inheritDisabled", "expandOnDoubleClick", "doubleClickDuration", "tooltipDelay", "controlledSelection", "selectedIds"], outputs: ["datasourceChange", "selectedIdsChange", "onBeforeDrop", "onNodeToggle", "onNodeSelect", "onNodeDoubleClick", "onNodeClick", "onSelectionChange", "onOrderChange", "onMoveChange", "onItemsChange"] }, { kind: "directive", type: NgTemplateOutlet, selector: "[ngTemplateOutlet]", inputs: ["ngTemplateOutletContext", "ngTemplateOutlet", "ngTemplateOutletInjector"] }, { kind: "pipe", type: AXTranslatorPipe, name: "translate" }, { kind: "pipe", type: AsyncPipe, name: "async" }], changeDetection: i0.ChangeDetectionStrategy.OnPush, encapsulation: i0.ViewEncapsulation.None }); }
|
|
1404
|
+
}
|
|
1405
|
+
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "22.0.8", ngImport: i0, type: AXLookupMultiSelectTreeComponent, decorators: [{
|
|
1406
|
+
type: Component,
|
|
1407
|
+
args: [{
|
|
1408
|
+
selector: 'ax-lookup-multi-select-tree',
|
|
1409
|
+
changeDetection: ChangeDetectionStrategy.OnPush,
|
|
1410
|
+
encapsulation: ViewEncapsulation.None,
|
|
1411
|
+
imports: [AXTreeViewComponent, NgTemplateOutlet, AXTranslatorPipe, AsyncPipe],
|
|
1412
|
+
template: `
|
|
1413
|
+
@if (isEmpty()) {
|
|
1414
|
+
@if (emptyTemplate()) {
|
|
1415
|
+
<ng-container [ngTemplateOutlet]="emptyTemplate()!" />
|
|
1416
|
+
} @else {
|
|
1417
|
+
<div class="ax-lookup-empty">
|
|
1418
|
+
{{ '@acorex:common.general.no-result-found' | translate | async }}
|
|
1419
|
+
</div>
|
|
1420
|
+
}
|
|
1421
|
+
} @else {
|
|
1422
|
+
<div class="ax-lookup-tree">
|
|
1423
|
+
@for (instance of treeInstances(); track instance.id) {
|
|
1424
|
+
<ax-tree-view
|
|
1425
|
+
[datasource]="instance.source"
|
|
1426
|
+
selectMode="multiple"
|
|
1427
|
+
[selectionBehavior]="selectionBehavior()"
|
|
1428
|
+
[controlledSelection]="true"
|
|
1429
|
+
[selectedIds]="selectedIds()"
|
|
1430
|
+
[idField]="valueField()"
|
|
1431
|
+
[titleField]="textField()"
|
|
1432
|
+
[disabledField]="disabledField()"
|
|
1433
|
+
[nodeTemplate]="nodeTemplate()"
|
|
1434
|
+
[alternate]="alternate()"
|
|
1435
|
+
(onSelectionChange)="handleSelectionChange($event)"
|
|
1436
|
+
/>
|
|
1437
|
+
}
|
|
1438
|
+
</div>
|
|
1439
|
+
}
|
|
1440
|
+
`,
|
|
1441
|
+
}]
|
|
1442
|
+
}], propDecorators: { dataSource: [{ type: i0.Input, args: [{ isSignal: true, alias: "dataSource", required: true }] }], valueField: [{ type: i0.Input, args: [{ isSignal: true, alias: "valueField", required: false }] }], textField: [{ type: i0.Input, args: [{ isSignal: true, alias: "textField", required: false }] }], disabledField: [{ type: i0.Input, args: [{ isSignal: true, alias: "disabledField", required: false }] }], selectedValues: [{ type: i0.Input, args: [{ isSignal: true, alias: "selectedValues", required: false }] }], selectionBehavior: [{ type: i0.Input, args: [{ isSignal: true, alias: "selectionBehavior", required: false }] }], nodeTemplate: [{ type: i0.Input, args: [{ isSignal: true, alias: "nodeTemplate", required: false }] }], emptyTemplate: [{ type: i0.Input, args: [{ isSignal: true, alias: "emptyTemplate", required: false }] }], alternate: [{ type: i0.Input, args: [{ isSignal: true, alias: "alternate", required: false }] }], filterKey: [{ type: i0.Input, args: [{ isSignal: true, alias: "filterKey", required: false }] }], selectionChange: [{ type: i0.Output, args: ["selectionChange"] }] } });
|
|
1443
|
+
|
|
1444
|
+
/**
|
|
1445
|
+
* Internal mini component for the `multi-select` lookup mode:
|
|
1446
|
+
* a predefined, virtualized list of options with checkboxes for multiple item selection.
|
|
1447
|
+
*
|
|
1448
|
+
* @category Components
|
|
1449
|
+
*/
|
|
1450
|
+
class AXLookupMultiSelectComponent extends AXLookupListViewBase {
|
|
1451
|
+
static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "22.0.8", ngImport: i0, type: AXLookupMultiSelectComponent, deps: null, target: i0.ɵɵFactoryTarget.Component }); }
|
|
1452
|
+
static { this.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "22.0.8", type: AXLookupMultiSelectComponent, isStandalone: true, selector: "ax-lookup-multi-select", providers: [{ provide: AXLookupListViewBase, useExisting: AXLookupMultiSelectComponent }], usesInheritance: true, ngImport: i0, template: `
|
|
1453
|
+
@if (isEmpty()) {
|
|
1454
|
+
@if (emptyTemplate()) {
|
|
1455
|
+
<ng-container [ngTemplateOutlet]="emptyTemplate()!" />
|
|
1456
|
+
} @else {
|
|
1457
|
+
<div class="ax-lookup-empty">
|
|
1458
|
+
{{ '@acorex:common.general.no-result-found' | translate | async }}
|
|
1459
|
+
</div>
|
|
1460
|
+
}
|
|
1461
|
+
} @else {
|
|
1462
|
+
<cdk-virtual-scroll-viewport
|
|
1463
|
+
class="ax-lookup-viewport"
|
|
1464
|
+
role="listbox"
|
|
1465
|
+
aria-multiselectable="true"
|
|
1466
|
+
axListNavigation
|
|
1467
|
+
#nav="axListNavigation"
|
|
1468
|
+
[itemSize]="itemHeight()"
|
|
1469
|
+
[style.height.px]="viewportHeight()"
|
|
1470
|
+
(onKeypress)="handleListKeypress($event)"
|
|
1471
|
+
>
|
|
1472
|
+
<div
|
|
1473
|
+
*cdkVirtualFor="let item of listDataSource(); let i = index; trackBy: trackByIndex"
|
|
1474
|
+
role="option"
|
|
1475
|
+
class="ax-lookup-option-host ax-lookup-option-multiple"
|
|
1476
|
+
axListNavigationItem
|
|
1477
|
+
#navItem="axListNavigationItem"
|
|
1478
|
+
[style.height.px]="itemHeight()"
|
|
1479
|
+
[class.ax-lookup-option]="!itemTemplate()"
|
|
1480
|
+
[class.ax-state-alternate]="alternate() && i % 2 === 1"
|
|
1481
|
+
[class.ax-state-selected]="item != null && isSelected(item)"
|
|
1482
|
+
[class.ax-state-disabled]="item != null && isDisabled(item)"
|
|
1483
|
+
[class.ax-state-active]="navItem.isActive()"
|
|
1484
|
+
[attr.aria-selected]="item != null ? isSelected(item) : null"
|
|
1485
|
+
(mouseenter)="activateNavItem(nav, navItem)"
|
|
1486
|
+
(mousedown)="handleItemMouseDown($event, item)"
|
|
1487
|
+
(onKeypress)="handleItemKeypress($event, item)"
|
|
1488
|
+
>
|
|
1489
|
+
@if (item != null) {
|
|
1490
|
+
<ax-check-box
|
|
1491
|
+
class="ax-lookup-checkbox"
|
|
1492
|
+
[tabIndex]="-1"
|
|
1493
|
+
[value]="isSelected(item)"
|
|
1494
|
+
[disabled]="isDisabled(item)"
|
|
1495
|
+
></ax-check-box>
|
|
1496
|
+
@if (itemTemplate()) {
|
|
1497
|
+
<ng-container [ngTemplateOutlet]="itemTemplate()!" [ngTemplateOutletContext]="{ $implicit: item }" />
|
|
1498
|
+
} @else {
|
|
1499
|
+
<span class="ax-lookup-option-text">{{ getText(item) }}</span>
|
|
1500
|
+
}
|
|
1501
|
+
} @else {
|
|
1502
|
+
<ng-container [ngTemplateOutlet]="loadingRow" />
|
|
1503
|
+
}
|
|
1504
|
+
</div>
|
|
1505
|
+
</cdk-virtual-scroll-viewport>
|
|
1506
|
+
}
|
|
1507
|
+
|
|
1508
|
+
<ng-template #loadingRow>
|
|
1509
|
+
@if (loadingTemplate()) {
|
|
1510
|
+
<ng-container [ngTemplateOutlet]="loadingTemplate()!" />
|
|
1511
|
+
} @else {
|
|
1512
|
+
<span class="ax-lookup-option-loading">{{ '@acorex:common.status.loading' | translate | async }}</span>
|
|
1513
|
+
}
|
|
1514
|
+
</ng-template>
|
|
1515
|
+
`, isInline: true, dependencies: [{ kind: "ngmodule", type: ScrollingModule }, { kind: "directive", type: i1.CdkFixedSizeVirtualScroll, selector: "cdk-virtual-scroll-viewport[itemSize]", inputs: ["itemSize", "minBufferPx", "maxBufferPx"] }, { kind: "directive", type: i1.CdkVirtualForOf, selector: "[cdkVirtualFor][cdkVirtualForOf]", inputs: ["cdkVirtualForOf", "cdkVirtualForTrackBy", "cdkVirtualForTemplate", "cdkVirtualForTemplateCacheSize"] }, { kind: "component", type: i1.CdkVirtualScrollViewport, selector: "cdk-virtual-scroll-viewport", inputs: ["orientation", "appendOnly"], outputs: ["scrolledIndexChange"] }, { kind: "directive", type: NgTemplateOutlet, selector: "[ngTemplateOutlet]", inputs: ["ngTemplateOutletContext", "ngTemplateOutlet", "ngTemplateOutletInjector"] }, { kind: "ngmodule", type: AXListNavigationModule }, { kind: "directive", type: i2.AXListNavigationDirective, selector: "[axListNavigation]", inputs: ["orientation"], outputs: ["onNavigationChanged", "onKeypress"], exportAs: ["axListNavigation"] }, { kind: "directive", type: i2.AXListNavigationItemDirective, selector: "[axListNavigationItem]", outputs: ["onKeypress"], exportAs: ["axListNavigationItem"] }, { kind: "component", type: AXCheckBoxComponent, selector: "ax-check-box", inputs: ["disabled", "tabIndex", "readonly", "color", "value", "name", "id", "isLoading", "indeterminate"], outputs: ["onBlur", "onFocus", "valueChange", "onValueChanged"] }, { kind: "pipe", type: AXTranslatorPipe, name: "translate" }, { kind: "pipe", type: AsyncPipe, name: "async" }], changeDetection: i0.ChangeDetectionStrategy.OnPush, encapsulation: i0.ViewEncapsulation.None }); }
|
|
1516
|
+
}
|
|
1517
|
+
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "22.0.8", ngImport: i0, type: AXLookupMultiSelectComponent, decorators: [{
|
|
1518
|
+
type: Component,
|
|
1519
|
+
args: [{
|
|
1520
|
+
selector: 'ax-lookup-multi-select',
|
|
1521
|
+
changeDetection: ChangeDetectionStrategy.OnPush,
|
|
1522
|
+
encapsulation: ViewEncapsulation.None,
|
|
1523
|
+
imports: [ScrollingModule, NgTemplateOutlet, AXTranslatorPipe, AsyncPipe, AXListNavigationModule, AXCheckBoxComponent],
|
|
1524
|
+
providers: [{ provide: AXLookupListViewBase, useExisting: AXLookupMultiSelectComponent }],
|
|
1525
|
+
template: `
|
|
1526
|
+
@if (isEmpty()) {
|
|
1527
|
+
@if (emptyTemplate()) {
|
|
1528
|
+
<ng-container [ngTemplateOutlet]="emptyTemplate()!" />
|
|
1529
|
+
} @else {
|
|
1530
|
+
<div class="ax-lookup-empty">
|
|
1531
|
+
{{ '@acorex:common.general.no-result-found' | translate | async }}
|
|
1532
|
+
</div>
|
|
1533
|
+
}
|
|
1534
|
+
} @else {
|
|
1535
|
+
<cdk-virtual-scroll-viewport
|
|
1536
|
+
class="ax-lookup-viewport"
|
|
1537
|
+
role="listbox"
|
|
1538
|
+
aria-multiselectable="true"
|
|
1539
|
+
axListNavigation
|
|
1540
|
+
#nav="axListNavigation"
|
|
1541
|
+
[itemSize]="itemHeight()"
|
|
1542
|
+
[style.height.px]="viewportHeight()"
|
|
1543
|
+
(onKeypress)="handleListKeypress($event)"
|
|
1544
|
+
>
|
|
1545
|
+
<div
|
|
1546
|
+
*cdkVirtualFor="let item of listDataSource(); let i = index; trackBy: trackByIndex"
|
|
1547
|
+
role="option"
|
|
1548
|
+
class="ax-lookup-option-host ax-lookup-option-multiple"
|
|
1549
|
+
axListNavigationItem
|
|
1550
|
+
#navItem="axListNavigationItem"
|
|
1551
|
+
[style.height.px]="itemHeight()"
|
|
1552
|
+
[class.ax-lookup-option]="!itemTemplate()"
|
|
1553
|
+
[class.ax-state-alternate]="alternate() && i % 2 === 1"
|
|
1554
|
+
[class.ax-state-selected]="item != null && isSelected(item)"
|
|
1555
|
+
[class.ax-state-disabled]="item != null && isDisabled(item)"
|
|
1556
|
+
[class.ax-state-active]="navItem.isActive()"
|
|
1557
|
+
[attr.aria-selected]="item != null ? isSelected(item) : null"
|
|
1558
|
+
(mouseenter)="activateNavItem(nav, navItem)"
|
|
1559
|
+
(mousedown)="handleItemMouseDown($event, item)"
|
|
1560
|
+
(onKeypress)="handleItemKeypress($event, item)"
|
|
1561
|
+
>
|
|
1562
|
+
@if (item != null) {
|
|
1563
|
+
<ax-check-box
|
|
1564
|
+
class="ax-lookup-checkbox"
|
|
1565
|
+
[tabIndex]="-1"
|
|
1566
|
+
[value]="isSelected(item)"
|
|
1567
|
+
[disabled]="isDisabled(item)"
|
|
1568
|
+
></ax-check-box>
|
|
1569
|
+
@if (itemTemplate()) {
|
|
1570
|
+
<ng-container [ngTemplateOutlet]="itemTemplate()!" [ngTemplateOutletContext]="{ $implicit: item }" />
|
|
1571
|
+
} @else {
|
|
1572
|
+
<span class="ax-lookup-option-text">{{ getText(item) }}</span>
|
|
1573
|
+
}
|
|
1574
|
+
} @else {
|
|
1575
|
+
<ng-container [ngTemplateOutlet]="loadingRow" />
|
|
1576
|
+
}
|
|
1577
|
+
</div>
|
|
1578
|
+
</cdk-virtual-scroll-viewport>
|
|
1579
|
+
}
|
|
1580
|
+
|
|
1581
|
+
<ng-template #loadingRow>
|
|
1582
|
+
@if (loadingTemplate()) {
|
|
1583
|
+
<ng-container [ngTemplateOutlet]="loadingTemplate()!" />
|
|
1584
|
+
} @else {
|
|
1585
|
+
<span class="ax-lookup-option-loading">{{ '@acorex:common.status.loading' | translate | async }}</span>
|
|
1586
|
+
}
|
|
1587
|
+
</ng-template>
|
|
1588
|
+
`,
|
|
1589
|
+
}]
|
|
1590
|
+
}] });
|
|
1591
|
+
|
|
1592
|
+
/**
|
|
1593
|
+
* An advanced drop-down (lookup) editor with six modes, `AXDataSource` support, and virtual scrolling.
|
|
1594
|
+
*
|
|
1595
|
+
* Modes (each rendered by its own internal mini component):
|
|
1596
|
+
* - `drop-down-list` — a predefined list of options for picking single values.
|
|
1597
|
+
* - `multi-select` — a predefined list of options for multiple item selection (chips in the trigger).
|
|
1598
|
+
* - `drop-down-tree` — a tree-like structure for single item selection; when searchable, the trigger
|
|
1599
|
+
* input filters nested nodes as you type (on small screens the search field is inside the actionsheet).
|
|
1600
|
+
* - `multi-select-tree` — a tree-like structure for multiple item selection; searchable the same way.
|
|
1601
|
+
* - `multi-column` — an `ax-data-table` grid; when searchable, the trigger input filters as you type
|
|
1602
|
+
* (on small screens the search field is inside the actionsheet).
|
|
1603
|
+
* - `multi-column-tree` — a multi-column `ax-data-table` with a drop-down tree inside it
|
|
1604
|
+
* (expandable hierarchical rows). Uses `treeDataSource` + `columns`, or a hierarchical `dataSource`.
|
|
1605
|
+
*
|
|
1606
|
+
* With `adaptivityEnabled` (default `true`), the list opens as a bottom actionsheet on small
|
|
1607
|
+
* screens instead of an anchored dropdown — the same alternate presentation as `ax-select-box`.
|
|
1608
|
+
*
|
|
1609
|
+
* Implements {@link FormValueControl} so `[(ngModel)]` / signal forms work via the `value` model
|
|
1610
|
+
* (no `ControlValueAccessor`).
|
|
1611
|
+
*
|
|
1612
|
+
* @category Components
|
|
1613
|
+
*/
|
|
1614
|
+
class AXLookupComponent extends NXValueComponent {
|
|
1615
|
+
#platform;
|
|
1616
|
+
#destroyRef;
|
|
1617
|
+
/** Whether search filters the tree datasource instead of `AXDataSource`. */
|
|
1618
|
+
#isTreeOnlySearchMode() {
|
|
1619
|
+
const mode = this.mode();
|
|
1620
|
+
return mode === 'drop-down-tree' || mode === 'multi-select-tree';
|
|
1621
|
+
}
|
|
1622
|
+
/**
|
|
1623
|
+
* Applied tree search query. Set only from `#applyFilterNow` so opening a single-select
|
|
1624
|
+
* with the selected label in the trigger does not filter the tree.
|
|
1625
|
+
*/
|
|
1626
|
+
#treeFilterQuery;
|
|
1627
|
+
#treeFilterEpoch;
|
|
1628
|
+
/** Reused so closing/reopening the popup does not create a new AXDataSource (which would miss cache). */
|
|
1629
|
+
#multiColumnTreeTableSource;
|
|
1630
|
+
#multiColumnTreeTableKey;
|
|
1631
|
+
#multiColumnTreeInput;
|
|
1632
|
+
/**
|
|
1633
|
+
* Tree callback results keyed by parent id. Survives popup remount so
|
|
1634
|
+
* drop-down-tree / multi-select-tree do not refetch on every open.
|
|
1635
|
+
*/
|
|
1636
|
+
#treeChildrenCache;
|
|
1637
|
+
#document;
|
|
1638
|
+
#itemsCache;
|
|
1639
|
+
#isUserInteraction;
|
|
1640
|
+
#lastValue;
|
|
1641
|
+
#lastExpanded;
|
|
1642
|
+
#resolveRevision;
|
|
1643
|
+
#selectionInitialized;
|
|
1644
|
+
#filterApplied;
|
|
1645
|
+
#searchDebounce;
|
|
1646
|
+
#searchEnterRevision;
|
|
1647
|
+
#sheetSearchFocused;
|
|
1648
|
+
constructor() {
|
|
1649
|
+
super();
|
|
1650
|
+
this.#platform = inject(AXPlatform);
|
|
1651
|
+
this.#destroyRef = inject(DestroyRef);
|
|
1652
|
+
/**
|
|
1653
|
+
* The name of the form field, used by validation rules and `ax-form.validate(names)`.
|
|
1654
|
+
*/
|
|
1655
|
+
this.name = input('', /* @ts-ignore */
|
|
1656
|
+
...(ngDevMode ? [{ debugName: "name" }] : /* istanbul ignore next */ []));
|
|
1657
|
+
/**
|
|
1658
|
+
* The lookup rendering mode. Selects which mini component renders in the popup.
|
|
1659
|
+
*/
|
|
1660
|
+
this.mode = input('drop-down-list', /* @ts-ignore */
|
|
1661
|
+
...(ngDevMode ? [{ debugName: "mode" }] : /* istanbul ignore next */ []));
|
|
1662
|
+
/**
|
|
1663
|
+
* The items source for list-based modes (`drop-down-list`, `multi-select`, `multi-column`)
|
|
1664
|
+
* and for `multi-column-tree` when `treeDataSource` is not set.
|
|
1665
|
+
* Accepts an `AXDataSource` (remote paging, `byKey`, server-side filter) or a plain array.
|
|
1666
|
+
*/
|
|
1667
|
+
this.dataSource = input(undefined, /* @ts-ignore */
|
|
1668
|
+
...(ngDevMode ? [{ debugName: "dataSource" }] : /* istanbul ignore next */ []));
|
|
1669
|
+
/**
|
|
1670
|
+
* The nodes source for tree modes (`drop-down-tree`, `multi-select-tree`, `multi-column-tree`):
|
|
1671
|
+
* an array of nodes or a lazy children callback.
|
|
1672
|
+
*/
|
|
1673
|
+
this.treeDataSource = input(undefined, /* @ts-ignore */
|
|
1674
|
+
...(ngDevMode ? [{ debugName: "treeDataSource" }] : /* istanbul ignore next */ []));
|
|
1675
|
+
/**
|
|
1676
|
+
* The item property used as the selection value. Maps to the tree `idField` in tree modes.
|
|
1677
|
+
*/
|
|
1678
|
+
this.valueField = input('id', /* @ts-ignore */
|
|
1679
|
+
...(ngDevMode ? [{ debugName: "valueField" }] : /* istanbul ignore next */ []));
|
|
1680
|
+
/**
|
|
1681
|
+
* The item property used as the display text. Maps to the tree `titleField` in tree modes
|
|
1682
|
+
* (set it to `title` when your nodes use the default tree shape).
|
|
1683
|
+
*/
|
|
1684
|
+
this.textField = input('text', /* @ts-ignore */
|
|
1685
|
+
...(ngDevMode ? [{ debugName: "textField" }] : /* istanbul ignore next */ []));
|
|
1686
|
+
/**
|
|
1687
|
+
* The item property marking an item as disabled.
|
|
1688
|
+
*/
|
|
1689
|
+
this.disabledField = input('disabled', /* @ts-ignore */
|
|
1690
|
+
...(ngDevMode ? [{ debugName: "disabledField" }] : /* istanbul ignore next */ []));
|
|
1691
|
+
/**
|
|
1692
|
+
* Column definitions for the `multi-column` and `multi-column-tree` modes
|
|
1693
|
+
* (rendered as `ax-text-column` in `ax-data-table`).
|
|
1694
|
+
*/
|
|
1695
|
+
this.columns = input([], /* @ts-ignore */
|
|
1696
|
+
...(ngDevMode ? [{ debugName: "columns" }] : /* istanbul ignore next */ []));
|
|
1697
|
+
/**
|
|
1698
|
+
* Field used by `multi-column-tree` to fetch children when a row is expanded
|
|
1699
|
+
* (`AXDataSource` filter). Defaults to `parentId`. Nested `children` arrays are also supported.
|
|
1700
|
+
*/
|
|
1701
|
+
this.treeParentField = input('parentId', /* @ts-ignore */
|
|
1702
|
+
...(ngDevMode ? [{ debugName: "treeParentField" }] : /* istanbul ignore next */ []));
|
|
1703
|
+
/**
|
|
1704
|
+
* Field used by `multi-column-tree` to decide whether a row shows an expand control.
|
|
1705
|
+
* Defaults to `hasChild`. Nodes with `children` / `childrenCount` are mapped automatically
|
|
1706
|
+
* when using `treeDataSource`.
|
|
1707
|
+
*/
|
|
1708
|
+
this.hasChildrenField = input('hasChild', /* @ts-ignore */
|
|
1709
|
+
...(ngDevMode ? [{ debugName: "hasChildrenField" }] : /* istanbul ignore next */ []));
|
|
1710
|
+
/**
|
|
1711
|
+
* Whether the trigger accepts typing and filters the datasource (`true`),
|
|
1712
|
+
* or is select-only with no writable input (`false`).
|
|
1713
|
+
* Applies to all modes, including `drop-down-tree` and `multi-select-tree`.
|
|
1714
|
+
* On small screens with `adaptivityEnabled`, search is typed in the actionsheet instead of the trigger.
|
|
1715
|
+
*/
|
|
1716
|
+
this.searchable = input(true, /* @ts-ignore */
|
|
1717
|
+
...(ngDevMode ? [{ debugName: "searchable" }] : /* istanbul ignore next */ []));
|
|
1718
|
+
/**
|
|
1719
|
+
* When `true` (default), the popup list uses the alternate actionsheet presentation on small
|
|
1720
|
+
* screens (`SM`). Searchable list modes then show a search field inside the sheet. When `false`,
|
|
1721
|
+
* the list always opens as an anchored dropdown.
|
|
1722
|
+
*/
|
|
1723
|
+
this.adaptivityEnabled = input(true, /* @ts-ignore */
|
|
1724
|
+
...(ngDevMode ? [{ debugName: "adaptivityEnabled" }] : /* istanbul ignore next */ []));
|
|
1725
|
+
/**
|
|
1726
|
+
* Title shown in the actionsheet header on small screens. Falls back to `placeholder`.
|
|
1727
|
+
*/
|
|
1728
|
+
this.caption = input('', /* @ts-ignore */
|
|
1729
|
+
...(ngDevMode ? [{ debugName: "caption" }] : /* istanbul ignore next */ []));
|
|
1730
|
+
/**
|
|
1731
|
+
* When `true`, list rows use alternating background colors for easier scanning
|
|
1732
|
+
* (all lookup modes, including drop-down-tree and multi-select-tree).
|
|
1733
|
+
*/
|
|
1734
|
+
this.alternate = input(false, /* @ts-ignore */
|
|
1735
|
+
...(ngDevMode ? [{ debugName: "alternate" }] : /* istanbul ignore next */ []));
|
|
1736
|
+
/**
|
|
1737
|
+
* Placeholder for the trigger search input when items are already selected
|
|
1738
|
+
* (mainly useful in `multi-select` / `multi-select-tree`), and for the in-sheet search field on small screens.
|
|
1739
|
+
* Falls back to `placeholder` when the selection is empty on desktop.
|
|
1740
|
+
*/
|
|
1741
|
+
this.searchPlaceholder = input('Search...', /* @ts-ignore */
|
|
1742
|
+
...(ngDevMode ? [{ debugName: "searchPlaceholder" }] : /* istanbul ignore next */ []));
|
|
1743
|
+
/**
|
|
1744
|
+
* The placeholder text shown when no value is selected.
|
|
1745
|
+
*/
|
|
1746
|
+
this.placeholder = input('', /* @ts-ignore */
|
|
1747
|
+
...(ngDevMode ? [{ debugName: "placeholder" }] : /* istanbul ignore next */ []));
|
|
1748
|
+
/**
|
|
1749
|
+
* Whether the lookup is disabled.
|
|
1750
|
+
*/
|
|
1751
|
+
this.disabled = input(false, /* @ts-ignore */
|
|
1752
|
+
...(ngDevMode ? [{ debugName: "disabled" }] : /* istanbul ignore next */ []));
|
|
1753
|
+
/**
|
|
1754
|
+
* Whether the lookup is readonly.
|
|
1755
|
+
*/
|
|
1756
|
+
this.readonly = input(false, /* @ts-ignore */
|
|
1757
|
+
...(ngDevMode ? [{ debugName: "readonly" }] : /* istanbul ignore next */ []));
|
|
1758
|
+
/**
|
|
1759
|
+
* Predefined look scheme of the editor container. Same looks as other editor components like ax-text-box.
|
|
1760
|
+
*/
|
|
1761
|
+
this.look = model('solid', /* @ts-ignore */
|
|
1762
|
+
...(ngDevMode ? [{ debugName: "look" }] : /* istanbul ignore next */ []));
|
|
1763
|
+
/**
|
|
1764
|
+
* The fixed row height in pixels used by the virtual scroll viewport (list-based modes).
|
|
1765
|
+
*/
|
|
1766
|
+
this.itemHeight = input(40, /* @ts-ignore */
|
|
1767
|
+
...(ngDevMode ? [{ debugName: "itemHeight" }] : /* istanbul ignore next */ []));
|
|
1768
|
+
/**
|
|
1769
|
+
* The maximum number of rows visible before the popup scrolls (list-based modes).
|
|
1770
|
+
*/
|
|
1771
|
+
this.maxVisibleItems = input(8, /* @ts-ignore */
|
|
1772
|
+
...(ngDevMode ? [{ debugName: "maxVisibleItems" }] : /* istanbul ignore next */ []));
|
|
1773
|
+
/**
|
|
1774
|
+
* How selecting parent/child nodes affects each other in `multi-select-tree` mode.
|
|
1775
|
+
*/
|
|
1776
|
+
this.treeSelectionBehavior = input('all', /* @ts-ignore */
|
|
1777
|
+
...(ngDevMode ? [{ debugName: "treeSelectionBehavior" }] : /* istanbul ignore next */ []));
|
|
1778
|
+
/**
|
|
1779
|
+
* Custom template rendered for each item/node. Context: `$implicit` is the item.
|
|
1780
|
+
* Default option chrome (padding, typography, check icon) is not applied; only the
|
|
1781
|
+
* template's styles are used. Selection and hover backgrounds remain on the row.
|
|
1782
|
+
*/
|
|
1783
|
+
this.itemTemplate = input(undefined, /* @ts-ignore */
|
|
1784
|
+
...(ngDevMode ? [{ debugName: "itemTemplate" }] : /* istanbul ignore next */ []));
|
|
1785
|
+
/**
|
|
1786
|
+
* Custom template for the selected item display (trigger text / chips). Context: `$implicit` is the item.
|
|
1787
|
+
*/
|
|
1788
|
+
this.selectedTemplate = input(undefined, /* @ts-ignore */
|
|
1789
|
+
...(ngDevMode ? [{ debugName: "selectedTemplate" }] : /* istanbul ignore next */ []));
|
|
1790
|
+
/**
|
|
1791
|
+
* Custom template rendered when the datasource has no items.
|
|
1792
|
+
*/
|
|
1793
|
+
this.emptyTemplate = input(undefined, /* @ts-ignore */
|
|
1794
|
+
...(ngDevMode ? [{ debugName: "emptyTemplate" }] : /* istanbul ignore next */ []));
|
|
1795
|
+
/**
|
|
1796
|
+
* Custom template rendered for rows whose page is still loading.
|
|
1797
|
+
*/
|
|
1798
|
+
this.loadingTemplate = input(undefined, /* @ts-ignore */
|
|
1799
|
+
...(ngDevMode ? [{ debugName: "loadingTemplate" }] : /* istanbul ignore next */ []));
|
|
1800
|
+
/**
|
|
1801
|
+
* The selected value(s): a scalar in single modes, an array in
|
|
1802
|
+
* `multi-select` / `multi-select-tree`. Supports `[(value)]`, `[(ngModel)]`, and signal forms
|
|
1803
|
+
* via {@link FormValueControl}.
|
|
1804
|
+
*/
|
|
1805
|
+
this.value = model(null, /* @ts-ignore */
|
|
1806
|
+
...(ngDevMode ? [{ debugName: "value" }] : /* istanbul ignore next */ []));
|
|
1807
|
+
/**
|
|
1808
|
+
* Full items that resolve the current `value` key(s) without calling datasource `byKey`.
|
|
1809
|
+
* Use when the parent already has the selected entity (e.g. edit forms). Seeds the internal
|
|
1810
|
+
* item cache; missing keys still fall through to `find` / `byKey`.
|
|
1811
|
+
*/
|
|
1812
|
+
this.valueItems = input([], /* @ts-ignore */
|
|
1813
|
+
...(ngDevMode ? [{ debugName: "valueItems" }] : /* istanbul ignore next */ []));
|
|
1814
|
+
/**
|
|
1815
|
+
* Emitted when the selected value changes.
|
|
1816
|
+
*/
|
|
1817
|
+
this.onValueChanged = output();
|
|
1818
|
+
/**
|
|
1819
|
+
* Emitted when the selection changes, carrying the resolved selected items.
|
|
1820
|
+
*/
|
|
1821
|
+
this.onSelectionChanged = output();
|
|
1822
|
+
/**
|
|
1823
|
+
* Emitted when the trigger receives focus.
|
|
1824
|
+
*/
|
|
1825
|
+
this.onFocus = output();
|
|
1826
|
+
/**
|
|
1827
|
+
* Emitted when the trigger loses focus.
|
|
1828
|
+
*/
|
|
1829
|
+
this.onBlur = output();
|
|
1830
|
+
/**
|
|
1831
|
+
* Emitted when a list/tree item is clicked.
|
|
1832
|
+
*/
|
|
1833
|
+
this.onItemClick = output();
|
|
1834
|
+
/**
|
|
1835
|
+
* Emitted when an item is selected (click or keyboard).
|
|
1836
|
+
*/
|
|
1837
|
+
this.onItemSelected = output();
|
|
1838
|
+
/**
|
|
1839
|
+
* Emitted when the popup opens.
|
|
1840
|
+
*/
|
|
1841
|
+
this.onOpened = output();
|
|
1842
|
+
/**
|
|
1843
|
+
* Emitted when the popup closes.
|
|
1844
|
+
*/
|
|
1845
|
+
this.onClosed = output();
|
|
1846
|
+
/** Whether the popup is expanded. */
|
|
1847
|
+
this.expanded = signal(false, /* @ts-ignore */
|
|
1848
|
+
...(ngDevMode ? [{ debugName: "expanded" }] : /* istanbul ignore next */ []));
|
|
1849
|
+
/** Whether the list is currently shown as a bottom actionsheet (small screens + adaptivity). */
|
|
1850
|
+
this.isActionsheetStyle = signal(false, /* @ts-ignore */
|
|
1851
|
+
...(ngDevMode ? [{ debugName: "isActionsheetStyle" }] : /* istanbul ignore next */ []));
|
|
1852
|
+
/** Whether the current mode selects multiple values. */
|
|
1853
|
+
this.isMultiple = computed(() => this.mode() === 'multi-select' || this.mode() === 'multi-select-tree', /* @ts-ignore */
|
|
1854
|
+
...(ngDevMode ? [{ debugName: "isMultiple" }] : /* istanbul ignore next */ []));
|
|
1855
|
+
/** Whether the current mode renders a tree. */
|
|
1856
|
+
this.isTreeMode = computed(() => {
|
|
1857
|
+
const mode = this.mode();
|
|
1858
|
+
return (mode === 'drop-down-tree' ||
|
|
1859
|
+
mode === 'multi-select-tree' ||
|
|
1860
|
+
(mode === 'multi-column-tree' && this.treeDataSource() != null));
|
|
1861
|
+
}, /* @ts-ignore */
|
|
1862
|
+
...(ngDevMode ? [{ debugName: "isTreeMode" }] : /* istanbul ignore next */ []));
|
|
1863
|
+
/** Whether the current mode can filter as you type (list, table, or tree). */
|
|
1864
|
+
this.isListSearchMode = computed(() => {
|
|
1865
|
+
const mode = this.mode();
|
|
1866
|
+
return (mode === 'drop-down-list' ||
|
|
1867
|
+
mode === 'multi-select' ||
|
|
1868
|
+
mode === 'drop-down-tree' ||
|
|
1869
|
+
mode === 'multi-select-tree' ||
|
|
1870
|
+
mode === 'multi-column' ||
|
|
1871
|
+
mode === 'multi-column-tree');
|
|
1872
|
+
}, /* @ts-ignore */
|
|
1873
|
+
...(ngDevMode ? [{ debugName: "isListSearchMode" }] : /* istanbul ignore next */ []));
|
|
1874
|
+
/** Whether the trigger input is writable and filters as you type (desktop only). */
|
|
1875
|
+
this.isEditableTrigger = computed(() => this.searchable() && !this.readonly() && !this.isActionsheetStyle() && this.isListSearchMode(), /* @ts-ignore */
|
|
1876
|
+
...(ngDevMode ? [{ debugName: "isEditableTrigger" }] : /* istanbul ignore next */ []));
|
|
1877
|
+
/** Whether search is typed in the actionsheet instead of the trigger. */
|
|
1878
|
+
this.isSheetSearchEnabled = computed(() => this.searchable() && !this.readonly() && this.isActionsheetStyle() && this.isListSearchMode(), /* @ts-ignore */
|
|
1879
|
+
...(ngDevMode ? [{ debugName: "isSheetSearchEnabled" }] : /* istanbul ignore next */ []));
|
|
1880
|
+
/** Query typed in the actionsheet search field (independent of the trigger display text). */
|
|
1881
|
+
this.sheetSearchText = signal('', /* @ts-ignore */
|
|
1882
|
+
...(ngDevMode ? [{ debugName: "sheetSearchText" }] : /* istanbul ignore next */ []));
|
|
1883
|
+
/**
|
|
1884
|
+
* Applied tree search query. Set only from `#applyFilterNow` so opening a single-select
|
|
1885
|
+
* with the selected label in the trigger does not filter the tree.
|
|
1886
|
+
*/
|
|
1887
|
+
this.#treeFilterQuery = signal('', /* @ts-ignore */
|
|
1888
|
+
...(ngDevMode ? [{ debugName: "#treeFilterQuery" }] : /* istanbul ignore next */ []));
|
|
1889
|
+
this.#treeFilterEpoch = signal(0, /* @ts-ignore */
|
|
1890
|
+
...(ngDevMode ? [{ debugName: "#treeFilterEpoch" }] : /* istanbul ignore next */ []));
|
|
1891
|
+
/** Increments on every tree filter apply so the tree view remounts with a new instance. */
|
|
1892
|
+
this.treeFilterKey = computed(() => String(this.#treeFilterEpoch()), /* @ts-ignore */
|
|
1893
|
+
...(ngDevMode ? [{ debugName: "treeFilterKey" }] : /* istanbul ignore next */ []));
|
|
1894
|
+
/** The datasource for list-based modes; plain arrays are converted. */
|
|
1895
|
+
this.resolvedDataSource = computed(() => {
|
|
1896
|
+
const tree = this.treeDataSource();
|
|
1897
|
+
if (this.mode() === 'multi-column-tree' && tree) {
|
|
1898
|
+
const key = `${this.valueField()}|${this.textField()}|${this.treeParentField()}|${this.hasChildrenField()}`;
|
|
1899
|
+
if (this.#multiColumnTreeTableSource &&
|
|
1900
|
+
this.#multiColumnTreeInput === tree &&
|
|
1901
|
+
this.#multiColumnTreeTableKey === key) {
|
|
1902
|
+
return this.#multiColumnTreeTableSource;
|
|
1903
|
+
}
|
|
1904
|
+
const cachedTree = Array.isArray(tree)
|
|
1905
|
+
? tree
|
|
1906
|
+
: (nodeId) => this.#loadCachedTreeNodes(tree, nodeId);
|
|
1907
|
+
this.#multiColumnTreeInput = tree;
|
|
1908
|
+
this.#multiColumnTreeTableKey = key;
|
|
1909
|
+
this.#multiColumnTreeTableSource = createLookupTreeTableDataSource(cachedTree, {
|
|
1910
|
+
valueField: this.valueField(),
|
|
1911
|
+
textField: this.textField(),
|
|
1912
|
+
parentField: this.treeParentField(),
|
|
1913
|
+
hasChildrenField: this.hasChildrenField(),
|
|
1914
|
+
});
|
|
1915
|
+
return this.#multiColumnTreeTableSource;
|
|
1916
|
+
}
|
|
1917
|
+
const source = this.dataSource();
|
|
1918
|
+
if (!source) {
|
|
1919
|
+
return convertArrayToDataSource([], { key: this.valueField(), pageSize: 20 });
|
|
1920
|
+
}
|
|
1921
|
+
return Array.isArray(source)
|
|
1922
|
+
? convertArrayToDataSource(source, { key: this.valueField(), pageSize: 20 })
|
|
1923
|
+
: source;
|
|
1924
|
+
}, /* @ts-ignore */
|
|
1925
|
+
...(ngDevMode ? [{ debugName: "resolvedDataSource" }] : /* istanbul ignore next */ []));
|
|
1926
|
+
/**
|
|
1927
|
+
* Tree callback results keyed by parent id. Survives popup remount so
|
|
1928
|
+
* drop-down-tree / multi-select-tree do not refetch on every open.
|
|
1929
|
+
*/
|
|
1930
|
+
this.#treeChildrenCache = new WeakMap();
|
|
1931
|
+
this.resolvedTreeDataSource = computed(() => {
|
|
1932
|
+
this.#treeFilterEpoch();
|
|
1933
|
+
const source = this.treeDataSource();
|
|
1934
|
+
const query = this.#treeFilterQuery();
|
|
1935
|
+
const textField = this.textField();
|
|
1936
|
+
if (!source) {
|
|
1937
|
+
return [];
|
|
1938
|
+
}
|
|
1939
|
+
if (Array.isArray(source)) {
|
|
1940
|
+
return query ? filterTreeNodes(source, textField, query) : cloneLookupTreeNodes(source);
|
|
1941
|
+
}
|
|
1942
|
+
if (!query) {
|
|
1943
|
+
return (nodeId) => this.#loadCachedTreeNodes(source, nodeId);
|
|
1944
|
+
}
|
|
1945
|
+
return (nodeId) => this.#loadFilteredCachedTreeNodes(source, nodeId, query);
|
|
1946
|
+
}, /* @ts-ignore */
|
|
1947
|
+
...(ngDevMode ? [{ debugName: "resolvedTreeDataSource" }] : /* istanbul ignore next */ []));
|
|
1948
|
+
/** The current selection normalized to an array. */
|
|
1949
|
+
this.selectedValues = computed(() => {
|
|
1950
|
+
const value = this.value();
|
|
1951
|
+
if (value == null) {
|
|
1952
|
+
return [];
|
|
1953
|
+
}
|
|
1954
|
+
return Array.isArray(value) ? value : [value];
|
|
1955
|
+
}, /* @ts-ignore */
|
|
1956
|
+
...(ngDevMode ? [{ debugName: "selectedValues" }] : /* istanbul ignore next */ []));
|
|
1957
|
+
/** The resolved selected items (via cache, datasource `find`/`byKey`, or tree node lookup). */
|
|
1958
|
+
this.selectedItems = signal([], /* @ts-ignore */
|
|
1959
|
+
...(ngDevMode ? [{ debugName: "selectedItems" }] : /* istanbul ignore next */ []));
|
|
1960
|
+
/** Display text shown in the trigger for single modes. */
|
|
1961
|
+
this.displayText = computed(() => {
|
|
1962
|
+
const item = this.selectedItems()[0];
|
|
1963
|
+
return item ? this.getItemText(item) : '';
|
|
1964
|
+
}, /* @ts-ignore */
|
|
1965
|
+
...(ngDevMode ? [{ debugName: "displayText" }] : /* istanbul ignore next */ []));
|
|
1966
|
+
/**
|
|
1967
|
+
* Text typed in the editable trigger input.
|
|
1968
|
+
* Multi-select starts empty; single modes sync from the selected display text.
|
|
1969
|
+
*/
|
|
1970
|
+
this.searchText = linkedSignal(() => (this.isMultiple() ? '' : this.displayText()), /* @ts-ignore */
|
|
1971
|
+
...(ngDevMode ? [{ debugName: "searchText" }] : /* istanbul ignore next */ []));
|
|
1972
|
+
/**
|
|
1973
|
+
* Whether the trigger should render `selectedTemplate` instead of the plain input text.
|
|
1974
|
+
* Searchable mode shows the template while the popup is closed and the input still matches
|
|
1975
|
+
* the selected display text (same pattern as combo-box).
|
|
1976
|
+
*/
|
|
1977
|
+
this.showSelectedTemplate = computed(() => {
|
|
1978
|
+
if (this.isMultiple() || !this.selectedTemplate() || this.selectedItems().length === 0) {
|
|
1979
|
+
return false;
|
|
1980
|
+
}
|
|
1981
|
+
if (!this.isEditableTrigger()) {
|
|
1982
|
+
return true;
|
|
1983
|
+
}
|
|
1984
|
+
return !this.expanded() && this.searchText() === this.displayText();
|
|
1985
|
+
}, /* @ts-ignore */
|
|
1986
|
+
...(ngDevMode ? [{ debugName: "showSelectedTemplate" }] : /* istanbul ignore next */ []));
|
|
1987
|
+
/** Placeholder for the editable trigger search input. */
|
|
1988
|
+
this.triggerSearchPlaceholder = computed(() => {
|
|
1989
|
+
if (this.isActionsheetStyle()) {
|
|
1990
|
+
return this.isMultiple() && this.selectedItems().length > 0 ? '' : this.placeholder();
|
|
1991
|
+
}
|
|
1992
|
+
if (this.isMultiple() && this.selectedItems().length > 0) {
|
|
1993
|
+
return this.searchPlaceholder();
|
|
1994
|
+
}
|
|
1995
|
+
return this.placeholder();
|
|
1996
|
+
}, /* @ts-ignore */
|
|
1997
|
+
...(ngDevMode ? [{ debugName: "triggerSearchPlaceholder" }] : /* istanbul ignore next */ []));
|
|
1998
|
+
this.popoverRef = viewChild(AXPopoverComponent, /* @ts-ignore */
|
|
1999
|
+
...(ngDevMode ? [{ debugName: "popoverRef" }] : /* istanbul ignore next */ []));
|
|
2000
|
+
this.originRef = viewChild('origin', /* @ts-ignore */
|
|
2001
|
+
...(ngDevMode ? [{ debugName: "originRef" }] : /* istanbul ignore next */ []));
|
|
2002
|
+
this.popupRef = viewChild('popup', /* @ts-ignore */
|
|
2003
|
+
...(ngDevMode ? [{ debugName: "popupRef" }] : /* istanbul ignore next */ []));
|
|
2004
|
+
this.triggerSearchInput = viewChild('triggerSearchInput', /* @ts-ignore */
|
|
2005
|
+
...(ngDevMode ? [{ debugName: "triggerSearchInput" }] : /* istanbul ignore next */ []));
|
|
2006
|
+
this.#document = inject(DOCUMENT);
|
|
2007
|
+
this.listView = viewChild(AXLookupListViewBase, /* @ts-ignore */
|
|
2008
|
+
...(ngDevMode ? [{ debugName: "listView" }] : /* istanbul ignore next */ []));
|
|
2009
|
+
this.dropDownTreeView = viewChild(AXLookupDropDownTreeComponent, /* @ts-ignore */
|
|
2010
|
+
...(ngDevMode ? [{ debugName: "dropDownTreeView" }] : /* istanbul ignore next */ []));
|
|
2011
|
+
this.multiSelectTreeView = viewChild(AXLookupMultiSelectTreeComponent, /* @ts-ignore */
|
|
2012
|
+
...(ngDevMode ? [{ debugName: "multiSelectTreeView" }] : /* istanbul ignore next */ []));
|
|
2013
|
+
this.sheetSearchRef = viewChild('sheetSearch', /* @ts-ignore */
|
|
2014
|
+
...(ngDevMode ? [{ debugName: "sheetSearchRef" }] : /* istanbul ignore next */ []));
|
|
2015
|
+
this.#itemsCache = new Map();
|
|
2016
|
+
this.#isUserInteraction = false;
|
|
2017
|
+
this.#lastValue = undefined;
|
|
2018
|
+
this.#lastExpanded = undefined;
|
|
2019
|
+
this.#resolveRevision = 0;
|
|
2020
|
+
this.#selectionInitialized = false;
|
|
2021
|
+
this.#filterApplied = false;
|
|
2022
|
+
this.#searchEnterRevision = 0;
|
|
2023
|
+
this.#sheetSearchFocused = false;
|
|
2024
|
+
effect(() => this.#emitValueChanged(this.value()));
|
|
2025
|
+
effect(() => this.#emitOpenedOrClosed(this.expanded()));
|
|
2026
|
+
effect(() => {
|
|
2027
|
+
this.adaptivityEnabled();
|
|
2028
|
+
untracked(() => this.#syncActionsheetStyle());
|
|
2029
|
+
});
|
|
2030
|
+
this.#platform.resize.pipe(takeUntilDestroyed(this.#destroyRef)).subscribe(() => {
|
|
2031
|
+
this.#syncActionsheetStyle();
|
|
2032
|
+
// Match dropdown-box: close anchored dropdowns on resize; keep actionsheet open.
|
|
2033
|
+
if (this.expanded() && !this.isActionsheetStyle()) {
|
|
2034
|
+
this.close();
|
|
2035
|
+
}
|
|
2036
|
+
});
|
|
2037
|
+
// Seed the actionsheet flag once.
|
|
2038
|
+
this.#syncActionsheetStyle();
|
|
2039
|
+
// Seed the item cache from valueItems, then resolve selection.
|
|
2040
|
+
effect(() => {
|
|
2041
|
+
const seeded = this.valueItems();
|
|
2042
|
+
const values = this.selectedValues();
|
|
2043
|
+
this.valueField();
|
|
2044
|
+
this.mode();
|
|
2045
|
+
this.dataSource();
|
|
2046
|
+
this.treeDataSource();
|
|
2047
|
+
untracked(() => {
|
|
2048
|
+
this.#seedItemsCache(seeded);
|
|
2049
|
+
void this.#resolveSelectedItems(values);
|
|
2050
|
+
});
|
|
2051
|
+
});
|
|
2052
|
+
// Keep the popover in sync with the expanded state.
|
|
2053
|
+
effect(() => {
|
|
2054
|
+
const expanded = this.expanded();
|
|
2055
|
+
const popover = this.popoverRef();
|
|
2056
|
+
if (!popover) {
|
|
2057
|
+
return;
|
|
2058
|
+
}
|
|
2059
|
+
untracked(() => {
|
|
2060
|
+
if (expanded && !popover.isOpen) {
|
|
2061
|
+
void popover.open();
|
|
2062
|
+
}
|
|
2063
|
+
else if (!expanded && popover.isOpen) {
|
|
2064
|
+
popover.close();
|
|
2065
|
+
}
|
|
2066
|
+
});
|
|
2067
|
+
});
|
|
2068
|
+
afterRenderEffect(() => {
|
|
2069
|
+
if (!this.expanded()) {
|
|
2070
|
+
this.#sheetSearchFocused = false;
|
|
2071
|
+
return;
|
|
2072
|
+
}
|
|
2073
|
+
this.#tryFocusSheetSearch();
|
|
2074
|
+
});
|
|
2075
|
+
}
|
|
2076
|
+
#syncActionsheetStyle() {
|
|
2077
|
+
this.isActionsheetStyle.set(this.adaptivityEnabled() && this.#platform.is('SM'));
|
|
2078
|
+
}
|
|
2079
|
+
/** Returns the display text of an item using the `textField` mapping. */
|
|
2080
|
+
getItemText(item) {
|
|
2081
|
+
return String(item?.[this.textField()] ?? '');
|
|
2082
|
+
}
|
|
2083
|
+
/** Stable unique key for selected chips — avoids NG0955 and remounts on reorder/remove. */
|
|
2084
|
+
trackSelectedKey(item) {
|
|
2085
|
+
const key = item?.[this.valueField()];
|
|
2086
|
+
return key != null ? key : item;
|
|
2087
|
+
}
|
|
2088
|
+
/**
|
|
2089
|
+
* Opens (editable trigger) or toggles the popup on trigger click.
|
|
2090
|
+
*/
|
|
2091
|
+
onTriggerClick() {
|
|
2092
|
+
if (this.disabled() || this.readonly()) {
|
|
2093
|
+
return;
|
|
2094
|
+
}
|
|
2095
|
+
if (this.isEditableTrigger()) {
|
|
2096
|
+
this.expanded.set(true);
|
|
2097
|
+
queueMicrotask(() => this.triggerSearchInput()?.nativeElement.focus());
|
|
2098
|
+
return;
|
|
2099
|
+
}
|
|
2100
|
+
this.expanded.update((open) => !open);
|
|
2101
|
+
if (!this.expanded()) {
|
|
2102
|
+
return;
|
|
2103
|
+
}
|
|
2104
|
+
queueMicrotask(() => this.#focusPopupSearchOrList());
|
|
2105
|
+
}
|
|
2106
|
+
/**
|
|
2107
|
+
* Focuses the lookup trigger input.
|
|
2108
|
+
*/
|
|
2109
|
+
focus(options) {
|
|
2110
|
+
if (this.disabled()) {
|
|
2111
|
+
return;
|
|
2112
|
+
}
|
|
2113
|
+
this.triggerSearchInput()?.nativeElement.focus(options);
|
|
2114
|
+
}
|
|
2115
|
+
/**
|
|
2116
|
+
* Handles keyboard interaction on the trigger input.
|
|
2117
|
+
*/
|
|
2118
|
+
onTriggerKeydown(e) {
|
|
2119
|
+
if (this.disabled() || this.readonly()) {
|
|
2120
|
+
return;
|
|
2121
|
+
}
|
|
2122
|
+
if (e.key === 'Escape') {
|
|
2123
|
+
this.close();
|
|
2124
|
+
return;
|
|
2125
|
+
}
|
|
2126
|
+
if (e.key === 'ArrowDown') {
|
|
2127
|
+
e.preventDefault();
|
|
2128
|
+
this.expanded.set(true);
|
|
2129
|
+
queueMicrotask(() => this.#focusPopupSearchOrList());
|
|
2130
|
+
return;
|
|
2131
|
+
}
|
|
2132
|
+
if (e.key === 'Enter' && this.isEditableTrigger()) {
|
|
2133
|
+
this.#onSearchEnter(e);
|
|
2134
|
+
return;
|
|
2135
|
+
}
|
|
2136
|
+
if (!this.isEditableTrigger() && (e.key === 'Enter' || e.key === ' ')) {
|
|
2137
|
+
e.preventDefault();
|
|
2138
|
+
this.expanded.update((open) => !open);
|
|
2139
|
+
if (this.expanded()) {
|
|
2140
|
+
queueMicrotask(() => this.#focusPopupSearchOrList());
|
|
2141
|
+
}
|
|
2142
|
+
}
|
|
2143
|
+
}
|
|
2144
|
+
/** Filters the datasource from the actionsheet search field and handles Enter with no matches. */
|
|
2145
|
+
onSheetSearchKeydown(e) {
|
|
2146
|
+
const event = e.nativeEvent;
|
|
2147
|
+
if (!event || event.key !== 'Enter') {
|
|
2148
|
+
return;
|
|
2149
|
+
}
|
|
2150
|
+
this.#onSearchEnter(event);
|
|
2151
|
+
}
|
|
2152
|
+
/**
|
|
2153
|
+
* Enter in search never submits the surrounding form.
|
|
2154
|
+
* - No matches: single-select value is cleared (`null`).
|
|
2155
|
+
* - Exactly one match: that item is selected (no list navigation required).
|
|
2156
|
+
* - Multiple matches: nothing is selected.
|
|
2157
|
+
*/
|
|
2158
|
+
#onSearchEnter(event) {
|
|
2159
|
+
event.preventDefault();
|
|
2160
|
+
event.stopPropagation();
|
|
2161
|
+
event.stopImmediatePropagation();
|
|
2162
|
+
void this.#commitOrClearFromSearch();
|
|
2163
|
+
}
|
|
2164
|
+
async #commitOrClearFromSearch() {
|
|
2165
|
+
const revision = ++this.#searchEnterRevision;
|
|
2166
|
+
this.#flushPendingFilter();
|
|
2167
|
+
if (this.#isTreeOnlySearchMode()) {
|
|
2168
|
+
const nodes = await this.#resolvedFilteredTreeNodes();
|
|
2169
|
+
if (revision !== this.#searchEnterRevision) {
|
|
2170
|
+
return;
|
|
2171
|
+
}
|
|
2172
|
+
const items = this.#enabledTreeItems(nodes);
|
|
2173
|
+
if (items.length === 0) {
|
|
2174
|
+
if (this.#currentSearchQuery() && !this.isMultiple()) {
|
|
2175
|
+
this.reset(true);
|
|
2176
|
+
this.close();
|
|
2177
|
+
}
|
|
2178
|
+
return;
|
|
2179
|
+
}
|
|
2180
|
+
if (items.length !== 1) {
|
|
2181
|
+
return;
|
|
2182
|
+
}
|
|
2183
|
+
this.#commitSearchSelection(items);
|
|
2184
|
+
return;
|
|
2185
|
+
}
|
|
2186
|
+
const source = this.resolvedDataSource();
|
|
2187
|
+
if (source.isLoading) {
|
|
2188
|
+
await this.#whenSourceIdle(source);
|
|
2189
|
+
if (revision !== this.#searchEnterRevision) {
|
|
2190
|
+
return;
|
|
2191
|
+
}
|
|
2192
|
+
}
|
|
2193
|
+
if (this.#hasNoSearchMatches()) {
|
|
2194
|
+
if (this.#currentSearchQuery() && !this.isMultiple()) {
|
|
2195
|
+
this.reset(true);
|
|
2196
|
+
this.close();
|
|
2197
|
+
}
|
|
2198
|
+
return;
|
|
2199
|
+
}
|
|
2200
|
+
if (this.#getSearchMatchCount() !== 1) {
|
|
2201
|
+
return;
|
|
2202
|
+
}
|
|
2203
|
+
const item = this.#pickFirstMatch();
|
|
2204
|
+
if (!item) {
|
|
2205
|
+
return;
|
|
2206
|
+
}
|
|
2207
|
+
this.#commitSearchSelection([item]);
|
|
2208
|
+
}
|
|
2209
|
+
#commitSearchSelection(items) {
|
|
2210
|
+
if (items.length === 0) {
|
|
2211
|
+
if (this.#currentSearchQuery() && !this.isMultiple()) {
|
|
2212
|
+
this.reset(true);
|
|
2213
|
+
this.close();
|
|
2214
|
+
}
|
|
2215
|
+
return;
|
|
2216
|
+
}
|
|
2217
|
+
if (!this.#isTypedFilterQuery()) {
|
|
2218
|
+
return;
|
|
2219
|
+
}
|
|
2220
|
+
const item = this.#pickFirstFromItems(items);
|
|
2221
|
+
if (!item) {
|
|
2222
|
+
return;
|
|
2223
|
+
}
|
|
2224
|
+
const event = { item, value: item[this.valueField()] };
|
|
2225
|
+
if (this.isMultiple()) {
|
|
2226
|
+
this.handleMultiToggle(event);
|
|
2227
|
+
}
|
|
2228
|
+
else {
|
|
2229
|
+
this.handleSinglePick(event);
|
|
2230
|
+
}
|
|
2231
|
+
}
|
|
2232
|
+
async #resolvedFilteredTreeNodes() {
|
|
2233
|
+
const source = this.resolvedTreeDataSource();
|
|
2234
|
+
if (Array.isArray(source)) {
|
|
2235
|
+
return source;
|
|
2236
|
+
}
|
|
2237
|
+
return (await source()) ?? [];
|
|
2238
|
+
}
|
|
2239
|
+
#enabledTreeItems(nodes) {
|
|
2240
|
+
const disabledField = this.disabledField();
|
|
2241
|
+
return flattenTreeNodes(nodes).filter((item) => !item[disabledField]);
|
|
2242
|
+
}
|
|
2243
|
+
#pickFirstMatch() {
|
|
2244
|
+
const disabledField = this.disabledField();
|
|
2245
|
+
const source = this.resolvedDataSource();
|
|
2246
|
+
const items = (source.cachedItems.length ? source.cachedItems : source.items).filter((item) => item != null && !item[disabledField]);
|
|
2247
|
+
return this.#pickFirstFromItems(items);
|
|
2248
|
+
}
|
|
2249
|
+
#pickFirstFromItems(items) {
|
|
2250
|
+
if (items.length === 0) {
|
|
2251
|
+
return null;
|
|
2252
|
+
}
|
|
2253
|
+
const query = this.#currentSearchQuery().toLowerCase();
|
|
2254
|
+
if (!query) {
|
|
2255
|
+
return items[0];
|
|
2256
|
+
}
|
|
2257
|
+
const textOf = (item) => String(item?.[this.textField()] ?? '').trim().toLowerCase();
|
|
2258
|
+
return items.find((item) => textOf(item) === query) ?? items.find((item) => textOf(item).includes(query)) ?? items[0];
|
|
2259
|
+
}
|
|
2260
|
+
#whenSourceIdle(source) {
|
|
2261
|
+
if (!source.isLoading) {
|
|
2262
|
+
return Promise.resolve();
|
|
2263
|
+
}
|
|
2264
|
+
return new Promise((resolve) => {
|
|
2265
|
+
const sub = source.onLoadingChanged.subscribe((loading) => {
|
|
2266
|
+
if (!loading) {
|
|
2267
|
+
sub.unsubscribe();
|
|
2268
|
+
resolve();
|
|
2269
|
+
}
|
|
2270
|
+
});
|
|
2271
|
+
});
|
|
2272
|
+
}
|
|
2273
|
+
#flushPendingFilter() {
|
|
2274
|
+
if (!this.#searchDebounce) {
|
|
2275
|
+
return;
|
|
2276
|
+
}
|
|
2277
|
+
clearTimeout(this.#searchDebounce);
|
|
2278
|
+
this.#searchDebounce = undefined;
|
|
2279
|
+
this.#applyFilterNow(this.#currentSearchQuery());
|
|
2280
|
+
}
|
|
2281
|
+
#currentSearchQuery() {
|
|
2282
|
+
if (this.isSheetSearchEnabled()) {
|
|
2283
|
+
return (this.sheetSearchText() || this.#sheetSearchInputValue()).trim();
|
|
2284
|
+
}
|
|
2285
|
+
return this.searchText().trim();
|
|
2286
|
+
}
|
|
2287
|
+
#isTypedFilterQuery() {
|
|
2288
|
+
const query = this.#currentSearchQuery();
|
|
2289
|
+
if (!query) {
|
|
2290
|
+
return false;
|
|
2291
|
+
}
|
|
2292
|
+
if (!this.isSheetSearchEnabled() && !this.isMultiple()) {
|
|
2293
|
+
return query.toLowerCase() !== this.displayText().trim().toLowerCase();
|
|
2294
|
+
}
|
|
2295
|
+
return true;
|
|
2296
|
+
}
|
|
2297
|
+
#hasNoSearchMatches() {
|
|
2298
|
+
return this.#getSearchMatchCount() === 0;
|
|
2299
|
+
}
|
|
2300
|
+
#getSearchMatchCount() {
|
|
2301
|
+
const list = this.listView();
|
|
2302
|
+
if (list) {
|
|
2303
|
+
return list.matchCount();
|
|
2304
|
+
}
|
|
2305
|
+
const source = this.resolvedDataSource();
|
|
2306
|
+
if (source.isLoading) {
|
|
2307
|
+
return -1;
|
|
2308
|
+
}
|
|
2309
|
+
return source.totalCount;
|
|
2310
|
+
}
|
|
2311
|
+
/** Blocks typing when the trigger is not editable (keeps Tab / keyboard open working). */
|
|
2312
|
+
onBeforeInput(event) {
|
|
2313
|
+
if (!this.isEditableTrigger() || this.readonly()) {
|
|
2314
|
+
event.preventDefault();
|
|
2315
|
+
}
|
|
2316
|
+
}
|
|
2317
|
+
/**
|
|
2318
|
+
* Returns focus to the search field when list navigation requests it.
|
|
2319
|
+
*/
|
|
2320
|
+
onListNavigateOut(_reason) {
|
|
2321
|
+
if (this.isSheetSearchEnabled()) {
|
|
2322
|
+
this.sheetSearchRef()?.focus();
|
|
2323
|
+
return;
|
|
2324
|
+
}
|
|
2325
|
+
this.triggerSearchInput()?.nativeElement.focus();
|
|
2326
|
+
}
|
|
2327
|
+
focusListFirst() {
|
|
2328
|
+
const tryFocus = (attempt = 0) => {
|
|
2329
|
+
const list = this.listView();
|
|
2330
|
+
if (list) {
|
|
2331
|
+
list.focusFirst();
|
|
2332
|
+
return;
|
|
2333
|
+
}
|
|
2334
|
+
if (attempt < 5) {
|
|
2335
|
+
setTimeout(() => tryFocus(attempt + 1), 16);
|
|
2336
|
+
}
|
|
2337
|
+
};
|
|
2338
|
+
tryFocus();
|
|
2339
|
+
}
|
|
2340
|
+
/**
|
|
2341
|
+
* Keeps the expanded state in sync when the popover closes (e.g. click outside),
|
|
2342
|
+
* and clears any applied search filter.
|
|
2343
|
+
*/
|
|
2344
|
+
onPopoverClosed() {
|
|
2345
|
+
this.expanded.set(false);
|
|
2346
|
+
this.searchText.set(this.isMultiple() ? '' : this.displayText());
|
|
2347
|
+
this.sheetSearchText.set('');
|
|
2348
|
+
this.#treeFilterQuery.set('');
|
|
2349
|
+
this.#treeFilterEpoch.update((value) => value + 1);
|
|
2350
|
+
if (this.#filterApplied) {
|
|
2351
|
+
this.#filterApplied = false;
|
|
2352
|
+
if (!this.#isTreeOnlySearchMode()) {
|
|
2353
|
+
const source = this.resolvedDataSource();
|
|
2354
|
+
source.clearFilter();
|
|
2355
|
+
source.refresh();
|
|
2356
|
+
}
|
|
2357
|
+
}
|
|
2358
|
+
}
|
|
2359
|
+
/**
|
|
2360
|
+
* Closes the popup.
|
|
2361
|
+
*/
|
|
2362
|
+
close() {
|
|
2363
|
+
this.expanded.set(false);
|
|
2364
|
+
}
|
|
2365
|
+
/**
|
|
2366
|
+
* Closes the popup (alias for {@link close}, required by `AXClosableComponent`).
|
|
2367
|
+
*/
|
|
2368
|
+
closeAll() {
|
|
2369
|
+
this.close();
|
|
2370
|
+
}
|
|
2371
|
+
/**
|
|
2372
|
+
* Opens the popup.
|
|
2373
|
+
*/
|
|
2374
|
+
open() {
|
|
2375
|
+
if (this.disabled() || this.readonly()) {
|
|
2376
|
+
return;
|
|
2377
|
+
}
|
|
2378
|
+
this.expanded.set(true);
|
|
2379
|
+
}
|
|
2380
|
+
/**
|
|
2381
|
+
* Handles typing in the editable trigger input.
|
|
2382
|
+
*/
|
|
2383
|
+
onTriggerSearchInput(text) {
|
|
2384
|
+
if (!this.isEditableTrigger()) {
|
|
2385
|
+
return;
|
|
2386
|
+
}
|
|
2387
|
+
this.searchText.set(text);
|
|
2388
|
+
this.expanded.set(true);
|
|
2389
|
+
this.#applyFilterDebounced(text);
|
|
2390
|
+
}
|
|
2391
|
+
/** Filters the datasource from the actionsheet search field (reads the input so delayed ngModel cannot block typing). */
|
|
2392
|
+
onSheetSearchInput() {
|
|
2393
|
+
const query = this.#sheetSearchInputValue();
|
|
2394
|
+
this.sheetSearchText.set(query);
|
|
2395
|
+
this.#applyFilterDebounced(query);
|
|
2396
|
+
}
|
|
2397
|
+
/**
|
|
2398
|
+
* Commits a single pick (drop-down-list, drop-down-tree, multi-column, multi-column-tree) and closes the popup.
|
|
2399
|
+
*/
|
|
2400
|
+
handleSinglePick(e) {
|
|
2401
|
+
this.#emitItemClick(e.item);
|
|
2402
|
+
this.#emitItemSelected(e.item);
|
|
2403
|
+
this.#itemsCache.set(e.value, e.item);
|
|
2404
|
+
this.selectedItems.set([e.item]);
|
|
2405
|
+
this.searchText.set(this.getItemText(e.item));
|
|
2406
|
+
this.#isUserInteraction = true;
|
|
2407
|
+
this.value.set(e.value);
|
|
2408
|
+
this.close();
|
|
2409
|
+
}
|
|
2410
|
+
/**
|
|
2411
|
+
* Toggles an item in the multi-select list; the popup stays open.
|
|
2412
|
+
* Clears the trigger search so the full list returns (select-box-like).
|
|
2413
|
+
*/
|
|
2414
|
+
handleMultiToggle(e) {
|
|
2415
|
+
this.#emitItemClick(e.item);
|
|
2416
|
+
this.#itemsCache.set(e.value, e.item);
|
|
2417
|
+
const current = this.selectedValues();
|
|
2418
|
+
const exists = current.some((v) => v == e.value);
|
|
2419
|
+
if (!exists) {
|
|
2420
|
+
this.#emitItemSelected(e.item);
|
|
2421
|
+
}
|
|
2422
|
+
const next = exists ? current.filter((v) => !(v == e.value)) : [...current, e.value];
|
|
2423
|
+
this.#isUserInteraction = true;
|
|
2424
|
+
this.value.set(next);
|
|
2425
|
+
if (this.isSheetSearchEnabled() && this.sheetSearchText()) {
|
|
2426
|
+
this.#clearSheetSearch();
|
|
2427
|
+
}
|
|
2428
|
+
else if (this.isEditableTrigger() && this.searchText()) {
|
|
2429
|
+
this.searchText.set('');
|
|
2430
|
+
this.#applyFilterDebounced('');
|
|
2431
|
+
}
|
|
2432
|
+
}
|
|
2433
|
+
/**
|
|
2434
|
+
* Applies the multi-select-tree selection to the value; the popup stays open.
|
|
2435
|
+
*/
|
|
2436
|
+
handleTreeSelectionChange(e) {
|
|
2437
|
+
const prev = new Set(this.selectedValues().map((v) => String(v)));
|
|
2438
|
+
const newlySelected = e.nodes.filter((node) => !prev.has(String(node[this.valueField()])));
|
|
2439
|
+
if (newlySelected.length > 0) {
|
|
2440
|
+
this.#emitItemSelected(newlySelected[0]);
|
|
2441
|
+
}
|
|
2442
|
+
for (const node of e.nodes) {
|
|
2443
|
+
this.#itemsCache.set(String(node[this.valueField()]), node);
|
|
2444
|
+
}
|
|
2445
|
+
this.#isUserInteraction = true;
|
|
2446
|
+
this.value.set([...e.ids]);
|
|
2447
|
+
if (this.isSheetSearchEnabled() && this.sheetSearchText()) {
|
|
2448
|
+
this.#clearSheetSearch();
|
|
2449
|
+
}
|
|
2450
|
+
else if (this.isEditableTrigger() && this.searchText()) {
|
|
2451
|
+
this.searchText.set('');
|
|
2452
|
+
this.#applyFilterDebounced('');
|
|
2453
|
+
}
|
|
2454
|
+
}
|
|
2455
|
+
/** Forwards native focus from the trigger input. */
|
|
2456
|
+
emitOnFocus(e) {
|
|
2457
|
+
this.onFocus.emit({
|
|
2458
|
+
component: this,
|
|
2459
|
+
htmlElement: this.nativeElement,
|
|
2460
|
+
nativeEvent: e,
|
|
2461
|
+
});
|
|
2462
|
+
}
|
|
2463
|
+
/** Forwards native blur from the trigger input. */
|
|
2464
|
+
emitOnBlur(e) {
|
|
2465
|
+
this.onBlur.emit({
|
|
2466
|
+
component: this,
|
|
2467
|
+
htmlElement: this.nativeElement,
|
|
2468
|
+
nativeEvent: e,
|
|
2469
|
+
});
|
|
2470
|
+
this.#scheduleCloseOnTriggerBlur(e);
|
|
2471
|
+
}
|
|
2472
|
+
/**
|
|
2473
|
+
* Closes the popup when the trigger input loses focus, unless focus moved into the
|
|
2474
|
+
* popover panel or another part of the trigger (e.g. sheet search or list navigation).
|
|
2475
|
+
*/
|
|
2476
|
+
#scheduleCloseOnTriggerBlur(e) {
|
|
2477
|
+
if (!this.expanded()) {
|
|
2478
|
+
return;
|
|
2479
|
+
}
|
|
2480
|
+
const related = e.relatedTarget;
|
|
2481
|
+
if (related instanceof Node && this.#isFocusWithinPopupOrTrigger(related)) {
|
|
2482
|
+
return;
|
|
2483
|
+
}
|
|
2484
|
+
queueMicrotask(() => {
|
|
2485
|
+
if (!this.expanded()) {
|
|
2486
|
+
return;
|
|
2487
|
+
}
|
|
2488
|
+
const active = this.#document.activeElement;
|
|
2489
|
+
if (active instanceof Node && this.#isFocusWithinPopupOrTrigger(active)) {
|
|
2490
|
+
return;
|
|
2491
|
+
}
|
|
2492
|
+
this.close();
|
|
2493
|
+
});
|
|
2494
|
+
}
|
|
2495
|
+
#isFocusWithinPopupOrTrigger(node) {
|
|
2496
|
+
const popup = this.popupRef()?.nativeElement;
|
|
2497
|
+
if (popup?.contains(node)) {
|
|
2498
|
+
return true;
|
|
2499
|
+
}
|
|
2500
|
+
const origin = this.originRef()?.nativeElement;
|
|
2501
|
+
return Boolean(origin?.contains(node));
|
|
2502
|
+
}
|
|
2503
|
+
#emitItemClick(item) {
|
|
2504
|
+
this.onItemClick.emit({
|
|
2505
|
+
component: this,
|
|
2506
|
+
item,
|
|
2507
|
+
htmlElement: this.nativeElement,
|
|
2508
|
+
isUserInteraction: true,
|
|
2509
|
+
});
|
|
2510
|
+
}
|
|
2511
|
+
#emitItemSelected(item) {
|
|
2512
|
+
this.onItemSelected.emit({
|
|
2513
|
+
component: this,
|
|
2514
|
+
item,
|
|
2515
|
+
htmlElement: this.nativeElement,
|
|
2516
|
+
isUserInteraction: true,
|
|
2517
|
+
});
|
|
2518
|
+
}
|
|
2519
|
+
/**
|
|
2520
|
+
* Removes a single chip from the multi selection.
|
|
2521
|
+
*/
|
|
2522
|
+
removeChip(event, item) {
|
|
2523
|
+
event.stopPropagation();
|
|
2524
|
+
if (this.disabled() || this.readonly()) {
|
|
2525
|
+
return;
|
|
2526
|
+
}
|
|
2527
|
+
const value = item?.[this.valueField()];
|
|
2528
|
+
this.#isUserInteraction = true;
|
|
2529
|
+
this.value.set(this.selectedValues().filter((v) => !(v == value)));
|
|
2530
|
+
}
|
|
2531
|
+
/**
|
|
2532
|
+
* Seeds the item cache with known items so matching `value` keys resolve without `byKey`.
|
|
2533
|
+
* Useful after an async parent-entity load when `valueItems` is not bound.
|
|
2534
|
+
*
|
|
2535
|
+
* @param items - Full items that include `valueField` (and ideally `textField`) properties.
|
|
2536
|
+
*/
|
|
2537
|
+
seedItems(items) {
|
|
2538
|
+
this.#seedItemsCache(items);
|
|
2539
|
+
void this.#resolveSelectedItems(this.selectedValues());
|
|
2540
|
+
}
|
|
2541
|
+
/**
|
|
2542
|
+
* Clears the whole selection.
|
|
2543
|
+
* Sets `null` in single modes and `[]` in multi modes. Used by projected `ax-clear-button`.
|
|
2544
|
+
*
|
|
2545
|
+
* @param isUserInteraction - Whether the clear was triggered by the user.
|
|
2546
|
+
*/
|
|
2547
|
+
reset(isUserInteraction = false) {
|
|
2548
|
+
if (this.disabled() || this.readonly()) {
|
|
2549
|
+
return;
|
|
2550
|
+
}
|
|
2551
|
+
const next = this.isMultiple() ? [] : null;
|
|
2552
|
+
const current = this.value();
|
|
2553
|
+
if (this.isMultiple()) {
|
|
2554
|
+
if (Array.isArray(current) && current.length === 0) {
|
|
2555
|
+
return;
|
|
2556
|
+
}
|
|
2557
|
+
}
|
|
2558
|
+
else if (current == null) {
|
|
2559
|
+
return;
|
|
2560
|
+
}
|
|
2561
|
+
this.#isUserInteraction = isUserInteraction;
|
|
2562
|
+
this.value.set(next);
|
|
2563
|
+
if (this.isSheetSearchEnabled() && this.sheetSearchText()) {
|
|
2564
|
+
this.#clearSheetSearch();
|
|
2565
|
+
}
|
|
2566
|
+
else if (this.isEditableTrigger() && this.searchText()) {
|
|
2567
|
+
this.searchText.set('');
|
|
2568
|
+
this.#applyFilterDebounced('');
|
|
2569
|
+
}
|
|
2570
|
+
}
|
|
2571
|
+
#clearSheetSearch() {
|
|
2572
|
+
this.sheetSearchText.set('');
|
|
2573
|
+
this.sheetSearchRef()?.commitValue('', false);
|
|
2574
|
+
this.#applyFilterDebounced('');
|
|
2575
|
+
}
|
|
2576
|
+
#sheetSearchInputValue() {
|
|
2577
|
+
return this.sheetSearchRef()?.getHostElement()?.querySelector('input')?.value ?? '';
|
|
2578
|
+
}
|
|
2579
|
+
#tryFocusSheetSearch() {
|
|
2580
|
+
if (!this.isSheetSearchEnabled() || this.#sheetSearchFocused) {
|
|
2581
|
+
return;
|
|
2582
|
+
}
|
|
2583
|
+
const search = this.sheetSearchRef();
|
|
2584
|
+
if (!search) {
|
|
2585
|
+
return;
|
|
2586
|
+
}
|
|
2587
|
+
this.#sheetSearchFocused = true;
|
|
2588
|
+
search.focus();
|
|
2589
|
+
}
|
|
2590
|
+
#focusPopupSearchOrList() {
|
|
2591
|
+
if (this.isSheetSearchEnabled()) {
|
|
2592
|
+
this.#tryFocusSheetSearch();
|
|
2593
|
+
return;
|
|
2594
|
+
}
|
|
2595
|
+
this.focusListFirst();
|
|
2596
|
+
}
|
|
2597
|
+
#loadCachedTreeNodes(source, nodeId) {
|
|
2598
|
+
let byParent = this.#treeChildrenCache.get(source);
|
|
2599
|
+
if (!byParent) {
|
|
2600
|
+
byParent = new Map();
|
|
2601
|
+
this.#treeChildrenCache.set(source, byParent);
|
|
2602
|
+
}
|
|
2603
|
+
const key = nodeId ?? '';
|
|
2604
|
+
const cached = byParent.get(key);
|
|
2605
|
+
if (cached) {
|
|
2606
|
+
return cached;
|
|
2607
|
+
}
|
|
2608
|
+
const request = Promise.resolve(source(nodeId)).then((nodes) => nodes ?? [], (error) => {
|
|
2609
|
+
byParent.delete(key);
|
|
2610
|
+
throw error;
|
|
2611
|
+
});
|
|
2612
|
+
byParent.set(key, request);
|
|
2613
|
+
return request;
|
|
2614
|
+
}
|
|
2615
|
+
#nodeMayHaveChildren(node) {
|
|
2616
|
+
const raw = node['children'];
|
|
2617
|
+
if (Array.isArray(raw) && raw.length > 0) {
|
|
2618
|
+
return true;
|
|
2619
|
+
}
|
|
2620
|
+
const count = node['childrenCount'];
|
|
2621
|
+
if (typeof count === 'number' && count > 0) {
|
|
2622
|
+
return true;
|
|
2623
|
+
}
|
|
2624
|
+
return node['hasChild'] === true || node['hasChildren'] === true;
|
|
2625
|
+
}
|
|
2626
|
+
/**
|
|
2627
|
+
* Builds a nested tree for search by loading lazy children (using the existing cache)
|
|
2628
|
+
* so a query can match sub-items that have not been expanded yet.
|
|
2629
|
+
*/
|
|
2630
|
+
async #hydrateTreeChildrenForSearch(source, nodes, visited = new Set()) {
|
|
2631
|
+
const valueField = this.valueField();
|
|
2632
|
+
return Promise.all(nodes.map(async (node) => {
|
|
2633
|
+
const raw = node['children'];
|
|
2634
|
+
const nested = Array.isArray(raw) && raw.length > 0 ? raw : undefined;
|
|
2635
|
+
if (nested) {
|
|
2636
|
+
const children = await this.#hydrateTreeChildrenForSearch(source, nested, visited);
|
|
2637
|
+
return { ...node, children };
|
|
2638
|
+
}
|
|
2639
|
+
const id = String(node[valueField] ?? '');
|
|
2640
|
+
if (!id || !this.#nodeMayHaveChildren(node) || visited.has(id)) {
|
|
2641
|
+
return node;
|
|
2642
|
+
}
|
|
2643
|
+
visited.add(id);
|
|
2644
|
+
const loaded = await this.#loadCachedTreeNodes(source, id);
|
|
2645
|
+
const children = await this.#hydrateTreeChildrenForSearch(source, loaded, visited);
|
|
2646
|
+
return { ...node, children };
|
|
2647
|
+
}));
|
|
2648
|
+
}
|
|
2649
|
+
async #loadFilteredCachedTreeNodes(source, nodeId, query) {
|
|
2650
|
+
const nodes = await this.#loadCachedTreeNodes(source, nodeId);
|
|
2651
|
+
const hydrated = await this.#hydrateTreeChildrenForSearch(source, nodes);
|
|
2652
|
+
return filterTreeNodes(hydrated, this.textField(), query);
|
|
2653
|
+
}
|
|
2654
|
+
#applyFilterNow(text) {
|
|
2655
|
+
const query = text?.trim() ?? '';
|
|
2656
|
+
if (this.#isTreeOnlySearchMode()) {
|
|
2657
|
+
this.#treeFilterQuery.set(query);
|
|
2658
|
+
this.#treeFilterEpoch.update((value) => value + 1);
|
|
2659
|
+
this.#filterApplied = query.length > 0;
|
|
2660
|
+
return;
|
|
2661
|
+
}
|
|
2662
|
+
const source = this.resolvedDataSource();
|
|
2663
|
+
if (query) {
|
|
2664
|
+
source.filter({ field: this.textField(), value: query, operator: { type: 'contains' } });
|
|
2665
|
+
this.#filterApplied = true;
|
|
2666
|
+
}
|
|
2667
|
+
else {
|
|
2668
|
+
source.clearFilter();
|
|
2669
|
+
}
|
|
2670
|
+
source.refresh();
|
|
2671
|
+
}
|
|
2672
|
+
#applyFilterDebounced(text) {
|
|
2673
|
+
if (this.#searchDebounce) {
|
|
2674
|
+
clearTimeout(this.#searchDebounce);
|
|
2675
|
+
this.#searchDebounce = undefined;
|
|
2676
|
+
}
|
|
2677
|
+
const query = text?.trim() ?? '';
|
|
2678
|
+
// Restore the full tree immediately when the query is cleared.
|
|
2679
|
+
if (!query) {
|
|
2680
|
+
this.#applyFilterNow('');
|
|
2681
|
+
return;
|
|
2682
|
+
}
|
|
2683
|
+
this.#searchDebounce = setTimeout(() => {
|
|
2684
|
+
this.#searchDebounce = undefined;
|
|
2685
|
+
this.#applyFilterNow(text);
|
|
2686
|
+
}, 300);
|
|
2687
|
+
}
|
|
2688
|
+
async #resolveSelectedItems(values) {
|
|
2689
|
+
const revision = ++this.#resolveRevision;
|
|
2690
|
+
const resolved = await Promise.all(values.map((value) => Promise.resolve(this.#resolveItem(value))));
|
|
2691
|
+
if (revision !== this.#resolveRevision) {
|
|
2692
|
+
return;
|
|
2693
|
+
}
|
|
2694
|
+
const items = resolved.filter((item) => item != null);
|
|
2695
|
+
this.selectedItems.set(items);
|
|
2696
|
+
if (this.#selectionInitialized) {
|
|
2697
|
+
this.onSelectionChanged.emit({
|
|
2698
|
+
component: this,
|
|
2699
|
+
htmlElement: this.nativeElement,
|
|
2700
|
+
isUserInteraction: this.#isUserInteraction,
|
|
2701
|
+
items,
|
|
2702
|
+
value: this.value(),
|
|
2703
|
+
});
|
|
2704
|
+
}
|
|
2705
|
+
this.#selectionInitialized = true;
|
|
2706
|
+
}
|
|
2707
|
+
#seedItemsCache(items) {
|
|
2708
|
+
if (!items?.length) {
|
|
2709
|
+
return;
|
|
2710
|
+
}
|
|
2711
|
+
const field = this.valueField();
|
|
2712
|
+
for (const item of items) {
|
|
2713
|
+
const key = item?.[field];
|
|
2714
|
+
if (key == null) {
|
|
2715
|
+
continue;
|
|
2716
|
+
}
|
|
2717
|
+
this.#itemsCache.set(key, item);
|
|
2718
|
+
this.#itemsCache.set(String(key), item);
|
|
2719
|
+
}
|
|
2720
|
+
}
|
|
2721
|
+
#resolveItem(value) {
|
|
2722
|
+
const cached = this.#itemsCache.get(value) ?? this.#itemsCache.get(String(value));
|
|
2723
|
+
if (cached) {
|
|
2724
|
+
return cached;
|
|
2725
|
+
}
|
|
2726
|
+
if (this.isTreeMode()) {
|
|
2727
|
+
const nodes = this.treeDataSource();
|
|
2728
|
+
if (Array.isArray(nodes)) {
|
|
2729
|
+
const found = this.#findTreeNode(nodes, value);
|
|
2730
|
+
if (found) {
|
|
2731
|
+
this.#itemsCache.set(value, found);
|
|
2732
|
+
return found;
|
|
2733
|
+
}
|
|
2734
|
+
}
|
|
2735
|
+
return this.#fallbackItem(value);
|
|
2736
|
+
}
|
|
2737
|
+
const source = this.resolvedDataSource();
|
|
2738
|
+
const result = source.find(value);
|
|
2739
|
+
if (result == null) {
|
|
2740
|
+
return this.#fallbackItem(value);
|
|
2741
|
+
}
|
|
2742
|
+
if (result instanceof Promise) {
|
|
2743
|
+
return result.then((item) => {
|
|
2744
|
+
if (item) {
|
|
2745
|
+
this.#itemsCache.set(value, item);
|
|
2746
|
+
return item;
|
|
2747
|
+
}
|
|
2748
|
+
return this.#fallbackItem(value);
|
|
2749
|
+
});
|
|
2750
|
+
}
|
|
2751
|
+
this.#itemsCache.set(value, result);
|
|
2752
|
+
return result;
|
|
2753
|
+
}
|
|
2754
|
+
#fallbackItem(value) {
|
|
2755
|
+
return { [this.valueField()]: value, [this.textField()]: String(value) };
|
|
2756
|
+
}
|
|
2757
|
+
#findTreeNode(nodes, value) {
|
|
2758
|
+
for (const node of nodes) {
|
|
2759
|
+
if (String(node[this.valueField()]) === String(value)) {
|
|
2760
|
+
return node;
|
|
2761
|
+
}
|
|
2762
|
+
const children = node['children'];
|
|
2763
|
+
if (Array.isArray(children)) {
|
|
2764
|
+
const found = this.#findTreeNode(children, value);
|
|
2765
|
+
if (found) {
|
|
2766
|
+
return found;
|
|
2767
|
+
}
|
|
2768
|
+
}
|
|
2769
|
+
}
|
|
2770
|
+
return null;
|
|
2771
|
+
}
|
|
2772
|
+
#valuesEqual(a, b) {
|
|
2773
|
+
if (a === b) {
|
|
2774
|
+
return true;
|
|
2775
|
+
}
|
|
2776
|
+
if (Array.isArray(a) && Array.isArray(b)) {
|
|
2777
|
+
return a.length === b.length && a.every((item, index) => item == b[index]);
|
|
2778
|
+
}
|
|
2779
|
+
return false;
|
|
2780
|
+
}
|
|
2781
|
+
/** Emits onValueChanged when the value actually changes (skips the initial value). */
|
|
2782
|
+
#emitValueChanged(value) {
|
|
2783
|
+
const previous = this.#lastValue;
|
|
2784
|
+
this.#lastValue = value;
|
|
2785
|
+
if (previous === undefined || this.#valuesEqual(previous, value)) {
|
|
2786
|
+
return;
|
|
2787
|
+
}
|
|
2788
|
+
this.onValueChanged.emit({
|
|
2789
|
+
component: this,
|
|
2790
|
+
htmlElement: this.nativeElement,
|
|
2791
|
+
name: 'value',
|
|
2792
|
+
value,
|
|
2793
|
+
oldValue: previous,
|
|
2794
|
+
isUserInteraction: this.#isUserInteraction,
|
|
2795
|
+
});
|
|
2796
|
+
this.#isUserInteraction = false;
|
|
2797
|
+
}
|
|
2798
|
+
/** Emits onOpened/onClosed when the expanded state actually changes (skips the initial state). */
|
|
2799
|
+
#emitOpenedOrClosed(expanded) {
|
|
2800
|
+
const previous = this.#lastExpanded;
|
|
2801
|
+
this.#lastExpanded = expanded;
|
|
2802
|
+
if (previous === undefined || previous === expanded) {
|
|
2803
|
+
return;
|
|
2804
|
+
}
|
|
2805
|
+
const event = {
|
|
2806
|
+
component: this,
|
|
2807
|
+
htmlElement: this.nativeElement,
|
|
2808
|
+
isUserInteraction: true,
|
|
2809
|
+
};
|
|
2810
|
+
expanded ? this.onOpened.emit(event) : this.onClosed.emit(event);
|
|
2811
|
+
}
|
|
2812
|
+
static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "22.0.8", ngImport: i0, type: AXLookupComponent, deps: [], target: i0.ɵɵFactoryTarget.Component }); }
|
|
2813
|
+
static { this.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "22.0.8", type: AXLookupComponent, isStandalone: true, selector: "ax-lookup", inputs: { name: { classPropertyName: "name", publicName: "name", isSignal: true, isRequired: false, transformFunction: null }, mode: { classPropertyName: "mode", publicName: "mode", isSignal: true, isRequired: false, transformFunction: null }, dataSource: { classPropertyName: "dataSource", publicName: "dataSource", isSignal: true, isRequired: false, transformFunction: null }, treeDataSource: { classPropertyName: "treeDataSource", publicName: "treeDataSource", isSignal: true, isRequired: false, transformFunction: null }, valueField: { classPropertyName: "valueField", publicName: "valueField", isSignal: true, isRequired: false, transformFunction: null }, textField: { classPropertyName: "textField", publicName: "textField", isSignal: true, isRequired: false, transformFunction: null }, disabledField: { classPropertyName: "disabledField", publicName: "disabledField", isSignal: true, isRequired: false, transformFunction: null }, columns: { classPropertyName: "columns", publicName: "columns", isSignal: true, isRequired: false, transformFunction: null }, treeParentField: { classPropertyName: "treeParentField", publicName: "treeParentField", isSignal: true, isRequired: false, transformFunction: null }, hasChildrenField: { classPropertyName: "hasChildrenField", publicName: "hasChildrenField", isSignal: true, isRequired: false, transformFunction: null }, searchable: { classPropertyName: "searchable", publicName: "searchable", isSignal: true, isRequired: false, transformFunction: null }, adaptivityEnabled: { classPropertyName: "adaptivityEnabled", publicName: "adaptivityEnabled", isSignal: true, isRequired: false, transformFunction: null }, caption: { classPropertyName: "caption", publicName: "caption", isSignal: true, isRequired: false, transformFunction: null }, alternate: { classPropertyName: "alternate", publicName: "alternate", isSignal: true, isRequired: false, transformFunction: null }, searchPlaceholder: { classPropertyName: "searchPlaceholder", publicName: "searchPlaceholder", isSignal: true, isRequired: false, transformFunction: null }, placeholder: { classPropertyName: "placeholder", publicName: "placeholder", isSignal: true, isRequired: false, transformFunction: null }, disabled: { classPropertyName: "disabled", publicName: "disabled", isSignal: true, isRequired: false, transformFunction: null }, readonly: { classPropertyName: "readonly", publicName: "readonly", isSignal: true, isRequired: false, transformFunction: null }, look: { classPropertyName: "look", publicName: "look", isSignal: true, isRequired: false, transformFunction: null }, itemHeight: { classPropertyName: "itemHeight", publicName: "itemHeight", isSignal: true, isRequired: false, transformFunction: null }, maxVisibleItems: { classPropertyName: "maxVisibleItems", publicName: "maxVisibleItems", isSignal: true, isRequired: false, transformFunction: null }, treeSelectionBehavior: { classPropertyName: "treeSelectionBehavior", publicName: "treeSelectionBehavior", isSignal: true, isRequired: false, transformFunction: null }, itemTemplate: { classPropertyName: "itemTemplate", publicName: "itemTemplate", isSignal: true, isRequired: false, transformFunction: null }, selectedTemplate: { classPropertyName: "selectedTemplate", publicName: "selectedTemplate", isSignal: true, isRequired: false, transformFunction: null }, emptyTemplate: { classPropertyName: "emptyTemplate", publicName: "emptyTemplate", isSignal: true, isRequired: false, transformFunction: null }, loadingTemplate: { classPropertyName: "loadingTemplate", publicName: "loadingTemplate", isSignal: true, isRequired: false, transformFunction: null }, value: { classPropertyName: "value", publicName: "value", isSignal: true, isRequired: false, transformFunction: null }, valueItems: { classPropertyName: "valueItems", publicName: "valueItems", isSignal: true, isRequired: false, transformFunction: null } }, outputs: { look: "lookChange", value: "valueChange", onValueChanged: "onValueChanged", onSelectionChanged: "onSelectionChanged", onFocus: "onFocus", onBlur: "onBlur", onItemClick: "onItemClick", onItemSelected: "onItemSelected", onOpened: "onOpened", onClosed: "onClosed" }, providers: [
|
|
2814
|
+
{ provide: AXComponent, useExisting: AXLookupComponent },
|
|
2815
|
+
{ provide: AXClearableComponent, useExisting: AXLookupComponent },
|
|
2816
|
+
{ provide: AXClosableComponent, useExisting: AXLookupComponent },
|
|
2817
|
+
{ provide: AXValuableComponent, useExisting: AXLookupComponent },
|
|
2818
|
+
], viewQueries: [{ propertyName: "popoverRef", first: true, predicate: AXPopoverComponent, descendants: true, isSignal: true }, { propertyName: "originRef", first: true, predicate: ["origin"], descendants: true, isSignal: true }, { propertyName: "popupRef", first: true, predicate: ["popup"], descendants: true, isSignal: true }, { propertyName: "triggerSearchInput", first: true, predicate: ["triggerSearchInput"], descendants: true, isSignal: true }, { propertyName: "listView", first: true, predicate: AXLookupListViewBase, descendants: true, isSignal: true }, { propertyName: "dropDownTreeView", first: true, predicate: AXLookupDropDownTreeComponent, descendants: true, isSignal: true }, { propertyName: "multiSelectTreeView", first: true, predicate: AXLookupMultiSelectTreeComponent, descendants: true, isSignal: true }, { propertyName: "sheetSearchRef", first: true, predicate: ["sheetSearch"], descendants: true, isSignal: true }], usesInheritance: true, ngImport: i0, template: "<div\n #origin\n class=\"ax-editor-container ax-{{ look() }} ax-default\"\n [class.ax-lookup-trigger]=\"!isEditableTrigger()\"\n [class.ax-lookup-trigger-multiple]=\"isMultiple()\"\n [class.ax-state-disabled]=\"disabled()\"\n [class.ax-state-readonly]=\"readonly()\"\n (click)=\"onTriggerClick()\"\n>\n <ng-content select=\"ax-prefix\"></ng-content>\n\n @if (isMultiple()) {\n <div class=\"ax-lookup-chips\">\n @for (item of selectedItems(); track trackSelectedKey(item)) {\n <ax-chips class=\"ax-sm\" look=\"fill\" [text]=\"selectedTemplate() ? '' : getItemText(item)\">\n @if (selectedTemplate()) {\n <ax-prefix>\n <ng-container\n [ngTemplateOutlet]=\"selectedTemplate()!\"\n [ngTemplateOutletContext]=\"{ $implicit: item }\"\n />\n </ax-prefix>\n }\n @if (!disabled() && !readonly()) {\n <ax-suffix>\n <button type=\"button\" tabindex=\"-1\" (click)=\"removeChip($event, item)\">\n <span class=\"ax-icon ax-icon-close\"></span>\n </button>\n </ax-suffix>\n }\n </ax-chips>\n }\n <input\n #triggerSearchInput\n type=\"text\"\n class=\"ax-input ax-lookup-trigger-search\"\n [class.ax-lookup-select-input]=\"!isEditableTrigger()\"\n [placeholder]=\"triggerSearchPlaceholder()\"\n [disabled]=\"disabled()\"\n [readonly]=\"readonly() || !isEditableTrigger()\"\n [attr.inputmode]=\"isEditableTrigger() ? null : 'none'\"\n [value]=\"searchText()\"\n (input)=\"onTriggerSearchInput($any($event.target).value)\"\n (keydown)=\"onTriggerKeydown($event)\"\n (beforeinput)=\"onBeforeInput($event)\"\n (focus)=\"emitOnFocus($event)\"\n (blur)=\"emitOnBlur($event)\"\n />\n </div>\n } @else {\n <div class=\"ax-lookup-value\">\n @if (showSelectedTemplate()) {\n <div class=\"ax-lookup-selected-content\" aria-hidden=\"true\">\n <ng-container\n [ngTemplateOutlet]=\"selectedTemplate()!\"\n [ngTemplateOutletContext]=\"{ $implicit: selectedItems()[0] }\"\n />\n </div>\n }\n <input\n #triggerSearchInput\n type=\"text\"\n class=\"ax-input\"\n [class.ax-lookup-select-input]=\"!isEditableTrigger()\"\n [class.ax-lookup-input-overlay]=\"showSelectedTemplate()\"\n [placeholder]=\"placeholder()\"\n [disabled]=\"disabled()\"\n [readonly]=\"readonly() || !isEditableTrigger()\"\n [attr.inputmode]=\"isEditableTrigger() ? null : 'none'\"\n [value]=\"searchText()\"\n (input)=\"onTriggerSearchInput($any($event.target).value)\"\n (keydown)=\"onTriggerKeydown($event)\"\n (beforeinput)=\"onBeforeInput($event)\"\n (focus)=\"emitOnFocus($event)\"\n (blur)=\"emitOnBlur($event)\"\n />\n </div>\n }\n\n @if (selectedValues().length > 0 && !disabled() && !readonly()) {\n <ng-content select=\"ax-clear-button\"></ng-content>\n }\n\n <button\n type=\"button\"\n class=\"ax-general-button-icon\"\n tabindex=\"-1\"\n [disabled]=\"disabled() || readonly()\"\n >\n <span\n class=\"ax-icon\"\n [class.ax-icon-chevron-down]=\"!expanded()\"\n [class.ax-icon-chevron-up]=\"expanded()\"\n ></span>\n </button>\n <ng-content select=\"ax-suffix\"></ng-content>\n</div>\n\n<ax-popover\n [target]=\"origin\"\n [openOn]=\"'manual'\"\n [closeOn]=\"isActionsheetStyle() ? 'manual' : 'clickOut'\"\n [closeOnScroll]=\"!isActionsheetStyle()\"\n [placement]=\"'bottom-start'\"\n [width]=\"isActionsheetStyle() ? '100%' : origin.offsetWidth + 'px'\"\n [adaptivityEnabled]=\"isActionsheetStyle()\"\n [disabled]=\"disabled() || readonly()\"\n (onClosed)=\"onPopoverClosed()\"\n>\n <div\n #popup\n class=\"ax-lookup-popup\"\n [class.ax-is-actionsheet]=\"isActionsheetStyle()\"\n [class.ax-is-alternate]=\"alternate()\"\n (keydown.escape)=\"close()\"\n >\n @if (isActionsheetStyle()) {\n <ax-header class=\"ax-solid\">\n <ax-title>{{ caption() || placeholder() || ('@acorex:selectbox.popover.title' | translate | async) }}</ax-title>\n @if (isMultiple()) {\n <ax-button\n class=\"ax-sm\"\n color=\"primary\"\n look=\"solid\"\n text=\"@acorex:common.actions.apply\"\n (onClick)=\"close()\"\n ></ax-button>\n } @else {\n <ax-close-button></ax-close-button>\n }\n </ax-header>\n }\n @if (isSheetSearchEnabled()) {\n <div class=\"ax-lookup-sheet-search\">\n <ax-search-box\n #sheetSearch\n class=\"ax-sm\"\n look=\"fill\"\n [autoSearch]=\"false\"\n [delayTime]=\"0\"\n [placeholder]=\"searchPlaceholder()\"\n (onValueChanged)=\"onSheetSearchInput()\"\n (onKeyUp)=\"onSheetSearchInput()\"\n (onKeyDown)=\"onSheetSearchKeydown($event)\"\n >\n <ax-clear-button></ax-clear-button>\n </ax-search-box>\n </div>\n }\n <ng-content select=\"ax-header\"></ng-content>\n @if (expanded()) {\n @switch (mode()) {\n @case ('drop-down-list') {\n <ax-lookup-drop-down-list\n [dataSource]=\"resolvedDataSource()\"\n [valueField]=\"valueField()\"\n [textField]=\"textField()\"\n [disabledField]=\"disabledField()\"\n [selectedValues]=\"selectedValues()\"\n [itemHeight]=\"itemHeight()\"\n [maxVisibleItems]=\"maxVisibleItems()\"\n [itemTemplate]=\"itemTemplate()\"\n [emptyTemplate]=\"emptyTemplate()\"\n [loadingTemplate]=\"loadingTemplate()\"\n [alternate]=\"alternate()\"\n (itemClick)=\"handleSinglePick($event)\"\n (navigateOut)=\"onListNavigateOut($event)\"\n />\n }\n @case ('multi-select') {\n <ax-lookup-multi-select\n [dataSource]=\"resolvedDataSource()\"\n [valueField]=\"valueField()\"\n [textField]=\"textField()\"\n [disabledField]=\"disabledField()\"\n [selectedValues]=\"selectedValues()\"\n [itemHeight]=\"itemHeight()\"\n [maxVisibleItems]=\"maxVisibleItems()\"\n [itemTemplate]=\"itemTemplate()\"\n [emptyTemplate]=\"emptyTemplate()\"\n [loadingTemplate]=\"loadingTemplate()\"\n [alternate]=\"alternate()\"\n (itemClick)=\"handleMultiToggle($event)\"\n (navigateOut)=\"onListNavigateOut($event)\"\n />\n }\n @case ('drop-down-tree') {\n <ax-lookup-drop-down-tree\n [dataSource]=\"resolvedTreeDataSource()\"\n [valueField]=\"valueField()\"\n [textField]=\"textField()\"\n [disabledField]=\"disabledField()\"\n [selectedValues]=\"selectedValues()\"\n [nodeTemplate]=\"$any(itemTemplate())\"\n [emptyTemplate]=\"emptyTemplate()\"\n [filterKey]=\"treeFilterKey()\"\n [alternate]=\"alternate()\"\n (itemClick)=\"handleSinglePick($event)\"\n />\n }\n @case ('multi-select-tree') {\n <ax-lookup-multi-select-tree\n [dataSource]=\"resolvedTreeDataSource()\"\n [valueField]=\"valueField()\"\n [textField]=\"textField()\"\n [disabledField]=\"disabledField()\"\n [selectedValues]=\"selectedValues()\"\n [selectionBehavior]=\"treeSelectionBehavior()\"\n [nodeTemplate]=\"$any(itemTemplate())\"\n [emptyTemplate]=\"emptyTemplate()\"\n [filterKey]=\"treeFilterKey()\"\n [alternate]=\"alternate()\"\n (selectionChange)=\"handleTreeSelectionChange($event)\"\n />\n }\n @case ('multi-column') {\n <ax-lookup-multi-column\n [dataSource]=\"resolvedDataSource()\"\n [valueField]=\"valueField()\"\n [textField]=\"textField()\"\n [disabledField]=\"disabledField()\"\n [selectedValues]=\"selectedValues()\"\n [itemHeight]=\"itemHeight()\"\n [maxVisibleItems]=\"maxVisibleItems()\"\n [columns]=\"columns()\"\n [itemTemplate]=\"itemTemplate()\"\n [emptyTemplate]=\"emptyTemplate()\"\n [loadingTemplate]=\"loadingTemplate()\"\n [alternate]=\"alternate()\"\n (itemClick)=\"handleSinglePick($event)\"\n />\n }\n @case ('multi-column-tree') {\n <ax-lookup-multi-column-tree\n [dataSource]=\"resolvedDataSource()\"\n [valueField]=\"valueField()\"\n [textField]=\"textField()\"\n [disabledField]=\"disabledField()\"\n [parentField]=\"treeParentField()\"\n [hasChildrenField]=\"hasChildrenField()\"\n [selectedValues]=\"selectedValues()\"\n [itemHeight]=\"itemHeight()\"\n [maxVisibleItems]=\"maxVisibleItems()\"\n [columns]=\"columns()\"\n [itemTemplate]=\"itemTemplate()\"\n [emptyTemplate]=\"emptyTemplate()\"\n [loadingTemplate]=\"loadingTemplate()\"\n [alternate]=\"alternate()\"\n (itemClick)=\"handleSinglePick($event)\"\n />\n }\n }\n }\n <ng-content select=\"ax-footer\"></ng-content>\n </div>\n</ax-popover>\n<ng-content select=\"ax-validation-rule\"></ng-content>\n", styles: ["@layer properties;@layer components{ax-lookup{display:block;width:100%}ax-lookup .ax-editor-container{justify-content:flex-start;gap:calc(var(--spacing, .25rem) * 1)}ax-lookup .ax-lookup-trigger{cursor:pointer;-webkit-user-select:none;user-select:none}ax-lookup .ax-lookup-trigger-multiple{height:auto;min-height:calc(var(--spacing, .25rem) * 9);padding-block:calc(var(--spacing, .25rem) * 1)}ax-lookup .ax-lookup-value{position:relative;display:flex;min-width:calc(var(--spacing, .25rem) * 0);flex:1;align-items:center;overflow:hidden}ax-lookup .ax-lookup-select-input{cursor:pointer;caret-color:transparent;-webkit-user-select:none;user-select:none}ax-lookup .ax-lookup-selected-content{pointer-events:none;position:relative;z-index:0;display:flex;min-width:calc(var(--spacing, .25rem) * 0);flex:1;align-items:center;overflow:hidden}ax-lookup .ax-lookup-input-overlay{position:absolute;inset:calc(var(--spacing, .25rem) * 0);z-index:10;margin:calc(var(--spacing, .25rem) * 0)!important;height:100%;width:100%;border-style:var(--tw-border-style);border-width:0px;background-color:transparent;padding:calc(var(--spacing, .25rem) * 0)!important;color:transparent;caret-color:transparent}ax-lookup .ax-lookup-chips{display:flex;min-width:calc(var(--spacing, .25rem) * 0);flex:1;flex-wrap:wrap;align-items:center;gap:calc(var(--spacing, .25rem) * 1)}ax-lookup .ax-lookup-trigger-search{margin:calc(var(--spacing, .25rem) * 0)!important;height:calc(var(--spacing, .25rem) * 7.5);width:auto!important;min-width:calc(var(--spacing, .25rem) * 16);flex:1;flex-basis:calc(var(--spacing, .25rem) * 16)}ax-lookup .ax-lookup-placeholder{overflow:hidden;text-overflow:ellipsis;white-space:nowrap;font-size:var(--text-sm, .875rem);line-height:var(--tw-leading, var(--text-sm--line-height, calc(1.25 / .875)));color:rgba(var(--ax-sys-color-on-surface))}@supports (color: color-mix(in lab,red,red)){ax-lookup .ax-lookup-placeholder{color:color-mix(in oklab,rgba(var(--ax-sys-color-on-surface)) 50%,transparent)}}ax-lookup ax-chips ax-prefix,ax-lookup ax-chips ax-suffix{padding:calc(var(--spacing, .25rem) * 0)!important}ax-lookup ax-chips ax-suffix button{display:flex;cursor:pointer;align-items:center;border-style:var(--tw-border-style);border-width:0px;background-color:transparent;padding:calc(var(--spacing, .25rem) * 0)}.ax-lookup-popup{box-sizing:border-box;display:flex;width:100%;max-width:100%;min-width:calc(var(--spacing, .25rem) * 0);flex-direction:column;overflow:hidden;border-radius:var(--ax-sys-border-radius);border-style:var(--tw-border-style);border-width:1px;border-color:rgba(var(--ax-sys-color-border-surface));background-color:rgba(var(--ax-sys-color-lightest-surface));--tw-shadow: 0 10px 15px -3px var(--tw-shadow-color, rgb(0 0 0 / .1)), 0 4px 6px -4px var(--tw-shadow-color, rgb(0 0 0 / .1));box-shadow:var(--tw-inset-shadow),var(--tw-inset-ring-shadow),var(--tw-ring-offset-shadow),var(--tw-ring-shadow),var(--tw-shadow)}.ax-lookup-popup:where(.ax-dark,.ax-dark *):not(:where(.ax-light,.ax-light *)){background-color:rgba(var(--ax-sys-color-darkest-surface))}.ax-lookup-popup.ax-is-actionsheet{height:100dvh;max-height:100dvh;min-height:100dvh;border-bottom-right-radius:0;border-bottom-left-radius:0;--tw-shadow: 0 0 #0000;box-shadow:var(--tw-inset-shadow),var(--tw-inset-ring-shadow),var(--tw-ring-offset-shadow),var(--tw-ring-shadow),var(--tw-shadow)}.ax-lookup-popup.ax-is-actionsheet>ax-header.ax-solid{border-bottom-style:var(--tw-border-style);border-bottom-width:1px;border-color:rgba(var(--ax-sys-color-border-lightest-surface))}.ax-lookup-popup.ax-is-actionsheet>ax-header.ax-solid ax-title{min-width:calc(var(--spacing, .25rem) * 0);flex:1;overflow:hidden;text-overflow:ellipsis;white-space:nowrap;font-size:var(--text-base, 1rem);line-height:var(--tw-leading, var(--text-base--line-height, 1.5 ));--tw-leading: calc(var(--spacing, .25rem) * 6);line-height:calc(var(--spacing, .25rem) * 6);--tw-font-weight: var(--font-weight-medium, 500);font-weight:var(--font-weight-medium, 500)}.ax-lookup-popup.ax-is-actionsheet>ax-header.ax-solid ax-button{flex-shrink:0}.ax-lookup-popup.ax-is-actionsheet ax-lookup-drop-down-list,.ax-lookup-popup.ax-is-actionsheet ax-lookup-multi-select,.ax-lookup-popup.ax-is-actionsheet ax-lookup-drop-down-tree,.ax-lookup-popup.ax-is-actionsheet ax-lookup-multi-select-tree,.ax-lookup-popup.ax-is-actionsheet ax-lookup-multi-column,.ax-lookup-popup.ax-is-actionsheet ax-lookup-multi-column-tree{display:flex;min-height:calc(var(--spacing, .25rem) * 0);flex:1;flex-direction:column;height:auto!important}.ax-lookup-popup.ax-is-actionsheet .ax-lookup-viewport{min-height:calc(var(--spacing, .25rem) * 0);flex:1;height:auto!important;max-height:none!important}.ax-lookup-popup.ax-is-actionsheet .ax-lookup-tree{max-height:none;min-height:calc(var(--spacing, .25rem) * 0);flex:1;overflow:auto}.ax-lookup-popup.ax-is-actionsheet .ax-lookup-empty{display:flex;flex:1;align-items:center;justify-content:center}:is(.ax-lookup-popup.ax-is-actionsheet .ax-lookup-multi-column,.ax-lookup-popup.ax-is-actionsheet .ax-lookup-multi-column-tree) .ax-lookup-multi-column-table,:is(.ax-lookup-popup.ax-is-actionsheet .ax-lookup-multi-column,.ax-lookup-popup.ax-is-actionsheet .ax-lookup-multi-column-tree) ax-data-table{height:100%;min-height:calc(var(--spacing, .25rem) * 0)}.ax-lookup-popup .ax-lookup-sheet-search{flex-shrink:0;border-bottom-style:var(--tw-border-style);border-bottom-width:1px;border-color:rgba(var(--ax-sys-color-border-lightest-surface));padding-inline:calc(var(--spacing, .25rem) * 3);padding-block:calc(var(--spacing, .25rem) * 2)}.ax-lookup-popup>ax-header:not(.ax-solid),.ax-lookup-popup>ax-footer{flex-shrink:0;border-color:rgba(var(--ax-sys-color-border-lightest-surface))}.ax-lookup-popup>ax-header:not(.ax-solid){border-bottom-style:var(--tw-border-style);border-bottom-width:1px}.ax-lookup-popup>ax-footer{border-top-style:var(--tw-border-style);border-top-width:1px}.ax-lookup-viewport{width:100%;min-width:calc(var(--spacing, .25rem) * 0);overflow-x:hidden}.ax-lookup-empty{display:flex;min-height:calc(var(--spacing, .25rem) * 12);width:100%;align-items:center;justify-content:center;padding-inline:calc(var(--spacing, .25rem) * 3);padding-block:calc(var(--spacing, .25rem) * 3);text-align:center;font-size:var(--text-sm, .875rem);line-height:var(--tw-leading, var(--text-sm--line-height, calc(1.25 / .875)));color:rgba(var(--ax-sys-color-on-surface))}@supports (color: color-mix(in lab,red,red)){.ax-lookup-empty{color:color-mix(in oklab,rgba(var(--ax-sys-color-on-surface)) 60%,transparent)}}.ax-lookup-option-host{box-sizing:border-box;cursor:pointer;border-style:var(--tw-border-style);border-width:1px;border-color:transparent;--tw-outline-style: none;outline-style:none}.ax-lookup-option-host.ax-state-alternate{background-color:rgba(var(--ax-sys-color-light-surface))}.ax-lookup-option-host.ax-state-alternate:where(.ax-dark,.ax-dark *):not(:where(.ax-light,.ax-light *)){background-color:rgba(var(--ax-sys-color-surface))}.ax-lookup-option-host:hover,.ax-lookup-option-host.ax-state-active{background-color:rgba(var(--ax-sys-color-on-surface))}@supports (color: color-mix(in lab,red,red)){.ax-lookup-option-host:hover,.ax-lookup-option-host.ax-state-active{background-color:color-mix(in oklab,rgba(var(--ax-sys-color-on-surface)) 10%,transparent)}}.ax-lookup-option-host.ax-state-alternate:hover,.ax-lookup-option-host.ax-state-alternate.ax-state-active{background-color:rgba(var(--ax-sys-color-on-surface))}@supports (color: color-mix(in lab,red,red)){.ax-lookup-option-host.ax-state-alternate:hover,.ax-lookup-option-host.ax-state-alternate.ax-state-active{background-color:color-mix(in oklab,rgba(var(--ax-sys-color-on-surface)) 15%,transparent)}}.ax-lookup-option-host.ax-state-selected,.ax-lookup-option-host.ax-state-selected:hover,.ax-lookup-option-host.ax-state-selected.ax-state-active,.ax-lookup-option-host.ax-state-selected.ax-state-alternate,.ax-lookup-option-host.ax-state-selected.ax-state-alternate:hover,.ax-lookup-option-host.ax-state-selected.ax-state-alternate.ax-state-active{background-color:rgba(var(--ax-sys-color-primary-lightest-surface))}:is(.ax-lookup-option-host.ax-state-selected,.ax-lookup-option-host.ax-state-selected:hover,.ax-lookup-option-host.ax-state-selected.ax-state-active,.ax-lookup-option-host.ax-state-selected.ax-state-alternate,.ax-lookup-option-host.ax-state-selected.ax-state-alternate:hover,.ax-lookup-option-host.ax-state-selected.ax-state-alternate.ax-state-active):where(.ax-dark,.ax-dark *):not(:where(.ax-light,.ax-light *)){background-color:rgba(var(--ax-sys-color-primary-darkest-surface))}@supports (color: color-mix(in lab,red,red)){:is(.ax-lookup-option-host.ax-state-selected,.ax-lookup-option-host.ax-state-selected:hover,.ax-lookup-option-host.ax-state-selected.ax-state-active,.ax-lookup-option-host.ax-state-selected.ax-state-alternate,.ax-lookup-option-host.ax-state-selected.ax-state-alternate:hover,.ax-lookup-option-host.ax-state-selected.ax-state-alternate.ax-state-active):where(.ax-dark,.ax-dark *):not(:where(.ax-light,.ax-light *)){background-color:color-mix(in oklab,rgba(var(--ax-sys-color-primary-darkest-surface)) 25%,transparent)}}.ax-lookup-option-host.ax-state-selected.ax-state-active,.ax-lookup-option-host.ax-state-selected.ax-state-alternate.ax-state-active{background-color:rgba(var(--ax-sys-color-primary-lightest-surface))}@supports (color: color-mix(in lab,red,red)){.ax-lookup-option-host.ax-state-selected.ax-state-active,.ax-lookup-option-host.ax-state-selected.ax-state-alternate.ax-state-active{background-color:color-mix(in oklab,rgba(var(--ax-sys-color-primary-lightest-surface)) 80%,transparent)}}:is(.ax-lookup-option-host.ax-state-selected.ax-state-active,.ax-lookup-option-host.ax-state-selected.ax-state-alternate.ax-state-active):where(.ax-dark,.ax-dark *):not(:where(.ax-light,.ax-light *)){background-color:rgba(var(--ax-sys-color-primary-darkest-surface))}@supports (color: color-mix(in lab,red,red)){:is(.ax-lookup-option-host.ax-state-selected.ax-state-active,.ax-lookup-option-host.ax-state-selected.ax-state-alternate.ax-state-active):where(.ax-dark,.ax-dark *):not(:where(.ax-light,.ax-light *)){background-color:color-mix(in oklab,rgba(var(--ax-sys-color-primary-darkest-surface)) 40%,transparent)}}.ax-lookup-option-host.ax-lookup-option-multiple{display:flex;align-items:center;gap:calc(var(--spacing, .25rem) * 2)}.ax-lookup-option-host.ax-lookup-option-multiple:not(.ax-lookup-option){padding-inline:calc(var(--spacing, .25rem) * 3)}.ax-lookup-option-host .ax-lookup-checkbox{pointer-events:none;display:inline-flex;flex-shrink:0;align-items:center}.ax-lookup-option-host .ax-lookup-option-loading{width:100%;padding-inline:calc(var(--spacing, .25rem) * 3);font-size:var(--text-sm, .875rem);line-height:var(--tw-leading, var(--text-sm--line-height, calc(1.25 / .875)));color:rgba(var(--ax-sys-color-on-surface))}@supports (color: color-mix(in lab,red,red)){.ax-lookup-option-host .ax-lookup-option-loading{color:color-mix(in oklab,rgba(var(--ax-sys-color-on-surface)) 50%,transparent)}}.ax-lookup-option{display:flex;align-items:center;justify-content:space-between;gap:calc(var(--spacing, .25rem) * 2);padding-inline:calc(var(--spacing, .25rem) * 3);font-size:var(--text-sm, .875rem);line-height:var(--tw-leading, var(--text-sm--line-height, calc(1.25 / .875)));color:rgba(var(--ax-sys-color-on-surface))}.ax-lookup-option.ax-state-selected{color:rgba(var(--ax-sys-color-primary-surface))}.ax-lookup-option.ax-lookup-option-multiple{justify-content:flex-start}.ax-lookup-option .ax-lookup-option-text{min-width:calc(var(--spacing, .25rem) * 0);flex:1;overflow:hidden;text-overflow:ellipsis;white-space:nowrap}.ax-lookup-option .ax-lookup-option-check{margin-inline-start:auto;flex-shrink:0;color:rgba(var(--ax-sys-color-primary-surface))}ax-lookup-multi-column,ax-lookup-multi-column-tree,.ax-lookup-multi-column,.ax-lookup-multi-column-tree{display:block;min-height:calc(var(--spacing, .25rem) * 0);width:100%}:is(ax-lookup-multi-column,ax-lookup-multi-column-tree,.ax-lookup-multi-column,.ax-lookup-multi-column-tree) .ax-lookup-multi-column-table,:is(ax-lookup-multi-column,ax-lookup-multi-column-tree,.ax-lookup-multi-column,.ax-lookup-multi-column-tree) ax-data-table{height:100%;min-height:calc(var(--spacing, .25rem) * 0);border-style:var(--tw-border-style)!important;border-width:0px!important}:is(ax-lookup-multi-column,ax-lookup-multi-column-tree,.ax-lookup-multi-column,.ax-lookup-multi-column-tree) tr.ax-state-selected{background-color:rgba(var(--ax-sys-color-primary-surface))}@supports (color: color-mix(in lab,red,red)){:is(ax-lookup-multi-column,ax-lookup-multi-column-tree,.ax-lookup-multi-column,.ax-lookup-multi-column-tree) tr.ax-state-selected{background-color:color-mix(in oklab,rgba(var(--ax-sys-color-primary-surface)) 10%,transparent)}}:is(ax-lookup-multi-column,ax-lookup-multi-column-tree,.ax-lookup-multi-column,.ax-lookup-multi-column-tree) tr.ax-state-disabled{pointer-events:none;opacity:50%}.ax-lookup-tree{max-height:calc(var(--spacing, .25rem) * 80);overflow:auto;padding:calc(var(--spacing, .25rem) * 2)}.ax-lookup-tree .ax-tree-view-node{margin-block:0;border-radius:0}.ax-lookup-tree .ax-tree-view-node.ax-state-alternate{background-color:rgba(var(--ax-sys-color-light-surface))}.ax-lookup-tree .ax-tree-view-node.ax-state-alternate:where(.ax-dark,.ax-dark *):not(:where(.ax-light,.ax-light *)){background-color:rgba(var(--ax-sys-color-surface))}.ax-lookup-tree .ax-tree-view-node.ax-state-alternate:hover:not(.ax-dragging){background-color:rgba(var(--ax-sys-color-on-surface))}@supports (color: color-mix(in lab,red,red)){.ax-lookup-tree .ax-tree-view-node.ax-state-alternate:hover:not(.ax-dragging){background-color:color-mix(in oklab,rgba(var(--ax-sys-color-on-surface)) 15%,transparent)}}.ax-lookup-tree .ax-tree-view-node.ax-tree-view-node-selected,.ax-lookup-tree .ax-tree-view-node.ax-state-alternate.ax-tree-view-node-selected{background-color:rgba(var(--ax-sys-color-primary-lightest-surface))}:is(.ax-lookup-tree .ax-tree-view-node.ax-tree-view-node-selected,.ax-lookup-tree .ax-tree-view-node.ax-state-alternate.ax-tree-view-node-selected):where(.ax-dark,.ax-dark *):not(:where(.ax-light,.ax-light *)){background-color:rgba(var(--ax-sys-color-primary-darkest-surface))}@supports (color: color-mix(in lab,red,red)){:is(.ax-lookup-tree .ax-tree-view-node.ax-tree-view-node-selected,.ax-lookup-tree .ax-tree-view-node.ax-state-alternate.ax-tree-view-node-selected):where(.ax-dark,.ax-dark *):not(:where(.ax-light,.ax-light *)){background-color:color-mix(in oklab,rgba(var(--ax-sys-color-primary-darkest-surface)) 25%,transparent)}}.ax-lookup-tree .ax-tree-view-node.ax-tree-view-node-selected:hover:not(.ax-dragging),.ax-lookup-tree .ax-tree-view-node.ax-state-alternate.ax-tree-view-node-selected:hover:not(.ax-dragging){background-color:rgba(var(--ax-sys-color-primary-lightest-surface))}@supports (color: color-mix(in lab,red,red)){.ax-lookup-tree .ax-tree-view-node.ax-tree-view-node-selected:hover:not(.ax-dragging),.ax-lookup-tree .ax-tree-view-node.ax-state-alternate.ax-tree-view-node-selected:hover:not(.ax-dragging){background-color:color-mix(in oklab,rgba(var(--ax-sys-color-primary-lightest-surface)) 80%,transparent)}}:is(.ax-lookup-tree .ax-tree-view-node.ax-tree-view-node-selected:hover:not(.ax-dragging),.ax-lookup-tree .ax-tree-view-node.ax-state-alternate.ax-tree-view-node-selected:hover:not(.ax-dragging)):where(.ax-dark,.ax-dark *):not(:where(.ax-light,.ax-light *)){background-color:rgba(var(--ax-sys-color-primary-darkest-surface))}@supports (color: color-mix(in lab,red,red)){:is(.ax-lookup-tree .ax-tree-view-node.ax-tree-view-node-selected:hover:not(.ax-dragging),.ax-lookup-tree .ax-tree-view-node.ax-state-alternate.ax-tree-view-node-selected:hover:not(.ax-dragging)):where(.ax-dark,.ax-dark *):not(:where(.ax-light,.ax-light *)){background-color:color-mix(in oklab,rgba(var(--ax-sys-color-primary-darkest-surface)) 40%,transparent)}}}ax-lookup .ax-editor-container.ax-fill ax-chips.ax-default.ax-fill-interactive{background-color:var(--color-lightest);color:var(--color-on-lightest);border-color:var(--color-border-lightest);border-color:rgba(var(--ax-sys-color-border-surface))}ax-lookup .ax-editor-container.ax-fill ax-chips.ax-default.ax-fill-interactive:where(.ax-dark,.ax-dark *):not(:where(.ax-light,.ax-light *)){background-color:var(--color-lighter);color:var(--color-on-lighter);border-color:var(--color-border-lighter)}ax-lookup .ax-editor-container.ax-fill ax-chips.ax-default.ax-fill-interactive:where(.ax-dark,.ax-dark *):not(:where(.ax-light,.ax-light *)){border-color:rgba(var(--ax-sys-color-border-light-surface))}ax-lookup .ax-editor-container.ax-fill ax-chips.ax-default.ax-fill-interactive:not(.ax-state-disabled):hover{background-color:var(--color-lighter);color:var(--color-on-lighter);border-color:var(--color-border-lighter)}ax-lookup .ax-editor-container.ax-fill ax-chips.ax-default.ax-fill-interactive:not(.ax-state-disabled):hover:where(.ax-dark,.ax-dark *):not(:where(.ax-light,.ax-light *)){background-color:var(--color-light);color:var(--color-on-light);border-color:var(--color-border-light)}@property --tw-border-style{syntax: \"*\"; inherits: false; initial-value: solid;}@property --tw-shadow{syntax: \"*\"; inherits: false; initial-value: 0 0 #0000;}@property --tw-shadow-color{syntax: \"*\"; inherits: false;}@property --tw-shadow-alpha{syntax: \"<percentage>\"; inherits: false; initial-value: 100%;}@property --tw-inset-shadow{syntax: \"*\"; inherits: false; initial-value: 0 0 #0000;}@property --tw-inset-shadow-color{syntax: \"*\"; inherits: false;}@property --tw-inset-shadow-alpha{syntax: \"<percentage>\"; inherits: false; initial-value: 100%;}@property --tw-ring-color{syntax: \"*\"; inherits: false;}@property --tw-ring-shadow{syntax: \"*\"; inherits: false; initial-value: 0 0 #0000;}@property --tw-inset-ring-color{syntax: \"*\"; inherits: false;}@property --tw-inset-ring-shadow{syntax: \"*\"; inherits: false; initial-value: 0 0 #0000;}@property --tw-ring-inset{syntax: \"*\"; inherits: false;}@property --tw-ring-offset-width{syntax: \"<length>\"; inherits: false; initial-value: 0px;}@property --tw-ring-offset-color{syntax: \"*\"; inherits: false; initial-value: #fff;}@property --tw-ring-offset-shadow{syntax: \"*\"; inherits: false; initial-value: 0 0 #0000;}@property --tw-leading{syntax: \"*\"; inherits: false;}@property --tw-font-weight{syntax: \"*\"; inherits: false;}@layer properties{@supports ((-webkit-hyphens: none) and (not (margin-trim: inline))) or ((-moz-orient: inline) and (not (color:rgb(from red r g b)))){*,:before,:after,::backdrop{--tw-border-style: solid;--tw-shadow: 0 0 #0000;--tw-shadow-color: initial;--tw-shadow-alpha: 100%;--tw-inset-shadow: 0 0 #0000;--tw-inset-shadow-color: initial;--tw-inset-shadow-alpha: 100%;--tw-ring-color: initial;--tw-ring-shadow: 0 0 #0000;--tw-inset-ring-color: initial;--tw-inset-ring-shadow: 0 0 #0000;--tw-ring-inset: initial;--tw-ring-offset-width: 0px;--tw-ring-offset-color: #fff;--tw-ring-offset-shadow: 0 0 #0000;--tw-leading: initial;--tw-font-weight: initial}}}\n/*! tailwindcss v4.1.16 | MIT License | https://tailwindcss.com */\n"], dependencies: [{ kind: "directive", type: NgTemplateOutlet, selector: "[ngTemplateOutlet]", inputs: ["ngTemplateOutletContext", "ngTemplateOutlet", "ngTemplateOutletInjector"] }, { kind: "component", type: AXButtonComponent, selector: "ax-button", inputs: ["disabled", "size", "tabIndex", "color", "look", "text", "toggleable", "selected", "iconOnly", "type", "loadingText"], outputs: ["onBlur", "onFocus", "onClick", "selectedChange", "toggleableChange", "lookChange", "colorChange", "disabledChange", "loadingTextChange"] }, { kind: "component", type: AXChipsComponent, selector: "ax-chips", inputs: ["tabIndex", "color", "look", "text"], outputs: ["textChange"] }, { kind: "ngmodule", type: AXDecoratorModule }, { kind: "component", type: i1$1.AXDecoratorClearButtonComponent, selector: "ax-clear-button", inputs: ["icon"] }, { kind: "component", type: i1$1.AXDecoratorCloseButtonComponent, selector: "ax-close-button", inputs: ["closeAll", "icon"] }, { kind: "component", type: i1$1.AXDecoratorGenericComponent, selector: "ax-footer, ax-header, ax-content, ax-divider, ax-form-hint, ax-prefix, ax-suffix, ax-text, ax-title, ax-subtitle, ax-placeholder, ax-overlay" }, { kind: "component", type: AXPopoverComponent, selector: "ax-popover", inputs: ["width", "disablePanelClass", "visualContextScope", "disabled", "offsetX", "offsetY", "target", "placement", "content", "openOn", "closeOn", "hasBackdrop", "openAfter", "closeAfter", "closeOnScroll", "backdropClass", "panelClass", "adaptivityEnabled"], outputs: ["onOpened", "onClosed"] }, { kind: "component", type: AXSearchBoxComponent, selector: "ax-search-box", inputs: ["disabled", "readonly", "tabIndex", "placeholder", "value", "state", "name", "id", "look", "class", "delayTime", "type", "autoSearch"], outputs: ["valueChange", "stateChange", "onValueChanged", "onBlur", "onFocus", "readonlyChange", "disabledChange", "onKeyDown", "onKeyUp", "onKeyPress"] }, { kind: "component", type: AXLookupDropDownListComponent, selector: "ax-lookup-drop-down-list" }, { kind: "component", type: AXLookupMultiSelectComponent, selector: "ax-lookup-multi-select" }, { kind: "component", type: AXLookupDropDownTreeComponent, selector: "ax-lookup-drop-down-tree", inputs: ["dataSource", "valueField", "textField", "disabledField", "selectedValues", "nodeTemplate", "emptyTemplate", "alternate", "filterKey"], outputs: ["itemClick"] }, { kind: "component", type: AXLookupMultiSelectTreeComponent, selector: "ax-lookup-multi-select-tree", inputs: ["dataSource", "valueField", "textField", "disabledField", "selectedValues", "selectionBehavior", "nodeTemplate", "emptyTemplate", "alternate", "filterKey"], outputs: ["selectionChange"] }, { kind: "component", type: AXLookupMultiColumnComponent, selector: "ax-lookup-multi-column", inputs: ["dataSource", "valueField", "textField", "disabledField", "selectedValues", "itemHeight", "maxVisibleItems", "columns", "itemTemplate", "emptyTemplate", "loadingTemplate", "alternate"], outputs: ["itemClick"] }, { kind: "component", type: AXLookupMultiColumnTreeComponent, selector: "ax-lookup-multi-column-tree", inputs: ["dataSource", "valueField", "textField", "disabledField", "parentField", "hasChildrenField", "selectedValues", "itemHeight", "maxVisibleItems", "columns", "itemTemplate", "emptyTemplate", "loadingTemplate", "alternate"], outputs: ["itemClick"] }, { kind: "pipe", type: AsyncPipe, name: "async" }, { kind: "pipe", type: AXTranslatorPipe, name: "translate" }], changeDetection: i0.ChangeDetectionStrategy.OnPush, encapsulation: i0.ViewEncapsulation.None }); }
|
|
2819
|
+
}
|
|
2820
|
+
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "22.0.8", ngImport: i0, type: AXLookupComponent, decorators: [{
|
|
2821
|
+
type: Component,
|
|
2822
|
+
args: [{ selector: 'ax-lookup', encapsulation: ViewEncapsulation.None, changeDetection: ChangeDetectionStrategy.OnPush, imports: [
|
|
2823
|
+
NgTemplateOutlet,
|
|
2824
|
+
AsyncPipe,
|
|
2825
|
+
AXTranslatorPipe,
|
|
2826
|
+
AXButtonComponent,
|
|
2827
|
+
AXChipsComponent,
|
|
2828
|
+
AXDecoratorModule,
|
|
2829
|
+
AXPopoverComponent,
|
|
2830
|
+
AXSearchBoxComponent,
|
|
2831
|
+
AXLookupDropDownListComponent,
|
|
2832
|
+
AXLookupMultiSelectComponent,
|
|
2833
|
+
AXLookupDropDownTreeComponent,
|
|
2834
|
+
AXLookupMultiSelectTreeComponent,
|
|
2835
|
+
AXLookupMultiColumnComponent,
|
|
2836
|
+
AXLookupMultiColumnTreeComponent,
|
|
2837
|
+
], providers: [
|
|
2838
|
+
{ provide: AXComponent, useExisting: AXLookupComponent },
|
|
2839
|
+
{ provide: AXClearableComponent, useExisting: AXLookupComponent },
|
|
2840
|
+
{ provide: AXClosableComponent, useExisting: AXLookupComponent },
|
|
2841
|
+
{ provide: AXValuableComponent, useExisting: AXLookupComponent },
|
|
2842
|
+
], template: "<div\n #origin\n class=\"ax-editor-container ax-{{ look() }} ax-default\"\n [class.ax-lookup-trigger]=\"!isEditableTrigger()\"\n [class.ax-lookup-trigger-multiple]=\"isMultiple()\"\n [class.ax-state-disabled]=\"disabled()\"\n [class.ax-state-readonly]=\"readonly()\"\n (click)=\"onTriggerClick()\"\n>\n <ng-content select=\"ax-prefix\"></ng-content>\n\n @if (isMultiple()) {\n <div class=\"ax-lookup-chips\">\n @for (item of selectedItems(); track trackSelectedKey(item)) {\n <ax-chips class=\"ax-sm\" look=\"fill\" [text]=\"selectedTemplate() ? '' : getItemText(item)\">\n @if (selectedTemplate()) {\n <ax-prefix>\n <ng-container\n [ngTemplateOutlet]=\"selectedTemplate()!\"\n [ngTemplateOutletContext]=\"{ $implicit: item }\"\n />\n </ax-prefix>\n }\n @if (!disabled() && !readonly()) {\n <ax-suffix>\n <button type=\"button\" tabindex=\"-1\" (click)=\"removeChip($event, item)\">\n <span class=\"ax-icon ax-icon-close\"></span>\n </button>\n </ax-suffix>\n }\n </ax-chips>\n }\n <input\n #triggerSearchInput\n type=\"text\"\n class=\"ax-input ax-lookup-trigger-search\"\n [class.ax-lookup-select-input]=\"!isEditableTrigger()\"\n [placeholder]=\"triggerSearchPlaceholder()\"\n [disabled]=\"disabled()\"\n [readonly]=\"readonly() || !isEditableTrigger()\"\n [attr.inputmode]=\"isEditableTrigger() ? null : 'none'\"\n [value]=\"searchText()\"\n (input)=\"onTriggerSearchInput($any($event.target).value)\"\n (keydown)=\"onTriggerKeydown($event)\"\n (beforeinput)=\"onBeforeInput($event)\"\n (focus)=\"emitOnFocus($event)\"\n (blur)=\"emitOnBlur($event)\"\n />\n </div>\n } @else {\n <div class=\"ax-lookup-value\">\n @if (showSelectedTemplate()) {\n <div class=\"ax-lookup-selected-content\" aria-hidden=\"true\">\n <ng-container\n [ngTemplateOutlet]=\"selectedTemplate()!\"\n [ngTemplateOutletContext]=\"{ $implicit: selectedItems()[0] }\"\n />\n </div>\n }\n <input\n #triggerSearchInput\n type=\"text\"\n class=\"ax-input\"\n [class.ax-lookup-select-input]=\"!isEditableTrigger()\"\n [class.ax-lookup-input-overlay]=\"showSelectedTemplate()\"\n [placeholder]=\"placeholder()\"\n [disabled]=\"disabled()\"\n [readonly]=\"readonly() || !isEditableTrigger()\"\n [attr.inputmode]=\"isEditableTrigger() ? null : 'none'\"\n [value]=\"searchText()\"\n (input)=\"onTriggerSearchInput($any($event.target).value)\"\n (keydown)=\"onTriggerKeydown($event)\"\n (beforeinput)=\"onBeforeInput($event)\"\n (focus)=\"emitOnFocus($event)\"\n (blur)=\"emitOnBlur($event)\"\n />\n </div>\n }\n\n @if (selectedValues().length > 0 && !disabled() && !readonly()) {\n <ng-content select=\"ax-clear-button\"></ng-content>\n }\n\n <button\n type=\"button\"\n class=\"ax-general-button-icon\"\n tabindex=\"-1\"\n [disabled]=\"disabled() || readonly()\"\n >\n <span\n class=\"ax-icon\"\n [class.ax-icon-chevron-down]=\"!expanded()\"\n [class.ax-icon-chevron-up]=\"expanded()\"\n ></span>\n </button>\n <ng-content select=\"ax-suffix\"></ng-content>\n</div>\n\n<ax-popover\n [target]=\"origin\"\n [openOn]=\"'manual'\"\n [closeOn]=\"isActionsheetStyle() ? 'manual' : 'clickOut'\"\n [closeOnScroll]=\"!isActionsheetStyle()\"\n [placement]=\"'bottom-start'\"\n [width]=\"isActionsheetStyle() ? '100%' : origin.offsetWidth + 'px'\"\n [adaptivityEnabled]=\"isActionsheetStyle()\"\n [disabled]=\"disabled() || readonly()\"\n (onClosed)=\"onPopoverClosed()\"\n>\n <div\n #popup\n class=\"ax-lookup-popup\"\n [class.ax-is-actionsheet]=\"isActionsheetStyle()\"\n [class.ax-is-alternate]=\"alternate()\"\n (keydown.escape)=\"close()\"\n >\n @if (isActionsheetStyle()) {\n <ax-header class=\"ax-solid\">\n <ax-title>{{ caption() || placeholder() || ('@acorex:selectbox.popover.title' | translate | async) }}</ax-title>\n @if (isMultiple()) {\n <ax-button\n class=\"ax-sm\"\n color=\"primary\"\n look=\"solid\"\n text=\"@acorex:common.actions.apply\"\n (onClick)=\"close()\"\n ></ax-button>\n } @else {\n <ax-close-button></ax-close-button>\n }\n </ax-header>\n }\n @if (isSheetSearchEnabled()) {\n <div class=\"ax-lookup-sheet-search\">\n <ax-search-box\n #sheetSearch\n class=\"ax-sm\"\n look=\"fill\"\n [autoSearch]=\"false\"\n [delayTime]=\"0\"\n [placeholder]=\"searchPlaceholder()\"\n (onValueChanged)=\"onSheetSearchInput()\"\n (onKeyUp)=\"onSheetSearchInput()\"\n (onKeyDown)=\"onSheetSearchKeydown($event)\"\n >\n <ax-clear-button></ax-clear-button>\n </ax-search-box>\n </div>\n }\n <ng-content select=\"ax-header\"></ng-content>\n @if (expanded()) {\n @switch (mode()) {\n @case ('drop-down-list') {\n <ax-lookup-drop-down-list\n [dataSource]=\"resolvedDataSource()\"\n [valueField]=\"valueField()\"\n [textField]=\"textField()\"\n [disabledField]=\"disabledField()\"\n [selectedValues]=\"selectedValues()\"\n [itemHeight]=\"itemHeight()\"\n [maxVisibleItems]=\"maxVisibleItems()\"\n [itemTemplate]=\"itemTemplate()\"\n [emptyTemplate]=\"emptyTemplate()\"\n [loadingTemplate]=\"loadingTemplate()\"\n [alternate]=\"alternate()\"\n (itemClick)=\"handleSinglePick($event)\"\n (navigateOut)=\"onListNavigateOut($event)\"\n />\n }\n @case ('multi-select') {\n <ax-lookup-multi-select\n [dataSource]=\"resolvedDataSource()\"\n [valueField]=\"valueField()\"\n [textField]=\"textField()\"\n [disabledField]=\"disabledField()\"\n [selectedValues]=\"selectedValues()\"\n [itemHeight]=\"itemHeight()\"\n [maxVisibleItems]=\"maxVisibleItems()\"\n [itemTemplate]=\"itemTemplate()\"\n [emptyTemplate]=\"emptyTemplate()\"\n [loadingTemplate]=\"loadingTemplate()\"\n [alternate]=\"alternate()\"\n (itemClick)=\"handleMultiToggle($event)\"\n (navigateOut)=\"onListNavigateOut($event)\"\n />\n }\n @case ('drop-down-tree') {\n <ax-lookup-drop-down-tree\n [dataSource]=\"resolvedTreeDataSource()\"\n [valueField]=\"valueField()\"\n [textField]=\"textField()\"\n [disabledField]=\"disabledField()\"\n [selectedValues]=\"selectedValues()\"\n [nodeTemplate]=\"$any(itemTemplate())\"\n [emptyTemplate]=\"emptyTemplate()\"\n [filterKey]=\"treeFilterKey()\"\n [alternate]=\"alternate()\"\n (itemClick)=\"handleSinglePick($event)\"\n />\n }\n @case ('multi-select-tree') {\n <ax-lookup-multi-select-tree\n [dataSource]=\"resolvedTreeDataSource()\"\n [valueField]=\"valueField()\"\n [textField]=\"textField()\"\n [disabledField]=\"disabledField()\"\n [selectedValues]=\"selectedValues()\"\n [selectionBehavior]=\"treeSelectionBehavior()\"\n [nodeTemplate]=\"$any(itemTemplate())\"\n [emptyTemplate]=\"emptyTemplate()\"\n [filterKey]=\"treeFilterKey()\"\n [alternate]=\"alternate()\"\n (selectionChange)=\"handleTreeSelectionChange($event)\"\n />\n }\n @case ('multi-column') {\n <ax-lookup-multi-column\n [dataSource]=\"resolvedDataSource()\"\n [valueField]=\"valueField()\"\n [textField]=\"textField()\"\n [disabledField]=\"disabledField()\"\n [selectedValues]=\"selectedValues()\"\n [itemHeight]=\"itemHeight()\"\n [maxVisibleItems]=\"maxVisibleItems()\"\n [columns]=\"columns()\"\n [itemTemplate]=\"itemTemplate()\"\n [emptyTemplate]=\"emptyTemplate()\"\n [loadingTemplate]=\"loadingTemplate()\"\n [alternate]=\"alternate()\"\n (itemClick)=\"handleSinglePick($event)\"\n />\n }\n @case ('multi-column-tree') {\n <ax-lookup-multi-column-tree\n [dataSource]=\"resolvedDataSource()\"\n [valueField]=\"valueField()\"\n [textField]=\"textField()\"\n [disabledField]=\"disabledField()\"\n [parentField]=\"treeParentField()\"\n [hasChildrenField]=\"hasChildrenField()\"\n [selectedValues]=\"selectedValues()\"\n [itemHeight]=\"itemHeight()\"\n [maxVisibleItems]=\"maxVisibleItems()\"\n [columns]=\"columns()\"\n [itemTemplate]=\"itemTemplate()\"\n [emptyTemplate]=\"emptyTemplate()\"\n [loadingTemplate]=\"loadingTemplate()\"\n [alternate]=\"alternate()\"\n (itemClick)=\"handleSinglePick($event)\"\n />\n }\n }\n }\n <ng-content select=\"ax-footer\"></ng-content>\n </div>\n</ax-popover>\n<ng-content select=\"ax-validation-rule\"></ng-content>\n", styles: ["@layer properties;@layer components{ax-lookup{display:block;width:100%}ax-lookup .ax-editor-container{justify-content:flex-start;gap:calc(var(--spacing, .25rem) * 1)}ax-lookup .ax-lookup-trigger{cursor:pointer;-webkit-user-select:none;user-select:none}ax-lookup .ax-lookup-trigger-multiple{height:auto;min-height:calc(var(--spacing, .25rem) * 9);padding-block:calc(var(--spacing, .25rem) * 1)}ax-lookup .ax-lookup-value{position:relative;display:flex;min-width:calc(var(--spacing, .25rem) * 0);flex:1;align-items:center;overflow:hidden}ax-lookup .ax-lookup-select-input{cursor:pointer;caret-color:transparent;-webkit-user-select:none;user-select:none}ax-lookup .ax-lookup-selected-content{pointer-events:none;position:relative;z-index:0;display:flex;min-width:calc(var(--spacing, .25rem) * 0);flex:1;align-items:center;overflow:hidden}ax-lookup .ax-lookup-input-overlay{position:absolute;inset:calc(var(--spacing, .25rem) * 0);z-index:10;margin:calc(var(--spacing, .25rem) * 0)!important;height:100%;width:100%;border-style:var(--tw-border-style);border-width:0px;background-color:transparent;padding:calc(var(--spacing, .25rem) * 0)!important;color:transparent;caret-color:transparent}ax-lookup .ax-lookup-chips{display:flex;min-width:calc(var(--spacing, .25rem) * 0);flex:1;flex-wrap:wrap;align-items:center;gap:calc(var(--spacing, .25rem) * 1)}ax-lookup .ax-lookup-trigger-search{margin:calc(var(--spacing, .25rem) * 0)!important;height:calc(var(--spacing, .25rem) * 7.5);width:auto!important;min-width:calc(var(--spacing, .25rem) * 16);flex:1;flex-basis:calc(var(--spacing, .25rem) * 16)}ax-lookup .ax-lookup-placeholder{overflow:hidden;text-overflow:ellipsis;white-space:nowrap;font-size:var(--text-sm, .875rem);line-height:var(--tw-leading, var(--text-sm--line-height, calc(1.25 / .875)));color:rgba(var(--ax-sys-color-on-surface))}@supports (color: color-mix(in lab,red,red)){ax-lookup .ax-lookup-placeholder{color:color-mix(in oklab,rgba(var(--ax-sys-color-on-surface)) 50%,transparent)}}ax-lookup ax-chips ax-prefix,ax-lookup ax-chips ax-suffix{padding:calc(var(--spacing, .25rem) * 0)!important}ax-lookup ax-chips ax-suffix button{display:flex;cursor:pointer;align-items:center;border-style:var(--tw-border-style);border-width:0px;background-color:transparent;padding:calc(var(--spacing, .25rem) * 0)}.ax-lookup-popup{box-sizing:border-box;display:flex;width:100%;max-width:100%;min-width:calc(var(--spacing, .25rem) * 0);flex-direction:column;overflow:hidden;border-radius:var(--ax-sys-border-radius);border-style:var(--tw-border-style);border-width:1px;border-color:rgba(var(--ax-sys-color-border-surface));background-color:rgba(var(--ax-sys-color-lightest-surface));--tw-shadow: 0 10px 15px -3px var(--tw-shadow-color, rgb(0 0 0 / .1)), 0 4px 6px -4px var(--tw-shadow-color, rgb(0 0 0 / .1));box-shadow:var(--tw-inset-shadow),var(--tw-inset-ring-shadow),var(--tw-ring-offset-shadow),var(--tw-ring-shadow),var(--tw-shadow)}.ax-lookup-popup:where(.ax-dark,.ax-dark *):not(:where(.ax-light,.ax-light *)){background-color:rgba(var(--ax-sys-color-darkest-surface))}.ax-lookup-popup.ax-is-actionsheet{height:100dvh;max-height:100dvh;min-height:100dvh;border-bottom-right-radius:0;border-bottom-left-radius:0;--tw-shadow: 0 0 #0000;box-shadow:var(--tw-inset-shadow),var(--tw-inset-ring-shadow),var(--tw-ring-offset-shadow),var(--tw-ring-shadow),var(--tw-shadow)}.ax-lookup-popup.ax-is-actionsheet>ax-header.ax-solid{border-bottom-style:var(--tw-border-style);border-bottom-width:1px;border-color:rgba(var(--ax-sys-color-border-lightest-surface))}.ax-lookup-popup.ax-is-actionsheet>ax-header.ax-solid ax-title{min-width:calc(var(--spacing, .25rem) * 0);flex:1;overflow:hidden;text-overflow:ellipsis;white-space:nowrap;font-size:var(--text-base, 1rem);line-height:var(--tw-leading, var(--text-base--line-height, 1.5 ));--tw-leading: calc(var(--spacing, .25rem) * 6);line-height:calc(var(--spacing, .25rem) * 6);--tw-font-weight: var(--font-weight-medium, 500);font-weight:var(--font-weight-medium, 500)}.ax-lookup-popup.ax-is-actionsheet>ax-header.ax-solid ax-button{flex-shrink:0}.ax-lookup-popup.ax-is-actionsheet ax-lookup-drop-down-list,.ax-lookup-popup.ax-is-actionsheet ax-lookup-multi-select,.ax-lookup-popup.ax-is-actionsheet ax-lookup-drop-down-tree,.ax-lookup-popup.ax-is-actionsheet ax-lookup-multi-select-tree,.ax-lookup-popup.ax-is-actionsheet ax-lookup-multi-column,.ax-lookup-popup.ax-is-actionsheet ax-lookup-multi-column-tree{display:flex;min-height:calc(var(--spacing, .25rem) * 0);flex:1;flex-direction:column;height:auto!important}.ax-lookup-popup.ax-is-actionsheet .ax-lookup-viewport{min-height:calc(var(--spacing, .25rem) * 0);flex:1;height:auto!important;max-height:none!important}.ax-lookup-popup.ax-is-actionsheet .ax-lookup-tree{max-height:none;min-height:calc(var(--spacing, .25rem) * 0);flex:1;overflow:auto}.ax-lookup-popup.ax-is-actionsheet .ax-lookup-empty{display:flex;flex:1;align-items:center;justify-content:center}:is(.ax-lookup-popup.ax-is-actionsheet .ax-lookup-multi-column,.ax-lookup-popup.ax-is-actionsheet .ax-lookup-multi-column-tree) .ax-lookup-multi-column-table,:is(.ax-lookup-popup.ax-is-actionsheet .ax-lookup-multi-column,.ax-lookup-popup.ax-is-actionsheet .ax-lookup-multi-column-tree) ax-data-table{height:100%;min-height:calc(var(--spacing, .25rem) * 0)}.ax-lookup-popup .ax-lookup-sheet-search{flex-shrink:0;border-bottom-style:var(--tw-border-style);border-bottom-width:1px;border-color:rgba(var(--ax-sys-color-border-lightest-surface));padding-inline:calc(var(--spacing, .25rem) * 3);padding-block:calc(var(--spacing, .25rem) * 2)}.ax-lookup-popup>ax-header:not(.ax-solid),.ax-lookup-popup>ax-footer{flex-shrink:0;border-color:rgba(var(--ax-sys-color-border-lightest-surface))}.ax-lookup-popup>ax-header:not(.ax-solid){border-bottom-style:var(--tw-border-style);border-bottom-width:1px}.ax-lookup-popup>ax-footer{border-top-style:var(--tw-border-style);border-top-width:1px}.ax-lookup-viewport{width:100%;min-width:calc(var(--spacing, .25rem) * 0);overflow-x:hidden}.ax-lookup-empty{display:flex;min-height:calc(var(--spacing, .25rem) * 12);width:100%;align-items:center;justify-content:center;padding-inline:calc(var(--spacing, .25rem) * 3);padding-block:calc(var(--spacing, .25rem) * 3);text-align:center;font-size:var(--text-sm, .875rem);line-height:var(--tw-leading, var(--text-sm--line-height, calc(1.25 / .875)));color:rgba(var(--ax-sys-color-on-surface))}@supports (color: color-mix(in lab,red,red)){.ax-lookup-empty{color:color-mix(in oklab,rgba(var(--ax-sys-color-on-surface)) 60%,transparent)}}.ax-lookup-option-host{box-sizing:border-box;cursor:pointer;border-style:var(--tw-border-style);border-width:1px;border-color:transparent;--tw-outline-style: none;outline-style:none}.ax-lookup-option-host.ax-state-alternate{background-color:rgba(var(--ax-sys-color-light-surface))}.ax-lookup-option-host.ax-state-alternate:where(.ax-dark,.ax-dark *):not(:where(.ax-light,.ax-light *)){background-color:rgba(var(--ax-sys-color-surface))}.ax-lookup-option-host:hover,.ax-lookup-option-host.ax-state-active{background-color:rgba(var(--ax-sys-color-on-surface))}@supports (color: color-mix(in lab,red,red)){.ax-lookup-option-host:hover,.ax-lookup-option-host.ax-state-active{background-color:color-mix(in oklab,rgba(var(--ax-sys-color-on-surface)) 10%,transparent)}}.ax-lookup-option-host.ax-state-alternate:hover,.ax-lookup-option-host.ax-state-alternate.ax-state-active{background-color:rgba(var(--ax-sys-color-on-surface))}@supports (color: color-mix(in lab,red,red)){.ax-lookup-option-host.ax-state-alternate:hover,.ax-lookup-option-host.ax-state-alternate.ax-state-active{background-color:color-mix(in oklab,rgba(var(--ax-sys-color-on-surface)) 15%,transparent)}}.ax-lookup-option-host.ax-state-selected,.ax-lookup-option-host.ax-state-selected:hover,.ax-lookup-option-host.ax-state-selected.ax-state-active,.ax-lookup-option-host.ax-state-selected.ax-state-alternate,.ax-lookup-option-host.ax-state-selected.ax-state-alternate:hover,.ax-lookup-option-host.ax-state-selected.ax-state-alternate.ax-state-active{background-color:rgba(var(--ax-sys-color-primary-lightest-surface))}:is(.ax-lookup-option-host.ax-state-selected,.ax-lookup-option-host.ax-state-selected:hover,.ax-lookup-option-host.ax-state-selected.ax-state-active,.ax-lookup-option-host.ax-state-selected.ax-state-alternate,.ax-lookup-option-host.ax-state-selected.ax-state-alternate:hover,.ax-lookup-option-host.ax-state-selected.ax-state-alternate.ax-state-active):where(.ax-dark,.ax-dark *):not(:where(.ax-light,.ax-light *)){background-color:rgba(var(--ax-sys-color-primary-darkest-surface))}@supports (color: color-mix(in lab,red,red)){:is(.ax-lookup-option-host.ax-state-selected,.ax-lookup-option-host.ax-state-selected:hover,.ax-lookup-option-host.ax-state-selected.ax-state-active,.ax-lookup-option-host.ax-state-selected.ax-state-alternate,.ax-lookup-option-host.ax-state-selected.ax-state-alternate:hover,.ax-lookup-option-host.ax-state-selected.ax-state-alternate.ax-state-active):where(.ax-dark,.ax-dark *):not(:where(.ax-light,.ax-light *)){background-color:color-mix(in oklab,rgba(var(--ax-sys-color-primary-darkest-surface)) 25%,transparent)}}.ax-lookup-option-host.ax-state-selected.ax-state-active,.ax-lookup-option-host.ax-state-selected.ax-state-alternate.ax-state-active{background-color:rgba(var(--ax-sys-color-primary-lightest-surface))}@supports (color: color-mix(in lab,red,red)){.ax-lookup-option-host.ax-state-selected.ax-state-active,.ax-lookup-option-host.ax-state-selected.ax-state-alternate.ax-state-active{background-color:color-mix(in oklab,rgba(var(--ax-sys-color-primary-lightest-surface)) 80%,transparent)}}:is(.ax-lookup-option-host.ax-state-selected.ax-state-active,.ax-lookup-option-host.ax-state-selected.ax-state-alternate.ax-state-active):where(.ax-dark,.ax-dark *):not(:where(.ax-light,.ax-light *)){background-color:rgba(var(--ax-sys-color-primary-darkest-surface))}@supports (color: color-mix(in lab,red,red)){:is(.ax-lookup-option-host.ax-state-selected.ax-state-active,.ax-lookup-option-host.ax-state-selected.ax-state-alternate.ax-state-active):where(.ax-dark,.ax-dark *):not(:where(.ax-light,.ax-light *)){background-color:color-mix(in oklab,rgba(var(--ax-sys-color-primary-darkest-surface)) 40%,transparent)}}.ax-lookup-option-host.ax-lookup-option-multiple{display:flex;align-items:center;gap:calc(var(--spacing, .25rem) * 2)}.ax-lookup-option-host.ax-lookup-option-multiple:not(.ax-lookup-option){padding-inline:calc(var(--spacing, .25rem) * 3)}.ax-lookup-option-host .ax-lookup-checkbox{pointer-events:none;display:inline-flex;flex-shrink:0;align-items:center}.ax-lookup-option-host .ax-lookup-option-loading{width:100%;padding-inline:calc(var(--spacing, .25rem) * 3);font-size:var(--text-sm, .875rem);line-height:var(--tw-leading, var(--text-sm--line-height, calc(1.25 / .875)));color:rgba(var(--ax-sys-color-on-surface))}@supports (color: color-mix(in lab,red,red)){.ax-lookup-option-host .ax-lookup-option-loading{color:color-mix(in oklab,rgba(var(--ax-sys-color-on-surface)) 50%,transparent)}}.ax-lookup-option{display:flex;align-items:center;justify-content:space-between;gap:calc(var(--spacing, .25rem) * 2);padding-inline:calc(var(--spacing, .25rem) * 3);font-size:var(--text-sm, .875rem);line-height:var(--tw-leading, var(--text-sm--line-height, calc(1.25 / .875)));color:rgba(var(--ax-sys-color-on-surface))}.ax-lookup-option.ax-state-selected{color:rgba(var(--ax-sys-color-primary-surface))}.ax-lookup-option.ax-lookup-option-multiple{justify-content:flex-start}.ax-lookup-option .ax-lookup-option-text{min-width:calc(var(--spacing, .25rem) * 0);flex:1;overflow:hidden;text-overflow:ellipsis;white-space:nowrap}.ax-lookup-option .ax-lookup-option-check{margin-inline-start:auto;flex-shrink:0;color:rgba(var(--ax-sys-color-primary-surface))}ax-lookup-multi-column,ax-lookup-multi-column-tree,.ax-lookup-multi-column,.ax-lookup-multi-column-tree{display:block;min-height:calc(var(--spacing, .25rem) * 0);width:100%}:is(ax-lookup-multi-column,ax-lookup-multi-column-tree,.ax-lookup-multi-column,.ax-lookup-multi-column-tree) .ax-lookup-multi-column-table,:is(ax-lookup-multi-column,ax-lookup-multi-column-tree,.ax-lookup-multi-column,.ax-lookup-multi-column-tree) ax-data-table{height:100%;min-height:calc(var(--spacing, .25rem) * 0);border-style:var(--tw-border-style)!important;border-width:0px!important}:is(ax-lookup-multi-column,ax-lookup-multi-column-tree,.ax-lookup-multi-column,.ax-lookup-multi-column-tree) tr.ax-state-selected{background-color:rgba(var(--ax-sys-color-primary-surface))}@supports (color: color-mix(in lab,red,red)){:is(ax-lookup-multi-column,ax-lookup-multi-column-tree,.ax-lookup-multi-column,.ax-lookup-multi-column-tree) tr.ax-state-selected{background-color:color-mix(in oklab,rgba(var(--ax-sys-color-primary-surface)) 10%,transparent)}}:is(ax-lookup-multi-column,ax-lookup-multi-column-tree,.ax-lookup-multi-column,.ax-lookup-multi-column-tree) tr.ax-state-disabled{pointer-events:none;opacity:50%}.ax-lookup-tree{max-height:calc(var(--spacing, .25rem) * 80);overflow:auto;padding:calc(var(--spacing, .25rem) * 2)}.ax-lookup-tree .ax-tree-view-node{margin-block:0;border-radius:0}.ax-lookup-tree .ax-tree-view-node.ax-state-alternate{background-color:rgba(var(--ax-sys-color-light-surface))}.ax-lookup-tree .ax-tree-view-node.ax-state-alternate:where(.ax-dark,.ax-dark *):not(:where(.ax-light,.ax-light *)){background-color:rgba(var(--ax-sys-color-surface))}.ax-lookup-tree .ax-tree-view-node.ax-state-alternate:hover:not(.ax-dragging){background-color:rgba(var(--ax-sys-color-on-surface))}@supports (color: color-mix(in lab,red,red)){.ax-lookup-tree .ax-tree-view-node.ax-state-alternate:hover:not(.ax-dragging){background-color:color-mix(in oklab,rgba(var(--ax-sys-color-on-surface)) 15%,transparent)}}.ax-lookup-tree .ax-tree-view-node.ax-tree-view-node-selected,.ax-lookup-tree .ax-tree-view-node.ax-state-alternate.ax-tree-view-node-selected{background-color:rgba(var(--ax-sys-color-primary-lightest-surface))}:is(.ax-lookup-tree .ax-tree-view-node.ax-tree-view-node-selected,.ax-lookup-tree .ax-tree-view-node.ax-state-alternate.ax-tree-view-node-selected):where(.ax-dark,.ax-dark *):not(:where(.ax-light,.ax-light *)){background-color:rgba(var(--ax-sys-color-primary-darkest-surface))}@supports (color: color-mix(in lab,red,red)){:is(.ax-lookup-tree .ax-tree-view-node.ax-tree-view-node-selected,.ax-lookup-tree .ax-tree-view-node.ax-state-alternate.ax-tree-view-node-selected):where(.ax-dark,.ax-dark *):not(:where(.ax-light,.ax-light *)){background-color:color-mix(in oklab,rgba(var(--ax-sys-color-primary-darkest-surface)) 25%,transparent)}}.ax-lookup-tree .ax-tree-view-node.ax-tree-view-node-selected:hover:not(.ax-dragging),.ax-lookup-tree .ax-tree-view-node.ax-state-alternate.ax-tree-view-node-selected:hover:not(.ax-dragging){background-color:rgba(var(--ax-sys-color-primary-lightest-surface))}@supports (color: color-mix(in lab,red,red)){.ax-lookup-tree .ax-tree-view-node.ax-tree-view-node-selected:hover:not(.ax-dragging),.ax-lookup-tree .ax-tree-view-node.ax-state-alternate.ax-tree-view-node-selected:hover:not(.ax-dragging){background-color:color-mix(in oklab,rgba(var(--ax-sys-color-primary-lightest-surface)) 80%,transparent)}}:is(.ax-lookup-tree .ax-tree-view-node.ax-tree-view-node-selected:hover:not(.ax-dragging),.ax-lookup-tree .ax-tree-view-node.ax-state-alternate.ax-tree-view-node-selected:hover:not(.ax-dragging)):where(.ax-dark,.ax-dark *):not(:where(.ax-light,.ax-light *)){background-color:rgba(var(--ax-sys-color-primary-darkest-surface))}@supports (color: color-mix(in lab,red,red)){:is(.ax-lookup-tree .ax-tree-view-node.ax-tree-view-node-selected:hover:not(.ax-dragging),.ax-lookup-tree .ax-tree-view-node.ax-state-alternate.ax-tree-view-node-selected:hover:not(.ax-dragging)):where(.ax-dark,.ax-dark *):not(:where(.ax-light,.ax-light *)){background-color:color-mix(in oklab,rgba(var(--ax-sys-color-primary-darkest-surface)) 40%,transparent)}}}ax-lookup .ax-editor-container.ax-fill ax-chips.ax-default.ax-fill-interactive{background-color:var(--color-lightest);color:var(--color-on-lightest);border-color:var(--color-border-lightest);border-color:rgba(var(--ax-sys-color-border-surface))}ax-lookup .ax-editor-container.ax-fill ax-chips.ax-default.ax-fill-interactive:where(.ax-dark,.ax-dark *):not(:where(.ax-light,.ax-light *)){background-color:var(--color-lighter);color:var(--color-on-lighter);border-color:var(--color-border-lighter)}ax-lookup .ax-editor-container.ax-fill ax-chips.ax-default.ax-fill-interactive:where(.ax-dark,.ax-dark *):not(:where(.ax-light,.ax-light *)){border-color:rgba(var(--ax-sys-color-border-light-surface))}ax-lookup .ax-editor-container.ax-fill ax-chips.ax-default.ax-fill-interactive:not(.ax-state-disabled):hover{background-color:var(--color-lighter);color:var(--color-on-lighter);border-color:var(--color-border-lighter)}ax-lookup .ax-editor-container.ax-fill ax-chips.ax-default.ax-fill-interactive:not(.ax-state-disabled):hover:where(.ax-dark,.ax-dark *):not(:where(.ax-light,.ax-light *)){background-color:var(--color-light);color:var(--color-on-light);border-color:var(--color-border-light)}@property --tw-border-style{syntax: \"*\"; inherits: false; initial-value: solid;}@property --tw-shadow{syntax: \"*\"; inherits: false; initial-value: 0 0 #0000;}@property --tw-shadow-color{syntax: \"*\"; inherits: false;}@property --tw-shadow-alpha{syntax: \"<percentage>\"; inherits: false; initial-value: 100%;}@property --tw-inset-shadow{syntax: \"*\"; inherits: false; initial-value: 0 0 #0000;}@property --tw-inset-shadow-color{syntax: \"*\"; inherits: false;}@property --tw-inset-shadow-alpha{syntax: \"<percentage>\"; inherits: false; initial-value: 100%;}@property --tw-ring-color{syntax: \"*\"; inherits: false;}@property --tw-ring-shadow{syntax: \"*\"; inherits: false; initial-value: 0 0 #0000;}@property --tw-inset-ring-color{syntax: \"*\"; inherits: false;}@property --tw-inset-ring-shadow{syntax: \"*\"; inherits: false; initial-value: 0 0 #0000;}@property --tw-ring-inset{syntax: \"*\"; inherits: false;}@property --tw-ring-offset-width{syntax: \"<length>\"; inherits: false; initial-value: 0px;}@property --tw-ring-offset-color{syntax: \"*\"; inherits: false; initial-value: #fff;}@property --tw-ring-offset-shadow{syntax: \"*\"; inherits: false; initial-value: 0 0 #0000;}@property --tw-leading{syntax: \"*\"; inherits: false;}@property --tw-font-weight{syntax: \"*\"; inherits: false;}@layer properties{@supports ((-webkit-hyphens: none) and (not (margin-trim: inline))) or ((-moz-orient: inline) and (not (color:rgb(from red r g b)))){*,:before,:after,::backdrop{--tw-border-style: solid;--tw-shadow: 0 0 #0000;--tw-shadow-color: initial;--tw-shadow-alpha: 100%;--tw-inset-shadow: 0 0 #0000;--tw-inset-shadow-color: initial;--tw-inset-shadow-alpha: 100%;--tw-ring-color: initial;--tw-ring-shadow: 0 0 #0000;--tw-inset-ring-color: initial;--tw-inset-ring-shadow: 0 0 #0000;--tw-ring-inset: initial;--tw-ring-offset-width: 0px;--tw-ring-offset-color: #fff;--tw-ring-offset-shadow: 0 0 #0000;--tw-leading: initial;--tw-font-weight: initial}}}\n/*! tailwindcss v4.1.16 | MIT License | https://tailwindcss.com */\n"] }]
|
|
2843
|
+
}], ctorParameters: () => [], propDecorators: { name: [{ type: i0.Input, args: [{ isSignal: true, alias: "name", required: false }] }], mode: [{ type: i0.Input, args: [{ isSignal: true, alias: "mode", required: false }] }], dataSource: [{ type: i0.Input, args: [{ isSignal: true, alias: "dataSource", required: false }] }], treeDataSource: [{ type: i0.Input, args: [{ isSignal: true, alias: "treeDataSource", required: false }] }], valueField: [{ type: i0.Input, args: [{ isSignal: true, alias: "valueField", required: false }] }], textField: [{ type: i0.Input, args: [{ isSignal: true, alias: "textField", required: false }] }], disabledField: [{ type: i0.Input, args: [{ isSignal: true, alias: "disabledField", required: false }] }], columns: [{ type: i0.Input, args: [{ isSignal: true, alias: "columns", required: false }] }], treeParentField: [{ type: i0.Input, args: [{ isSignal: true, alias: "treeParentField", required: false }] }], hasChildrenField: [{ type: i0.Input, args: [{ isSignal: true, alias: "hasChildrenField", required: false }] }], searchable: [{ type: i0.Input, args: [{ isSignal: true, alias: "searchable", required: false }] }], adaptivityEnabled: [{ type: i0.Input, args: [{ isSignal: true, alias: "adaptivityEnabled", required: false }] }], caption: [{ type: i0.Input, args: [{ isSignal: true, alias: "caption", required: false }] }], alternate: [{ type: i0.Input, args: [{ isSignal: true, alias: "alternate", required: false }] }], searchPlaceholder: [{ type: i0.Input, args: [{ isSignal: true, alias: "searchPlaceholder", required: false }] }], placeholder: [{ type: i0.Input, args: [{ isSignal: true, alias: "placeholder", required: false }] }], disabled: [{ type: i0.Input, args: [{ isSignal: true, alias: "disabled", required: false }] }], readonly: [{ type: i0.Input, args: [{ isSignal: true, alias: "readonly", required: false }] }], look: [{ type: i0.Input, args: [{ isSignal: true, alias: "look", required: false }] }, { type: i0.Output, args: ["lookChange"] }], itemHeight: [{ type: i0.Input, args: [{ isSignal: true, alias: "itemHeight", required: false }] }], maxVisibleItems: [{ type: i0.Input, args: [{ isSignal: true, alias: "maxVisibleItems", required: false }] }], treeSelectionBehavior: [{ type: i0.Input, args: [{ isSignal: true, alias: "treeSelectionBehavior", required: false }] }], itemTemplate: [{ type: i0.Input, args: [{ isSignal: true, alias: "itemTemplate", required: false }] }], selectedTemplate: [{ type: i0.Input, args: [{ isSignal: true, alias: "selectedTemplate", required: false }] }], emptyTemplate: [{ type: i0.Input, args: [{ isSignal: true, alias: "emptyTemplate", required: false }] }], loadingTemplate: [{ type: i0.Input, args: [{ isSignal: true, alias: "loadingTemplate", required: false }] }], value: [{ type: i0.Input, args: [{ isSignal: true, alias: "value", required: false }] }, { type: i0.Output, args: ["valueChange"] }], valueItems: [{ type: i0.Input, args: [{ isSignal: true, alias: "valueItems", required: false }] }], onValueChanged: [{ type: i0.Output, args: ["onValueChanged"] }], onSelectionChanged: [{ type: i0.Output, args: ["onSelectionChanged"] }], onFocus: [{ type: i0.Output, args: ["onFocus"] }], onBlur: [{ type: i0.Output, args: ["onBlur"] }], onItemClick: [{ type: i0.Output, args: ["onItemClick"] }], onItemSelected: [{ type: i0.Output, args: ["onItemSelected"] }], onOpened: [{ type: i0.Output, args: ["onOpened"] }], onClosed: [{ type: i0.Output, args: ["onClosed"] }], popoverRef: [{ type: i0.ViewChild, args: [i0.forwardRef(() => AXPopoverComponent), { isSignal: true }] }], originRef: [{ type: i0.ViewChild, args: ['origin', { isSignal: true }] }], popupRef: [{ type: i0.ViewChild, args: ['popup', { isSignal: true }] }], triggerSearchInput: [{ type: i0.ViewChild, args: ['triggerSearchInput', { isSignal: true }] }], listView: [{ type: i0.ViewChild, args: [i0.forwardRef(() => AXLookupListViewBase), { isSignal: true }] }], dropDownTreeView: [{ type: i0.ViewChild, args: [i0.forwardRef(() => AXLookupDropDownTreeComponent), { isSignal: true }] }], multiSelectTreeView: [{ type: i0.ViewChild, args: [i0.forwardRef(() => AXLookupMultiSelectTreeComponent), { isSignal: true }] }], sheetSearchRef: [{ type: i0.ViewChild, args: ['sheetSearch', { isSignal: true }] }] } });
|
|
2844
|
+
|
|
2845
|
+
class AXLookupModule {
|
|
2846
|
+
static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "22.0.8", ngImport: i0, type: AXLookupModule, deps: [], target: i0.ɵɵFactoryTarget.NgModule }); }
|
|
2847
|
+
static { this.ɵmod = i0.ɵɵngDeclareNgModule({ minVersion: "14.0.0", version: "22.0.8", ngImport: i0, type: AXLookupModule, imports: [AXLookupComponent,
|
|
2848
|
+
AXLookupDropDownListComponent,
|
|
2849
|
+
AXLookupMultiSelectComponent,
|
|
2850
|
+
AXLookupDropDownTreeComponent,
|
|
2851
|
+
AXLookupMultiSelectTreeComponent,
|
|
2852
|
+
AXLookupMultiColumnComponent,
|
|
2853
|
+
AXLookupMultiColumnTreeComponent], exports: [AXLookupComponent,
|
|
2854
|
+
AXLookupDropDownListComponent,
|
|
2855
|
+
AXLookupMultiSelectComponent,
|
|
2856
|
+
AXLookupDropDownTreeComponent,
|
|
2857
|
+
AXLookupMultiSelectTreeComponent,
|
|
2858
|
+
AXLookupMultiColumnComponent,
|
|
2859
|
+
AXLookupMultiColumnTreeComponent] }); }
|
|
2860
|
+
static { this.ɵinj = i0.ɵɵngDeclareInjector({ minVersion: "12.0.0", version: "22.0.8", ngImport: i0, type: AXLookupModule, imports: [AXLookupComponent,
|
|
2861
|
+
AXLookupDropDownListComponent,
|
|
2862
|
+
AXLookupMultiSelectComponent,
|
|
2863
|
+
AXLookupDropDownTreeComponent,
|
|
2864
|
+
AXLookupMultiSelectTreeComponent,
|
|
2865
|
+
AXLookupMultiColumnComponent,
|
|
2866
|
+
AXLookupMultiColumnTreeComponent] }); }
|
|
2867
|
+
}
|
|
2868
|
+
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "22.0.8", ngImport: i0, type: AXLookupModule, decorators: [{
|
|
2869
|
+
type: NgModule,
|
|
2870
|
+
args: [{
|
|
2871
|
+
imports: [
|
|
2872
|
+
AXLookupComponent,
|
|
2873
|
+
AXLookupDropDownListComponent,
|
|
2874
|
+
AXLookupMultiSelectComponent,
|
|
2875
|
+
AXLookupDropDownTreeComponent,
|
|
2876
|
+
AXLookupMultiSelectTreeComponent,
|
|
2877
|
+
AXLookupMultiColumnComponent,
|
|
2878
|
+
AXLookupMultiColumnTreeComponent,
|
|
2879
|
+
],
|
|
2880
|
+
exports: [
|
|
2881
|
+
AXLookupComponent,
|
|
2882
|
+
AXLookupDropDownListComponent,
|
|
2883
|
+
AXLookupMultiSelectComponent,
|
|
2884
|
+
AXLookupDropDownTreeComponent,
|
|
2885
|
+
AXLookupMultiSelectTreeComponent,
|
|
2886
|
+
AXLookupMultiColumnComponent,
|
|
2887
|
+
AXLookupMultiColumnTreeComponent,
|
|
2888
|
+
],
|
|
2889
|
+
}]
|
|
2890
|
+
}] });
|
|
2891
|
+
|
|
2892
|
+
/**
|
|
2893
|
+
* Generated bundle index. Do not edit.
|
|
2894
|
+
*/
|
|
2895
|
+
|
|
2896
|
+
export { AXLookupComponent, AXLookupDropDownListComponent, AXLookupDropDownTreeComponent, AXLookupModule, AXLookupMultiColumnComponent, AXLookupMultiColumnTreeComponent, AXLookupMultiSelectComponent, AXLookupMultiSelectTreeComponent };
|
|
2897
|
+
//# sourceMappingURL=acorex-components-lookup.mjs.map
|