@acorex/components 22.0.0-next.9 → 22.0.1-next.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (205) hide show
  1. package/combo-box/README.md +35 -0
  2. package/emoji/README.md +3 -0
  3. package/emojipicker/README.md +3 -0
  4. package/fesm2022/acorex-components-accordion.mjs +4 -4
  5. package/fesm2022/acorex-components-accordion.mjs.map +1 -1
  6. package/fesm2022/acorex-components-action-sheet.mjs +1 -0
  7. package/fesm2022/acorex-components-action-sheet.mjs.map +1 -1
  8. package/fesm2022/acorex-components-alert.mjs +2 -2
  9. package/fesm2022/acorex-components-alert.mjs.map +1 -1
  10. package/fesm2022/acorex-components-audio-wave.mjs +291 -267
  11. package/fesm2022/acorex-components-audio-wave.mjs.map +1 -1
  12. package/fesm2022/acorex-components-bubble.mjs +71 -0
  13. package/fesm2022/acorex-components-bubble.mjs.map +1 -0
  14. package/fesm2022/acorex-components-button-group.mjs +12 -5
  15. package/fesm2022/acorex-components-button-group.mjs.map +1 -1
  16. package/fesm2022/acorex-components-button.mjs +6 -6
  17. package/fesm2022/acorex-components-button.mjs.map +1 -1
  18. package/fesm2022/acorex-components-calendar.mjs +328 -127
  19. package/fesm2022/acorex-components-calendar.mjs.map +1 -1
  20. package/fesm2022/acorex-components-check-box.mjs +2 -2
  21. package/fesm2022/acorex-components-check-box.mjs.map +1 -1
  22. package/fesm2022/acorex-components-combo-box.mjs +973 -0
  23. package/fesm2022/acorex-components-combo-box.mjs.map +1 -0
  24. package/fesm2022/acorex-components-conversation-acorex-components-conversation-DDkiZfPb.mjs +19058 -0
  25. package/fesm2022/acorex-components-conversation-acorex-components-conversation-DDkiZfPb.mjs.map +1 -0
  26. package/fesm2022/acorex-components-conversation-composer-action-choice-dialog.component-COUB9zrM.mjs +50 -0
  27. package/fesm2022/acorex-components-conversation-composer-action-choice-dialog.component-COUB9zrM.mjs.map +1 -0
  28. package/fesm2022/acorex-components-conversation-image-picker-editor-dialog.component-COT96F_v.mjs +87 -0
  29. package/fesm2022/acorex-components-conversation-image-picker-editor-dialog.component-COT96F_v.mjs.map +1 -0
  30. package/fesm2022/acorex-components-conversation-picker-rename-file-dialog.component-CH3Q6Hry.mjs +65 -0
  31. package/fesm2022/acorex-components-conversation-picker-rename-file-dialog.component-CH3Q6Hry.mjs.map +1 -0
  32. package/fesm2022/acorex-components-conversation.mjs +1 -22920
  33. package/fesm2022/acorex-components-conversation.mjs.map +1 -1
  34. package/fesm2022/acorex-components-cron-job.mjs +1 -1
  35. package/fesm2022/acorex-components-cron-job.mjs.map +1 -1
  36. package/fesm2022/acorex-components-data-pager.mjs +4 -4
  37. package/fesm2022/acorex-components-data-pager.mjs.map +1 -1
  38. package/fesm2022/acorex-components-data-table.mjs +310 -90
  39. package/fesm2022/acorex-components-data-table.mjs.map +1 -1
  40. package/fesm2022/acorex-components-datetime-box.mjs +14 -16
  41. package/fesm2022/acorex-components-datetime-box.mjs.map +1 -1
  42. package/fesm2022/acorex-components-datetime-input.mjs +61 -32
  43. package/fesm2022/acorex-components-datetime-input.mjs.map +1 -1
  44. package/fesm2022/acorex-components-datetime-picker.mjs +1 -1
  45. package/fesm2022/acorex-components-datetime-picker.mjs.map +1 -1
  46. package/fesm2022/acorex-components-decorators.mjs +57 -11
  47. package/fesm2022/acorex-components-decorators.mjs.map +1 -1
  48. package/fesm2022/acorex-components-dialog.mjs +7 -4
  49. package/fesm2022/acorex-components-dialog.mjs.map +1 -1
  50. package/fesm2022/acorex-components-drawer.mjs +2 -2
  51. package/fesm2022/acorex-components-drawer.mjs.map +1 -1
  52. package/fesm2022/acorex-components-dropdown-button.mjs +1 -1
  53. package/fesm2022/acorex-components-dropdown-button.mjs.map +1 -1
  54. package/fesm2022/acorex-components-dropdown.mjs +4 -4
  55. package/fesm2022/acorex-components-dropdown.mjs.map +1 -1
  56. package/fesm2022/acorex-components-emoji.mjs +74 -0
  57. package/fesm2022/acorex-components-emoji.mjs.map +1 -0
  58. package/fesm2022/acorex-components-emojipicker.mjs +425 -0
  59. package/fesm2022/acorex-components-emojipicker.mjs.map +1 -0
  60. package/fesm2022/acorex-components-fab.mjs +5 -5
  61. package/fesm2022/acorex-components-fab.mjs.map +1 -1
  62. package/fesm2022/acorex-components-file-viewer.mjs +359 -109
  63. package/fesm2022/acorex-components-file-viewer.mjs.map +1 -1
  64. package/fesm2022/acorex-components-form.mjs +22 -6
  65. package/fesm2022/acorex-components-form.mjs.map +1 -1
  66. package/fesm2022/acorex-components-grid-layout-builder.mjs +238 -36
  67. package/fesm2022/acorex-components-grid-layout-builder.mjs.map +1 -1
  68. package/fesm2022/acorex-components-highlight.mjs +80 -0
  69. package/fesm2022/acorex-components-highlight.mjs.map +1 -0
  70. package/fesm2022/acorex-components-image-editor.mjs +686 -416
  71. package/fesm2022/acorex-components-image-editor.mjs.map +1 -1
  72. package/fesm2022/acorex-components-inline-reaction.mjs +111 -0
  73. package/fesm2022/acorex-components-inline-reaction.mjs.map +1 -0
  74. package/fesm2022/acorex-components-kanban.mjs +1 -1
  75. package/fesm2022/acorex-components-kanban.mjs.map +1 -1
  76. package/fesm2022/acorex-components-label.mjs +2 -2
  77. package/fesm2022/acorex-components-label.mjs.map +1 -1
  78. package/fesm2022/acorex-components-list.mjs +2 -2
  79. package/fesm2022/acorex-components-list.mjs.map +1 -1
  80. package/fesm2022/acorex-components-loading-dialog.mjs +59 -42
  81. package/fesm2022/acorex-components-loading-dialog.mjs.map +1 -1
  82. package/fesm2022/acorex-components-lookup.mjs +3505 -0
  83. package/fesm2022/acorex-components-lookup.mjs.map +1 -0
  84. package/fesm2022/acorex-components-map.mjs +9 -2
  85. package/fesm2022/acorex-components-map.mjs.map +1 -1
  86. package/fesm2022/acorex-components-menu.mjs +322 -79
  87. package/fesm2022/acorex-components-menu.mjs.map +1 -1
  88. package/fesm2022/acorex-components-message-status.mjs +71 -0
  89. package/fesm2022/acorex-components-message-status.mjs.map +1 -0
  90. package/fesm2022/acorex-components-message-time.mjs +36 -0
  91. package/fesm2022/acorex-components-message-time.mjs.map +1 -0
  92. package/fesm2022/acorex-components-message.mjs +120 -0
  93. package/fesm2022/acorex-components-message.mjs.map +1 -0
  94. package/fesm2022/acorex-components-notification.mjs +13 -6
  95. package/fesm2022/acorex-components-notification.mjs.map +1 -1
  96. package/fesm2022/acorex-components-number-box.mjs +30 -29
  97. package/fesm2022/acorex-components-number-box.mjs.map +1 -1
  98. package/fesm2022/acorex-components-paint.mjs +1 -1
  99. package/fesm2022/acorex-components-paint.mjs.map +1 -1
  100. package/fesm2022/acorex-components-password-box.mjs +3 -3
  101. package/fesm2022/acorex-components-password-box.mjs.map +1 -1
  102. package/fesm2022/acorex-components-popover.mjs +40 -6
  103. package/fesm2022/acorex-components-popover.mjs.map +1 -1
  104. package/fesm2022/acorex-components-popup.mjs +4 -2
  105. package/fesm2022/acorex-components-popup.mjs.map +1 -1
  106. package/fesm2022/acorex-components-radio.mjs +2 -2
  107. package/fesm2022/acorex-components-radio.mjs.map +1 -1
  108. package/fesm2022/acorex-components-rail-navigation.mjs +2 -2
  109. package/fesm2022/acorex-components-rail-navigation.mjs.map +1 -1
  110. package/fesm2022/acorex-components-range-slider.mjs +2 -2
  111. package/fesm2022/acorex-components-range-slider.mjs.map +1 -1
  112. package/fesm2022/acorex-components-reaction.mjs +144 -0
  113. package/fesm2022/acorex-components-reaction.mjs.map +1 -0
  114. package/fesm2022/acorex-components-rest-api-generator.mjs +5 -5
  115. package/fesm2022/acorex-components-rest-api-generator.mjs.map +1 -1
  116. package/fesm2022/acorex-components-rrule.mjs +1 -1
  117. package/fesm2022/acorex-components-rrule.mjs.map +1 -1
  118. package/fesm2022/acorex-components-scheduler-picker.mjs +5 -5
  119. package/fesm2022/acorex-components-scheduler-picker.mjs.map +1 -1
  120. package/fesm2022/acorex-components-scheduler.mjs +12 -22
  121. package/fesm2022/acorex-components-scheduler.mjs.map +1 -1
  122. package/fesm2022/acorex-components-select-box.mjs +55 -18
  123. package/fesm2022/acorex-components-select-box.mjs.map +1 -1
  124. package/fesm2022/acorex-components-selection-list.mjs +3 -4
  125. package/fesm2022/acorex-components-selection-list.mjs.map +1 -1
  126. package/fesm2022/acorex-components-switch.mjs +2 -2
  127. package/fesm2022/acorex-components-switch.mjs.map +1 -1
  128. package/fesm2022/acorex-components-tabs.mjs +510 -74
  129. package/fesm2022/acorex-components-tabs.mjs.map +1 -1
  130. package/fesm2022/acorex-components-tag-box.mjs +2 -2
  131. package/fesm2022/acorex-components-tag-box.mjs.map +1 -1
  132. package/fesm2022/acorex-components-text-area.mjs +2 -2
  133. package/fesm2022/acorex-components-text-area.mjs.map +1 -1
  134. package/fesm2022/acorex-components-toast.mjs +9 -2
  135. package/fesm2022/acorex-components-toast.mjs.map +1 -1
  136. package/fesm2022/acorex-components-tooltip.mjs +2 -2
  137. package/fesm2022/acorex-components-tooltip.mjs.map +1 -1
  138. package/fesm2022/acorex-components-tree-view.mjs +86 -6
  139. package/fesm2022/acorex-components-tree-view.mjs.map +1 -1
  140. package/fesm2022/acorex-components-wysiwyg.mjs +76 -6
  141. package/fesm2022/acorex-components-wysiwyg.mjs.map +1 -1
  142. package/highlight/README.md +13 -0
  143. package/inline-reaction/README.md +3 -0
  144. package/lookup/README.md +74 -0
  145. package/message/README.md +3 -0
  146. package/message-status/README.md +3 -0
  147. package/message-time/README.md +3 -0
  148. package/package.json +51 -16
  149. package/reaction/README.md +3 -0
  150. package/select-box/README.md +5 -0
  151. package/types/acorex-components-action-sheet.d.ts +9 -1
  152. package/types/acorex-components-audio-wave.d.ts +132 -73
  153. package/types/acorex-components-bubble.d.ts +31 -0
  154. package/types/acorex-components-button-group.d.ts +4 -0
  155. package/types/acorex-components-button.d.ts +1 -1
  156. package/types/acorex-components-calendar.d.ts +41 -9
  157. package/types/acorex-components-combo-box.d.ts +310 -0
  158. package/types/acorex-components-conversation.d.ts +1806 -1790
  159. package/types/acorex-components-data-table.d.ts +74 -12
  160. package/types/acorex-components-datetime-box.d.ts +2 -0
  161. package/types/acorex-components-datetime-input.d.ts +24 -5
  162. package/types/acorex-components-decorators.d.ts +14 -1
  163. package/types/acorex-components-dialog.d.ts +9 -0
  164. package/types/acorex-components-emoji.d.ts +42 -0
  165. package/types/acorex-components-emojipicker.d.ts +146 -0
  166. package/types/acorex-components-file-viewer.d.ts +48 -4
  167. package/types/acorex-components-grid-layout-builder.d.ts +34 -2
  168. package/types/acorex-components-highlight.d.ts +31 -0
  169. package/types/acorex-components-image-editor.d.ts +68 -48
  170. package/types/acorex-components-inline-reaction.d.ts +52 -0
  171. package/types/acorex-components-loading-dialog.d.ts +12 -4
  172. package/types/acorex-components-lookup.d.ts +962 -0
  173. package/types/acorex-components-map.d.ts +5 -0
  174. package/types/acorex-components-menu.d.ts +43 -7
  175. package/types/acorex-components-message-status.d.ts +23 -0
  176. package/types/acorex-components-message-time.d.ts +19 -0
  177. package/types/acorex-components-message.d.ts +59 -0
  178. package/types/acorex-components-notification.d.ts +11 -1
  179. package/types/acorex-components-number-box.d.ts +3 -1
  180. package/types/acorex-components-popover.d.ts +12 -1
  181. package/types/acorex-components-popup.d.ts +9 -1
  182. package/types/acorex-components-reaction.d.ts +85 -0
  183. package/types/acorex-components-scheduler.d.ts +2 -4
  184. package/types/acorex-components-select-box.d.ts +21 -4
  185. package/types/acorex-components-selection-list.d.ts +1 -1
  186. package/types/acorex-components-tabs.d.ts +148 -19
  187. package/types/acorex-components-toast.d.ts +10 -1
  188. package/types/acorex-components-tree-view.d.ts +39 -2
  189. package/types/acorex-components-wysiwyg.d.ts +13 -0
  190. package/fesm2022/acorex-components-conversation-composer-action-choice-dialog.component-CNHiM1Sp.mjs +0 -106
  191. package/fesm2022/acorex-components-conversation-composer-action-choice-dialog.component-CNHiM1Sp.mjs.map +0 -1
  192. package/fesm2022/acorex-components-conversation-open-composer-picker-for-files-Hh5Oyp3p.mjs +0 -223
  193. package/fesm2022/acorex-components-conversation-open-composer-picker-for-files-Hh5Oyp3p.mjs.map +0 -1
  194. package/fesm2022/acorex-components-flow-chart.mjs +0 -735
  195. package/fesm2022/acorex-components-flow-chart.mjs.map +0 -1
  196. package/fesm2022/acorex-components-query-builder.mjs +0 -267
  197. package/fesm2022/acorex-components-query-builder.mjs.map +0 -1
  198. package/fesm2022/acorex-components-selection-list-2.mjs +0 -168
  199. package/fesm2022/acorex-components-selection-list-2.mjs.map +0 -1
  200. package/flow-chart/README.md +0 -3
  201. package/query-builder/README.md +0 -3
  202. package/selection-list-2/README.md +0 -3
  203. package/types/acorex-components-flow-chart.d.ts +0 -187
  204. package/types/acorex-components-query-builder.d.ts +0 -52
  205. package/types/acorex-components-selection-list-2.d.ts +0 -52
@@ -0,0 +1,3505 @@
1
+ import { AXDataSource, retryFrames, scrollNearestIntoView, AXListDataSource, NXValueComponent, 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, AXTranslationService, toTranslatedSignal } 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, afterRenderEffect, DestroyRef, model, booleanAttribute, linkedSignal, 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 { AXHighlightTextComponent } from '@acorex/components/highlight';
17
+ import * as i1 from '@angular/cdk/scrolling';
18
+ import { CdkVirtualScrollViewport, ScrollingModule } from '@angular/cdk/scrolling';
19
+ import { AXTreeViewComponent } from '@acorex/components/tree-view';
20
+ import { AXDataTableComponent, AXDataTableTextColumnComponent } from '@acorex/components/data-table';
21
+ import { fromEvent, auditTime } from 'rxjs';
22
+ import { AXCheckBoxComponent } from '@acorex/components/check-box';
23
+
24
+ /** Whether a tree node may have descendants (embedded children or lazy metadata). */
25
+ function lookupTreeNodeMayHaveChildren(node) {
26
+ const raw = node['children'];
27
+ if (Array.isArray(raw) && raw.length > 0) {
28
+ return true;
29
+ }
30
+ const count = node['childrenCount'];
31
+ if (typeof count === 'number' && count > 0) {
32
+ return true;
33
+ }
34
+ return node['hasChild'] === true || node['hasChildren'] === true;
35
+ }
36
+ async function mapWithConcurrency(items, concurrency, fn, isCancelled) {
37
+ if (!items.length) {
38
+ return [];
39
+ }
40
+ const results = new Array(items.length);
41
+ let nextIndex = 0;
42
+ const worker = async () => {
43
+ while (nextIndex < items.length) {
44
+ if (isCancelled?.()) {
45
+ return;
46
+ }
47
+ const index = nextIndex++;
48
+ if (index >= items.length) {
49
+ break;
50
+ }
51
+ results[index] = await fn(items[index]);
52
+ }
53
+ };
54
+ const workers = Math.min(concurrency, items.length);
55
+ await Promise.all(Array.from({ length: workers }, () => worker()));
56
+ return results;
57
+ }
58
+ /**
59
+ * Loads a lazy tree into a nested in-memory snapshot using bounded-concurrency BFS.
60
+ * Returns new node objects and never mutates the input nodes.
61
+ */
62
+ async function hydrateLookupTree(roots, loadChildren, options) {
63
+ const { valueField, maxConcurrent = 6, maxNodes = 5000, isCancelled } = options;
64
+ const visited = new Set();
65
+ let nodeCount = 0;
66
+ const hydrateLevel = async (nodes) => {
67
+ if (!nodes.length || isCancelled?.()) {
68
+ return nodes.map((node) => ({ ...node }));
69
+ }
70
+ const hydrateNode = async (node) => {
71
+ if (isCancelled?.()) {
72
+ return { ...node };
73
+ }
74
+ const raw = node['children'];
75
+ if (Array.isArray(raw) && raw.length > 0) {
76
+ const children = await hydrateLevel(raw);
77
+ return { ...node, children };
78
+ }
79
+ const id = String(node[valueField] ?? '');
80
+ if (!id || visited.has(id) || !lookupTreeNodeMayHaveChildren(node)) {
81
+ return { ...node };
82
+ }
83
+ visited.add(id);
84
+ nodeCount++;
85
+ if (nodeCount > maxNodes) {
86
+ return { ...node };
87
+ }
88
+ const loaded = await loadChildren(id);
89
+ if (isCancelled?.() || !loaded.length) {
90
+ return { ...node };
91
+ }
92
+ const children = await hydrateLevel(loaded);
93
+ return children.length > 0 ? { ...node, children } : { ...node };
94
+ };
95
+ return mapWithConcurrency(nodes, maxConcurrent, hydrateNode, isCancelled);
96
+ };
97
+ return hydrateLevel(roots);
98
+ }
99
+
100
+ /** Whether an item label matches a search query (raw or translated). */
101
+ function matchesLookupText(text, query, translateText) {
102
+ const needle = query.trim().toLowerCase();
103
+ if (!needle) {
104
+ return true;
105
+ }
106
+ const raw = String(text ?? '').toLowerCase();
107
+ if (raw.includes(needle)) {
108
+ return true;
109
+ }
110
+ const value = String(text ?? '');
111
+ if (translateText && value.startsWith('@')) {
112
+ return translateText(value).toLowerCase().includes(needle);
113
+ }
114
+ return false;
115
+ }
116
+ /**
117
+ * Array-backed datasource with optional i18n-aware text filtering.
118
+ */
119
+ function convertLookupArrayToDataSource(items, options) {
120
+ const normalizedItems = items.map((candidate) => {
121
+ const isObjectItem = candidate != null && typeof candidate === 'object';
122
+ if (isObjectItem) {
123
+ return candidate;
124
+ }
125
+ return { [options.key]: candidate, text: String(candidate ?? '') };
126
+ });
127
+ const config = {
128
+ key: options.key,
129
+ pageSize: options.pageSize,
130
+ load: async (e) => {
131
+ const itemsForFilter = normalizedItems;
132
+ const resultNormalized = e.filter
133
+ ? applyLookupArrayFilter(itemsForFilter, e.filter, options.textField, options.translateText)
134
+ : itemsForFilter;
135
+ const result = resultNormalized;
136
+ return {
137
+ items: result.slice(e.skip, e.skip + e.take),
138
+ total: resultNormalized.length,
139
+ };
140
+ },
141
+ byKey: (v) => normalizedItems.find((record) => record[options.key] == v),
142
+ };
143
+ return new AXDataSource(config);
144
+ }
145
+ function applyLookupArrayFilter(items, filter, textField, translateText) {
146
+ if (!filter?.field || filter.value === undefined || filter.value === null) {
147
+ return items;
148
+ }
149
+ const query = String(filter.value);
150
+ return items.filter((item) => {
151
+ const itemField = item[filter.field];
152
+ if (filter.field === textField) {
153
+ return matchesLookupText(String(itemField ?? ''), query, translateText);
154
+ }
155
+ if (typeof itemField === 'string' && typeof filter.value === 'string') {
156
+ return itemField.toLowerCase().includes(filter.value.toLowerCase());
157
+ }
158
+ return false;
159
+ });
160
+ }
161
+ /**
162
+ * Converts a drop-down-tree datasource (nested array or lazy callback) into an
163
+ * `AXDataSource` that a multi-column data table can load and expand.
164
+ */
165
+ function createLookupTreeTableDataSource(source, options) {
166
+ const isCallback = typeof source === 'function';
167
+ return new AXDataSource({
168
+ pageSize: 8,
169
+ key: options.valueField,
170
+ load: (query) => loadTreeTableRows(source, options, query, isCallback),
171
+ byKey: (key) => findTreeTableItem(source, options.valueField, key) ?? {},
172
+ });
173
+ }
174
+ async function loadTreeTableRows(source, options, query, isCallback) {
175
+ const parentFilter = query.filter?.field === options.parentField ? query.filter : undefined;
176
+ const textFilter = query.filter && query.filter.field !== options.parentField ? query.filter : undefined;
177
+ if (parentFilter) {
178
+ const children = await loadChildren(source, options, parentFilter.value, isCallback);
179
+ return { items: children, total: children.length };
180
+ }
181
+ const rootNodes = textFilter && options.loadSearchRoots
182
+ ? await options.loadSearchRoots()
183
+ : await loadRoots(source, isCallback);
184
+ const roots = mapTreeNodes(rootNodes, options);
185
+ const items = textFilter
186
+ ? prepareFilteredTreeTableRows(filterTreeNodes(roots, options.searchFields?.length ? options.searchFields : options.textField, String(textFilter.value ?? '')))
187
+ : roots;
188
+ return { items, total: items.length };
189
+ }
190
+ async function loadRoots(source, isCallback) {
191
+ if (!isCallback) {
192
+ return source ?? [];
193
+ }
194
+ return (await source()) ?? [];
195
+ }
196
+ async function loadChildren(source, options, parentId, isCallback) {
197
+ if (isCallback) {
198
+ const nodes = (await source(String(parentId))) ?? [];
199
+ return mapTreeNodes(nodes, options);
200
+ }
201
+ const parent = findTreeNode(source, options.valueField, parentId);
202
+ const children = Array.isArray(parent?.['children']) ? parent['children'] : [];
203
+ return mapTreeNodes(children, options);
204
+ }
205
+ function mapTreeNodes(nodes, options) {
206
+ return nodes.map((node) => mapTreeNode(node, options));
207
+ }
208
+ function mapTreeNode(node, options) {
209
+ const rawChildren = node['children'];
210
+ const children = Array.isArray(rawChildren) ? mapTreeNodes(rawChildren, options) : undefined;
211
+ const hasChildren = lookupTreeNodeMayHaveChildren(node) || (children?.length ?? 0) > 0;
212
+ return {
213
+ ...node,
214
+ [options.hasChildrenField]: hasChildren,
215
+ ...(children && children.length > 0 ? { children } : {}),
216
+ };
217
+ }
218
+ /**
219
+ * Recursively filters a nested tree by `textField` (case-insensitive contains).
220
+ * A node is kept if it matches or any descendant matches. Matching parents keep
221
+ * all children. Every kept ancestor is a new object with `expanded: true` so
222
+ * nested hits are visible without mutating the original tree.
223
+ */
224
+ /** Reads a possibly dotted field path off a node. */
225
+ function readNodeField(node, field) {
226
+ if (!field.includes('.')) {
227
+ return node[field];
228
+ }
229
+ return field.split('.').reduce((current, segment) => {
230
+ if (current == null || typeof current !== 'object') {
231
+ return undefined;
232
+ }
233
+ return current[segment];
234
+ }, node);
235
+ }
236
+ /** Whether any of `fields` on the node matches the query. */
237
+ function matchesLookupNode(node, fields, needle, translateText) {
238
+ return fields.some((field) => {
239
+ const value = readNodeField(node, field);
240
+ if (value == null) {
241
+ return false;
242
+ }
243
+ return matchesLookupText(String(value), needle, translateText);
244
+ });
245
+ }
246
+ function filterTreeNodes(nodes, textField, query, translateText) {
247
+ const needle = query.trim().toLowerCase();
248
+ if (!needle) {
249
+ return nodes;
250
+ }
251
+ const fields = (Array.isArray(textField) ? textField : [textField]).filter((field) => !!field);
252
+ const result = [];
253
+ for (const node of nodes) {
254
+ const rawChildren = node['children'];
255
+ const nested = Array.isArray(rawChildren) ? rawChildren : undefined;
256
+ const selfMatch = matchesLookupNode(node, fields, needle, translateText);
257
+ if (selfMatch) {
258
+ result.push({
259
+ ...node,
260
+ ...(nested && nested.length > 0 ? { children: cloneTreeNodes(nested), expanded: true } : {}),
261
+ });
262
+ continue;
263
+ }
264
+ const children = nested ? filterTreeNodes(nested, fields, needle, translateText) : undefined;
265
+ if (children && children.length > 0) {
266
+ result.push({
267
+ ...node,
268
+ children,
269
+ expanded: true,
270
+ });
271
+ }
272
+ }
273
+ return result;
274
+ }
275
+ /**
276
+ * Maps `filterTreeNodes` output to data-table row metadata so matching branches
277
+ * are expanded and nested rows are visible for search highlighting.
278
+ */
279
+ function prepareFilteredTreeTableRows(nodes) {
280
+ return nodes.map((node) => prepareFilteredTreeTableNode(node, 0));
281
+ }
282
+ function prepareFilteredTreeTableNode(node, level) {
283
+ const rawChildren = node['children'];
284
+ const nested = Array.isArray(rawChildren) ? rawChildren : undefined;
285
+ const children = nested?.map((child) => prepareFilteredTreeTableNode(child, level + 1));
286
+ const hasChildren = (children?.length ?? 0) > 0;
287
+ const priorMeta = node['__meta__'];
288
+ const shouldExpand = hasChildren || node['expanded'] === true;
289
+ return {
290
+ ...node,
291
+ ...(children ? { children } : {}),
292
+ __meta__: {
293
+ ...(typeof priorMeta === 'object' && priorMeta != null ? priorMeta : {}),
294
+ level,
295
+ expanded: shouldExpand,
296
+ },
297
+ };
298
+ }
299
+ function cloneTreeNodes(nodes) {
300
+ return nodes.map((node) => {
301
+ const raw = node['children'];
302
+ const children = Array.isArray(raw) && raw.length > 0 ? cloneTreeNodes(raw) : undefined;
303
+ return children ? { ...node, children } : { ...node };
304
+ });
305
+ }
306
+ /** Immutable copy of a nested tree so tree-view mutations cannot poison the source. */
307
+ function cloneLookupTreeNodes(nodes) {
308
+ return cloneTreeNodes(nodes);
309
+ }
310
+ /** Depth-first flattening of nested `children` arrays. */
311
+ function flattenTreeNodes(nodes) {
312
+ const result = [];
313
+ for (const node of nodes) {
314
+ result.push(node);
315
+ const children = node['children'];
316
+ if (Array.isArray(children)) {
317
+ result.push(...flattenTreeNodes(children));
318
+ }
319
+ }
320
+ return result;
321
+ }
322
+ function findTreeTableItem(source, valueField, key) {
323
+ if (typeof source === 'function' || !Array.isArray(source)) {
324
+ return undefined;
325
+ }
326
+ return findTreeNode(source, valueField, key) ?? undefined;
327
+ }
328
+ function findTreeNode(nodes, valueField, key) {
329
+ for (const node of nodes) {
330
+ if (String(node[valueField]) === String(key)) {
331
+ return node;
332
+ }
333
+ const children = node['children'];
334
+ if (Array.isArray(children)) {
335
+ const found = findTreeNode(children, valueField, key);
336
+ if (found) {
337
+ return found;
338
+ }
339
+ }
340
+ }
341
+ return null;
342
+ }
343
+
344
+ /**
345
+ * Scrolls a CDK virtual viewport so the row at `index` is visible using nearest-edge behavior.
346
+ * Uses offset math because the row may not be rendered in the DOM yet.
347
+ */
348
+ function scrollNearestByOffset(viewport, index, itemHeight, totalCount) {
349
+ const viewportSize = viewport.getViewportSize();
350
+ const maxOffset = Math.max(0, totalCount * itemHeight - viewportSize);
351
+ const itemTop = index * itemHeight;
352
+ const itemBottom = itemTop + itemHeight;
353
+ const currentOffset = viewport.measureScrollOffset();
354
+ if (itemTop < currentOffset) {
355
+ viewport.scrollToOffset(itemTop);
356
+ }
357
+ else if (itemBottom > currentOffset + viewportSize) {
358
+ viewport.scrollToOffset(Math.min(maxOffset, itemBottom - viewportSize));
359
+ }
360
+ }
361
+ /**
362
+ * Scrolls a data-table body so the selected row is visible, accounting for a sticky header.
363
+ */
364
+ function scrollTableToSelectedRow(host, attempts = 5) {
365
+ retryFrames(() => {
366
+ const wrapper = host.querySelector('.ax-data-table-wrapper');
367
+ const row = wrapper?.querySelector('tr.ax-state-selected');
368
+ if (!wrapper || !row) {
369
+ return false;
370
+ }
371
+ const thead = wrapper.querySelector('thead');
372
+ const topInset = thead?.offsetHeight ?? 0;
373
+ scrollNearestIntoView(wrapper, row, topInset);
374
+ return true;
375
+ }, attempts);
376
+ }
377
+ /**
378
+ * Scrolls a lookup tree container so the node with `selectedId` is visible.
379
+ * Nodes inside collapsed branches are not in the DOM and are skipped.
380
+ */
381
+ function scrollTreeToSelectedNode(host, selectedId, attempts = 5) {
382
+ if (!selectedId) {
383
+ return;
384
+ }
385
+ retryFrames(() => {
386
+ const container = host.querySelector('.ax-lookup-tree');
387
+ const node = container?.querySelector(`[data-tree-node-id="${CSS.escape(selectedId)}"]`);
388
+ if (!container || !node) {
389
+ return false;
390
+ }
391
+ scrollNearestIntoView(container, node);
392
+ return true;
393
+ }, attempts);
394
+ }
395
+
396
+ /**
397
+ * Shared `AXDataSource` + CDK virtual scroll plumbing for the list-based lookup views
398
+ * (`ax-lookup-drop-down-list`, `ax-lookup-multi-select`).
399
+ */
400
+ class AXLookupListViewBase {
401
+ /** Whether the filtered datasource currently has no items. */
402
+ hasNoMatches() {
403
+ return this.isEmpty();
404
+ }
405
+ /** Number of items in the current filtered result set. */
406
+ matchCount() {
407
+ return this.totalCount();
408
+ }
409
+ #ngZone;
410
+ /**
411
+ * Before the first page loads, `totalCount` is 0 but `cachedItems` is pre-sized to `pageSize`.
412
+ * After a completed load with no rows, `cachedItems` is an empty array.
413
+ */
414
+ #hasPendingInitialLoad(source) {
415
+ return source.totalCount === 0 && source.cachedItems.length > 0 && !source.isLoading;
416
+ }
417
+ #syncLoadingState(source, isLoading) {
418
+ this.isLoading.set(isLoading || this.#hasPendingInitialLoad(source));
419
+ }
420
+ constructor() {
421
+ /**
422
+ * The datasource providing the items (paged, remote-capable).
423
+ */
424
+ this.dataSource = input.required(/* @ts-ignore */
425
+ ...(ngDevMode ? [{ debugName: "dataSource" }] : /* istanbul ignore next */ []));
426
+ /**
427
+ * The item property used as the selection value.
428
+ */
429
+ this.valueField = input('id', /* @ts-ignore */
430
+ ...(ngDevMode ? [{ debugName: "valueField" }] : /* istanbul ignore next */ []));
431
+ /**
432
+ * The item property used as the display text.
433
+ */
434
+ this.textField = input('text', /* @ts-ignore */
435
+ ...(ngDevMode ? [{ debugName: "textField" }] : /* istanbul ignore next */ []));
436
+ /**
437
+ * The item property marking an item as disabled.
438
+ */
439
+ this.disabledField = input('disabled', /* @ts-ignore */
440
+ ...(ngDevMode ? [{ debugName: "disabledField" }] : /* istanbul ignore next */ []));
441
+ /**
442
+ * Currently selected values (always an array, even for single selection).
443
+ */
444
+ this.selectedValues = input([], /* @ts-ignore */
445
+ ...(ngDevMode ? [{ debugName: "selectedValues" }] : /* istanbul ignore next */ []));
446
+ /**
447
+ * The fixed row height in pixels used by the virtual scroll viewport.
448
+ */
449
+ this.itemHeight = input(40, /* @ts-ignore */
450
+ ...(ngDevMode ? [{ debugName: "itemHeight" }] : /* istanbul ignore next */ []));
451
+ /**
452
+ * The maximum number of rows visible before the popup scrolls.
453
+ */
454
+ this.maxVisibleItems = input(8, /* @ts-ignore */
455
+ ...(ngDevMode ? [{ debugName: "maxVisibleItems" }] : /* istanbul ignore next */ []));
456
+ /**
457
+ * Custom template rendered for each item. Context: `$implicit` is the item;
458
+ * `highlightText` is the active search query when result highlighting is enabled.
459
+ * Default option chrome is not applied on top of the template.
460
+ */
461
+ this.itemTemplate = input(undefined, /* @ts-ignore */
462
+ ...(ngDevMode ? [{ debugName: "itemTemplate" }] : /* istanbul ignore next */ []));
463
+ /**
464
+ * Custom template rendered when the datasource has no items.
465
+ */
466
+ this.emptyTemplate = input(undefined, /* @ts-ignore */
467
+ ...(ngDevMode ? [{ debugName: "emptyTemplate" }] : /* istanbul ignore next */ []));
468
+ /**
469
+ * Custom template rendered for rows whose page is still loading.
470
+ */
471
+ this.loadingTemplate = input(undefined, /* @ts-ignore */
472
+ ...(ngDevMode ? [{ debugName: "loadingTemplate" }] : /* istanbul ignore next */ []));
473
+ /**
474
+ * When `true`, list rows use alternating background colors for easier scanning.
475
+ */
476
+ this.alternate = input(false, /* @ts-ignore */
477
+ ...(ngDevMode ? [{ debugName: "alternate" }] : /* istanbul ignore next */ []));
478
+ /**
479
+ * When set, matching characters in the default option label are highlighted.
480
+ */
481
+ this.highlightText = input('', /* @ts-ignore */
482
+ ...(ngDevMode ? [{ debugName: "highlightText" }] : /* istanbul ignore next */ []));
483
+ /**
484
+ * Emitted when the user picks (or toggles) an item.
485
+ */
486
+ this.itemClick = output();
487
+ /**
488
+ * Emitted when keyboard navigation should leave the list (e.g. ArrowUp on the first
489
+ * item, or a printable key that should return focus to the trigger search input).
490
+ */
491
+ this.navigateOut = output();
492
+ /** CDK virtual scroll adapter over the datasource. */
493
+ this.listDataSource = signal(null, /* @ts-ignore */
494
+ ...(ngDevMode ? [{ debugName: "listDataSource" }] : /* istanbul ignore next */ []));
495
+ this.totalCount = signal(0, /* @ts-ignore */
496
+ ...(ngDevMode ? [{ debugName: "totalCount" }] : /* istanbul ignore next */ []));
497
+ this.isLoading = signal(true, /* @ts-ignore */
498
+ ...(ngDevMode ? [{ debugName: "isLoading" }] : /* istanbul ignore next */ []));
499
+ this.isEmpty = computed(() => this.totalCount() === 0 && !this.isLoading(), /* @ts-ignore */
500
+ ...(ngDevMode ? [{ debugName: "isEmpty" }] : /* istanbul ignore next */ []));
501
+ /** Viewport height so the popup grows with the items up to `maxVisibleItems`. */
502
+ this.viewportHeight = computed(() => {
503
+ const count = this.totalCount() || (this.isLoading() ? 3 : 1);
504
+ return Math.min(count, this.maxVisibleItems()) * this.itemHeight();
505
+ }, /* @ts-ignore */
506
+ ...(ngDevMode ? [{ debugName: "viewportHeight" }] : /* istanbul ignore next */ []));
507
+ this.viewportRef = viewChild(CdkVirtualScrollViewport, /* @ts-ignore */
508
+ ...(ngDevMode ? [{ debugName: "viewportRef" }] : /* istanbul ignore next */ []));
509
+ this.listNavigation = viewChild(AXListNavigationDirective, /* @ts-ignore */
510
+ ...(ngDevMode ? [{ debugName: "listNavigation" }] : /* istanbul ignore next */ []));
511
+ this.navItems = viewChildren(AXListNavigationItemDirective, /* @ts-ignore */
512
+ ...(ngDevMode ? [{ debugName: "navItems" }] : /* istanbul ignore next */ []));
513
+ this.#ngZone = inject(NgZone);
514
+ this.trackByIndex = (index) => index;
515
+ // CDK measures the viewport size only once, when it initializes. Inside the popover the
516
+ // panel is still animating/positioning at that moment (and the height also changes when
517
+ // the loading placeholder is replaced by the real item count), so the measurement is stale
518
+ // and CDK renders too few rows, leaving empty space. A ResizeObserver on the viewport
519
+ // element re-measures on every actual size change, covering all of these cases.
520
+ effect((onCleanup) => {
521
+ const viewport = this.viewportRef();
522
+ if (!viewport || typeof ResizeObserver === 'undefined') {
523
+ return;
524
+ }
525
+ const observer = new ResizeObserver(() => {
526
+ this.#ngZone.run(() => viewport.checkViewportSize());
527
+ });
528
+ observer.observe(viewport.elementRef.nativeElement);
529
+ onCleanup(() => observer.disconnect());
530
+ });
531
+ effect((onCleanup) => {
532
+ const source = this.dataSource();
533
+ const list = new AXListDataSource({ source });
534
+ untracked(() => {
535
+ this.totalCount.set(source.totalCount);
536
+ this.#syncLoadingState(source, source.isLoading);
537
+ this.listDataSource.set(list);
538
+ });
539
+ const loadingSub = source.onLoadingChanged.subscribe((value) => this.#syncLoadingState(source, value));
540
+ const changedSub = source.onChanged.subscribe((e) => {
541
+ this.totalCount.set(e.totalCount);
542
+ if (!source.isLoading) {
543
+ this.#syncLoadingState(source, false);
544
+ }
545
+ });
546
+ onCleanup(() => {
547
+ loadingSub.unsubscribe();
548
+ changedSub.unsubscribe();
549
+ });
550
+ });
551
+ // Scroll the selected row into view once the virtual viewport and data are ready.
552
+ effect(() => {
553
+ const viewport = this.viewportRef();
554
+ const loading = this.isLoading();
555
+ const count = this.totalCount();
556
+ const values = this.selectedValues();
557
+ const field = this.valueField();
558
+ const height = this.itemHeight();
559
+ const source = this.dataSource();
560
+ if (!viewport || loading || count === 0 || values.length === 0) {
561
+ return;
562
+ }
563
+ untracked(() => {
564
+ requestAnimationFrame(() => {
565
+ viewport.checkViewportSize();
566
+ const index = this.#resolveSelectedIndex(source, values, field);
567
+ if (index >= 0) {
568
+ scrollNearestByOffset(viewport, index, height, count);
569
+ }
570
+ });
571
+ });
572
+ });
573
+ }
574
+ #resolveSelectedIndex(source, values, valueField) {
575
+ const selectedValue = values[0];
576
+ if (selectedValue == null) {
577
+ return -1;
578
+ }
579
+ const items = source.cachedItems;
580
+ for (let index = 0; index < items.length; index++) {
581
+ const item = items[index];
582
+ if (item != null && item[valueField] == selectedValue) {
583
+ return index;
584
+ }
585
+ }
586
+ return -1;
587
+ }
588
+ /** Moves keyboard focus to the selected list option, or the first option when none is selected. */
589
+ focusFirst() {
590
+ const nav = this.listNavigation();
591
+ if (!nav) {
592
+ return;
593
+ }
594
+ const viewport = this.viewportRef();
595
+ const selectedHost = viewport?.elementRef.nativeElement.querySelector('.ax-lookup-option-host.ax-state-selected');
596
+ if (selectedHost) {
597
+ const items = this.navItems();
598
+ const index = items.findIndex((item) => item.itemElem.nativeElement === selectedHost);
599
+ if (index >= 0) {
600
+ nav.activeIndex.set(index);
601
+ nav.navigateTo(items[index]);
602
+ return;
603
+ }
604
+ }
605
+ nav.focusOnIndex(0);
606
+ }
607
+ getValue(item) {
608
+ return item?.[this.valueField()];
609
+ }
610
+ getText(item) {
611
+ return String(item?.[this.textField()] ?? '');
612
+ }
613
+ isSelected(item) {
614
+ const value = this.getValue(item);
615
+ return this.selectedValues().some((v) => v == value);
616
+ }
617
+ isDisabled(item) {
618
+ return Boolean(item?.[this.disabledField()]);
619
+ }
620
+ handleItemClick(item) {
621
+ if (!item || this.isDisabled(item)) {
622
+ return;
623
+ }
624
+ this.itemClick.emit({ item, value: this.getValue(item) });
625
+ }
626
+ /**
627
+ * Commit on mousedown (not click) so a searchable trigger blur cannot destroy the
628
+ * list before the pick is applied.
629
+ */
630
+ handleItemMouseDown(event, item) {
631
+ event.preventDefault();
632
+ event.stopPropagation();
633
+ this.handleItemClick(item);
634
+ }
635
+ handleItemKeypress(e, item) {
636
+ if (e.nativeEvent.key === 'Enter' || e.nativeEvent.code === 'Space') {
637
+ e.nativeEvent.stopPropagation();
638
+ e.nativeEvent.preventDefault();
639
+ this.handleItemClick(item);
640
+ }
641
+ }
642
+ handleListKeypress(e) {
643
+ const key = e.nativeEvent.key;
644
+ const nav = this.listNavigation();
645
+ const viewport = this.viewportRef();
646
+ if (key === 'ArrowUp' && nav && nav.activeIndex() === 0) {
647
+ const offset = viewport?.measureScrollOffset() ?? 0;
648
+ if (offset > 0) {
649
+ e.nativeEvent.preventDefault();
650
+ viewport.scrollToOffset(Math.max(0, offset - this.itemHeight()));
651
+ queueMicrotask(() => nav.focusOnIndex(0));
652
+ return;
653
+ }
654
+ e.nativeEvent.preventDefault();
655
+ this.navigateOut.emit('up');
656
+ return;
657
+ }
658
+ if (key === 'ArrowDown' && nav && viewport) {
659
+ const items = this.navItems();
660
+ if (items.length > 0 && nav.activeIndex() >= items.length - 1) {
661
+ const maxOffset = Math.max(0, this.totalCount() * this.itemHeight() - viewport.getViewportSize());
662
+ const nextOffset = Math.min(maxOffset, viewport.measureScrollOffset() + this.itemHeight());
663
+ if (nextOffset > viewport.measureScrollOffset()) {
664
+ e.nativeEvent.preventDefault();
665
+ viewport.scrollToOffset(nextOffset);
666
+ queueMicrotask(() => nav.focusOnIndex(this.navItems().length - 1));
667
+ }
668
+ return;
669
+ }
670
+ }
671
+ if (key === 'ArrowUp' ||
672
+ key === 'ArrowDown' ||
673
+ key === 'Tab' ||
674
+ key === 'Shift' ||
675
+ key === 'Enter' ||
676
+ key === 'Escape' ||
677
+ key === ' ') {
678
+ return;
679
+ }
680
+ this.navigateOut.emit('typeahead');
681
+ }
682
+ activateNavItem(nav, item) {
683
+ nav?.navigateTo(item);
684
+ }
685
+ static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "22.0.8", ngImport: i0, type: AXLookupListViewBase, deps: [], target: i0.ɵɵFactoryTarget.Directive }); }
686
+ 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 }, highlightText: { classPropertyName: "highlightText", publicName: "highlightText", 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 }); }
687
+ }
688
+ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "22.0.8", ngImport: i0, type: AXLookupListViewBase, decorators: [{
689
+ type: Directive
690
+ }], 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 }] }], highlightText: [{ type: i0.Input, args: [{ isSignal: true, alias: "highlightText", 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 }] }] } });
691
+
692
+ /**
693
+ * Internal mini component for the `drop-down-list` lookup mode:
694
+ * a predefined, virtualized list of options for picking single values.
695
+ *
696
+ * @category Components
697
+ */
698
+ class AXLookupDropDownListComponent extends AXLookupListViewBase {
699
+ static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "22.0.8", ngImport: i0, type: AXLookupDropDownListComponent, deps: null, target: i0.ɵɵFactoryTarget.Component }); }
700
+ 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: `
701
+ @if (isEmpty()) {
702
+ @if (emptyTemplate()) {
703
+ <ng-container [ngTemplateOutlet]="emptyTemplate()!" />
704
+ } @else {
705
+ <div class="ax-lookup-empty">
706
+ {{ '@acorex:common.general.no-result-found' | translate | async }}
707
+ </div>
708
+ }
709
+ } @else {
710
+ <cdk-virtual-scroll-viewport
711
+ class="ax-lookup-viewport"
712
+ role="listbox"
713
+ axListNavigation
714
+ #nav="axListNavigation"
715
+ [itemSize]="itemHeight()"
716
+ [style.height.px]="viewportHeight()"
717
+ (onKeypress)="handleListKeypress($event)"
718
+ >
719
+ <div
720
+ *cdkVirtualFor="let item of listDataSource(); let i = index; trackBy: trackByIndex"
721
+ role="option"
722
+ class="ax-lookup-option-host"
723
+ axListNavigationItem
724
+ #navItem="axListNavigationItem"
725
+ [style.height.px]="itemHeight()"
726
+ [class.ax-lookup-option]="!itemTemplate()"
727
+ [class.ax-state-alternate]="alternate() && i % 2 === 1"
728
+ [class.ax-state-selected]="item != null && isSelected(item)"
729
+ [class.ax-state-disabled]="item != null && isDisabled(item)"
730
+ [class.ax-state-active]="navItem.isActive()"
731
+ [attr.aria-selected]="item != null ? isSelected(item) : null"
732
+ (mouseenter)="activateNavItem(nav, navItem)"
733
+ (mousedown)="handleItemMouseDown($event, item)"
734
+ (onKeypress)="handleItemKeypress($event, item)"
735
+ >
736
+ @if (item != null) {
737
+ @if (itemTemplate()) {
738
+ <ng-container
739
+ [ngTemplateOutlet]="itemTemplate()!"
740
+ [ngTemplateOutletContext]="{ $implicit: item, highlightText: highlightText() }"
741
+ />
742
+ } @else {
743
+ <span class="ax-lookup-option-text">
744
+ <ax-highlight-text [text]="getText(item) | translate | async" [query]="highlightText()" />
745
+ </span>
746
+ @if (isSelected(item)) {
747
+ <span class="ax-lookup-option-check ax-icon ax-icon-check" aria-hidden="true"></span>
748
+ }
749
+ }
750
+ } @else {
751
+ <ng-container [ngTemplateOutlet]="loadingRow" />
752
+ }
753
+ </div>
754
+ </cdk-virtual-scroll-viewport>
755
+ }
756
+
757
+ <ng-template #loadingRow>
758
+ @if (loadingTemplate()) {
759
+ <ng-container [ngTemplateOutlet]="loadingTemplate()!" />
760
+ } @else {
761
+ <span class="ax-lookup-option-loading">{{ '@acorex:common.status.loading' | translate | async }}</span>
762
+ }
763
+ </ng-template>
764
+ `, 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: AXHighlightTextComponent, selector: "ax-highlight-text", inputs: ["text", "query", "highlightDisabled", "highlightOptions"] }, { kind: "pipe", type: AXTranslatorPipe, name: "translate" }, { kind: "pipe", type: AsyncPipe, name: "async" }], changeDetection: i0.ChangeDetectionStrategy.OnPush, encapsulation: i0.ViewEncapsulation.None }); }
765
+ }
766
+ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "22.0.8", ngImport: i0, type: AXLookupDropDownListComponent, decorators: [{
767
+ type: Component,
768
+ args: [{
769
+ selector: 'ax-lookup-drop-down-list',
770
+ changeDetection: ChangeDetectionStrategy.OnPush,
771
+ encapsulation: ViewEncapsulation.None,
772
+ imports: [ScrollingModule, NgTemplateOutlet, AXTranslatorPipe, AsyncPipe, AXListNavigationModule, AXHighlightTextComponent],
773
+ providers: [{ provide: AXLookupListViewBase, useExisting: AXLookupDropDownListComponent }],
774
+ template: `
775
+ @if (isEmpty()) {
776
+ @if (emptyTemplate()) {
777
+ <ng-container [ngTemplateOutlet]="emptyTemplate()!" />
778
+ } @else {
779
+ <div class="ax-lookup-empty">
780
+ {{ '@acorex:common.general.no-result-found' | translate | async }}
781
+ </div>
782
+ }
783
+ } @else {
784
+ <cdk-virtual-scroll-viewport
785
+ class="ax-lookup-viewport"
786
+ role="listbox"
787
+ axListNavigation
788
+ #nav="axListNavigation"
789
+ [itemSize]="itemHeight()"
790
+ [style.height.px]="viewportHeight()"
791
+ (onKeypress)="handleListKeypress($event)"
792
+ >
793
+ <div
794
+ *cdkVirtualFor="let item of listDataSource(); let i = index; trackBy: trackByIndex"
795
+ role="option"
796
+ class="ax-lookup-option-host"
797
+ axListNavigationItem
798
+ #navItem="axListNavigationItem"
799
+ [style.height.px]="itemHeight()"
800
+ [class.ax-lookup-option]="!itemTemplate()"
801
+ [class.ax-state-alternate]="alternate() && i % 2 === 1"
802
+ [class.ax-state-selected]="item != null && isSelected(item)"
803
+ [class.ax-state-disabled]="item != null && isDisabled(item)"
804
+ [class.ax-state-active]="navItem.isActive()"
805
+ [attr.aria-selected]="item != null ? isSelected(item) : null"
806
+ (mouseenter)="activateNavItem(nav, navItem)"
807
+ (mousedown)="handleItemMouseDown($event, item)"
808
+ (onKeypress)="handleItemKeypress($event, item)"
809
+ >
810
+ @if (item != null) {
811
+ @if (itemTemplate()) {
812
+ <ng-container
813
+ [ngTemplateOutlet]="itemTemplate()!"
814
+ [ngTemplateOutletContext]="{ $implicit: item, highlightText: highlightText() }"
815
+ />
816
+ } @else {
817
+ <span class="ax-lookup-option-text">
818
+ <ax-highlight-text [text]="getText(item) | translate | async" [query]="highlightText()" />
819
+ </span>
820
+ @if (isSelected(item)) {
821
+ <span class="ax-lookup-option-check ax-icon ax-icon-check" aria-hidden="true"></span>
822
+ }
823
+ }
824
+ } @else {
825
+ <ng-container [ngTemplateOutlet]="loadingRow" />
826
+ }
827
+ </div>
828
+ </cdk-virtual-scroll-viewport>
829
+ }
830
+
831
+ <ng-template #loadingRow>
832
+ @if (loadingTemplate()) {
833
+ <ng-container [ngTemplateOutlet]="loadingTemplate()!" />
834
+ } @else {
835
+ <span class="ax-lookup-option-loading">{{ '@acorex:common.status.loading' | translate | async }}</span>
836
+ }
837
+ </ng-template>
838
+ `,
839
+ }]
840
+ }] });
841
+
842
+ /**
843
+ * Internal mini component for the `drop-down-tree` lookup mode:
844
+ * a predefined list rendered in a tree-like structure for single item selection.
845
+ *
846
+ * @category Components
847
+ */
848
+ class AXLookupDropDownTreeComponent {
849
+ #host;
850
+ constructor() {
851
+ this.#host = inject((ElementRef));
852
+ /**
853
+ * The tree datasource: an array of nodes or a lazy children callback.
854
+ */
855
+ this.dataSource = input.required(/* @ts-ignore */
856
+ ...(ngDevMode ? [{ debugName: "dataSource" }] : /* istanbul ignore next */ []));
857
+ /**
858
+ * The node property used as the selection value (tree `idField`).
859
+ */
860
+ this.valueField = input('id', /* @ts-ignore */
861
+ ...(ngDevMode ? [{ debugName: "valueField" }] : /* istanbul ignore next */ []));
862
+ /**
863
+ * The node property used as the display text (tree `titleField`).
864
+ */
865
+ this.textField = input('title', /* @ts-ignore */
866
+ ...(ngDevMode ? [{ debugName: "textField" }] : /* istanbul ignore next */ []));
867
+ /**
868
+ * The node property marking a node as disabled.
869
+ */
870
+ this.disabledField = input('disabled', /* @ts-ignore */
871
+ ...(ngDevMode ? [{ debugName: "disabledField" }] : /* istanbul ignore next */ []));
872
+ /**
873
+ * Currently selected values (at most one for single selection).
874
+ */
875
+ this.selectedValues = input([], /* @ts-ignore */
876
+ ...(ngDevMode ? [{ debugName: "selectedValues" }] : /* istanbul ignore next */ []));
877
+ /**
878
+ * Custom template rendered for each tree node.
879
+ */
880
+ this.nodeTemplate = input(undefined, /* @ts-ignore */
881
+ ...(ngDevMode ? [{ debugName: "nodeTemplate" }] : /* istanbul ignore next */ []));
882
+ /**
883
+ * Custom template rendered when the filtered tree has no nodes.
884
+ */
885
+ this.emptyTemplate = input(undefined, /* @ts-ignore */
886
+ ...(ngDevMode ? [{ debugName: "emptyTemplate" }] : /* istanbul ignore next */ []));
887
+ /**
888
+ * Custom template rendered while the tree is hydrating for search.
889
+ */
890
+ this.loadingTemplate = input(undefined, /* @ts-ignore */
891
+ ...(ngDevMode ? [{ debugName: "loadingTemplate" }] : /* istanbul ignore next */ []));
892
+ /**
893
+ * When `true`, a loading placeholder is shown while lazy tree data is hydrated for search.
894
+ */
895
+ this.loading = input(false, /* @ts-ignore */
896
+ ...(ngDevMode ? [{ debugName: "loading" }] : /* istanbul ignore next */ []));
897
+ /**
898
+ * When `true`, visible tree nodes use alternating background colors.
899
+ */
900
+ this.alternate = input(false, /* @ts-ignore */
901
+ ...(ngDevMode ? [{ debugName: "alternate" }] : /* istanbul ignore next */ []));
902
+ /**
903
+ * Unique id that changes on every search apply so a new tree instance is created.
904
+ */
905
+ this.filterKey = input('0', /* @ts-ignore */
906
+ ...(ngDevMode ? [{ debugName: "filterKey" }] : /* istanbul ignore next */ []));
907
+ /**
908
+ * When set, matching characters in the default node label are highlighted.
909
+ */
910
+ this.highlightText = input('', /* @ts-ignore */
911
+ ...(ngDevMode ? [{ debugName: "highlightText" }] : /* istanbul ignore next */ []));
912
+ /**
913
+ * Emitted when the user selects a node.
914
+ */
915
+ this.itemClick = output();
916
+ this.selectedIds = computed(() => this.selectedValues().map((v) => String(v)), /* @ts-ignore */
917
+ ...(ngDevMode ? [{ debugName: "selectedIds" }] : /* istanbul ignore next */ []));
918
+ this.isEmpty = computed(() => {
919
+ const source = this.dataSource();
920
+ return Array.isArray(source) && source.length === 0;
921
+ }, /* @ts-ignore */
922
+ ...(ngDevMode ? [{ debugName: "isEmpty" }] : /* istanbul ignore next */ []));
923
+ this.treeInstances = computed(() => [{ id: this.filterKey(), source: this.dataSource() }], /* @ts-ignore */
924
+ ...(ngDevMode ? [{ debugName: "treeInstances" }] : /* istanbul ignore next */ []));
925
+ afterRenderEffect(() => {
926
+ const selectedId = this.selectedIds()[0];
927
+ if (!selectedId || this.isEmpty()) {
928
+ return;
929
+ }
930
+ scrollTreeToSelectedNode(this.#host.nativeElement, selectedId);
931
+ });
932
+ }
933
+ /** Whether the filtered tree currently has no nodes. */
934
+ hasNoMatches() {
935
+ return this.isEmpty();
936
+ }
937
+ handleSelectionChange(e) {
938
+ if (e.source !== 'user') {
939
+ return;
940
+ }
941
+ const node = e.selectedNodes[0];
942
+ if (!node) {
943
+ return;
944
+ }
945
+ this.itemClick.emit({ item: node, value: node[this.valueField()] });
946
+ }
947
+ static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "22.0.8", ngImport: i0, type: AXLookupDropDownTreeComponent, deps: [], target: i0.ɵɵFactoryTarget.Component }); }
948
+ 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 }, loadingTemplate: { classPropertyName: "loadingTemplate", publicName: "loadingTemplate", isSignal: true, isRequired: false, transformFunction: null }, loading: { classPropertyName: "loading", publicName: "loading", 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 }, highlightText: { classPropertyName: "highlightText", publicName: "highlightText", isSignal: true, isRequired: false, transformFunction: null } }, outputs: { itemClick: "itemClick" }, ngImport: i0, template: `
949
+ @if (loading()) {
950
+ @if (loadingTemplate()) {
951
+ <ng-container [ngTemplateOutlet]="loadingTemplate()!" />
952
+ } @else {
953
+ <div class="ax-lookup-empty">
954
+ {{ '@acorex:common.status.loading' | translate | async }}
955
+ </div>
956
+ }
957
+ } @else if (isEmpty()) {
958
+ @if (emptyTemplate()) {
959
+ <ng-container [ngTemplateOutlet]="emptyTemplate()!" />
960
+ } @else {
961
+ <div class="ax-lookup-empty">
962
+ {{ '@acorex:common.general.no-result-found' | translate | async }}
963
+ </div>
964
+ }
965
+ } @else {
966
+ <div class="ax-lookup-tree">
967
+ @for (instance of treeInstances(); track instance.id) {
968
+ <ax-tree-view
969
+ [datasource]="instance.source"
970
+ selectMode="single"
971
+ selectionBehavior="all"
972
+ [controlledSelection]="true"
973
+ [selectedIds]="selectedIds()"
974
+ [idField]="valueField()"
975
+ [titleField]="textField()"
976
+ [disabledField]="disabledField()"
977
+ [nodeTemplate]="nodeTemplate() ?? defaultNodeTemplate"
978
+ [alternate]="alternate()"
979
+ [highlightText]="highlightText()"
980
+ (onSelectionChange)="handleSelectionChange($event)"
981
+ />
982
+ }
983
+ </div>
984
+ }
985
+
986
+ <ng-template #defaultNodeTemplate let-node>
987
+ <span class="ax-lookup-tree-node-label">
988
+ <ax-highlight-text [text]="node?.[textField()] | translate | async" [query]="highlightText()" />
989
+ </span>
990
+ </ng-template>
991
+ `, 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", "highlightText", "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: "component", type: AXHighlightTextComponent, selector: "ax-highlight-text", inputs: ["text", "query", "highlightDisabled", "highlightOptions"] }, { kind: "pipe", type: AXTranslatorPipe, name: "translate" }, { kind: "pipe", type: AsyncPipe, name: "async" }], changeDetection: i0.ChangeDetectionStrategy.OnPush, encapsulation: i0.ViewEncapsulation.None }); }
992
+ }
993
+ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "22.0.8", ngImport: i0, type: AXLookupDropDownTreeComponent, decorators: [{
994
+ type: Component,
995
+ args: [{
996
+ selector: 'ax-lookup-drop-down-tree',
997
+ changeDetection: ChangeDetectionStrategy.OnPush,
998
+ encapsulation: ViewEncapsulation.None,
999
+ imports: [AXTreeViewComponent, NgTemplateOutlet, AXTranslatorPipe, AsyncPipe, AXHighlightTextComponent],
1000
+ template: `
1001
+ @if (loading()) {
1002
+ @if (loadingTemplate()) {
1003
+ <ng-container [ngTemplateOutlet]="loadingTemplate()!" />
1004
+ } @else {
1005
+ <div class="ax-lookup-empty">
1006
+ {{ '@acorex:common.status.loading' | translate | async }}
1007
+ </div>
1008
+ }
1009
+ } @else if (isEmpty()) {
1010
+ @if (emptyTemplate()) {
1011
+ <ng-container [ngTemplateOutlet]="emptyTemplate()!" />
1012
+ } @else {
1013
+ <div class="ax-lookup-empty">
1014
+ {{ '@acorex:common.general.no-result-found' | translate | async }}
1015
+ </div>
1016
+ }
1017
+ } @else {
1018
+ <div class="ax-lookup-tree">
1019
+ @for (instance of treeInstances(); track instance.id) {
1020
+ <ax-tree-view
1021
+ [datasource]="instance.source"
1022
+ selectMode="single"
1023
+ selectionBehavior="all"
1024
+ [controlledSelection]="true"
1025
+ [selectedIds]="selectedIds()"
1026
+ [idField]="valueField()"
1027
+ [titleField]="textField()"
1028
+ [disabledField]="disabledField()"
1029
+ [nodeTemplate]="nodeTemplate() ?? defaultNodeTemplate"
1030
+ [alternate]="alternate()"
1031
+ [highlightText]="highlightText()"
1032
+ (onSelectionChange)="handleSelectionChange($event)"
1033
+ />
1034
+ }
1035
+ </div>
1036
+ }
1037
+
1038
+ <ng-template #defaultNodeTemplate let-node>
1039
+ <span class="ax-lookup-tree-node-label">
1040
+ <ax-highlight-text [text]="node?.[textField()] | translate | async" [query]="highlightText()" />
1041
+ </span>
1042
+ </ng-template>
1043
+ `,
1044
+ }]
1045
+ }], 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 }] }], nodeTemplate: [{ type: i0.Input, args: [{ isSignal: true, alias: "nodeTemplate", required: false }] }], emptyTemplate: [{ type: i0.Input, args: [{ isSignal: true, alias: "emptyTemplate", required: false }] }], loadingTemplate: [{ type: i0.Input, args: [{ isSignal: true, alias: "loadingTemplate", required: false }] }], loading: [{ type: i0.Input, args: [{ isSignal: true, alias: "loading", required: false }] }], alternate: [{ type: i0.Input, args: [{ isSignal: true, alias: "alternate", required: false }] }], filterKey: [{ type: i0.Input, args: [{ isSignal: true, alias: "filterKey", required: false }] }], highlightText: [{ type: i0.Input, args: [{ isSignal: true, alias: "highlightText", required: false }] }], itemClick: [{ type: i0.Output, args: ["itemClick"] }] } });
1046
+
1047
+ /**
1048
+ * Internal mini component for the `multi-column-tree` lookup mode:
1049
+ * a multi-column `ax-data-table` with a drop-down tree inside it.
1050
+ * Rows expand/collapse via the data-table hierarchy (`parentField` / nested `children`).
1051
+ *
1052
+ * @category Components
1053
+ */
1054
+ class AXLookupMultiColumnTreeComponent {
1055
+ #host;
1056
+ constructor() {
1057
+ this.#host = inject((ElementRef));
1058
+ /**
1059
+ * The datasource providing hierarchical rows (roots on load, children via `parentField`).
1060
+ */
1061
+ this.dataSource = input.required(/* @ts-ignore */
1062
+ ...(ngDevMode ? [{ debugName: "dataSource" }] : /* istanbul ignore next */ []));
1063
+ /**
1064
+ * The item property used as the selection value (also the data-table row key).
1065
+ */
1066
+ this.valueField = input('id', /* @ts-ignore */
1067
+ ...(ngDevMode ? [{ debugName: "valueField" }] : /* istanbul ignore next */ []));
1068
+ /**
1069
+ * The item property used as the display text. The matching column shows the expand control
1070
+ * unless another column sets `expandHandler`.
1071
+ */
1072
+ this.textField = input('text', /* @ts-ignore */
1073
+ ...(ngDevMode ? [{ debugName: "textField" }] : /* istanbul ignore next */ []));
1074
+ /**
1075
+ * The item property marking an item as disabled.
1076
+ */
1077
+ this.disabledField = input('disabled', /* @ts-ignore */
1078
+ ...(ngDevMode ? [{ debugName: "disabledField" }] : /* istanbul ignore next */ []));
1079
+ /**
1080
+ * Field used by the data table to fetch children (`AXDataSource` filter on expand).
1081
+ */
1082
+ this.parentField = input('parentId', /* @ts-ignore */
1083
+ ...(ngDevMode ? [{ debugName: "parentField" }] : /* istanbul ignore next */ []));
1084
+ /**
1085
+ * Field used by the data table to decide whether a row can expand.
1086
+ */
1087
+ this.hasChildrenField = input('hasChild', /* @ts-ignore */
1088
+ ...(ngDevMode ? [{ debugName: "hasChildrenField" }] : /* istanbul ignore next */ []));
1089
+ /**
1090
+ * Currently selected values (always an array, even for single selection).
1091
+ */
1092
+ this.selectedValues = input([], /* @ts-ignore */
1093
+ ...(ngDevMode ? [{ debugName: "selectedValues" }] : /* istanbul ignore next */ []));
1094
+ /**
1095
+ * The fixed row height in pixels passed to the data table.
1096
+ */
1097
+ this.itemHeight = input(40, /* @ts-ignore */
1098
+ ...(ngDevMode ? [{ debugName: "itemHeight" }] : /* istanbul ignore next */ []));
1099
+ /**
1100
+ * The maximum number of body rows visible before the table scrolls.
1101
+ */
1102
+ this.maxVisibleItems = input(8, /* @ts-ignore */
1103
+ ...(ngDevMode ? [{ debugName: "maxVisibleItems" }] : /* istanbul ignore next */ []));
1104
+ /**
1105
+ * Column definitions rendered as `ax-text-column` instances.
1106
+ */
1107
+ this.columns = input([], /* @ts-ignore */
1108
+ ...(ngDevMode ? [{ debugName: "columns" }] : /* istanbul ignore next */ []));
1109
+ /**
1110
+ * Optional custom row content. Context: `$implicit` is the row item.
1111
+ * When set, replaces the default multi-column cell layout.
1112
+ */
1113
+ this.itemTemplate = input(undefined, /* @ts-ignore */
1114
+ ...(ngDevMode ? [{ debugName: "itemTemplate" }] : /* istanbul ignore next */ []));
1115
+ /**
1116
+ * Custom template rendered when the datasource has no items.
1117
+ */
1118
+ this.emptyTemplate = input(undefined, /* @ts-ignore */
1119
+ ...(ngDevMode ? [{ debugName: "emptyTemplate" }] : /* istanbul ignore next */ []));
1120
+ /**
1121
+ * Custom template rendered while the table is loading.
1122
+ */
1123
+ this.loadingTemplate = input(undefined, /* @ts-ignore */
1124
+ ...(ngDevMode ? [{ debugName: "loadingTemplate" }] : /* istanbul ignore next */ []));
1125
+ /**
1126
+ * When `true`, table rows use alternating background colors for easier scanning.
1127
+ */
1128
+ this.alternate = input(false, /* @ts-ignore */
1129
+ ...(ngDevMode ? [{ debugName: "alternate" }] : /* istanbul ignore next */ []));
1130
+ /**
1131
+ * When set, matching text in table cells is highlighted.
1132
+ */
1133
+ this.highlightText = input('', /* @ts-ignore */
1134
+ ...(ngDevMode ? [{ debugName: "highlightText" }] : /* istanbul ignore next */ []));
1135
+ /**
1136
+ * Emitted when the user picks a row (not when expanding/collapsing).
1137
+ */
1138
+ this.itemClick = output();
1139
+ /**
1140
+ * Header (~40px) + up to `maxVisibleItems` body rows. Expanded children scroll inside.
1141
+ */
1142
+ this.tableHeight = computed(() => 40 + this.maxVisibleItems() * this.itemHeight(), /* @ts-ignore */
1143
+ ...(ngDevMode ? [{ debugName: "tableHeight" }] : /* istanbul ignore next */ []));
1144
+ this.loadingConfig = computed(() => ({
1145
+ enabled: true,
1146
+ animation: true,
1147
+ loadingTemplate: this.loadingTemplate(),
1148
+ }), /* @ts-ignore */
1149
+ ...(ngDevMode ? [{ debugName: "loadingConfig" }] : /* istanbul ignore next */ []));
1150
+ this.resolveRowCssClass = (row) => {
1151
+ const item = row;
1152
+ if (!item) {
1153
+ return '';
1154
+ }
1155
+ const classes = [];
1156
+ if (this.isSelected(item)) {
1157
+ classes.push('ax-state-selected');
1158
+ }
1159
+ if (this.isDisabled(item)) {
1160
+ classes.push('ax-state-disabled');
1161
+ }
1162
+ return classes.join(' ');
1163
+ };
1164
+ afterRenderEffect(() => {
1165
+ if (this.selectedValues().length === 0) {
1166
+ return;
1167
+ }
1168
+ scrollTableToSelectedRow(this.#host.nativeElement);
1169
+ });
1170
+ }
1171
+ /** Stable unique key for `@for` — avoids NG0955 when `field` is missing or duplicated. */
1172
+ trackColumnKey(index, column) {
1173
+ return `${column?.field ?? ''}::${index}`;
1174
+ }
1175
+ resolveColumnWidth(column) {
1176
+ const width = column.width?.trim();
1177
+ if (!width || width.includes('fr')) {
1178
+ return 'auto';
1179
+ }
1180
+ return width;
1181
+ }
1182
+ isExpandColumn(index, column) {
1183
+ if (column.expandHandler === true) {
1184
+ return true;
1185
+ }
1186
+ if (this.columns().some((item) => item.expandHandler === true)) {
1187
+ return false;
1188
+ }
1189
+ const textIndex = this.columns().findIndex((item) => item.field === this.textField());
1190
+ return (textIndex === -1 ? 0 : textIndex) === index;
1191
+ }
1192
+ handleRowClick(event) {
1193
+ this.handleItemClick(event.data);
1194
+ }
1195
+ handleItemClick(item) {
1196
+ if (!item || this.isDisabled(item)) {
1197
+ return;
1198
+ }
1199
+ this.itemClick.emit({ item, value: this.getValue(item) });
1200
+ }
1201
+ handleItemMouseDown(event, item) {
1202
+ event.preventDefault();
1203
+ event.stopPropagation();
1204
+ this.handleItemClick(item);
1205
+ }
1206
+ isSelected(item) {
1207
+ const value = this.getValue(item);
1208
+ return this.selectedValues().some((v) => v == value);
1209
+ }
1210
+ isDisabled(item) {
1211
+ return Boolean(item?.[this.disabledField()]);
1212
+ }
1213
+ getValue(item) {
1214
+ return item?.[this.valueField()];
1215
+ }
1216
+ static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "22.0.8", ngImport: i0, type: AXLookupMultiColumnTreeComponent, deps: [], target: i0.ɵɵFactoryTarget.Component }); }
1217
+ 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 }, highlightText: { classPropertyName: "highlightText", publicName: "highlightText", 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: `
1218
+ <ax-data-table
1219
+ class="ax-lookup-multi-column-table"
1220
+ look="minimal"
1221
+ [dataSource]="dataSource()"
1222
+ [parentField]="parentField()"
1223
+ [hasChildrenField]="hasChildrenField()"
1224
+ [itemHeight]="itemHeight()"
1225
+ [alternative]="alternate()"
1226
+ [emptyTemplate]="emptyTemplate()"
1227
+ [highlightText]="highlightText()"
1228
+ [loading]="loadingConfig()"
1229
+ [paging]="false"
1230
+ [showHeader]="true"
1231
+ [fixedHeader]="true"
1232
+ [showFooter]="false"
1233
+ [allowReordering]="false"
1234
+ [rowTemplate]="itemTemplate() ? customRowTemplate : undefined"
1235
+ [rowCssClass]="resolveRowCssClass"
1236
+ (onRowClick)="handleRowClick($event)"
1237
+ >
1238
+ @for (column of columns(); track trackColumnKey($index, column)) {
1239
+ <ax-text-column
1240
+ [dataField]="column.field"
1241
+ [caption]="column.title | translate | async"
1242
+ [translate]="true"
1243
+ [width]="resolveColumnWidth(column)"
1244
+ [expandHandler]="isExpandColumn($index, column)"
1245
+ [allowSorting]="false"
1246
+ [allowResizing]="false"
1247
+ />
1248
+ }
1249
+ </ax-data-table>
1250
+
1251
+ <ng-template #customRowTemplate let-ctx>
1252
+ <tr
1253
+ [class.ax-state-selected]="ctx.data != null && isSelected(ctx.data)"
1254
+ [class.ax-state-disabled]="ctx.data != null && isDisabled(ctx.data)"
1255
+ [style.height.px]="itemHeight()"
1256
+ [style.max-height.px]="itemHeight()"
1257
+ (mousedown)="handleItemMouseDown($event, ctx.data)"
1258
+ >
1259
+ <td [attr.colspan]="columns().length || 1">
1260
+ @if (ctx.data != null && itemTemplate()) {
1261
+ <ng-container
1262
+ [ngTemplateOutlet]="itemTemplate()!"
1263
+ [ngTemplateOutletContext]="{ $implicit: ctx.data, highlightText: highlightText() }"
1264
+ />
1265
+ }
1266
+ </td>
1267
+ </tr>
1268
+ </ng-template>
1269
+ `, 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", "translate", "cellTemplate", "footerTemplate", "headerTemplate", "format", "formatOptions"] }, { kind: "pipe", type: AsyncPipe, name: "async" }, { kind: "pipe", type: AXTranslatorPipe, name: "translate" }], changeDetection: i0.ChangeDetectionStrategy.OnPush, encapsulation: i0.ViewEncapsulation.None }); }
1270
+ }
1271
+ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "22.0.8", ngImport: i0, type: AXLookupMultiColumnTreeComponent, decorators: [{
1272
+ type: Component,
1273
+ args: [{
1274
+ selector: 'ax-lookup-multi-column-tree',
1275
+ changeDetection: ChangeDetectionStrategy.OnPush,
1276
+ encapsulation: ViewEncapsulation.None,
1277
+ imports: [NgTemplateOutlet, AsyncPipe, AXTranslatorPipe, AXDataTableComponent, AXDataTableTextColumnComponent],
1278
+ host: {
1279
+ class: 'ax-lookup-multi-column ax-lookup-multi-column-tree',
1280
+ '[style.height.px]': 'tableHeight()',
1281
+ },
1282
+ template: `
1283
+ <ax-data-table
1284
+ class="ax-lookup-multi-column-table"
1285
+ look="minimal"
1286
+ [dataSource]="dataSource()"
1287
+ [parentField]="parentField()"
1288
+ [hasChildrenField]="hasChildrenField()"
1289
+ [itemHeight]="itemHeight()"
1290
+ [alternative]="alternate()"
1291
+ [emptyTemplate]="emptyTemplate()"
1292
+ [highlightText]="highlightText()"
1293
+ [loading]="loadingConfig()"
1294
+ [paging]="false"
1295
+ [showHeader]="true"
1296
+ [fixedHeader]="true"
1297
+ [showFooter]="false"
1298
+ [allowReordering]="false"
1299
+ [rowTemplate]="itemTemplate() ? customRowTemplate : undefined"
1300
+ [rowCssClass]="resolveRowCssClass"
1301
+ (onRowClick)="handleRowClick($event)"
1302
+ >
1303
+ @for (column of columns(); track trackColumnKey($index, column)) {
1304
+ <ax-text-column
1305
+ [dataField]="column.field"
1306
+ [caption]="column.title | translate | async"
1307
+ [translate]="true"
1308
+ [width]="resolveColumnWidth(column)"
1309
+ [expandHandler]="isExpandColumn($index, column)"
1310
+ [allowSorting]="false"
1311
+ [allowResizing]="false"
1312
+ />
1313
+ }
1314
+ </ax-data-table>
1315
+
1316
+ <ng-template #customRowTemplate let-ctx>
1317
+ <tr
1318
+ [class.ax-state-selected]="ctx.data != null && isSelected(ctx.data)"
1319
+ [class.ax-state-disabled]="ctx.data != null && isDisabled(ctx.data)"
1320
+ [style.height.px]="itemHeight()"
1321
+ [style.max-height.px]="itemHeight()"
1322
+ (mousedown)="handleItemMouseDown($event, ctx.data)"
1323
+ >
1324
+ <td [attr.colspan]="columns().length || 1">
1325
+ @if (ctx.data != null && itemTemplate()) {
1326
+ <ng-container
1327
+ [ngTemplateOutlet]="itemTemplate()!"
1328
+ [ngTemplateOutletContext]="{ $implicit: ctx.data, highlightText: highlightText() }"
1329
+ />
1330
+ }
1331
+ </td>
1332
+ </tr>
1333
+ </ng-template>
1334
+ `,
1335
+ }]
1336
+ }], 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 }] }], 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 }] }], highlightText: [{ type: i0.Input, args: [{ isSignal: true, alias: "highlightText", required: false }] }], itemClick: [{ type: i0.Output, args: ["itemClick"] }] } });
1337
+
1338
+ /**
1339
+ * Internal mini component for the `multi-column` lookup mode:
1340
+ * renders selectable rows in an `ax-data-table` grid and loads further
1341
+ * pages as the user scrolls (no pager UI).
1342
+ *
1343
+ * @category Components
1344
+ */
1345
+ class AXLookupMultiColumnComponent {
1346
+ /** Accumulated rows fed to the table (grows as pages are scrolled in). */
1347
+ #loadedItems;
1348
+ /** Total matching rows from the source (used to size the popup). */
1349
+ #totalCount;
1350
+ #host;
1351
+ constructor() {
1352
+ /**
1353
+ * The datasource providing the grid rows (paged, remote-capable).
1354
+ * Pages are fetched on demand as the user scrolls the table body.
1355
+ */
1356
+ this.dataSource = input.required(/* @ts-ignore */
1357
+ ...(ngDevMode ? [{ debugName: "dataSource" }] : /* istanbul ignore next */ []));
1358
+ /**
1359
+ * The item property used as the selection value.
1360
+ */
1361
+ this.valueField = input('id', /* @ts-ignore */
1362
+ ...(ngDevMode ? [{ debugName: "valueField" }] : /* istanbul ignore next */ []));
1363
+ /**
1364
+ * The item property used as the display text.
1365
+ */
1366
+ this.textField = input('text', /* @ts-ignore */
1367
+ ...(ngDevMode ? [{ debugName: "textField" }] : /* istanbul ignore next */ []));
1368
+ /**
1369
+ * The item property marking an item as disabled.
1370
+ */
1371
+ this.disabledField = input('disabled', /* @ts-ignore */
1372
+ ...(ngDevMode ? [{ debugName: "disabledField" }] : /* istanbul ignore next */ []));
1373
+ /**
1374
+ * Currently selected values (always an array, even for single selection).
1375
+ */
1376
+ this.selectedValues = input([], /* @ts-ignore */
1377
+ ...(ngDevMode ? [{ debugName: "selectedValues" }] : /* istanbul ignore next */ []));
1378
+ /**
1379
+ * The fixed row height in pixels passed to the data table.
1380
+ */
1381
+ this.itemHeight = input(40, /* @ts-ignore */
1382
+ ...(ngDevMode ? [{ debugName: "itemHeight" }] : /* istanbul ignore next */ []));
1383
+ /**
1384
+ * The maximum number of body rows visible before the table scrolls.
1385
+ */
1386
+ this.maxVisibleItems = input(8, /* @ts-ignore */
1387
+ ...(ngDevMode ? [{ debugName: "maxVisibleItems" }] : /* istanbul ignore next */ []));
1388
+ /**
1389
+ * Column definitions rendered as `ax-text-column` instances.
1390
+ */
1391
+ this.columns = input([], /* @ts-ignore */
1392
+ ...(ngDevMode ? [{ debugName: "columns" }] : /* istanbul ignore next */ []));
1393
+ /**
1394
+ * Optional custom row content. Context: `$implicit` is the row item.
1395
+ * When set, replaces the default multi-column cell layout.
1396
+ */
1397
+ this.itemTemplate = input(undefined, /* @ts-ignore */
1398
+ ...(ngDevMode ? [{ debugName: "itemTemplate" }] : /* istanbul ignore next */ []));
1399
+ /**
1400
+ * Custom template rendered when the datasource has no items.
1401
+ */
1402
+ this.emptyTemplate = input(undefined, /* @ts-ignore */
1403
+ ...(ngDevMode ? [{ debugName: "emptyTemplate" }] : /* istanbul ignore next */ []));
1404
+ /**
1405
+ * Custom template rendered while the table is loading.
1406
+ */
1407
+ this.loadingTemplate = input(undefined, /* @ts-ignore */
1408
+ ...(ngDevMode ? [{ debugName: "loadingTemplate" }] : /* istanbul ignore next */ []));
1409
+ /**
1410
+ * When `true`, table rows use alternating background colors for easier scanning.
1411
+ */
1412
+ this.alternate = input(false, /* @ts-ignore */
1413
+ ...(ngDevMode ? [{ debugName: "alternate" }] : /* istanbul ignore next */ []));
1414
+ /**
1415
+ * When set, matching text in table cells is highlighted.
1416
+ */
1417
+ this.highlightText = input('', /* @ts-ignore */
1418
+ ...(ngDevMode ? [{ debugName: "highlightText" }] : /* istanbul ignore next */ []));
1419
+ /**
1420
+ * Emitted when the user picks a row.
1421
+ */
1422
+ this.itemClick = output();
1423
+ this.tableRef = viewChild(AXDataTableComponent, /* @ts-ignore */
1424
+ ...(ngDevMode ? [{ debugName: "tableRef" }] : /* istanbul ignore next */ []));
1425
+ /** Accumulated rows fed to the table (grows as pages are scrolled in). */
1426
+ this.#loadedItems = [];
1427
+ /** Total matching rows from the source (used to size the popup). */
1428
+ this.#totalCount = signal(0, /* @ts-ignore */
1429
+ ...(ngDevMode ? [{ debugName: "#totalCount" }] : /* istanbul ignore next */ []));
1430
+ /**
1431
+ * Local table source: one page of whatever has been scrolled in so far.
1432
+ * Kept as a stable instance so the table host is not recreated on each page load.
1433
+ * `pageSize` grows with `#loadedItems` — never seed with a huge empty array (data-table
1434
+ * initializes `displayedRows` as `new Array(pageSize)`, which caused NG0955-level jank).
1435
+ */
1436
+ this.tableDataSource = new AXDataSource({
1437
+ pageSize: 1,
1438
+ key: 'id',
1439
+ load: async () => ({
1440
+ items: this.#loadedItems,
1441
+ total: this.#loadedItems.length,
1442
+ }),
1443
+ });
1444
+ /**
1445
+ * Header (~40px) + body rows. Grows with results up to `maxVisibleItems`,
1446
+ * then the table body scrolls for the rest.
1447
+ */
1448
+ this.tableHeight = computed(() => {
1449
+ const header = 40;
1450
+ const total = this.#totalCount();
1451
+ const rows = total > 0 ? total : Math.min(3, this.maxVisibleItems());
1452
+ return header + Math.min(rows, this.maxVisibleItems()) * this.itemHeight();
1453
+ }, /* @ts-ignore */
1454
+ ...(ngDevMode ? [{ debugName: "tableHeight" }] : /* istanbul ignore next */ []));
1455
+ this.loadingConfig = computed(() => ({
1456
+ enabled: true,
1457
+ animation: true,
1458
+ loadingTemplate: this.loadingTemplate(),
1459
+ }), /* @ts-ignore */
1460
+ ...(ngDevMode ? [{ debugName: "loadingConfig" }] : /* istanbul ignore next */ []));
1461
+ this.#host = inject((ElementRef));
1462
+ this.resolveRowCssClass = (row) => {
1463
+ const item = row;
1464
+ if (!item) {
1465
+ return '';
1466
+ }
1467
+ const classes = [];
1468
+ if (this.isSelected(item)) {
1469
+ classes.push('ax-state-selected');
1470
+ }
1471
+ if (this.isDisabled(item)) {
1472
+ classes.push('ax-state-disabled');
1473
+ }
1474
+ return classes.join(' ');
1475
+ };
1476
+ afterRenderEffect(() => {
1477
+ if (this.selectedValues().length === 0 || this.#totalCount() === 0) {
1478
+ return;
1479
+ }
1480
+ scrollTableToSelectedRow(this.#host.nativeElement);
1481
+ });
1482
+ effect((onCleanup) => {
1483
+ const source = this.dataSource();
1484
+ this.tableDataSource.config.key = source.config.key || this.valueField();
1485
+ untracked(() => {
1486
+ this.#applyLoadedItems(source.cachedItems, source.totalCount);
1487
+ });
1488
+ const changedSub = source.onChanged.subscribe((event) => {
1489
+ this.#applyLoadedItems(event.cachedItems, event.totalCount);
1490
+ });
1491
+ // Fetch page 0 only when the source has never loaded. Reopen remounts this
1492
+ // view; setPage(0) is a no-op on a warm source and must not force a new API call.
1493
+ queueMicrotask(() => {
1494
+ if (!source.cachedItems.some((item) => item != null)) {
1495
+ source.setPage(0);
1496
+ }
1497
+ });
1498
+ onCleanup(() => changedSub.unsubscribe());
1499
+ });
1500
+ effect((onCleanup) => {
1501
+ // Rebind when the table instance appears / source changes.
1502
+ this.tableRef();
1503
+ this.dataSource();
1504
+ let scrollSub;
1505
+ const timer = setTimeout(() => {
1506
+ const wrapper = this.tableRef()?.getHostElement()?.querySelector('.ax-data-table-wrapper') ??
1507
+ this.#host.nativeElement.querySelector('.ax-data-table-wrapper');
1508
+ if (!wrapper) {
1509
+ return;
1510
+ }
1511
+ scrollSub = fromEvent(wrapper, 'scroll')
1512
+ .pipe(auditTime(80))
1513
+ .subscribe(() => this.#tryLoadMore(wrapper));
1514
+ }, 0);
1515
+ onCleanup(() => {
1516
+ clearTimeout(timer);
1517
+ scrollSub?.unsubscribe();
1518
+ });
1519
+ });
1520
+ }
1521
+ /** Stable unique key for `@for` — avoids NG0955 when `field` is missing or duplicated. */
1522
+ trackColumnKey(index, column) {
1523
+ return `${column?.field ?? ''}::${index}`;
1524
+ }
1525
+ resolveColumnWidth(column) {
1526
+ const width = column.width?.trim();
1527
+ if (!width || width.includes('fr')) {
1528
+ return 'auto';
1529
+ }
1530
+ return width;
1531
+ }
1532
+ #applyLoadedItems(cachedItems, totalCount) {
1533
+ this.#loadedItems = cachedItems.filter((item) => item != null);
1534
+ this.#totalCount.set(totalCount);
1535
+ this.#syncTablePageSize();
1536
+ this.tableDataSource.refresh({ reset: true });
1537
+ }
1538
+ #syncTablePageSize() {
1539
+ this.tableDataSource.config.pageSize = Math.max(this.#loadedItems.length, 1);
1540
+ }
1541
+ handleRowClick(event) {
1542
+ this.handleItemClick(event.data);
1543
+ }
1544
+ handleItemClick(item) {
1545
+ if (!item || this.isDisabled(item)) {
1546
+ return;
1547
+ }
1548
+ this.itemClick.emit({ item, value: this.getValue(item) });
1549
+ }
1550
+ handleItemMouseDown(event, item) {
1551
+ event.preventDefault();
1552
+ event.stopPropagation();
1553
+ this.handleItemClick(item);
1554
+ }
1555
+ isSelected(item) {
1556
+ const value = this.getValue(item);
1557
+ return this.selectedValues().some((v) => v == value);
1558
+ }
1559
+ isDisabled(item) {
1560
+ return Boolean(item?.[this.disabledField()]);
1561
+ }
1562
+ #tryLoadMore(wrapper) {
1563
+ const nearBottom = wrapper.scrollTop + wrapper.clientHeight >= wrapper.scrollHeight - 48;
1564
+ if (!nearBottom) {
1565
+ return;
1566
+ }
1567
+ const source = this.dataSource();
1568
+ if (source.isLoading || source.totalCount === 0) {
1569
+ return;
1570
+ }
1571
+ const loadedCount = source.cachedItems.filter((item) => item != null).length;
1572
+ if (loadedCount >= source.totalCount) {
1573
+ return;
1574
+ }
1575
+ const nextPage = Math.floor(loadedCount / source.pageSize);
1576
+ source.setPage(nextPage);
1577
+ }
1578
+ getValue(item) {
1579
+ return item?.[this.valueField()];
1580
+ }
1581
+ static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "22.0.8", ngImport: i0, type: AXLookupMultiColumnComponent, deps: [], target: i0.ɵɵFactoryTarget.Component }); }
1582
+ 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 }, highlightText: { classPropertyName: "highlightText", publicName: "highlightText", 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: `
1583
+ <ax-data-table
1584
+ class="ax-lookup-multi-column-table"
1585
+ look="minimal"
1586
+ [dataSource]="tableDataSource"
1587
+ [itemHeight]="itemHeight()"
1588
+ [alternative]="alternate()"
1589
+ [emptyTemplate]="emptyTemplate()"
1590
+ [highlightText]="highlightText()"
1591
+ [loading]="loadingConfig()"
1592
+ [paging]="false"
1593
+ [showHeader]="true"
1594
+ [fixedHeader]="true"
1595
+ [showFooter]="false"
1596
+ [allowReordering]="false"
1597
+ [rowTemplate]="itemTemplate() ? customRowTemplate : undefined"
1598
+ [rowCssClass]="resolveRowCssClass"
1599
+ (onRowClick)="handleRowClick($event)"
1600
+ >
1601
+ @for (column of columns(); track trackColumnKey($index, column)) {
1602
+ <ax-text-column
1603
+ [dataField]="column.field"
1604
+ [caption]="column.title | translate | async"
1605
+ [translate]="true"
1606
+ [width]="resolveColumnWidth(column)"
1607
+ [allowSorting]="false"
1608
+ [allowResizing]="false"
1609
+ />
1610
+ }
1611
+ </ax-data-table>
1612
+
1613
+ <ng-template #customRowTemplate let-ctx>
1614
+ <tr
1615
+ [class.ax-state-selected]="ctx.data != null && isSelected(ctx.data)"
1616
+ [class.ax-state-disabled]="ctx.data != null && isDisabled(ctx.data)"
1617
+ [style.height.px]="itemHeight()"
1618
+ [style.max-height.px]="itemHeight()"
1619
+ (mousedown)="handleItemMouseDown($event, ctx.data)"
1620
+ >
1621
+ <td [attr.colspan]="columns().length || 1">
1622
+ @if (ctx.data != null && itemTemplate()) {
1623
+ <ng-container
1624
+ [ngTemplateOutlet]="itemTemplate()!"
1625
+ [ngTemplateOutletContext]="{ $implicit: ctx.data, highlightText: highlightText() }"
1626
+ />
1627
+ }
1628
+ </td>
1629
+ </tr>
1630
+ </ng-template>
1631
+ `, 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", "translate", "cellTemplate", "footerTemplate", "headerTemplate", "format", "formatOptions"] }, { kind: "pipe", type: AsyncPipe, name: "async" }, { kind: "pipe", type: AXTranslatorPipe, name: "translate" }], changeDetection: i0.ChangeDetectionStrategy.OnPush, encapsulation: i0.ViewEncapsulation.None }); }
1632
+ }
1633
+ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "22.0.8", ngImport: i0, type: AXLookupMultiColumnComponent, decorators: [{
1634
+ type: Component,
1635
+ args: [{
1636
+ selector: 'ax-lookup-multi-column',
1637
+ changeDetection: ChangeDetectionStrategy.OnPush,
1638
+ encapsulation: ViewEncapsulation.None,
1639
+ imports: [NgTemplateOutlet, AsyncPipe, AXTranslatorPipe, AXDataTableComponent, AXDataTableTextColumnComponent],
1640
+ host: {
1641
+ class: 'ax-lookup-multi-column',
1642
+ '[style.height.px]': 'tableHeight()',
1643
+ },
1644
+ template: `
1645
+ <ax-data-table
1646
+ class="ax-lookup-multi-column-table"
1647
+ look="minimal"
1648
+ [dataSource]="tableDataSource"
1649
+ [itemHeight]="itemHeight()"
1650
+ [alternative]="alternate()"
1651
+ [emptyTemplate]="emptyTemplate()"
1652
+ [highlightText]="highlightText()"
1653
+ [loading]="loadingConfig()"
1654
+ [paging]="false"
1655
+ [showHeader]="true"
1656
+ [fixedHeader]="true"
1657
+ [showFooter]="false"
1658
+ [allowReordering]="false"
1659
+ [rowTemplate]="itemTemplate() ? customRowTemplate : undefined"
1660
+ [rowCssClass]="resolveRowCssClass"
1661
+ (onRowClick)="handleRowClick($event)"
1662
+ >
1663
+ @for (column of columns(); track trackColumnKey($index, column)) {
1664
+ <ax-text-column
1665
+ [dataField]="column.field"
1666
+ [caption]="column.title | translate | async"
1667
+ [translate]="true"
1668
+ [width]="resolveColumnWidth(column)"
1669
+ [allowSorting]="false"
1670
+ [allowResizing]="false"
1671
+ />
1672
+ }
1673
+ </ax-data-table>
1674
+
1675
+ <ng-template #customRowTemplate let-ctx>
1676
+ <tr
1677
+ [class.ax-state-selected]="ctx.data != null && isSelected(ctx.data)"
1678
+ [class.ax-state-disabled]="ctx.data != null && isDisabled(ctx.data)"
1679
+ [style.height.px]="itemHeight()"
1680
+ [style.max-height.px]="itemHeight()"
1681
+ (mousedown)="handleItemMouseDown($event, ctx.data)"
1682
+ >
1683
+ <td [attr.colspan]="columns().length || 1">
1684
+ @if (ctx.data != null && itemTemplate()) {
1685
+ <ng-container
1686
+ [ngTemplateOutlet]="itemTemplate()!"
1687
+ [ngTemplateOutletContext]="{ $implicit: ctx.data, highlightText: highlightText() }"
1688
+ />
1689
+ }
1690
+ </td>
1691
+ </tr>
1692
+ </ng-template>
1693
+ `,
1694
+ }]
1695
+ }], 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 }] }], highlightText: [{ type: i0.Input, args: [{ isSignal: true, alias: "highlightText", required: false }] }], itemClick: [{ type: i0.Output, args: ["itemClick"] }], tableRef: [{ type: i0.ViewChild, args: [i0.forwardRef(() => AXDataTableComponent), { isSignal: true }] }] } });
1696
+
1697
+ /**
1698
+ * Internal mini component for the `multi-select-tree` lookup mode:
1699
+ * a predefined list rendered in a tree-like structure for multiple item selection.
1700
+ *
1701
+ * @category Components
1702
+ */
1703
+ class AXLookupMultiSelectTreeComponent {
1704
+ #host;
1705
+ constructor() {
1706
+ this.#host = inject((ElementRef));
1707
+ /**
1708
+ * The tree datasource: an array of nodes or a lazy children callback.
1709
+ */
1710
+ this.dataSource = input.required(/* @ts-ignore */
1711
+ ...(ngDevMode ? [{ debugName: "dataSource" }] : /* istanbul ignore next */ []));
1712
+ /**
1713
+ * The node property used as the selection value (tree `idField`).
1714
+ */
1715
+ this.valueField = input('id', /* @ts-ignore */
1716
+ ...(ngDevMode ? [{ debugName: "valueField" }] : /* istanbul ignore next */ []));
1717
+ /**
1718
+ * The node property used as the display text (tree `titleField`).
1719
+ */
1720
+ this.textField = input('title', /* @ts-ignore */
1721
+ ...(ngDevMode ? [{ debugName: "textField" }] : /* istanbul ignore next */ []));
1722
+ /**
1723
+ * The node property marking a node as disabled.
1724
+ */
1725
+ this.disabledField = input('disabled', /* @ts-ignore */
1726
+ ...(ngDevMode ? [{ debugName: "disabledField" }] : /* istanbul ignore next */ []));
1727
+ /**
1728
+ * Currently selected values.
1729
+ */
1730
+ this.selectedValues = input([], /* @ts-ignore */
1731
+ ...(ngDevMode ? [{ debugName: "selectedValues" }] : /* istanbul ignore next */ []));
1732
+ /**
1733
+ * How selecting parent/child nodes affects each other. Passed through to the tree-view.
1734
+ */
1735
+ this.selectionBehavior = input('all', /* @ts-ignore */
1736
+ ...(ngDevMode ? [{ debugName: "selectionBehavior" }] : /* istanbul ignore next */ []));
1737
+ /**
1738
+ * Custom template rendered for each tree node.
1739
+ */
1740
+ this.nodeTemplate = input(undefined, /* @ts-ignore */
1741
+ ...(ngDevMode ? [{ debugName: "nodeTemplate" }] : /* istanbul ignore next */ []));
1742
+ /**
1743
+ * Custom template rendered when the filtered tree has no nodes.
1744
+ */
1745
+ this.emptyTemplate = input(undefined, /* @ts-ignore */
1746
+ ...(ngDevMode ? [{ debugName: "emptyTemplate" }] : /* istanbul ignore next */ []));
1747
+ /**
1748
+ * Custom template rendered while the tree is hydrating for search.
1749
+ */
1750
+ this.loadingTemplate = input(undefined, /* @ts-ignore */
1751
+ ...(ngDevMode ? [{ debugName: "loadingTemplate" }] : /* istanbul ignore next */ []));
1752
+ /**
1753
+ * When `true`, a loading placeholder is shown while lazy tree data is hydrated for search.
1754
+ */
1755
+ this.loading = input(false, /* @ts-ignore */
1756
+ ...(ngDevMode ? [{ debugName: "loading" }] : /* istanbul ignore next */ []));
1757
+ /**
1758
+ * When `true`, visible tree nodes use alternating background colors.
1759
+ */
1760
+ this.alternate = input(false, /* @ts-ignore */
1761
+ ...(ngDevMode ? [{ debugName: "alternate" }] : /* istanbul ignore next */ []));
1762
+ /**
1763
+ * Unique id that changes on every search apply so a new tree instance is created.
1764
+ */
1765
+ this.filterKey = input('0', /* @ts-ignore */
1766
+ ...(ngDevMode ? [{ debugName: "filterKey" }] : /* istanbul ignore next */ []));
1767
+ /**
1768
+ * When set, matching characters in the default node label are highlighted.
1769
+ */
1770
+ this.highlightText = input('', /* @ts-ignore */
1771
+ ...(ngDevMode ? [{ debugName: "highlightText" }] : /* istanbul ignore next */ []));
1772
+ /**
1773
+ * Emitted when the user changes the tree selection.
1774
+ */
1775
+ this.selectionChange = output();
1776
+ this.selectedIds = computed(() => this.selectedValues().map((v) => String(v)), /* @ts-ignore */
1777
+ ...(ngDevMode ? [{ debugName: "selectedIds" }] : /* istanbul ignore next */ []));
1778
+ this.isEmpty = computed(() => {
1779
+ const source = this.dataSource();
1780
+ return Array.isArray(source) && source.length === 0;
1781
+ }, /* @ts-ignore */
1782
+ ...(ngDevMode ? [{ debugName: "isEmpty" }] : /* istanbul ignore next */ []));
1783
+ this.treeInstances = computed(() => [{ id: this.filterKey(), source: this.dataSource() }], /* @ts-ignore */
1784
+ ...(ngDevMode ? [{ debugName: "treeInstances" }] : /* istanbul ignore next */ []));
1785
+ afterRenderEffect(() => {
1786
+ const selectedId = this.selectedIds()[0];
1787
+ if (!selectedId || this.isEmpty()) {
1788
+ return;
1789
+ }
1790
+ scrollTreeToSelectedNode(this.#host.nativeElement, selectedId);
1791
+ });
1792
+ }
1793
+ /** Whether the filtered tree currently has no nodes. */
1794
+ hasNoMatches() {
1795
+ return this.isEmpty();
1796
+ }
1797
+ handleSelectionChange(e) {
1798
+ if (e.source !== 'user') {
1799
+ return;
1800
+ }
1801
+ this.selectionChange.emit({ ids: e.selectedIds, nodes: e.selectedNodes });
1802
+ }
1803
+ static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "22.0.8", ngImport: i0, type: AXLookupMultiSelectTreeComponent, deps: [], target: i0.ɵɵFactoryTarget.Component }); }
1804
+ 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 }, loadingTemplate: { classPropertyName: "loadingTemplate", publicName: "loadingTemplate", isSignal: true, isRequired: false, transformFunction: null }, loading: { classPropertyName: "loading", publicName: "loading", 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 }, highlightText: { classPropertyName: "highlightText", publicName: "highlightText", isSignal: true, isRequired: false, transformFunction: null } }, outputs: { selectionChange: "selectionChange" }, ngImport: i0, template: `
1805
+ @if (loading()) {
1806
+ @if (loadingTemplate()) {
1807
+ <ng-container [ngTemplateOutlet]="loadingTemplate()!" />
1808
+ } @else {
1809
+ <div class="ax-lookup-empty">
1810
+ {{ '@acorex:common.status.loading' | translate | async }}
1811
+ </div>
1812
+ }
1813
+ } @else if (isEmpty()) {
1814
+ @if (emptyTemplate()) {
1815
+ <ng-container [ngTemplateOutlet]="emptyTemplate()!" />
1816
+ } @else {
1817
+ <div class="ax-lookup-empty">
1818
+ {{ '@acorex:common.general.no-result-found' | translate | async }}
1819
+ </div>
1820
+ }
1821
+ } @else {
1822
+ <div class="ax-lookup-tree">
1823
+ @for (instance of treeInstances(); track instance.id) {
1824
+ <ax-tree-view
1825
+ [datasource]="instance.source"
1826
+ selectMode="multiple"
1827
+ [selectionBehavior]="selectionBehavior()"
1828
+ [controlledSelection]="true"
1829
+ [selectedIds]="selectedIds()"
1830
+ [idField]="valueField()"
1831
+ [titleField]="textField()"
1832
+ [disabledField]="disabledField()"
1833
+ [nodeTemplate]="nodeTemplate() ?? defaultNodeTemplate"
1834
+ [alternate]="alternate()"
1835
+ [highlightText]="highlightText()"
1836
+ (onSelectionChange)="handleSelectionChange($event)"
1837
+ />
1838
+ }
1839
+ </div>
1840
+ }
1841
+
1842
+ <ng-template #defaultNodeTemplate let-node>
1843
+ <span class="ax-lookup-tree-node-label">
1844
+ <ax-highlight-text [text]="node?.[textField()] | translate | async" [query]="highlightText()" />
1845
+ </span>
1846
+ </ng-template>
1847
+ `, 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", "highlightText", "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: "component", type: AXHighlightTextComponent, selector: "ax-highlight-text", inputs: ["text", "query", "highlightDisabled", "highlightOptions"] }, { kind: "pipe", type: AXTranslatorPipe, name: "translate" }, { kind: "pipe", type: AsyncPipe, name: "async" }], changeDetection: i0.ChangeDetectionStrategy.OnPush, encapsulation: i0.ViewEncapsulation.None }); }
1848
+ }
1849
+ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "22.0.8", ngImport: i0, type: AXLookupMultiSelectTreeComponent, decorators: [{
1850
+ type: Component,
1851
+ args: [{
1852
+ selector: 'ax-lookup-multi-select-tree',
1853
+ changeDetection: ChangeDetectionStrategy.OnPush,
1854
+ encapsulation: ViewEncapsulation.None,
1855
+ imports: [AXTreeViewComponent, NgTemplateOutlet, AXTranslatorPipe, AsyncPipe, AXHighlightTextComponent],
1856
+ template: `
1857
+ @if (loading()) {
1858
+ @if (loadingTemplate()) {
1859
+ <ng-container [ngTemplateOutlet]="loadingTemplate()!" />
1860
+ } @else {
1861
+ <div class="ax-lookup-empty">
1862
+ {{ '@acorex:common.status.loading' | translate | async }}
1863
+ </div>
1864
+ }
1865
+ } @else if (isEmpty()) {
1866
+ @if (emptyTemplate()) {
1867
+ <ng-container [ngTemplateOutlet]="emptyTemplate()!" />
1868
+ } @else {
1869
+ <div class="ax-lookup-empty">
1870
+ {{ '@acorex:common.general.no-result-found' | translate | async }}
1871
+ </div>
1872
+ }
1873
+ } @else {
1874
+ <div class="ax-lookup-tree">
1875
+ @for (instance of treeInstances(); track instance.id) {
1876
+ <ax-tree-view
1877
+ [datasource]="instance.source"
1878
+ selectMode="multiple"
1879
+ [selectionBehavior]="selectionBehavior()"
1880
+ [controlledSelection]="true"
1881
+ [selectedIds]="selectedIds()"
1882
+ [idField]="valueField()"
1883
+ [titleField]="textField()"
1884
+ [disabledField]="disabledField()"
1885
+ [nodeTemplate]="nodeTemplate() ?? defaultNodeTemplate"
1886
+ [alternate]="alternate()"
1887
+ [highlightText]="highlightText()"
1888
+ (onSelectionChange)="handleSelectionChange($event)"
1889
+ />
1890
+ }
1891
+ </div>
1892
+ }
1893
+
1894
+ <ng-template #defaultNodeTemplate let-node>
1895
+ <span class="ax-lookup-tree-node-label">
1896
+ <ax-highlight-text [text]="node?.[textField()] | translate | async" [query]="highlightText()" />
1897
+ </span>
1898
+ </ng-template>
1899
+ `,
1900
+ }]
1901
+ }], 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 }] }], 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 }] }], loadingTemplate: [{ type: i0.Input, args: [{ isSignal: true, alias: "loadingTemplate", required: false }] }], loading: [{ type: i0.Input, args: [{ isSignal: true, alias: "loading", required: false }] }], alternate: [{ type: i0.Input, args: [{ isSignal: true, alias: "alternate", required: false }] }], filterKey: [{ type: i0.Input, args: [{ isSignal: true, alias: "filterKey", required: false }] }], highlightText: [{ type: i0.Input, args: [{ isSignal: true, alias: "highlightText", required: false }] }], selectionChange: [{ type: i0.Output, args: ["selectionChange"] }] } });
1902
+
1903
+ /**
1904
+ * Internal mini component for the `multi-select` lookup mode:
1905
+ * a predefined, virtualized list of options with checkboxes for multiple item selection.
1906
+ *
1907
+ * @category Components
1908
+ */
1909
+ class AXLookupMultiSelectComponent extends AXLookupListViewBase {
1910
+ static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "22.0.8", ngImport: i0, type: AXLookupMultiSelectComponent, deps: null, target: i0.ɵɵFactoryTarget.Component }); }
1911
+ 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: `
1912
+ @if (isEmpty()) {
1913
+ @if (emptyTemplate()) {
1914
+ <ng-container [ngTemplateOutlet]="emptyTemplate()!" />
1915
+ } @else {
1916
+ <div class="ax-lookup-empty">
1917
+ {{ '@acorex:common.general.no-result-found' | translate | async }}
1918
+ </div>
1919
+ }
1920
+ } @else {
1921
+ <cdk-virtual-scroll-viewport
1922
+ class="ax-lookup-viewport"
1923
+ role="listbox"
1924
+ aria-multiselectable="true"
1925
+ axListNavigation
1926
+ #nav="axListNavigation"
1927
+ [itemSize]="itemHeight()"
1928
+ [style.height.px]="viewportHeight()"
1929
+ (onKeypress)="handleListKeypress($event)"
1930
+ >
1931
+ <div
1932
+ *cdkVirtualFor="let item of listDataSource(); let i = index; trackBy: trackByIndex"
1933
+ role="option"
1934
+ class="ax-lookup-option-host ax-lookup-option-multiple"
1935
+ axListNavigationItem
1936
+ #navItem="axListNavigationItem"
1937
+ [style.height.px]="itemHeight()"
1938
+ [class.ax-lookup-option]="!itemTemplate()"
1939
+ [class.ax-state-alternate]="alternate() && i % 2 === 1"
1940
+ [class.ax-state-selected]="item != null && isSelected(item)"
1941
+ [class.ax-state-disabled]="item != null && isDisabled(item)"
1942
+ [class.ax-state-active]="navItem.isActive()"
1943
+ [attr.aria-selected]="item != null ? isSelected(item) : null"
1944
+ (mouseenter)="activateNavItem(nav, navItem)"
1945
+ (mousedown)="handleItemMouseDown($event, item)"
1946
+ (onKeypress)="handleItemKeypress($event, item)"
1947
+ >
1948
+ @if (item != null) {
1949
+ <ax-check-box
1950
+ class="ax-lookup-checkbox"
1951
+ [tabIndex]="-1"
1952
+ [value]="isSelected(item)"
1953
+ [disabled]="isDisabled(item)"
1954
+ ></ax-check-box>
1955
+ @if (itemTemplate()) {
1956
+ <ng-container
1957
+ [ngTemplateOutlet]="itemTemplate()!"
1958
+ [ngTemplateOutletContext]="{ $implicit: item, highlightText: highlightText() }"
1959
+ />
1960
+ } @else {
1961
+ <span class="ax-lookup-option-text">
1962
+ <ax-highlight-text [text]="getText(item) | translate | async" [query]="highlightText()" />
1963
+ </span>
1964
+ }
1965
+ } @else {
1966
+ <ng-container [ngTemplateOutlet]="loadingRow" />
1967
+ }
1968
+ </div>
1969
+ </cdk-virtual-scroll-viewport>
1970
+ }
1971
+
1972
+ <ng-template #loadingRow>
1973
+ @if (loadingTemplate()) {
1974
+ <ng-container [ngTemplateOutlet]="loadingTemplate()!" />
1975
+ } @else {
1976
+ <span class="ax-lookup-option-loading">{{ '@acorex:common.status.loading' | translate | async }}</span>
1977
+ }
1978
+ </ng-template>
1979
+ `, 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: "component", type: AXHighlightTextComponent, selector: "ax-highlight-text", inputs: ["text", "query", "highlightDisabled", "highlightOptions"] }, { kind: "pipe", type: AXTranslatorPipe, name: "translate" }, { kind: "pipe", type: AsyncPipe, name: "async" }], changeDetection: i0.ChangeDetectionStrategy.OnPush, encapsulation: i0.ViewEncapsulation.None }); }
1980
+ }
1981
+ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "22.0.8", ngImport: i0, type: AXLookupMultiSelectComponent, decorators: [{
1982
+ type: Component,
1983
+ args: [{
1984
+ selector: 'ax-lookup-multi-select',
1985
+ changeDetection: ChangeDetectionStrategy.OnPush,
1986
+ encapsulation: ViewEncapsulation.None,
1987
+ imports: [ScrollingModule, NgTemplateOutlet, AXTranslatorPipe, AsyncPipe, AXListNavigationModule, AXCheckBoxComponent, AXHighlightTextComponent],
1988
+ providers: [{ provide: AXLookupListViewBase, useExisting: AXLookupMultiSelectComponent }],
1989
+ template: `
1990
+ @if (isEmpty()) {
1991
+ @if (emptyTemplate()) {
1992
+ <ng-container [ngTemplateOutlet]="emptyTemplate()!" />
1993
+ } @else {
1994
+ <div class="ax-lookup-empty">
1995
+ {{ '@acorex:common.general.no-result-found' | translate | async }}
1996
+ </div>
1997
+ }
1998
+ } @else {
1999
+ <cdk-virtual-scroll-viewport
2000
+ class="ax-lookup-viewport"
2001
+ role="listbox"
2002
+ aria-multiselectable="true"
2003
+ axListNavigation
2004
+ #nav="axListNavigation"
2005
+ [itemSize]="itemHeight()"
2006
+ [style.height.px]="viewportHeight()"
2007
+ (onKeypress)="handleListKeypress($event)"
2008
+ >
2009
+ <div
2010
+ *cdkVirtualFor="let item of listDataSource(); let i = index; trackBy: trackByIndex"
2011
+ role="option"
2012
+ class="ax-lookup-option-host ax-lookup-option-multiple"
2013
+ axListNavigationItem
2014
+ #navItem="axListNavigationItem"
2015
+ [style.height.px]="itemHeight()"
2016
+ [class.ax-lookup-option]="!itemTemplate()"
2017
+ [class.ax-state-alternate]="alternate() && i % 2 === 1"
2018
+ [class.ax-state-selected]="item != null && isSelected(item)"
2019
+ [class.ax-state-disabled]="item != null && isDisabled(item)"
2020
+ [class.ax-state-active]="navItem.isActive()"
2021
+ [attr.aria-selected]="item != null ? isSelected(item) : null"
2022
+ (mouseenter)="activateNavItem(nav, navItem)"
2023
+ (mousedown)="handleItemMouseDown($event, item)"
2024
+ (onKeypress)="handleItemKeypress($event, item)"
2025
+ >
2026
+ @if (item != null) {
2027
+ <ax-check-box
2028
+ class="ax-lookup-checkbox"
2029
+ [tabIndex]="-1"
2030
+ [value]="isSelected(item)"
2031
+ [disabled]="isDisabled(item)"
2032
+ ></ax-check-box>
2033
+ @if (itemTemplate()) {
2034
+ <ng-container
2035
+ [ngTemplateOutlet]="itemTemplate()!"
2036
+ [ngTemplateOutletContext]="{ $implicit: item, highlightText: highlightText() }"
2037
+ />
2038
+ } @else {
2039
+ <span class="ax-lookup-option-text">
2040
+ <ax-highlight-text [text]="getText(item) | translate | async" [query]="highlightText()" />
2041
+ </span>
2042
+ }
2043
+ } @else {
2044
+ <ng-container [ngTemplateOutlet]="loadingRow" />
2045
+ }
2046
+ </div>
2047
+ </cdk-virtual-scroll-viewport>
2048
+ }
2049
+
2050
+ <ng-template #loadingRow>
2051
+ @if (loadingTemplate()) {
2052
+ <ng-container [ngTemplateOutlet]="loadingTemplate()!" />
2053
+ } @else {
2054
+ <span class="ax-lookup-option-loading">{{ '@acorex:common.status.loading' | translate | async }}</span>
2055
+ }
2056
+ </ng-template>
2057
+ `,
2058
+ }]
2059
+ }] });
2060
+
2061
+ /**
2062
+ * An advanced drop-down (lookup) editor with six modes, `AXDataSource` support, and virtual scrolling.
2063
+ *
2064
+ * Modes (each rendered by its own internal mini component):
2065
+ * - `drop-down-list` — a predefined list of options for picking single values.
2066
+ * - `multi-select` — a predefined list of options for multiple item selection (chips in the trigger).
2067
+ * In multi modes, Backspace with an empty trigger input removes the last chip; repeated presses clear
2068
+ * the whole selection.
2069
+ * - `drop-down-tree` — a tree-like structure for single item selection; when searchable, the trigger
2070
+ * input filters nested nodes as you type (on small screens the search field is inside the actionsheet).
2071
+ * - `multi-select-tree` — a tree-like structure for multiple item selection; searchable the same way.
2072
+ * - `multi-column` — an `ax-data-table` grid; when searchable, the trigger input filters as you type
2073
+ * (on small screens the search field is inside the actionsheet).
2074
+ * - `multi-column-tree` — a multi-column `ax-data-table` with a drop-down tree inside it
2075
+ * (expandable hierarchical rows). Uses `treeDataSource` + `columns`, or a hierarchical `dataSource`.
2076
+ *
2077
+ * With `adaptivityEnabled` (default `true`), the list opens as a bottom actionsheet on small
2078
+ * screens instead of an anchored dropdown — the same alternate presentation as `ax-select-box`.
2079
+ *
2080
+ * Implements {@link FormValueControl} so `[(ngModel)]` / signal forms work via the `value` model
2081
+ * (no `ControlValueAccessor`).
2082
+ *
2083
+ * @category Components
2084
+ */
2085
+ class AXLookupComponent extends NXValueComponent {
2086
+ #platform;
2087
+ #destroyRef;
2088
+ #translation;
2089
+ /** Whether search filters the tree datasource instead of `AXDataSource`. */
2090
+ #isTreeOnlySearchMode() {
2091
+ const mode = this.mode();
2092
+ return mode === 'drop-down-tree' || mode === 'multi-select-tree';
2093
+ }
2094
+ /** Applied tree search query. Set only from `#applyFilterNow` so opening a single-select
2095
+ * with the selected label in the trigger does not filter the tree.
2096
+ */
2097
+ #treeFilterQuery;
2098
+ #treeFilterEpoch;
2099
+ #hydratedTreeNodes;
2100
+ #hydrationPromise;
2101
+ #hydrationRevision;
2102
+ /** Applied (debounced) search query used for result highlighting. */
2103
+ #appliedSearchQuery;
2104
+ /** Reused so closing/reopening the popup does not create a new AXDataSource (which would miss cache). */
2105
+ #multiColumnTreeTableSource;
2106
+ #multiColumnTreeTableKey;
2107
+ #multiColumnTreeInput;
2108
+ /**
2109
+ * Tree callback results keyed by parent id. Survives popup remount so
2110
+ * drop-down-tree / multi-select-tree do not refetch on every open.
2111
+ */
2112
+ #treeChildrenCache;
2113
+ /** Stable lazy loader for on-demand expansion when no search query is active. */
2114
+ #lazyTreeLoader;
2115
+ #document;
2116
+ #itemsCache;
2117
+ #isUserInteraction;
2118
+ #lastValue;
2119
+ #lastExpanded;
2120
+ #resolveRevision;
2121
+ #selectionInitialized;
2122
+ #filterApplied;
2123
+ #searchDebounce;
2124
+ #searchEnterRevision;
2125
+ #sheetSearchFocused;
2126
+ constructor() {
2127
+ super();
2128
+ this.#platform = inject(AXPlatform);
2129
+ this.#destroyRef = inject(DestroyRef);
2130
+ this.#translation = inject(AXTranslationService);
2131
+ /**
2132
+ * The name of the form field, used by validation rules and `ax-form.validate(names)`.
2133
+ */
2134
+ this.name = input('', /* @ts-ignore */
2135
+ ...(ngDevMode ? [{ debugName: "name" }] : /* istanbul ignore next */ []));
2136
+ /**
2137
+ * The lookup rendering mode. Selects which mini component renders in the popup.
2138
+ */
2139
+ this.mode = input('drop-down-list', /* @ts-ignore */
2140
+ ...(ngDevMode ? [{ debugName: "mode" }] : /* istanbul ignore next */ []));
2141
+ /**
2142
+ * The items source for list-based modes (`drop-down-list`, `multi-select`, `multi-column`)
2143
+ * and for `multi-column-tree` when `treeDataSource` is not set.
2144
+ * Accepts an `AXDataSource` (remote paging, `byKey`, server-side filter) or a plain array.
2145
+ */
2146
+ this.dataSource = input(undefined, /* @ts-ignore */
2147
+ ...(ngDevMode ? [{ debugName: "dataSource" }] : /* istanbul ignore next */ []));
2148
+ /**
2149
+ * The nodes source for tree modes (`drop-down-tree`, `multi-select-tree`, `multi-column-tree`):
2150
+ * an array of nodes or a lazy children callback.
2151
+ */
2152
+ this.treeDataSource = input(undefined, /* @ts-ignore */
2153
+ ...(ngDevMode ? [{ debugName: "treeDataSource" }] : /* istanbul ignore next */ []));
2154
+ /**
2155
+ * The item property used as the selection value. Maps to the tree `idField` in tree modes.
2156
+ */
2157
+ this.valueField = input('id', /* @ts-ignore */
2158
+ ...(ngDevMode ? [{ debugName: "valueField" }] : /* istanbul ignore next */ []));
2159
+ /**
2160
+ * The item property used as the display text. Maps to the tree `titleField` in tree modes
2161
+ * (set it to `title` when your nodes use the default tree shape).
2162
+ */
2163
+ this.textField = input('text', /* @ts-ignore */
2164
+ ...(ngDevMode ? [{ debugName: "textField" }] : /* istanbul ignore next */ []));
2165
+ /**
2166
+ * The item property marking an item as disabled.
2167
+ */
2168
+ this.disabledField = input('disabled', /* @ts-ignore */
2169
+ ...(ngDevMode ? [{ debugName: "disabledField" }] : /* istanbul ignore next */ []));
2170
+ /**
2171
+ * Column definitions for the `multi-column` and `multi-column-tree` modes
2172
+ * (rendered as `ax-text-column` in `ax-data-table`).
2173
+ */
2174
+ this.columns = input([], /* @ts-ignore */
2175
+ ...(ngDevMode ? [{ debugName: "columns" }] : /* istanbul ignore next */ []));
2176
+ /**
2177
+ * Field used by `multi-column-tree` to fetch children when a row is expanded
2178
+ * (`AXDataSource` filter). Defaults to `parentId`. Nested `children` arrays are also supported.
2179
+ */
2180
+ this.treeParentField = input('parentId', /* @ts-ignore */
2181
+ ...(ngDevMode ? [{ debugName: "treeParentField" }] : /* istanbul ignore next */ []));
2182
+ /**
2183
+ * Field used by `multi-column-tree` to decide whether a row shows an expand control.
2184
+ * Defaults to `hasChild`. Nodes with `children` / `childrenCount` are mapped automatically
2185
+ * when using `treeDataSource`.
2186
+ */
2187
+ this.hasChildrenField = input('hasChild', /* @ts-ignore */
2188
+ ...(ngDevMode ? [{ debugName: "hasChildrenField" }] : /* istanbul ignore next */ []));
2189
+ /**
2190
+ * Whether the trigger accepts typing and filters the datasource (`true`),
2191
+ * or is select-only with no writable input (`false`).
2192
+ * Applies to all modes, including `drop-down-tree` and `multi-select-tree`.
2193
+ * Lazy callback trees are hydrated once per popup open and searched in full.
2194
+ * On small screens with `adaptivityEnabled`, search is typed in the actionsheet instead of the trigger.
2195
+ */
2196
+ this.searchable = input(true, /* @ts-ignore */
2197
+ ...(ngDevMode ? [{ debugName: "searchable" }] : /* istanbul ignore next */ []));
2198
+ /**
2199
+ * When `true` (default), the popup list uses the alternate actionsheet presentation on small
2200
+ * screens (`SM`). Searchable list modes then show a search field inside the sheet. When `false`,
2201
+ * the list always opens as an anchored dropdown.
2202
+ */
2203
+ this.adaptivityEnabled = input(true, /* @ts-ignore */
2204
+ ...(ngDevMode ? [{ debugName: "adaptivityEnabled" }] : /* istanbul ignore next */ []));
2205
+ /**
2206
+ * Title shown in the actionsheet header on small screens. Falls back to `placeholder`.
2207
+ * Supports i18n expressions (e.g. `@acorex:selectbox.popover.title`).
2208
+ */
2209
+ this.caption = input('', /* @ts-ignore */
2210
+ ...(ngDevMode ? [{ debugName: "caption" }] : /* istanbul ignore next */ []));
2211
+ /**
2212
+ * When `true`, list rows use alternating background colors for easier scanning
2213
+ * (all lookup modes, including drop-down-tree and multi-select-tree).
2214
+ */
2215
+ this.alternate = input(false, /* @ts-ignore */
2216
+ ...(ngDevMode ? [{ debugName: "alternate" }] : /* istanbul ignore next */ []));
2217
+ /**
2218
+ * Placeholder for the trigger search input when items are already selected
2219
+ * (mainly useful in `multi-select` / `multi-select-tree`), and for the in-sheet search field on small screens.
2220
+ * Falls back to `placeholder` when the selection is empty on desktop.
2221
+ * Supports i18n expressions (e.g. `@acorex:common.actions.search`).
2222
+ */
2223
+ this.searchPlaceholder = input('@acorex:common.actions.search', /* @ts-ignore */
2224
+ ...(ngDevMode ? [{ debugName: "searchPlaceholder" }] : /* istanbul ignore next */ []));
2225
+ /**
2226
+ * The placeholder text shown when no value is selected.
2227
+ * Supports i18n expressions (e.g. `@acorex:chat.placeholders.select-conversation`).
2228
+ */
2229
+ this.placeholder = input('', /* @ts-ignore */
2230
+ ...(ngDevMode ? [{ debugName: "placeholder" }] : /* istanbul ignore next */ []));
2231
+ /** Resolved `placeholder` (i18n-aware). */
2232
+ this.translatedPlaceholder = toTranslatedSignal(this.placeholder);
2233
+ /** Resolved `searchPlaceholder` (i18n-aware). */
2234
+ this.translatedSearchPlaceholder = toTranslatedSignal(this.searchPlaceholder);
2235
+ /**
2236
+ * Whether the lookup is disabled.
2237
+ */
2238
+ this.disabled = input(false, /* @ts-ignore */
2239
+ ...(ngDevMode ? [{ debugName: "disabled" }] : /* istanbul ignore next */ []));
2240
+ /**
2241
+ * Whether the lookup is readonly.
2242
+ */
2243
+ this.readonly = input(false, /* @ts-ignore */
2244
+ ...(ngDevMode ? [{ debugName: "readonly" }] : /* istanbul ignore next */ []));
2245
+ /**
2246
+ * Predefined look scheme of the editor container. Same looks as other editor components like ax-text-box.
2247
+ */
2248
+ this.look = model('solid', /* @ts-ignore */
2249
+ ...(ngDevMode ? [{ debugName: "look" }] : /* istanbul ignore next */ []));
2250
+ /**
2251
+ * The fixed row height in pixels used by the virtual scroll viewport (list-based modes).
2252
+ */
2253
+ this.itemHeight = input(40, /* @ts-ignore */
2254
+ ...(ngDevMode ? [{ debugName: "itemHeight" }] : /* istanbul ignore next */ []));
2255
+ /**
2256
+ * The maximum number of rows visible before the popup scrolls (list-based modes).
2257
+ */
2258
+ this.maxVisibleItems = input(8, /* @ts-ignore */
2259
+ ...(ngDevMode ? [{ debugName: "maxVisibleItems" }] : /* istanbul ignore next */ []));
2260
+ /**
2261
+ * How selecting parent/child nodes affects each other in `multi-select-tree` mode.
2262
+ */
2263
+ this.treeSelectionBehavior = input('all', /* @ts-ignore */
2264
+ ...(ngDevMode ? [{ debugName: "treeSelectionBehavior" }] : /* istanbul ignore next */ []));
2265
+ /**
2266
+ * When `true` (default), matching characters in popup result items are highlighted
2267
+ * while the user searches.
2268
+ */
2269
+ this.highlightSearch = input(true, { ...(ngDevMode ? { debugName: "highlightSearch" } : /* istanbul ignore next */ {}), transform: booleanAttribute });
2270
+ /**
2271
+ * Custom template rendered for each item/node. Context: `$implicit` is the item;
2272
+ * `highlightText` is the active search query when result highlighting is enabled.
2273
+ * Default option chrome (padding, typography, check icon) is not applied; only the
2274
+ * template's styles are used. Selection and hover backgrounds remain on the row.
2275
+ */
2276
+ this.itemTemplate = input(undefined, /* @ts-ignore */
2277
+ ...(ngDevMode ? [{ debugName: "itemTemplate" }] : /* istanbul ignore next */ []));
2278
+ /**
2279
+ * Custom template for the selected item display (trigger text / chips). Context: `$implicit` is the item.
2280
+ */
2281
+ this.selectedTemplate = input(undefined, /* @ts-ignore */
2282
+ ...(ngDevMode ? [{ debugName: "selectedTemplate" }] : /* istanbul ignore next */ []));
2283
+ /**
2284
+ * Custom template rendered when the datasource has no items.
2285
+ */
2286
+ this.emptyTemplate = input(undefined, /* @ts-ignore */
2287
+ ...(ngDevMode ? [{ debugName: "emptyTemplate" }] : /* istanbul ignore next */ []));
2288
+ /**
2289
+ * Custom template rendered for rows whose page is still loading.
2290
+ */
2291
+ this.loadingTemplate = input(undefined, /* @ts-ignore */
2292
+ ...(ngDevMode ? [{ debugName: "loadingTemplate" }] : /* istanbul ignore next */ []));
2293
+ /**
2294
+ * The selected value(s): a scalar in single modes, an array in
2295
+ * `multi-select` / `multi-select-tree`. Supports `[(value)]`, `[(ngModel)]`, and signal forms
2296
+ * via {@link FormValueControl}.
2297
+ */
2298
+ this.value = model(null, /* @ts-ignore */
2299
+ ...(ngDevMode ? [{ debugName: "value" }] : /* istanbul ignore next */ []));
2300
+ /**
2301
+ * Full items that resolve the current `value` key(s) without calling datasource `byKey`.
2302
+ * Use when the parent already has the selected entity (e.g. edit forms). Seeds the internal
2303
+ * item cache; missing keys still fall through to `find` / `byKey`.
2304
+ */
2305
+ this.valueItems = input([], /* @ts-ignore */
2306
+ ...(ngDevMode ? [{ debugName: "valueItems" }] : /* istanbul ignore next */ []));
2307
+ /**
2308
+ * Emitted when the selected value changes.
2309
+ */
2310
+ this.onValueChanged = output();
2311
+ /**
2312
+ * Emitted when the selection changes, carrying the resolved selected items.
2313
+ */
2314
+ this.onSelectionChanged = output();
2315
+ /**
2316
+ * Emitted when the trigger receives focus.
2317
+ */
2318
+ this.onFocus = output();
2319
+ /**
2320
+ * Emitted when the trigger loses focus.
2321
+ */
2322
+ this.onBlur = output();
2323
+ /**
2324
+ * Emitted when a list/tree item is clicked.
2325
+ */
2326
+ this.onItemClick = output();
2327
+ /**
2328
+ * Emitted when an item is selected (click or keyboard).
2329
+ */
2330
+ this.onItemSelected = output();
2331
+ /**
2332
+ * Emitted when the popup opens.
2333
+ */
2334
+ this.onOpened = output();
2335
+ /**
2336
+ * Emitted when the popup closes.
2337
+ */
2338
+ this.onClosed = output();
2339
+ /** Whether the popup is expanded. */
2340
+ this.expanded = signal(false, /* @ts-ignore */
2341
+ ...(ngDevMode ? [{ debugName: "expanded" }] : /* istanbul ignore next */ []));
2342
+ /** Whether the list is currently shown as a bottom actionsheet (small screens + adaptivity). */
2343
+ this.isActionsheetStyle = signal(false, /* @ts-ignore */
2344
+ ...(ngDevMode ? [{ debugName: "isActionsheetStyle" }] : /* istanbul ignore next */ []));
2345
+ /** Whether the current mode selects multiple values. */
2346
+ this.isMultiple = computed(() => this.mode() === 'multi-select' || this.mode() === 'multi-select-tree', /* @ts-ignore */
2347
+ ...(ngDevMode ? [{ debugName: "isMultiple" }] : /* istanbul ignore next */ []));
2348
+ /** Whether the current mode renders a tree. */
2349
+ this.isTreeMode = computed(() => {
2350
+ const mode = this.mode();
2351
+ return (mode === 'drop-down-tree' ||
2352
+ mode === 'multi-select-tree' ||
2353
+ (mode === 'multi-column-tree' && this.treeDataSource() != null));
2354
+ }, /* @ts-ignore */
2355
+ ...(ngDevMode ? [{ debugName: "isTreeMode" }] : /* istanbul ignore next */ []));
2356
+ /** Whether the current mode can filter as you type (list, table, or tree). */
2357
+ this.isListSearchMode = computed(() => {
2358
+ const mode = this.mode();
2359
+ return (mode === 'drop-down-list' ||
2360
+ mode === 'multi-select' ||
2361
+ mode === 'drop-down-tree' ||
2362
+ mode === 'multi-select-tree' ||
2363
+ mode === 'multi-column' ||
2364
+ mode === 'multi-column-tree');
2365
+ }, /* @ts-ignore */
2366
+ ...(ngDevMode ? [{ debugName: "isListSearchMode" }] : /* istanbul ignore next */ []));
2367
+ /** Whether the trigger input is writable and filters as you type (desktop only). */
2368
+ this.isEditableTrigger = computed(() => this.searchable() && !this.readonly() && !this.isActionsheetStyle() && this.isListSearchMode(), /* @ts-ignore */
2369
+ ...(ngDevMode ? [{ debugName: "isEditableTrigger" }] : /* istanbul ignore next */ []));
2370
+ /** Whether search is typed in the actionsheet instead of the trigger. */
2371
+ this.isSheetSearchEnabled = computed(() => this.searchable() && !this.readonly() && this.isActionsheetStyle() && this.isListSearchMode(), /* @ts-ignore */
2372
+ ...(ngDevMode ? [{ debugName: "isSheetSearchEnabled" }] : /* istanbul ignore next */ []));
2373
+ /** Query typed in the actionsheet search field (independent of the trigger display text). */
2374
+ this.sheetSearchText = signal('', /* @ts-ignore */
2375
+ ...(ngDevMode ? [{ debugName: "sheetSearchText" }] : /* istanbul ignore next */ []));
2376
+ /** Applied tree search query. Set only from `#applyFilterNow` so opening a single-select
2377
+ * with the selected label in the trigger does not filter the tree.
2378
+ */
2379
+ this.#treeFilterQuery = signal('', /* @ts-ignore */
2380
+ ...(ngDevMode ? [{ debugName: "#treeFilterQuery" }] : /* istanbul ignore next */ []));
2381
+ this.#treeFilterEpoch = signal(0, /* @ts-ignore */
2382
+ ...(ngDevMode ? [{ debugName: "#treeFilterEpoch" }] : /* istanbul ignore next */ []));
2383
+ this.#hydratedTreeNodes = signal(undefined, /* @ts-ignore */
2384
+ ...(ngDevMode ? [{ debugName: "#hydratedTreeNodes" }] : /* istanbul ignore next */ []));
2385
+ this.#hydrationRevision = 0;
2386
+ this.treeSearchLoading = signal(false, /* @ts-ignore */
2387
+ ...(ngDevMode ? [{ debugName: "treeSearchLoading" }] : /* istanbul ignore next */ []));
2388
+ /** Applied (debounced) search query used for result highlighting. */
2389
+ this.#appliedSearchQuery = signal('', /* @ts-ignore */
2390
+ ...(ngDevMode ? [{ debugName: "#appliedSearchQuery" }] : /* istanbul ignore next */ []));
2391
+ /** Increments on every tree filter apply so the tree view remounts with a new instance. */
2392
+ this.treeFilterKey = computed(() => String(this.#treeFilterEpoch()), /* @ts-ignore */
2393
+ ...(ngDevMode ? [{ debugName: "treeFilterKey" }] : /* istanbul ignore next */ []));
2394
+ /** Query passed to result-item highlighting (empty when disabled). */
2395
+ this.highlightQuery = computed(() => (this.highlightSearch() ? this.#appliedSearchQuery() : ''), /* @ts-ignore */
2396
+ ...(ngDevMode ? [{ debugName: "highlightQuery" }] : /* istanbul ignore next */ []));
2397
+ /** The datasource for list-based modes; plain arrays are converted. */
2398
+ this.resolvedDataSource = computed(() => {
2399
+ const tree = this.treeDataSource();
2400
+ if (this.mode() === 'multi-column-tree' && tree) {
2401
+ const key = `${this.valueField()}|${this.textField()}|${this.treeParentField()}|${this.hasChildrenField()}`;
2402
+ if (this.#multiColumnTreeTableSource &&
2403
+ this.#multiColumnTreeInput === tree &&
2404
+ this.#multiColumnTreeTableKey === key) {
2405
+ return this.#multiColumnTreeTableSource;
2406
+ }
2407
+ const cachedTree = Array.isArray(tree)
2408
+ ? tree
2409
+ : (nodeId) => this.#loadCachedTreeNodes(tree, nodeId);
2410
+ this.#multiColumnTreeInput = tree;
2411
+ this.#multiColumnTreeTableKey = key;
2412
+ this.#multiColumnTreeTableSource = createLookupTreeTableDataSource(cachedTree, {
2413
+ valueField: this.valueField(),
2414
+ textField: this.textField(),
2415
+ parentField: this.treeParentField(),
2416
+ hasChildrenField: this.hasChildrenField(),
2417
+ loadSearchRoots: Array.isArray(tree) ? undefined : () => this.#ensureHydratedTree(),
2418
+ });
2419
+ return this.#multiColumnTreeTableSource;
2420
+ }
2421
+ const source = this.dataSource();
2422
+ if (!source) {
2423
+ return convertLookupArrayToDataSource([], {
2424
+ key: this.valueField(),
2425
+ pageSize: 20,
2426
+ textField: this.textField(),
2427
+ translateText: (text) => this.#translateItemText(text),
2428
+ });
2429
+ }
2430
+ return Array.isArray(source)
2431
+ ? convertLookupArrayToDataSource(source, {
2432
+ key: this.valueField(),
2433
+ pageSize: 20,
2434
+ textField: this.textField(),
2435
+ translateText: (text) => this.#translateItemText(text),
2436
+ })
2437
+ : source;
2438
+ }, /* @ts-ignore */
2439
+ ...(ngDevMode ? [{ debugName: "resolvedDataSource" }] : /* istanbul ignore next */ []));
2440
+ /**
2441
+ * Tree callback results keyed by parent id. Survives popup remount so
2442
+ * drop-down-tree / multi-select-tree do not refetch on every open.
2443
+ */
2444
+ this.#treeChildrenCache = new WeakMap();
2445
+ /** Stable lazy loader for on-demand expansion when no search query is active. */
2446
+ this.#lazyTreeLoader = (nodeId) => {
2447
+ const source = this.treeDataSource();
2448
+ if (typeof source !== 'function') {
2449
+ return [];
2450
+ }
2451
+ return this.#loadCachedTreeNodes(source, nodeId);
2452
+ };
2453
+ this.resolvedTreeDataSource = computed(() => {
2454
+ this.#treeFilterEpoch();
2455
+ const source = this.treeDataSource();
2456
+ const query = this.#treeFilterQuery().trim();
2457
+ const textField = this.textField();
2458
+ const translate = (text) => this.#translateItemTextForFilter(text);
2459
+ if (!source) {
2460
+ return [];
2461
+ }
2462
+ if (Array.isArray(source)) {
2463
+ return query ? filterTreeNodes(source, textField, query, translate) : cloneLookupTreeNodes(source);
2464
+ }
2465
+ if (!query) {
2466
+ return this.#lazyTreeLoader;
2467
+ }
2468
+ const snapshot = this.#hydratedTreeNodes();
2469
+ if (snapshot) {
2470
+ return filterTreeNodes(snapshot, textField, query, translate);
2471
+ }
2472
+ return [];
2473
+ }, /* @ts-ignore */
2474
+ ...(ngDevMode ? [{ debugName: "resolvedTreeDataSource" }] : /* istanbul ignore next */ []));
2475
+ /** The current selection normalized to an array. */
2476
+ this.selectedValues = computed(() => {
2477
+ const value = this.value();
2478
+ if (value == null) {
2479
+ return [];
2480
+ }
2481
+ return Array.isArray(value) ? value : [value];
2482
+ }, /* @ts-ignore */
2483
+ ...(ngDevMode ? [{ debugName: "selectedValues" }] : /* istanbul ignore next */ []));
2484
+ /** The resolved selected items (via cache, datasource `find`/`byKey`, or tree node lookup). */
2485
+ this.selectedItems = signal([], /* @ts-ignore */
2486
+ ...(ngDevMode ? [{ debugName: "selectedItems" }] : /* istanbul ignore next */ []));
2487
+ /** Display text shown in the trigger for single modes. */
2488
+ this.displayText = computed(() => {
2489
+ const item = this.selectedItems()[0];
2490
+ return item ? this.getItemText(item) : '';
2491
+ }, /* @ts-ignore */
2492
+ ...(ngDevMode ? [{ debugName: "displayText" }] : /* istanbul ignore next */ []));
2493
+ /** Resolved display text for the trigger input (i18n-aware). */
2494
+ this.translatedDisplayText = toTranslatedSignal(this.displayText);
2495
+ /** Actionsheet header title with i18n fallback chain. */
2496
+ this.actionsheetTitleSource = computed(() => this.caption() || this.placeholder() || '@acorex:selectbox.popover.title', /* @ts-ignore */
2497
+ ...(ngDevMode ? [{ debugName: "actionsheetTitleSource" }] : /* istanbul ignore next */ []));
2498
+ /** Resolved actionsheet title (i18n-aware). */
2499
+ this.actionsheetTitle = toTranslatedSignal(this.actionsheetTitleSource);
2500
+ /**
2501
+ * Text typed in the editable trigger input.
2502
+ * Multi-select starts empty; single modes sync from the selected display text.
2503
+ */
2504
+ this.searchText = linkedSignal(() => (this.isMultiple() ? '' : this.translatedDisplayText()), /* @ts-ignore */
2505
+ ...(ngDevMode ? [{ debugName: "searchText" }] : /* istanbul ignore next */ []));
2506
+ /**
2507
+ * Whether the trigger should render `selectedTemplate` instead of the plain input text.
2508
+ * Searchable mode shows the template while the popup is closed and the input still matches
2509
+ * the selected display text (same pattern as combo-box).
2510
+ */
2511
+ this.showSelectedTemplate = computed(() => {
2512
+ if (this.isMultiple() || !this.selectedTemplate() || this.selectedItems().length === 0) {
2513
+ return false;
2514
+ }
2515
+ if (!this.isEditableTrigger()) {
2516
+ return true;
2517
+ }
2518
+ return !this.expanded() && this.searchText() === this.translatedDisplayText();
2519
+ }, /* @ts-ignore */
2520
+ ...(ngDevMode ? [{ debugName: "showSelectedTemplate" }] : /* istanbul ignore next */ []));
2521
+ /** Placeholder for the editable trigger search input. */
2522
+ this.triggerSearchPlaceholder = computed(() => {
2523
+ if (this.isActionsheetStyle()) {
2524
+ return this.isMultiple() && this.selectedItems().length > 0 ? '' : this.translatedPlaceholder();
2525
+ }
2526
+ if (this.isMultiple() && this.selectedItems().length > 0) {
2527
+ return this.translatedSearchPlaceholder();
2528
+ }
2529
+ return this.translatedPlaceholder();
2530
+ }, /* @ts-ignore */
2531
+ ...(ngDevMode ? [{ debugName: "triggerSearchPlaceholder" }] : /* istanbul ignore next */ []));
2532
+ this.popoverRef = viewChild(AXPopoverComponent, /* @ts-ignore */
2533
+ ...(ngDevMode ? [{ debugName: "popoverRef" }] : /* istanbul ignore next */ []));
2534
+ this.originRef = viewChild('origin', /* @ts-ignore */
2535
+ ...(ngDevMode ? [{ debugName: "originRef" }] : /* istanbul ignore next */ []));
2536
+ this.popupRef = viewChild('popup', /* @ts-ignore */
2537
+ ...(ngDevMode ? [{ debugName: "popupRef" }] : /* istanbul ignore next */ []));
2538
+ this.triggerSearchInput = viewChild('triggerSearchInput', /* @ts-ignore */
2539
+ ...(ngDevMode ? [{ debugName: "triggerSearchInput" }] : /* istanbul ignore next */ []));
2540
+ this.#document = inject(DOCUMENT);
2541
+ this.listView = viewChild(AXLookupListViewBase, /* @ts-ignore */
2542
+ ...(ngDevMode ? [{ debugName: "listView" }] : /* istanbul ignore next */ []));
2543
+ this.sheetSearchRef = viewChild('sheetSearch', /* @ts-ignore */
2544
+ ...(ngDevMode ? [{ debugName: "sheetSearchRef" }] : /* istanbul ignore next */ []));
2545
+ this.#itemsCache = new Map();
2546
+ this.#isUserInteraction = false;
2547
+ this.#lastValue = undefined;
2548
+ this.#lastExpanded = undefined;
2549
+ this.#resolveRevision = 0;
2550
+ this.#selectionInitialized = false;
2551
+ this.#filterApplied = false;
2552
+ this.#searchEnterRevision = 0;
2553
+ this.#sheetSearchFocused = false;
2554
+ effect(() => this.#emitValueChanged(this.value()));
2555
+ effect(() => this.#emitOpenedOrClosed(this.expanded()));
2556
+ effect(() => {
2557
+ this.adaptivityEnabled();
2558
+ untracked(() => this.#syncActionsheetStyle());
2559
+ });
2560
+ this.#platform.resize.pipe(takeUntilDestroyed(this.#destroyRef)).subscribe(() => {
2561
+ this.#syncActionsheetStyle();
2562
+ // Match dropdown-box: close anchored dropdowns on resize; keep actionsheet open.
2563
+ if (this.expanded() && !this.isActionsheetStyle()) {
2564
+ this.close();
2565
+ }
2566
+ });
2567
+ // Seed the actionsheet flag once.
2568
+ this.#syncActionsheetStyle();
2569
+ // Seed the item cache from valueItems, then resolve selection.
2570
+ effect(() => {
2571
+ const seeded = this.valueItems();
2572
+ const values = this.selectedValues();
2573
+ this.valueField();
2574
+ this.mode();
2575
+ this.dataSource();
2576
+ this.treeDataSource();
2577
+ untracked(() => {
2578
+ this.#seedItemsCache(seeded);
2579
+ void this.#resolveSelectedItems(values);
2580
+ });
2581
+ });
2582
+ // Keep the popover in sync with the expanded state.
2583
+ effect(() => {
2584
+ const expanded = this.expanded();
2585
+ const popover = this.popoverRef();
2586
+ if (!popover) {
2587
+ return;
2588
+ }
2589
+ untracked(() => {
2590
+ if (expanded && !popover.isOpen) {
2591
+ void popover.open();
2592
+ }
2593
+ else if (!expanded && popover.isOpen) {
2594
+ popover.close();
2595
+ }
2596
+ });
2597
+ });
2598
+ afterRenderEffect(() => {
2599
+ if (!this.expanded()) {
2600
+ this.#sheetSearchFocused = false;
2601
+ return;
2602
+ }
2603
+ this.#tryFocusSheetSearch();
2604
+ });
2605
+ }
2606
+ #syncActionsheetStyle() {
2607
+ this.isActionsheetStyle.set(this.adaptivityEnabled() && this.#platform.is('SM'));
2608
+ }
2609
+ /** Returns the display text of an item using the `textField` mapping. */
2610
+ getItemText(item) {
2611
+ return String(item?.[this.textField()] ?? '');
2612
+ }
2613
+ /** Stable unique key for selected chips — avoids NG0955 and remounts on reorder/remove. */
2614
+ trackSelectedKey(item) {
2615
+ const key = item?.[this.valueField()];
2616
+ return key != null ? key : item;
2617
+ }
2618
+ /**
2619
+ * Opens (editable trigger) or toggles the popup on trigger click.
2620
+ */
2621
+ onTriggerClick() {
2622
+ if (this.disabled() || this.readonly()) {
2623
+ return;
2624
+ }
2625
+ if (this.isEditableTrigger()) {
2626
+ this.expanded.set(true);
2627
+ queueMicrotask(() => this.triggerSearchInput()?.nativeElement.focus());
2628
+ return;
2629
+ }
2630
+ this.expanded.update((open) => !open);
2631
+ if (!this.expanded()) {
2632
+ return;
2633
+ }
2634
+ queueMicrotask(() => this.#focusPopupSearchOrList());
2635
+ }
2636
+ /**
2637
+ * Toggles the popup when the chevron button is clicked.
2638
+ */
2639
+ onChevronClick(event) {
2640
+ event.stopPropagation();
2641
+ if (this.disabled() || this.readonly()) {
2642
+ return;
2643
+ }
2644
+ this.expanded.update((open) => !open);
2645
+ if (!this.expanded()) {
2646
+ return;
2647
+ }
2648
+ if (this.isEditableTrigger()) {
2649
+ queueMicrotask(() => this.triggerSearchInput()?.nativeElement.focus());
2650
+ return;
2651
+ }
2652
+ queueMicrotask(() => this.#focusPopupSearchOrList());
2653
+ }
2654
+ /**
2655
+ * Focuses the lookup trigger input.
2656
+ */
2657
+ focus(options) {
2658
+ if (this.disabled()) {
2659
+ return;
2660
+ }
2661
+ this.triggerSearchInput()?.nativeElement.focus(options);
2662
+ }
2663
+ /**
2664
+ * Handles keyboard interaction on the trigger input.
2665
+ * In multi modes, Backspace with an empty trigger input removes the last chip; repeated presses
2666
+ * clear the whole selection.
2667
+ */
2668
+ onTriggerKeydown(e) {
2669
+ if (this.disabled() || this.readonly()) {
2670
+ return;
2671
+ }
2672
+ if (e.key === 'Escape') {
2673
+ this.close();
2674
+ return;
2675
+ }
2676
+ if (e.key === 'Backspace' && this.#removeLastChipOnBackspace(e)) {
2677
+ return;
2678
+ }
2679
+ if (e.key === 'ArrowDown') {
2680
+ e.preventDefault();
2681
+ this.expanded.set(true);
2682
+ queueMicrotask(() => this.#focusPopupSearchOrList());
2683
+ return;
2684
+ }
2685
+ if (e.key === 'Enter' && this.isEditableTrigger()) {
2686
+ this.#onSearchEnter(e);
2687
+ return;
2688
+ }
2689
+ if (!this.isEditableTrigger() && (e.key === 'Enter' || e.key === ' ')) {
2690
+ e.preventDefault();
2691
+ this.expanded.update((open) => !open);
2692
+ if (this.expanded()) {
2693
+ queueMicrotask(() => this.#focusPopupSearchOrList());
2694
+ }
2695
+ }
2696
+ }
2697
+ /** Filters the datasource from the actionsheet search field and handles Enter with no matches. */
2698
+ onSheetSearchKeydown(e) {
2699
+ const event = e.nativeEvent;
2700
+ if (!event || event.key !== 'Enter') {
2701
+ return;
2702
+ }
2703
+ this.#onSearchEnter(event);
2704
+ }
2705
+ /**
2706
+ * Enter in search never submits the surrounding form.
2707
+ * - No matches: single-select value is cleared (`null`).
2708
+ * - Exactly one match: that item is selected (no list navigation required).
2709
+ * - Multiple matches: nothing is selected.
2710
+ */
2711
+ #onSearchEnter(event) {
2712
+ event.preventDefault();
2713
+ event.stopPropagation();
2714
+ event.stopImmediatePropagation();
2715
+ void this.#commitOrClearFromSearch();
2716
+ }
2717
+ async #commitOrClearFromSearch() {
2718
+ const revision = ++this.#searchEnterRevision;
2719
+ this.#flushPendingFilter();
2720
+ if (this.#isTreeOnlySearchMode()) {
2721
+ const nodes = await this.#resolvedFilteredTreeNodes();
2722
+ if (revision !== this.#searchEnterRevision) {
2723
+ return;
2724
+ }
2725
+ const items = this.#enabledTreeItems(nodes);
2726
+ if (items.length === 0) {
2727
+ if (this.#currentSearchQuery() && !this.isMultiple()) {
2728
+ this.reset(true);
2729
+ this.close();
2730
+ }
2731
+ return;
2732
+ }
2733
+ if (items.length !== 1) {
2734
+ return;
2735
+ }
2736
+ this.#commitSearchSelection(items);
2737
+ return;
2738
+ }
2739
+ const source = this.resolvedDataSource();
2740
+ if (source.isLoading) {
2741
+ await this.#whenSourceIdle(source);
2742
+ if (revision !== this.#searchEnterRevision) {
2743
+ return;
2744
+ }
2745
+ }
2746
+ if (this.#hasNoSearchMatches()) {
2747
+ if (this.#currentSearchQuery() && !this.isMultiple()) {
2748
+ this.reset(true);
2749
+ this.close();
2750
+ }
2751
+ return;
2752
+ }
2753
+ if (this.#getSearchMatchCount() !== 1) {
2754
+ return;
2755
+ }
2756
+ const item = this.#pickFirstMatch();
2757
+ if (!item) {
2758
+ return;
2759
+ }
2760
+ this.#commitSearchSelection([item]);
2761
+ }
2762
+ #commitSearchSelection(items) {
2763
+ if (items.length === 0) {
2764
+ if (this.#currentSearchQuery() && !this.isMultiple()) {
2765
+ this.reset(true);
2766
+ this.close();
2767
+ }
2768
+ return;
2769
+ }
2770
+ if (!this.#isTypedFilterQuery()) {
2771
+ return;
2772
+ }
2773
+ const item = this.#pickFirstFromItems(items);
2774
+ if (!item) {
2775
+ return;
2776
+ }
2777
+ const event = { item, value: item[this.valueField()] };
2778
+ if (this.isMultiple()) {
2779
+ this.handleMultiToggle(event);
2780
+ }
2781
+ else {
2782
+ this.handleSinglePick(event);
2783
+ }
2784
+ }
2785
+ async #resolvedFilteredTreeNodes() {
2786
+ const query = this.#treeFilterQuery().trim();
2787
+ const treeSource = this.treeDataSource();
2788
+ if (query && treeSource && typeof treeSource === 'function') {
2789
+ await this.#ensureHydratedTree();
2790
+ const snapshot = this.#hydratedTreeNodes();
2791
+ if (snapshot) {
2792
+ return filterTreeNodes(snapshot, this.textField(), query, (text) => this.#translateItemTextForFilter(text));
2793
+ }
2794
+ return [];
2795
+ }
2796
+ const source = this.resolvedTreeDataSource();
2797
+ if (Array.isArray(source)) {
2798
+ return source;
2799
+ }
2800
+ return (await source()) ?? [];
2801
+ }
2802
+ #enabledTreeItems(nodes) {
2803
+ const disabledField = this.disabledField();
2804
+ return flattenTreeNodes(nodes).filter((item) => !item[disabledField]);
2805
+ }
2806
+ #pickFirstMatch() {
2807
+ const disabledField = this.disabledField();
2808
+ const source = this.resolvedDataSource();
2809
+ const items = (source.cachedItems.length ? source.cachedItems : source.items).filter((item) => item != null && !item[disabledField]);
2810
+ return this.#pickFirstFromItems(items);
2811
+ }
2812
+ #pickFirstFromItems(items) {
2813
+ if (items.length === 0) {
2814
+ return null;
2815
+ }
2816
+ const query = this.#currentSearchQuery().toLowerCase();
2817
+ if (!query) {
2818
+ return items[0];
2819
+ }
2820
+ const textOf = (item) => String(item?.[this.textField()] ?? '').trim().toLowerCase();
2821
+ return items.find((item) => textOf(item) === query) ?? items.find((item) => textOf(item).includes(query)) ?? items[0];
2822
+ }
2823
+ #whenSourceIdle(source) {
2824
+ if (!source.isLoading) {
2825
+ return Promise.resolve();
2826
+ }
2827
+ return new Promise((resolve) => {
2828
+ const sub = source.onLoadingChanged.subscribe((loading) => {
2829
+ if (!loading) {
2830
+ sub.unsubscribe();
2831
+ resolve();
2832
+ }
2833
+ });
2834
+ });
2835
+ }
2836
+ #flushPendingFilter() {
2837
+ if (!this.#searchDebounce) {
2838
+ return;
2839
+ }
2840
+ clearTimeout(this.#searchDebounce);
2841
+ this.#searchDebounce = undefined;
2842
+ this.#applyFilterNow(this.#currentSearchQuery());
2843
+ }
2844
+ #currentSearchQuery() {
2845
+ if (this.isSheetSearchEnabled()) {
2846
+ return (this.sheetSearchText() || this.#sheetSearchInputValue()).trim();
2847
+ }
2848
+ return this.searchText().trim();
2849
+ }
2850
+ #isTypedFilterQuery() {
2851
+ const query = this.#currentSearchQuery();
2852
+ if (!query) {
2853
+ return false;
2854
+ }
2855
+ if (!this.isSheetSearchEnabled() && !this.isMultiple()) {
2856
+ const queryLower = query.toLowerCase();
2857
+ const translated = this.translatedDisplayText().trim().toLowerCase();
2858
+ const raw = this.displayText().trim().toLowerCase();
2859
+ return queryLower !== translated && queryLower !== raw;
2860
+ }
2861
+ return true;
2862
+ }
2863
+ #hasNoSearchMatches() {
2864
+ return this.#getSearchMatchCount() === 0;
2865
+ }
2866
+ #getSearchMatchCount() {
2867
+ const list = this.listView();
2868
+ if (list) {
2869
+ return list.matchCount();
2870
+ }
2871
+ const source = this.resolvedDataSource();
2872
+ if (source.isLoading) {
2873
+ return -1;
2874
+ }
2875
+ return source.totalCount;
2876
+ }
2877
+ /** Blocks typing when the trigger is not editable (keeps Tab / keyboard open working). */
2878
+ onBeforeInput(event) {
2879
+ if (!this.isEditableTrigger() || this.readonly()) {
2880
+ event.preventDefault();
2881
+ }
2882
+ }
2883
+ /**
2884
+ * Returns focus to the search field when list navigation requests it.
2885
+ */
2886
+ onListNavigateOut(_reason) {
2887
+ if (this.isSheetSearchEnabled()) {
2888
+ this.sheetSearchRef()?.focus();
2889
+ return;
2890
+ }
2891
+ this.triggerSearchInput()?.nativeElement.focus();
2892
+ }
2893
+ focusListFirst() {
2894
+ const tryFocus = (attempt = 0) => {
2895
+ const list = this.listView();
2896
+ if (list) {
2897
+ list.focusFirst();
2898
+ return;
2899
+ }
2900
+ if (attempt < 5) {
2901
+ setTimeout(() => tryFocus(attempt + 1), 16);
2902
+ }
2903
+ };
2904
+ tryFocus();
2905
+ }
2906
+ /**
2907
+ * Keeps the expanded state in sync when the popover closes (e.g. click outside),
2908
+ * and clears any applied search filter.
2909
+ */
2910
+ onPopoverClosed() {
2911
+ this.expanded.set(false);
2912
+ this.searchText.set(this.isMultiple() ? '' : this.translatedDisplayText());
2913
+ this.sheetSearchText.set('');
2914
+ this.#appliedSearchQuery.set('');
2915
+ this.#treeFilterQuery.set('');
2916
+ this.#hydratedTreeNodes.set(undefined);
2917
+ this.#hydrationPromise = undefined;
2918
+ this.#hydrationRevision++;
2919
+ this.treeSearchLoading.set(false);
2920
+ this.#treeFilterEpoch.update((value) => value + 1);
2921
+ if (this.#filterApplied) {
2922
+ this.#filterApplied = false;
2923
+ if (!this.#isTreeOnlySearchMode()) {
2924
+ const source = this.resolvedDataSource();
2925
+ source.clearFilter();
2926
+ source.refresh();
2927
+ }
2928
+ }
2929
+ }
2930
+ /**
2931
+ * Closes the popup.
2932
+ */
2933
+ close() {
2934
+ this.expanded.set(false);
2935
+ }
2936
+ /**
2937
+ * Closes the popup (alias for {@link close}, required by `AXClosableComponent`).
2938
+ */
2939
+ closeAll() {
2940
+ this.close();
2941
+ }
2942
+ /**
2943
+ * Opens the popup.
2944
+ */
2945
+ open() {
2946
+ if (this.disabled() || this.readonly()) {
2947
+ return;
2948
+ }
2949
+ this.expanded.set(true);
2950
+ }
2951
+ /**
2952
+ * Handles typing in the editable trigger input.
2953
+ */
2954
+ onTriggerSearchInput(text) {
2955
+ if (!this.isEditableTrigger()) {
2956
+ return;
2957
+ }
2958
+ this.searchText.set(text);
2959
+ this.expanded.set(true);
2960
+ this.#applyFilterDebounced(text);
2961
+ }
2962
+ /** Filters the datasource from the actionsheet search field (reads the input so delayed ngModel cannot block typing). */
2963
+ onSheetSearchInput() {
2964
+ const query = this.#sheetSearchInputValue();
2965
+ this.sheetSearchText.set(query);
2966
+ this.#applyFilterDebounced(query);
2967
+ }
2968
+ /**
2969
+ * Commits a single pick (drop-down-list, drop-down-tree, multi-column, multi-column-tree) and closes the popup.
2970
+ */
2971
+ handleSinglePick(e) {
2972
+ this.#emitItemClick(e.item);
2973
+ this.#emitItemSelected(e.item);
2974
+ this.#itemsCache.set(e.value, e.item);
2975
+ this.selectedItems.set([e.item]);
2976
+ this.searchText.set(this.#translateItemText(this.getItemText(e.item)));
2977
+ this.#isUserInteraction = true;
2978
+ this.value.set(e.value);
2979
+ this.close();
2980
+ }
2981
+ /**
2982
+ * Toggles an item in the multi-select list; the popup stays open.
2983
+ * Clears the trigger search so the full list returns (select-box-like).
2984
+ */
2985
+ handleMultiToggle(e) {
2986
+ this.#emitItemClick(e.item);
2987
+ this.#itemsCache.set(e.value, e.item);
2988
+ const current = this.selectedValues();
2989
+ const exists = current.some((v) => v == e.value);
2990
+ if (!exists) {
2991
+ this.#emitItemSelected(e.item);
2992
+ }
2993
+ const next = exists ? current.filter((v) => !(v == e.value)) : [...current, e.value];
2994
+ this.#isUserInteraction = true;
2995
+ this.value.set(next);
2996
+ if (this.isSheetSearchEnabled() && this.sheetSearchText()) {
2997
+ this.#clearSheetSearch();
2998
+ }
2999
+ else if (this.isEditableTrigger() && this.searchText()) {
3000
+ this.searchText.set('');
3001
+ this.#applyFilterDebounced('');
3002
+ }
3003
+ }
3004
+ /**
3005
+ * Applies the multi-select-tree selection to the value; the popup stays open.
3006
+ */
3007
+ handleTreeSelectionChange(e) {
3008
+ const prev = new Set(this.selectedValues().map((v) => String(v)));
3009
+ const newlySelected = e.nodes.filter((node) => !prev.has(String(node[this.valueField()])));
3010
+ if (newlySelected.length > 0) {
3011
+ this.#emitItemSelected(newlySelected[0]);
3012
+ }
3013
+ for (const node of e.nodes) {
3014
+ this.#itemsCache.set(String(node[this.valueField()]), node);
3015
+ }
3016
+ this.#isUserInteraction = true;
3017
+ this.value.set([...e.ids]);
3018
+ if (this.isSheetSearchEnabled() && this.sheetSearchText()) {
3019
+ this.#clearSheetSearch();
3020
+ }
3021
+ else if (this.isEditableTrigger() && this.searchText()) {
3022
+ this.searchText.set('');
3023
+ this.#applyFilterDebounced('');
3024
+ }
3025
+ }
3026
+ /** Forwards native focus from the trigger input. */
3027
+ emitOnFocus(e) {
3028
+ this.onFocus.emit({
3029
+ component: this,
3030
+ htmlElement: this.nativeElement,
3031
+ nativeEvent: e,
3032
+ });
3033
+ }
3034
+ /** Forwards native blur from the trigger input. */
3035
+ emitOnBlur(e) {
3036
+ this.onBlur.emit({
3037
+ component: this,
3038
+ htmlElement: this.nativeElement,
3039
+ nativeEvent: e,
3040
+ });
3041
+ this.#scheduleCloseOnTriggerBlur(e);
3042
+ }
3043
+ /**
3044
+ * Closes the popup when the trigger input loses focus, unless focus moved into the
3045
+ * popover panel or another part of the trigger (e.g. sheet search or list navigation).
3046
+ */
3047
+ #scheduleCloseOnTriggerBlur(e) {
3048
+ if (!this.expanded()) {
3049
+ return;
3050
+ }
3051
+ const related = e.relatedTarget;
3052
+ if (related instanceof Node && this.#isFocusWithinPopupOrTrigger(related)) {
3053
+ return;
3054
+ }
3055
+ queueMicrotask(() => {
3056
+ if (!this.expanded()) {
3057
+ return;
3058
+ }
3059
+ const active = this.#document.activeElement;
3060
+ if (active instanceof Node && this.#isFocusWithinPopupOrTrigger(active)) {
3061
+ return;
3062
+ }
3063
+ this.close();
3064
+ });
3065
+ }
3066
+ #isFocusWithinPopupOrTrigger(node) {
3067
+ const popup = this.popupRef()?.nativeElement;
3068
+ if (popup?.contains(node)) {
3069
+ return true;
3070
+ }
3071
+ const origin = this.originRef()?.nativeElement;
3072
+ return Boolean(origin?.contains(node));
3073
+ }
3074
+ #emitItemClick(item) {
3075
+ this.onItemClick.emit({
3076
+ component: this,
3077
+ item,
3078
+ htmlElement: this.nativeElement,
3079
+ isUserInteraction: true,
3080
+ });
3081
+ }
3082
+ #emitItemSelected(item) {
3083
+ this.onItemSelected.emit({
3084
+ component: this,
3085
+ item,
3086
+ htmlElement: this.nativeElement,
3087
+ isUserInteraction: true,
3088
+ });
3089
+ }
3090
+ /**
3091
+ * Removes a single chip from the multi selection.
3092
+ */
3093
+ removeChip(event, item) {
3094
+ event.stopPropagation();
3095
+ if (this.disabled() || this.readonly()) {
3096
+ return;
3097
+ }
3098
+ const value = item?.[this.valueField()];
3099
+ this.#isUserInteraction = true;
3100
+ this.value.set(this.selectedValues().filter((v) => !(v == value)));
3101
+ }
3102
+ /** Removes the last chip when Backspace is pressed with an empty trigger input (multi modes). */
3103
+ #removeLastChipOnBackspace(event) {
3104
+ if (!this.isMultiple() || !this.#isTriggerInputEmpty(event)) {
3105
+ return false;
3106
+ }
3107
+ const items = this.selectedItems();
3108
+ if (items.length === 0) {
3109
+ return false;
3110
+ }
3111
+ event.preventDefault();
3112
+ event.stopPropagation();
3113
+ this.removeChip(event, items[items.length - 1]);
3114
+ return true;
3115
+ }
3116
+ #isTriggerInputEmpty(event) {
3117
+ const input = event.target instanceof HTMLInputElement ? event.target : this.triggerSearchInput()?.nativeElement;
3118
+ return input ? input.value.length === 0 : !this.searchText();
3119
+ }
3120
+ /**
3121
+ * Seeds the item cache with known items so matching `value` keys resolve without `byKey`.
3122
+ * Useful after an async parent-entity load when `valueItems` is not bound.
3123
+ *
3124
+ * @param items - Full items that include `valueField` (and ideally `textField`) properties.
3125
+ */
3126
+ seedItems(items) {
3127
+ this.#seedItemsCache(items);
3128
+ void this.#resolveSelectedItems(this.selectedValues());
3129
+ }
3130
+ /**
3131
+ * Clears the whole selection.
3132
+ * Sets `null` in single modes and `[]` in multi modes. Used by projected `ax-clear-button`.
3133
+ *
3134
+ * @param isUserInteraction - Whether the clear was triggered by the user.
3135
+ */
3136
+ reset(isUserInteraction = false) {
3137
+ if (this.disabled() || this.readonly()) {
3138
+ return;
3139
+ }
3140
+ const next = this.isMultiple() ? [] : null;
3141
+ const current = this.value();
3142
+ if (this.isMultiple()) {
3143
+ if (Array.isArray(current) && current.length === 0) {
3144
+ return;
3145
+ }
3146
+ }
3147
+ else if (current == null) {
3148
+ return;
3149
+ }
3150
+ this.#isUserInteraction = isUserInteraction;
3151
+ this.value.set(next);
3152
+ if (this.isSheetSearchEnabled() && this.sheetSearchText()) {
3153
+ this.#clearSheetSearch();
3154
+ }
3155
+ else if (this.isEditableTrigger() && this.searchText()) {
3156
+ this.searchText.set('');
3157
+ this.#applyFilterDebounced('');
3158
+ }
3159
+ }
3160
+ #clearSheetSearch() {
3161
+ this.sheetSearchText.set('');
3162
+ this.sheetSearchRef()?.commitValue('', false);
3163
+ this.#applyFilterDebounced('');
3164
+ }
3165
+ #sheetSearchInputValue() {
3166
+ return this.sheetSearchRef()?.getHostElement()?.querySelector('input')?.value ?? '';
3167
+ }
3168
+ #tryFocusSheetSearch() {
3169
+ if (!this.isSheetSearchEnabled() || this.#sheetSearchFocused) {
3170
+ return;
3171
+ }
3172
+ const search = this.sheetSearchRef();
3173
+ if (!search) {
3174
+ return;
3175
+ }
3176
+ this.#sheetSearchFocused = true;
3177
+ search.focus();
3178
+ }
3179
+ #focusPopupSearchOrList() {
3180
+ if (this.isSheetSearchEnabled()) {
3181
+ this.#tryFocusSheetSearch();
3182
+ return;
3183
+ }
3184
+ this.focusListFirst();
3185
+ }
3186
+ #loadCachedTreeNodes(source, nodeId) {
3187
+ let byParent = this.#treeChildrenCache.get(source);
3188
+ if (!byParent) {
3189
+ byParent = new Map();
3190
+ this.#treeChildrenCache.set(source, byParent);
3191
+ }
3192
+ const key = nodeId ?? '';
3193
+ const cached = byParent.get(key);
3194
+ if (cached) {
3195
+ return cached;
3196
+ }
3197
+ const request = Promise.resolve(source(nodeId)).then((nodes) => nodes ?? [], (error) => {
3198
+ byParent.delete(key);
3199
+ throw error;
3200
+ });
3201
+ byParent.set(key, request);
3202
+ return request;
3203
+ }
3204
+ /**
3205
+ * Hydrates a lazy tree once per popup open so whole-tree search can filter in memory.
3206
+ */
3207
+ #ensureHydratedTree() {
3208
+ const cached = this.#hydratedTreeNodes();
3209
+ if (cached) {
3210
+ return Promise.resolve(cached);
3211
+ }
3212
+ if (this.#hydrationPromise) {
3213
+ return this.#hydrationPromise;
3214
+ }
3215
+ const source = this.treeDataSource();
3216
+ if (!source || Array.isArray(source)) {
3217
+ return Promise.resolve([]);
3218
+ }
3219
+ const revision = this.#hydrationRevision;
3220
+ this.treeSearchLoading.set(true);
3221
+ this.#hydrationPromise = (async () => {
3222
+ const roots = await this.#loadCachedTreeNodes(source, undefined);
3223
+ const hydrated = await hydrateLookupTree(roots, (id) => this.#loadCachedTreeNodes(source, id), {
3224
+ valueField: this.valueField(),
3225
+ isCancelled: () => revision !== this.#hydrationRevision,
3226
+ });
3227
+ if (revision !== this.#hydrationRevision) {
3228
+ return [];
3229
+ }
3230
+ this.#hydratedTreeNodes.set(hydrated);
3231
+ this.treeSearchLoading.set(false);
3232
+ this.#treeFilterEpoch.update((value) => value + 1);
3233
+ return hydrated;
3234
+ })().finally(() => {
3235
+ if (revision === this.#hydrationRevision) {
3236
+ this.#hydrationPromise = undefined;
3237
+ }
3238
+ if (revision === this.#hydrationRevision && !this.#hydratedTreeNodes()) {
3239
+ this.treeSearchLoading.set(false);
3240
+ }
3241
+ });
3242
+ return this.#hydrationPromise;
3243
+ }
3244
+ #applyFilterNow(text) {
3245
+ const query = text?.trim() ?? '';
3246
+ this.#appliedSearchQuery.set(query);
3247
+ if (this.#isTreeOnlySearchMode()) {
3248
+ this.#treeFilterQuery.set(query);
3249
+ this.#filterApplied = query.length > 0;
3250
+ this.#treeFilterEpoch.update((value) => value + 1);
3251
+ if (query) {
3252
+ const source = this.treeDataSource();
3253
+ if (source && typeof source === 'function') {
3254
+ void this.#ensureHydratedTree();
3255
+ }
3256
+ }
3257
+ return;
3258
+ }
3259
+ const source = this.resolvedDataSource();
3260
+ if (query) {
3261
+ source.filter({ field: this.textField(), value: query, operator: { type: 'contains' } });
3262
+ this.#filterApplied = true;
3263
+ }
3264
+ else {
3265
+ source.clearFilter();
3266
+ }
3267
+ source.refresh();
3268
+ }
3269
+ #applyFilterDebounced(text) {
3270
+ if (this.#searchDebounce) {
3271
+ clearTimeout(this.#searchDebounce);
3272
+ this.#searchDebounce = undefined;
3273
+ }
3274
+ const query = text?.trim() ?? '';
3275
+ // Restore the full tree immediately when the query is cleared.
3276
+ if (!query) {
3277
+ this.#applyFilterNow('');
3278
+ return;
3279
+ }
3280
+ this.#searchDebounce = setTimeout(() => {
3281
+ this.#searchDebounce = undefined;
3282
+ this.#applyFilterNow(text);
3283
+ }, 300);
3284
+ }
3285
+ async #resolveSelectedItems(values) {
3286
+ const revision = ++this.#resolveRevision;
3287
+ const resolved = await Promise.all(values.map((value) => Promise.resolve(this.#resolveItem(value))));
3288
+ if (revision !== this.#resolveRevision) {
3289
+ return;
3290
+ }
3291
+ const items = resolved.filter((item) => item != null);
3292
+ this.selectedItems.set(items);
3293
+ if (this.#selectionInitialized) {
3294
+ this.onSelectionChanged.emit({
3295
+ component: this,
3296
+ htmlElement: this.nativeElement,
3297
+ isUserInteraction: this.#isUserInteraction,
3298
+ items: items,
3299
+ value: this.value(),
3300
+ });
3301
+ }
3302
+ this.#selectionInitialized = true;
3303
+ }
3304
+ #seedItemsCache(items) {
3305
+ if (!items?.length) {
3306
+ return;
3307
+ }
3308
+ const field = this.valueField();
3309
+ for (const item of items) {
3310
+ const key = item?.[field];
3311
+ if (key == null) {
3312
+ continue;
3313
+ }
3314
+ this.#itemsCache.set(key, item);
3315
+ this.#itemsCache.set(String(key), item);
3316
+ }
3317
+ }
3318
+ #resolveItem(value) {
3319
+ const cached = this.#itemsCache.get(value) ?? this.#itemsCache.get(String(value));
3320
+ if (cached) {
3321
+ return cached;
3322
+ }
3323
+ if (this.isTreeMode()) {
3324
+ const nodes = this.treeDataSource();
3325
+ if (Array.isArray(nodes)) {
3326
+ const found = this.#findTreeNode(nodes, value);
3327
+ if (found) {
3328
+ this.#itemsCache.set(value, found);
3329
+ return found;
3330
+ }
3331
+ }
3332
+ return this.#fallbackItem(value);
3333
+ }
3334
+ const source = this.resolvedDataSource();
3335
+ const result = source.find(value);
3336
+ if (result == null) {
3337
+ return this.#fallbackItem(value);
3338
+ }
3339
+ if (result instanceof Promise) {
3340
+ return result.then((item) => {
3341
+ if (item) {
3342
+ this.#itemsCache.set(value, item);
3343
+ return item;
3344
+ }
3345
+ return this.#fallbackItem(value);
3346
+ });
3347
+ }
3348
+ this.#itemsCache.set(value, result);
3349
+ return result;
3350
+ }
3351
+ #fallbackItem(value) {
3352
+ return { [this.valueField()]: value, [this.textField()]: String(value) };
3353
+ }
3354
+ #findTreeNode(nodes, value) {
3355
+ for (const node of nodes) {
3356
+ if (String(node[this.valueField()]) === String(value)) {
3357
+ return node;
3358
+ }
3359
+ const children = node['children'];
3360
+ if (Array.isArray(children)) {
3361
+ const found = this.#findTreeNode(children, value);
3362
+ if (found) {
3363
+ return found;
3364
+ }
3365
+ }
3366
+ }
3367
+ return null;
3368
+ }
3369
+ #valuesEqual(a, b) {
3370
+ if (a === b) {
3371
+ return true;
3372
+ }
3373
+ if (Array.isArray(a) && Array.isArray(b)) {
3374
+ return a.length === b.length && a.every((item, index) => item == b[index]);
3375
+ }
3376
+ return false;
3377
+ }
3378
+ /** Emits onValueChanged when the value actually changes (skips the initial value). */
3379
+ #emitValueChanged(value) {
3380
+ const previous = this.#lastValue;
3381
+ this.#lastValue = value;
3382
+ if (previous === undefined || this.#valuesEqual(previous, value)) {
3383
+ return;
3384
+ }
3385
+ this.onValueChanged.emit({
3386
+ component: this,
3387
+ htmlElement: this.nativeElement,
3388
+ name: 'value',
3389
+ value,
3390
+ oldValue: previous,
3391
+ isUserInteraction: this.#isUserInteraction,
3392
+ });
3393
+ this.#isUserInteraction = false;
3394
+ }
3395
+ /** Emits onOpened/onClosed when the expanded state actually changes (skips the initial state). */
3396
+ #emitOpenedOrClosed(expanded) {
3397
+ const previous = this.#lastExpanded;
3398
+ this.#lastExpanded = expanded;
3399
+ if (previous === undefined || previous === expanded) {
3400
+ return;
3401
+ }
3402
+ const event = {
3403
+ component: this,
3404
+ htmlElement: this.nativeElement,
3405
+ isUserInteraction: true,
3406
+ };
3407
+ expanded ? this.onOpened.emit(event) : this.onClosed.emit(event);
3408
+ }
3409
+ #translateItemText(text) {
3410
+ return this.#translation.translateSync(text, { waitForLoad: true });
3411
+ }
3412
+ /** Fast path for search filtering — skips sync translation for plain labels. */
3413
+ #translateItemTextForFilter(text) {
3414
+ const value = String(text ?? '');
3415
+ if (!value.startsWith('@')) {
3416
+ return value;
3417
+ }
3418
+ return this.#translation.translateSync(value, { waitForLoad: false });
3419
+ }
3420
+ static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "22.0.8", ngImport: i0, type: AXLookupComponent, deps: [], target: i0.ɵɵFactoryTarget.Component }); }
3421
+ 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 }, highlightSearch: { classPropertyName: "highlightSearch", publicName: "highlightSearch", 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: [
3422
+ { provide: AXComponent, useExisting: AXLookupComponent },
3423
+ { provide: AXClearableComponent, useExisting: AXLookupComponent },
3424
+ { provide: AXClosableComponent, useExisting: AXLookupComponent },
3425
+ { provide: AXValuableComponent, useExisting: AXLookupComponent },
3426
+ ], 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: "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) | translate | async)\">\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]=\"translatedPlaceholder()\"\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 (click)=\"onChevronClick($event)\"\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>{{ actionsheetTitle() }}</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 [highlightText]=\"highlightQuery()\"\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 [highlightText]=\"highlightQuery()\"\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 [loadingTemplate]=\"loadingTemplate()\"\n [loading]=\"treeSearchLoading()\"\n [filterKey]=\"treeFilterKey()\"\n [alternate]=\"alternate()\"\n [highlightText]=\"highlightQuery()\"\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 [loadingTemplate]=\"loadingTemplate()\"\n [loading]=\"treeSearchLoading()\"\n [filterKey]=\"treeFilterKey()\"\n [alternate]=\"alternate()\"\n [highlightText]=\"highlightQuery()\"\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 [highlightText]=\"highlightQuery()\"\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 [highlightText]=\"highlightQuery()\"\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{--ax-comp-lookup-highlight-bg-color: var(--ax-sys-color-warning-lighter-surface);--ax-comp-lookup-highlight-text-color: var(--ax-sys-color-on-warning-lighter-surface);--ax-comp-lookup-highlight-border-color: var(--ax-sys-color-warning-500);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 .ax-highlight{display:inline;margin:0;padding:0;background-color:rgb(var(--ax-comp-lookup-highlight-bg-color));color:rgb(var(--ax-comp-lookup-highlight-text-color));font-weight:inherit;box-shadow:none}.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}.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", "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", "loadingTemplate", "loading", "alternate", "filterKey", "highlightText"], outputs: ["itemClick"] }, { kind: "component", type: AXLookupMultiSelectTreeComponent, selector: "ax-lookup-multi-select-tree", inputs: ["dataSource", "valueField", "textField", "disabledField", "selectedValues", "selectionBehavior", "nodeTemplate", "emptyTemplate", "loadingTemplate", "loading", "alternate", "filterKey", "highlightText"], outputs: ["selectionChange"] }, { kind: "component", type: AXLookupMultiColumnComponent, selector: "ax-lookup-multi-column", inputs: ["dataSource", "valueField", "textField", "disabledField", "selectedValues", "itemHeight", "maxVisibleItems", "columns", "itemTemplate", "emptyTemplate", "loadingTemplate", "alternate", "highlightText"], 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", "highlightText"], outputs: ["itemClick"] }, { kind: "pipe", type: AsyncPipe, name: "async" }, { kind: "pipe", type: AXTranslatorPipe, name: "translate" }], changeDetection: i0.ChangeDetectionStrategy.OnPush, encapsulation: i0.ViewEncapsulation.None }); }
3427
+ }
3428
+ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "22.0.8", ngImport: i0, type: AXLookupComponent, decorators: [{
3429
+ type: Component,
3430
+ args: [{ selector: 'ax-lookup', encapsulation: ViewEncapsulation.None, changeDetection: ChangeDetectionStrategy.OnPush, imports: [
3431
+ NgTemplateOutlet,
3432
+ AsyncPipe,
3433
+ AXTranslatorPipe,
3434
+ AXButtonComponent,
3435
+ AXChipsComponent,
3436
+ AXDecoratorModule,
3437
+ AXPopoverComponent,
3438
+ AXSearchBoxComponent,
3439
+ AXLookupDropDownListComponent,
3440
+ AXLookupMultiSelectComponent,
3441
+ AXLookupDropDownTreeComponent,
3442
+ AXLookupMultiSelectTreeComponent,
3443
+ AXLookupMultiColumnComponent,
3444
+ AXLookupMultiColumnTreeComponent,
3445
+ ], providers: [
3446
+ { provide: AXComponent, useExisting: AXLookupComponent },
3447
+ { provide: AXClearableComponent, useExisting: AXLookupComponent },
3448
+ { provide: AXClosableComponent, useExisting: AXLookupComponent },
3449
+ { provide: AXValuableComponent, useExisting: AXLookupComponent },
3450
+ ], 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) | translate | async)\">\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]=\"translatedPlaceholder()\"\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 (click)=\"onChevronClick($event)\"\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>{{ actionsheetTitle() }}</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 [highlightText]=\"highlightQuery()\"\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 [highlightText]=\"highlightQuery()\"\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 [loadingTemplate]=\"loadingTemplate()\"\n [loading]=\"treeSearchLoading()\"\n [filterKey]=\"treeFilterKey()\"\n [alternate]=\"alternate()\"\n [highlightText]=\"highlightQuery()\"\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 [loadingTemplate]=\"loadingTemplate()\"\n [loading]=\"treeSearchLoading()\"\n [filterKey]=\"treeFilterKey()\"\n [alternate]=\"alternate()\"\n [highlightText]=\"highlightQuery()\"\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 [highlightText]=\"highlightQuery()\"\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 [highlightText]=\"highlightQuery()\"\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{--ax-comp-lookup-highlight-bg-color: var(--ax-sys-color-warning-lighter-surface);--ax-comp-lookup-highlight-text-color: var(--ax-sys-color-on-warning-lighter-surface);--ax-comp-lookup-highlight-border-color: var(--ax-sys-color-warning-500);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 .ax-highlight{display:inline;margin:0;padding:0;background-color:rgb(var(--ax-comp-lookup-highlight-bg-color));color:rgb(var(--ax-comp-lookup-highlight-text-color));font-weight:inherit;box-shadow:none}.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}.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"] }]
3451
+ }], 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 }] }], highlightSearch: [{ type: i0.Input, args: [{ isSignal: true, alias: "highlightSearch", 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 }] }], sheetSearchRef: [{ type: i0.ViewChild, args: ['sheetSearch', { isSignal: true }] }] } });
3452
+
3453
+ class AXLookupModule {
3454
+ static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "22.0.8", ngImport: i0, type: AXLookupModule, deps: [], target: i0.ɵɵFactoryTarget.NgModule }); }
3455
+ static { this.ɵmod = i0.ɵɵngDeclareNgModule({ minVersion: "14.0.0", version: "22.0.8", ngImport: i0, type: AXLookupModule, imports: [AXLookupComponent,
3456
+ AXLookupDropDownListComponent,
3457
+ AXLookupMultiSelectComponent,
3458
+ AXLookupDropDownTreeComponent,
3459
+ AXLookupMultiSelectTreeComponent,
3460
+ AXLookupMultiColumnComponent,
3461
+ AXLookupMultiColumnTreeComponent], exports: [AXLookupComponent,
3462
+ AXLookupDropDownListComponent,
3463
+ AXLookupMultiSelectComponent,
3464
+ AXLookupDropDownTreeComponent,
3465
+ AXLookupMultiSelectTreeComponent,
3466
+ AXLookupMultiColumnComponent,
3467
+ AXLookupMultiColumnTreeComponent] }); }
3468
+ static { this.ɵinj = i0.ɵɵngDeclareInjector({ minVersion: "12.0.0", version: "22.0.8", ngImport: i0, type: AXLookupModule, imports: [AXLookupComponent,
3469
+ AXLookupDropDownListComponent,
3470
+ AXLookupMultiSelectComponent,
3471
+ AXLookupDropDownTreeComponent,
3472
+ AXLookupMultiSelectTreeComponent,
3473
+ AXLookupMultiColumnComponent,
3474
+ AXLookupMultiColumnTreeComponent] }); }
3475
+ }
3476
+ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "22.0.8", ngImport: i0, type: AXLookupModule, decorators: [{
3477
+ type: NgModule,
3478
+ args: [{
3479
+ imports: [
3480
+ AXLookupComponent,
3481
+ AXLookupDropDownListComponent,
3482
+ AXLookupMultiSelectComponent,
3483
+ AXLookupDropDownTreeComponent,
3484
+ AXLookupMultiSelectTreeComponent,
3485
+ AXLookupMultiColumnComponent,
3486
+ AXLookupMultiColumnTreeComponent,
3487
+ ],
3488
+ exports: [
3489
+ AXLookupComponent,
3490
+ AXLookupDropDownListComponent,
3491
+ AXLookupMultiSelectComponent,
3492
+ AXLookupDropDownTreeComponent,
3493
+ AXLookupMultiSelectTreeComponent,
3494
+ AXLookupMultiColumnComponent,
3495
+ AXLookupMultiColumnTreeComponent,
3496
+ ],
3497
+ }]
3498
+ }] });
3499
+
3500
+ /**
3501
+ * Generated bundle index. Do not edit.
3502
+ */
3503
+
3504
+ export { AXLookupComponent, AXLookupDropDownListComponent, AXLookupDropDownTreeComponent, AXLookupModule, AXLookupMultiColumnComponent, AXLookupMultiColumnTreeComponent, AXLookupMultiSelectComponent, AXLookupMultiSelectTreeComponent, cloneLookupTreeNodes, convertLookupArrayToDataSource, createLookupTreeTableDataSource, filterTreeNodes, flattenTreeNodes, hydrateLookupTree, lookupTreeNodeMayHaveChildren, matchesLookupText, prepareFilteredTreeTableRows };
3505
+ //# sourceMappingURL=acorex-components-lookup.mjs.map