@acorex/components 22.0.0-next.21 → 22.0.0-next.22

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 (42) hide show
  1. package/fesm2022/acorex-components-calendar.mjs +2 -2
  2. package/fesm2022/acorex-components-calendar.mjs.map +1 -1
  3. package/fesm2022/acorex-components-color-palette.mjs +2 -2
  4. package/fesm2022/acorex-components-color-palette.mjs.map +1 -1
  5. package/fesm2022/acorex-components-cron-job.mjs +12 -12
  6. package/fesm2022/acorex-components-cron-job.mjs.map +1 -1
  7. package/fesm2022/acorex-components-datetime-box.mjs +10 -12
  8. package/fesm2022/acorex-components-datetime-box.mjs.map +1 -1
  9. package/fesm2022/acorex-components-datetime-input.mjs +49 -30
  10. package/fesm2022/acorex-components-datetime-input.mjs.map +1 -1
  11. package/fesm2022/acorex-components-form.mjs +3 -4
  12. package/fesm2022/acorex-components-form.mjs.map +1 -1
  13. package/fesm2022/acorex-components-list.mjs +19 -265
  14. package/fesm2022/acorex-components-list.mjs.map +1 -1
  15. package/fesm2022/acorex-components-phone-box.mjs +6 -6
  16. package/fesm2022/acorex-components-phone-box.mjs.map +1 -1
  17. package/fesm2022/acorex-components-query-builder.mjs +2 -6
  18. package/fesm2022/acorex-components-query-builder.mjs.map +1 -1
  19. package/fesm2022/acorex-components-rest-api-generator.mjs +2 -2
  20. package/fesm2022/acorex-components-rest-api-generator.mjs.map +1 -1
  21. package/fesm2022/acorex-components-rrule.mjs +2 -2
  22. package/fesm2022/acorex-components-rrule.mjs.map +1 -1
  23. package/fesm2022/acorex-components-scheduler-picker.mjs +16 -16
  24. package/fesm2022/acorex-components-scheduler-picker.mjs.map +1 -1
  25. package/fesm2022/acorex-components-scheduler.mjs +2 -2
  26. package/fesm2022/acorex-components-scheduler.mjs.map +1 -1
  27. package/fesm2022/acorex-components-select-box.mjs +451 -176
  28. package/fesm2022/acorex-components-select-box.mjs.map +1 -1
  29. package/fesm2022/acorex-components-selection-list.mjs +4 -0
  30. package/fesm2022/acorex-components-selection-list.mjs.map +1 -1
  31. package/package.json +3 -7
  32. package/select-box/README.md +0 -2
  33. package/types/acorex-components-datetime-input.d.ts +14 -5
  34. package/types/acorex-components-list.d.ts +3 -65
  35. package/types/acorex-components-phone-box.d.ts +2 -2
  36. package/types/acorex-components-query-builder.d.ts +9 -10
  37. package/types/acorex-components-select-box.d.ts +147 -36
  38. package/types/acorex-components-selection-list.d.ts +2 -1
  39. package/combo-box/README.md +0 -3
  40. package/fesm2022/acorex-components-combo-box.mjs +0 -669
  41. package/fesm2022/acorex-components-combo-box.mjs.map +0 -1
  42. package/types/acorex-components-combo-box.d.ts +0 -202
@@ -1,53 +1,58 @@
1
- import { MXSelectionValueComponent, MXLookComponent, AXHotkeysService, AX_SELECTION_DATA_TOKEN, AXComponent, AXFocusableComponent, AXValuableComponent, AXClearableComponent, AXClosableComponent, AXSearchableComponent, MXSelectionBridgeService, AXCommonModule } from '@acorex/cdk/common';
1
+ import { MXSelectionValueComponent, MXLookComponent, AXHotkeysService, convertArrayToDataSource, AX_SELECTION_DATA_TOKEN, AXDataSource, AXComponent, AXFocusableComponent, AXValuableComponent, AXClearableComponent, AXClosableComponent, AXSearchableComponent, MXSelectionBridgeService, AXCommonModule } from '@acorex/cdk/common';
2
2
  import { AXDecoratorGenericComponent, AXDecoratorCloseButtonComponent, AXDecoratorModule } from '@acorex/components/decorators';
3
3
  import { MXDropdownBoxBaseComponent, AXDropdownBoxComponent, AXDropdownModule } from '@acorex/components/dropdown';
4
+ import { AXListComponent, AXListModule } from '@acorex/components/list';
5
+ import { AXLoadingSpinnerComponent, AXLoadingModule } from '@acorex/components/loading';
4
6
  import { AXSearchBoxComponent } from '@acorex/components/search-box';
5
- import { AXSelectionListComponent, AXSelectionListModule } from '@acorex/components/selection-list';
6
7
  import { AXTagComponent } from '@acorex/components/tag';
7
8
  import { AXTranslatorPipe, AXTranslationModule } from '@acorex/core/translation';
8
9
  import { AXUnsubscriber } from '@acorex/core/utils';
9
- import { NgTemplateOutlet, AsyncPipe, CommonModule } from '@angular/common';
10
+ import { NgTemplateOutlet, NgClass, AsyncPipe, CommonModule } from '@angular/common';
10
11
  import * as i0 from '@angular/core';
11
- import { input, signal, inject, viewChild, contentChild, effect, untracked, afterNextRender, forwardRef, ViewEncapsulation, Component, NgModule } from '@angular/core';
12
+ import { input, inject, ElementRef, signal, linkedSignal, afterNextRender, forwardRef, HostListener, ViewChild, ContentChild, Input, ViewEncapsulation, Component, NgModule } from '@angular/core';
12
13
  import * as i1 from '@angular/forms';
13
14
  import { FormsModule, NG_VALUE_ACCESSOR } from '@angular/forms';
14
15
  import { isEqual, get, last, findLastIndex, nth } from 'lodash-es';
15
16
  import { classes } from 'polytype';
16
17
  import { AXBadgeModule } from '@acorex/components/badge';
17
18
  import { AXCheckBoxModule } from '@acorex/components/check-box';
18
- import { AXLoadingModule } from '@acorex/components/loading';
19
19
  import { AXPopoverModule } from '@acorex/components/popover';
20
20
  import { A11yModule } from '@angular/cdk/a11y';
21
21
  import { AXTextBoxModule } from '@acorex/components/text-box';
22
22
 
23
23
  /**
24
- * Simple dropdown select for a static items array.
25
- * For AXDataSource / lazy-load support, use ComboBox.
24
+ * The Button is a component which detects user interaction and triggers a corresponding event
25
+ * @category
26
26
  */
27
27
  class AXSelectBoxComponent extends classes(MXDropdownBoxBaseComponent, MXSelectionValueComponent, MXLookComponent) {
28
28
  constructor() {
29
29
  super(...arguments);
30
- /** Static items shown in the dropdown. */
31
- this.items = input([], /* @ts-ignore */
32
- ...(ngDevMode ? [{ debugName: "items" }] : /* istanbul ignore next */ []));
33
- this.placeholder = input(/* @ts-ignore */
34
- ...(ngDevMode ? [undefined, { debugName: "placeholder" }] : /* istanbul ignore next */ []));
35
- this.minRecordsForSearch = input(/* @ts-ignore */
36
- ...(ngDevMode ? [undefined, { debugName: "minRecordsForSearch" }] : /* istanbul ignore next */ []));
37
- this.caption = input(/* @ts-ignore */
38
- ...(ngDevMode ? [undefined, { debugName: "caption" }] : /* istanbul ignore next */ []));
39
- this.itemTemplate = input(/* @ts-ignore */
40
- ...(ngDevMode ? [undefined, { debugName: "itemTemplate" }] : /* istanbul ignore next */ []));
41
- this.selectedTemplate = input(/* @ts-ignore */
42
- ...(ngDevMode ? [undefined, { debugName: "selectedTemplate" }] : /* istanbul ignore next */ []));
43
- this.emptyTemplate = input(/* @ts-ignore */
44
- ...(ngDevMode ? [undefined, { debugName: "emptyTemplate" }] : /* istanbul ignore next */ []));
30
+ /**
31
+ * Determines if an item is truncated.
32
+ *
33
+ * @defaultValue true
34
+ */
35
+ this.isItemTruncated = input(true, /* @ts-ignore */
36
+ ...(ngDevMode ? [{ debugName: "isItemTruncated" }] : /* istanbul ignore next */ []));
37
+ /**
38
+ * Determines if a tooltip is shown for an item.
39
+ *
40
+ * @defaultValue false
41
+ */
42
+ this.showItemTooltip = input(false, /* @ts-ignore */
43
+ ...(ngDevMode ? [{ debugName: "showItemTooltip" }] : /* istanbul ignore next */ []));
44
+ this.host = inject(ElementRef);
45
+ /** Height of each list item in pixels, or 'auto' to let list measure. */
46
+ this.itemHeight = input(40, /* @ts-ignore */
47
+ ...(ngDevMode ? [{ debugName: "itemHeight" }] : /* istanbul ignore next */ []));
48
+ /** Maximum number of visible items before scrolling. */
45
49
  this.maxVisibleItems = input(5, /* @ts-ignore */
46
50
  ...(ngDevMode ? [{ debugName: "maxVisibleItems" }] : /* istanbul ignore next */ []));
47
- this.dropdownWidth = input(null, /* @ts-ignore */
48
- ...(ngDevMode ? [{ debugName: "dropdownWidth" }] : /* istanbul ignore next */ []));
49
- this.searchBoxAutoFocus = input(true, /* @ts-ignore */
50
- ...(ngDevMode ? [{ debugName: "searchBoxAutoFocus" }] : /* istanbul ignore next */ []));
51
+ /** @ignore */
52
+ this.hotKeyService = inject(AXHotkeysService);
53
+ /** @ignore */
54
+ this.isLoading = signal(false, /* @ts-ignore */
55
+ ...(ngDevMode ? [{ debugName: "isLoading" }] : /* istanbul ignore next */ []));
51
56
  /** @ignore */
52
57
  this.searchValue = signal('', /* @ts-ignore */
53
58
  ...(ngDevMode ? [{ debugName: "searchValue" }] : /* istanbul ignore next */ []));
@@ -55,211 +60,441 @@ class AXSelectBoxComponent extends classes(MXDropdownBoxBaseComponent, MXSelecti
55
60
  this.renderList = signal(false, /* @ts-ignore */
56
61
  ...(ngDevMode ? [{ debugName: "renderList" }] : /* istanbul ignore next */ []));
57
62
  /** @ignore */
58
- this._dropdownWidth = signal('auto', /* @ts-ignore */
63
+ this._dropdownWidth = linkedSignal(() => this.dropdownWidth(), /* @ts-ignore */
59
64
  ...(ngDevMode ? [{ debugName: "_dropdownWidth" }] : /* istanbul ignore next */ []));
60
65
  /** @ignore */
61
66
  this._dropdownHeight = signal('auto', /* @ts-ignore */
62
67
  ...(ngDevMode ? [{ debugName: "_dropdownHeight" }] : /* istanbul ignore next */ []));
63
68
  /** @ignore */
64
- this.visibleItems = signal([], /* @ts-ignore */
65
- ...(ngDevMode ? [{ debugName: "visibleItems" }] : /* istanbul ignore next */ []));
66
- this.hotKeyService = inject(AXHotkeysService);
67
- this._unsubscriber = inject(AXUnsubscriber);
68
- this.selectionService = inject(AX_SELECTION_DATA_TOKEN);
69
- this.panel = viewChild('panel', /* @ts-ignore */
70
- ...(ngDevMode ? [{ debugName: "panel" }] : /* istanbul ignore next */ []));
71
- this.selectionList = viewChild(AXSelectionListComponent, /* @ts-ignore */
72
- ...(ngDevMode ? [{ debugName: "selectionList" }] : /* istanbul ignore next */ []));
73
- this.searchBox = contentChild(AXSearchBoxComponent, /* @ts-ignore */
74
- ...(ngDevMode ? [{ debugName: "searchBox" }] : /* istanbul ignore next */ []));
75
- this.dropdownRef = viewChild.required(AXDropdownBoxComponent, /* @ts-ignore */
76
- ...(ngDevMode ? [{ debugName: "dropdownRef" }] : /* istanbul ignore next */ []));
77
- this.#prevItems = [];
78
- this.#itemsEffect = effect(() => {
79
- const next = this.items() ?? [];
80
- if (isEqual(next, this.#prevItems)) {
81
- return;
82
- }
83
- this.#prevItems = next;
84
- this.#applyFilter(untracked(() => this.searchValue()));
85
- untracked(() => this.forceRefreshSelectedItems());
86
- }, /* @ts-ignore */
87
- ...(ngDevMode ? [{ debugName: "#itemsEffect" }] : /* istanbul ignore next */ []));
88
- this.#floatLabel = afterNextRender(() => {
69
+ this._listDataSource = convertArrayToDataSource([], {
70
+ key: this.valueField,
71
+ pageSize: 10,
72
+ });
73
+ this.#init = afterNextRender(() => {
89
74
  const formField = this.getHostElement().closest('ax-form-field');
90
75
  if (formField?.classList.contains('ax-state-floating-label')) {
91
76
  this.getHostElement().classList.add('ax-float-label');
92
77
  }
93
78
  });
79
+ /**
80
+ * The width of the dropdown in pixels.
81
+ * @defaultValue null
82
+ */
83
+ this.dropdownWidth = input(null, /* @ts-ignore */
84
+ ...(ngDevMode ? [{ debugName: "dropdownWidth" }] : /* istanbul ignore next */ []));
85
+ this.searchBoxAutoFocus = input(true, /* @ts-ignore */
86
+ ...(ngDevMode ? [{ debugName: "searchBoxAutoFocus" }] : /* istanbul ignore next */ []));
87
+ /**
88
+ * Service for managing selection data, injected via `AX_SELECTION_DATA_TOKEN`.
89
+ */
90
+ this.selectionService = inject(AX_SELECTION_DATA_TOKEN);
91
+ /** @ignore */
92
+ this._unsubscriber = inject(AXUnsubscriber);
93
+ }
94
+ #init;
95
+ /**
96
+ * Gets the data source for the component, which can be either an `AXDataSource` or an array of items.
97
+ * @returns {AXDataSource<any> | any[]}
98
+ */
99
+ get dataSource() {
100
+ return this._originalDataSource;
94
101
  }
95
- /** Required by MXDropdownBoxBaseComponent. */
96
- get dropdown() {
97
- return this.dropdownRef();
102
+ /**
103
+ * Sets the data source, either as an `AXDataSource` or an array.
104
+ * @param {AXDataSource<any> | any[]} v
105
+ */
106
+ set dataSource(v) {
107
+ // check if the data source is the same
108
+ if (Array.isArray(v) && Array.isArray(this._originalDataSource) && isEqual(v, this._originalDataSource)) {
109
+ return;
110
+ }
111
+ if (v instanceof AXDataSource && v == this._originalDataSource) {
112
+ return;
113
+ }
114
+ //
115
+ this._originalDataSource = v;
116
+ if (Array.isArray(v)) {
117
+ this._listDataSource = convertArrayToDataSource(v, {
118
+ key: this.valueField,
119
+ pageSize: v.length || 10,
120
+ });
121
+ }
122
+ else {
123
+ this._listDataSource = this.dataSource;
124
+ }
125
+ //
126
+ this.onChangedSubscription?.unsubscribe();
127
+ this.onChangedSubscription = this._listDataSource.onChanged
128
+ .pipe(this._unsubscriber.takeUntilDestroy)
129
+ .subscribe(() => {
130
+ this.updateDropdownSize();
131
+ // Force refresh of selected items when data source changes
132
+ this.forceRefreshSelectedItems();
133
+ });
134
+ //
135
+ this.onLoadingChangedSubscription?.unsubscribe();
136
+ this.onLoadingChangedSubscription = this._listDataSource.onLoadingChanged
137
+ .pipe(this._unsubscriber.takeUntilDestroy)
138
+ .subscribe((loading) => {
139
+ this.isLoading.set(loading);
140
+ });
141
+ // After setting data source, try to fetch item data if needed
142
+ setTimeout(() => this.fetchItemDataIfNeeded(), 0);
98
143
  }
99
- #prevItems;
100
- #itemsEffect;
101
- #floatLabel;
144
+ /** @ignore */
102
145
  ngOnInit() {
103
146
  super.ngOnInit();
147
+ //
104
148
  this.registerValidation();
149
+ // Proactively fetch item data if we have a value but no corresponding item
150
+ this.fetchItemDataIfNeeded();
151
+ }
152
+ /**
153
+ * Proactively fetches item data if the component has a value but no corresponding item data.
154
+ * This prevents showing "loading..." when the component has a value.
155
+ */
156
+ async fetchItemDataIfNeeded() {
157
+ const isEmptyValue = this.value == null || (Array.isArray(this.value) && this.value.length === 0);
158
+ if (!isEmptyValue && this._listDataSource && !this.selectedItems?.length) {
159
+ try {
160
+ const item = await this.getItemByKey(this.value);
161
+ if (item) {
162
+ // Force refresh to update the display
163
+ this.forceRefreshSelectedItems();
164
+ }
165
+ }
166
+ catch (error) {
167
+ console.warn('Failed to fetch item data:', error);
168
+ }
169
+ }
105
170
  }
171
+ /** @ignore */
106
172
  ngOnDestroy() {
107
- this.searchBox()?.onKeyDown.unsubscribe();
173
+ this.searchBox?.onKeyDown.unsubscribe();
174
+ this.onChangedSubscription?.unsubscribe();
175
+ this.onLoadingChangedSubscription?.unsubscribe();
108
176
  }
109
- /** Finds an item by value key in the full items array. */
177
+ /**
178
+ * Retrieves an item by its key.
179
+ * @param {any} key
180
+ */
110
181
  getItemByKey(key) {
111
- for (const candidate of this.items()) {
112
- if (candidate != null && typeof candidate === 'object') {
113
- if (get(candidate, this.valueField) == key || get(candidate, this.textField) == key) {
114
- return candidate;
182
+ // Static array data sources resolve synchronously to avoid a false loading state
183
+ // for primitive values (e.g. color format "hex" / "rgba").
184
+ if (Array.isArray(this._originalDataSource)) {
185
+ for (const candidate of this._originalDataSource) {
186
+ if (candidate != null && typeof candidate === 'object') {
187
+ if (get(candidate, this.valueField) == key || get(candidate, this.textField) == key) {
188
+ return candidate;
189
+ }
190
+ }
191
+ else if (candidate == key) {
192
+ return { [this.valueField]: candidate, [this.textField]: String(candidate ?? '') };
115
193
  }
116
194
  }
117
- else if (candidate == key) {
118
- return { [this.valueField]: candidate, [this.textField]: String(candidate ?? '') };
119
- }
195
+ return null;
120
196
  }
197
+ if (this._listDataSource && typeof this._listDataSource.find === 'function') {
198
+ return this._listDataSource.find(key);
199
+ }
200
+ // If neither method is available, return null
201
+ console.warn('No find method available on data source');
121
202
  return null;
122
203
  }
123
- /** Filters visible items by textField contains. */
124
- search(term) {
125
- this.#applyFilter(term ?? '');
126
- this.#syncDropdownSize();
127
- }
128
- /** Resets selection and closes the dropdown. */
129
- refresh() {
130
- this.reset(false);
131
- this.clearSelectionCache();
132
- this.#applyFilter('');
133
- this.close();
134
- }
135
- internalValueChanged(value) {
136
- super.internalValueChanged(value);
137
- this.dropdown?.updatePosition();
138
- }
139
204
  /** @ignore */
140
205
  _handleOnOpenedEvent(e) {
141
- this.renderList.set(true);
142
- this.#focusPanel();
143
- this.onOpened.emit({ component: this, isUserInteraction: e.isUserInteraction });
144
- this.#syncDropdownSize();
206
+ if (!this.renderList()) {
207
+ this.renderList.set(true);
208
+ }
209
+ else if (!this._listDataSource.totalCount || this._listDataSource.totalCount == 0) {
210
+ this.list?.refresh(false);
211
+ }
212
+ this._handleFocus();
213
+ //
214
+ this.onOpened.emit({
215
+ component: this,
216
+ isUserInteraction: e.isUserInteraction,
217
+ });
218
+ this.updateDropdownSize();
219
+ // Force refresh of selected items when opening to show updated text
145
220
  this.forceRefreshSelectedItems();
146
221
  }
147
222
  /** @ignore */
148
223
  _handleOnClosedEvent(e) {
149
- this.onClosed.emit({ component: this, isUserInteraction: e.isUserInteraction });
224
+ this.onClosed.emit({
225
+ component: this,
226
+ isUserInteraction: e.isUserInteraction,
227
+ });
150
228
  this._unsubscriber.unsubscribe();
151
229
  }
152
230
  /** @ignore */
231
+ _handleFocus() {
232
+ setTimeout(() => {
233
+ if (this.searchBox) {
234
+ this.searchBox.look = 'flat';
235
+ if (this.searchBoxAutoFocus()) {
236
+ this.searchBox.focus();
237
+ }
238
+ //TODO: unsubscribe
239
+ this.hotKeyService
240
+ .addShortcut({ keys: 'Control.f', element: this.panel.nativeElement })
241
+ .pipe(this._unsubscriber.takeUntilDestroy)
242
+ .subscribe(() => {
243
+ this.searchBox.focus();
244
+ });
245
+ this.searchBox.onKeyDown.pipe(this._unsubscriber.takeUntilDestroy).subscribe((e) => {
246
+ if (e.nativeEvent.code === 'ArrowDown' || e.nativeEvent.key === 'ArrowDown') {
247
+ this.list?.focus();
248
+ e.nativeEvent.preventDefault();
249
+ }
250
+ });
251
+ }
252
+ else {
253
+ this.list?.focus();
254
+ }
255
+ });
256
+ }
257
+ /** @ignore */
153
258
  _handleBadgeRemove(e, item) {
154
259
  this.unselectItems(item);
155
260
  e.stopPropagation();
156
261
  }
157
262
  /** @ignore */
158
263
  _handleValueChanged(e) {
159
- if (!e.isUserInteraction)
160
- return;
161
- if (!this.multiple)
162
- this.close();
163
- this.commitValue(e.component.selectedItems, true);
164
- const searchBox = this.searchBox();
165
- if (searchBox?.value)
166
- searchBox.commitValue('', false);
264
+ if (e.isUserInteraction) {
265
+ if (!this.multiple) {
266
+ this.close();
267
+ }
268
+ this.commitValue(e.component.selectedItems, true);
269
+ }
167
270
  }
168
271
  /** @ignore */
169
- _handleKeydown(e) {
170
- if (e.code === 'ArrowDown' || e.code === 'ArrowUp') {
171
- this.#selectByNav(e.code === 'ArrowDown' ? 1 : -1);
172
- e.preventDefault();
272
+ _handleItemClick(e) {
273
+ this.onItemClick.emit(e);
274
+ if (!this.multiple) {
275
+ this.close();
173
276
  }
174
- else if (e.code === 'Backspace') {
175
- this.unselectItems(this.selectedItems.pop());
176
- e.preventDefault();
277
+ }
278
+ /** @ignore */
279
+ _handleItemSelected(e) {
280
+ this.onItemSelected.emit(e);
281
+ this.resetSearchAfterSelection();
282
+ if (!this.multiple) {
283
+ this.close();
177
284
  }
178
285
  }
179
- #applyFilter(term) {
180
- this.searchValue.set(term);
181
- const source = this.items() ?? [];
182
- if (!term) {
183
- this.visibleItems.set(source);
286
+ resetSearchAfterSelection() {
287
+ if (!this.searchBox && !this.searchBox?.value)
184
288
  return;
185
- }
186
- const upper = term.toUpperCase();
187
- this.visibleItems.set(source.filter((item) => {
188
- const text = item != null && typeof item === 'object' ? String(get(item, this.textField) ?? '') : String(item ?? '');
189
- return text.toUpperCase().includes(upper);
190
- }));
289
+ if (this.searchBox && this.searchBox?.value)
290
+ this.searchBox.commitValue('', false);
191
291
  }
192
- #focusPanel() {
292
+ /** @ignore */
293
+ setDropdownSize(count = 0) {
294
+ const itemPx = typeof this.itemHeight() === 'number' ? this.itemHeight() : 40;
295
+ const isActionsheet = this.dropdown.isActionsheetStyle;
296
+ if (isActionsheet) {
297
+ this._dropdownWidth.set('100%');
298
+ // Prefer maxVisibleItems on actionsheet too; still clamp to the pane afterwards.
299
+ const maxItems = Math.max(Number(this.maxVisibleItems()) || 5, 1);
300
+ this._dropdownHeight.set(`${Math.min(maxItems, Math.max(count, 1)) * itemPx}px`);
301
+ }
302
+ else {
303
+ const hostWidth = Math.max(this.getHostElement().offsetWidth, Number(this.dropdownWidth()) || 0);
304
+ const maxItems = Number(this.maxVisibleItems());
305
+ this._dropdownWidth.set(`${hostWidth}px`);
306
+ this._dropdownHeight.set(count == 0 ? 'auto' : `${Math.min(maxItems, count) * itemPx}px`);
307
+ }
193
308
  setTimeout(() => {
194
- const searchBox = this.searchBox();
195
- const selectionList = this.selectionList();
196
- const panel = this.panel();
197
- if (!searchBox) {
198
- selectionList?.focus();
199
- return;
200
- }
201
- searchBox.look = 'flat';
202
- if (this.searchBoxAutoFocus())
203
- searchBox.focus();
204
- if (panel) {
205
- this.hotKeyService
206
- .addShortcut({ keys: 'Control.f', element: panel.nativeElement })
207
- .pipe(this._unsubscriber.takeUntilDestroy)
208
- .subscribe(() => searchBox.focus());
209
- }
210
- searchBox.onKeyDown.pipe(this._unsubscriber.takeUntilDestroy).subscribe((e) => {
211
- if (e.nativeEvent.code === 'ArrowDown' || e.nativeEvent.key === 'ArrowDown') {
212
- selectionList?.focus();
213
- e.nativeEvent.preventDefault();
214
- }
309
+ this._fitListHeightToAvailableSpace(itemPx);
310
+ this.dropdown.updatePosition();
311
+ this.list?.render();
312
+ // Second pass after the overlay pane applies max-height / overflow constraints.
313
+ requestAnimationFrame(() => {
314
+ setTimeout(() => {
315
+ this._fitListHeightToAvailableSpace(itemPx);
316
+ this.list?.render();
317
+ }, 0);
215
318
  });
216
319
  });
217
320
  }
218
- #selectByNav(sign) {
219
- const source = this.items() ?? [];
220
- if (this.multiple || !source.length) {
221
- this.open();
321
+ /**
322
+ * Shrinks list height to the visible overlay area so virtual scroll ends on fully
323
+ * visible rows instead of inside an overflow:hidden clipped region.
324
+ * @ignore
325
+ */
326
+ _fitListHeightToAvailableSpace(itemPx) {
327
+ if (itemPx <= 0 || this._dropdownHeight() === 'auto') {
222
328
  return;
223
329
  }
224
- const items = this.normalizeItemsList(source);
225
- const selected = last(this.selectedItems);
226
- let index = selected ? findLastIndex(items, [this.valueField, get(selected, this.valueField)]) : -1;
227
- index += sign;
228
- if (index < 0 || index >= items.length)
330
+ const panel = this.panel?.nativeElement;
331
+ const listEl = this.list?.getHostElement?.();
332
+ if (!panel || !listEl) {
229
333
  return;
230
- const next = nth(items, index);
231
- if (next)
232
- this.selectItems(next);
334
+ }
335
+ const pane = panel.closest('.ax-overlay-pane');
336
+ if (!pane) {
337
+ return;
338
+ }
339
+ const listRect = listEl.getBoundingClientRect();
340
+ const paneRect = pane.getBoundingClientRect();
341
+ const paneOverflow = listRect.bottom - paneRect.bottom;
342
+ const viewportOverflow = listRect.bottom - window.innerHeight;
343
+ const overflow = Math.max(paneOverflow, viewportOverflow);
344
+ let nextHeight = listEl.clientHeight || parseFloat(this._dropdownHeight());
345
+ if (!Number.isFinite(nextHeight) || nextHeight <= 0) {
346
+ return;
347
+ }
348
+ // When the list extends past the overlay pane or screen, shrink it to the visible area.
349
+ if (overflow > 1) {
350
+ nextHeight = Math.max(itemPx, nextHeight - overflow);
351
+ }
352
+ // Keep height as whole rows so the last item is never permanently cropped.
353
+ nextHeight = Math.max(itemPx, Math.floor(nextHeight / itemPx) * itemPx);
354
+ const current = parseFloat(this._dropdownHeight());
355
+ if (!Number.isFinite(current) || nextHeight !== current) {
356
+ this._dropdownHeight.set(`${nextHeight}px`);
357
+ }
233
358
  }
234
- #syncDropdownSize() {
359
+ updateDropdownPosition() {
235
360
  setTimeout(() => {
236
- const count = this.visibleItems().length;
237
- const maxItems = Math.max(Number(this.maxVisibleItems()) || 5, 1);
238
- // Approximate row height of ax-selection-list items (padding + text).
239
- const rowHeightPx = 40;
240
- if (this.dropdown.isActionsheetStyle) {
241
- this._dropdownWidth.set('100%');
361
+ this.dropdown.updatePosition();
362
+ });
363
+ }
364
+ updateDropdownSize() {
365
+ setTimeout(() => {
366
+ this.setDropdownSize(this._listDataSource.totalCount);
367
+ this.updateDropdownPosition();
368
+ this.list?.render();
369
+ if (!this.isItemTruncated()) {
370
+ setTimeout(() => {
371
+ this._fitDropdownToContent();
372
+ setTimeout(() => this._fitDropdownToContent(), 100);
373
+ });
374
+ }
375
+ });
376
+ }
377
+ _fitDropdownToContent() {
378
+ const panel = this.panel?.nativeElement;
379
+ if (!panel)
380
+ return;
381
+ const hostWidth = Math.max(this.getHostElement().offsetWidth, Number(this.dropdownWidth()) || 0);
382
+ let contentWidth = hostWidth;
383
+ panel.querySelectorAll('li.list-item').forEach((item) => {
384
+ const label = item.querySelector('.ax-label-container span');
385
+ if (label) {
386
+ const labelContainer = label.parentElement;
387
+ const horizontalPadding = labelContainer ? item.offsetWidth - labelContainer.clientWidth : 0;
388
+ contentWidth = Math.max(contentWidth, label.scrollWidth + horizontalPadding);
242
389
  }
243
390
  else {
244
- const hostWidth = Math.max(this.getHostElement().offsetWidth, Number(this.dropdownWidth()) || 0);
245
- this._dropdownWidth.set(`${hostWidth}px`);
391
+ contentWidth = Math.max(contentWidth, item.scrollWidth);
246
392
  }
247
- this._dropdownHeight.set(count === 0 ? 'auto' : `${Math.min(maxItems, count) * rowHeightPx}px`);
248
- this.dropdown.updatePosition();
249
393
  });
394
+ const nextWidth = `${Math.max(hostWidth, contentWidth)}px`;
395
+ if (this._dropdownWidth() !== nextWidth) {
396
+ this._dropdownWidth.set(nextWidth);
397
+ this.dropdown.updatePosition();
398
+ }
399
+ }
400
+ internalValueChanged(value) {
401
+ super.internalValueChanged(value);
402
+ this.updateDropdownPosition();
403
+ // Try to fetch item data when value changes
404
+ setTimeout(() => this.fetchItemDataIfNeeded(), 0);
405
+ }
406
+ /** @ignore */
407
+ _handleKeydown(e) {
408
+ if (e.code === 'ArrowDown' || e.code === 'ArrowUp') {
409
+ this.selectItemByNav(e.code === 'ArrowDown' ? 1 : -1);
410
+ e.preventDefault();
411
+ }
412
+ else if (e.code === 'Backspace') {
413
+ this.unselectItems(this.selectedItems.pop());
414
+ e.preventDefault();
415
+ }
416
+ // if ((e.code === 'Space' || e.code === 'Enter') && this.hasItems) {
417
+ // if (this.readonly || this.disabled) {
418
+ // e.preventDefault();
419
+ // e.stopPropagation();
420
+ // return;
421
+ // }
422
+ // const id = document.activeElement?.closest('li')?.dataset?.id;
423
+ // this.toggleSelect(id);
424
+ // e.preventDefault();
425
+ // e.stopPropagation()
426
+ // }
427
+ }
428
+ /** @ignore */
429
+ selectItemByNav(sign) {
430
+ if (Array.isArray(this.dataSource) && !this.multiple) {
431
+ const items = this.normalizeItemsList(this.dataSource);
432
+ const _last = last(this.selectedItems);
433
+ let i = -1;
434
+ if (_last) {
435
+ i = findLastIndex(items, [this.valueField, get(_last, this.valueField)]);
436
+ }
437
+ i += sign;
438
+ if (i < 0 || i >= items.length)
439
+ return;
440
+ const next = nth(items, i);
441
+ if (next) {
442
+ this.selectItems(next);
443
+ }
444
+ }
445
+ else {
446
+ this.open();
447
+ }
448
+ }
449
+ /**
450
+ * Filters the data source based on the provided search term.
451
+ * @param {string} term
452
+ */
453
+ search(term) {
454
+ this.searchValue.set(term);
455
+ if (term) {
456
+ this._listDataSource.filter({
457
+ field: this.textField,
458
+ value: term,
459
+ operator: { type: 'contains' },
460
+ });
461
+ }
462
+ else {
463
+ this._listDataSource.clearFilter();
464
+ }
465
+ this._listDataSource.refresh();
466
+ }
467
+ /**
468
+ * Refreshes the component by resetting state, clearing selection cache, refreshing the list, and closing the component.
469
+ */
470
+ refresh() {
471
+ this.reset(false);
472
+ this.clearSelectionCache();
473
+ this.list?.refresh();
474
+ this.close();
475
+ }
476
+ hostClickListener() {
477
+ this.toggle();
250
478
  }
251
479
  static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "22.0.8", ngImport: i0, type: AXSelectBoxComponent, deps: null, target: i0.ɵɵFactoryTarget.Component }); }
252
- static { this.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "22.0.8", type: AXSelectBoxComponent, isStandalone: true, selector: "ax-select-box", inputs: { disabled: { classPropertyName: "disabled", publicName: "disabled", isSignal: false, isRequired: false, transformFunction: null }, readonly: { classPropertyName: "readonly", publicName: "readonly", isSignal: false, isRequired: false, transformFunction: null }, tabIndex: { classPropertyName: "tabIndex", publicName: "tabIndex", isSignal: false, isRequired: false, transformFunction: null }, minValue: { classPropertyName: "minValue", publicName: "minValue", isSignal: false, isRequired: false, transformFunction: null }, maxValue: { classPropertyName: "maxValue", publicName: "maxValue", isSignal: false, isRequired: false, transformFunction: null }, value: { classPropertyName: "value", publicName: "value", isSignal: false, isRequired: false, transformFunction: null }, state: { classPropertyName: "state", publicName: "state", isSignal: false, isRequired: false, transformFunction: null }, name: { classPropertyName: "name", publicName: "name", isSignal: false, isRequired: false, transformFunction: null }, id: { classPropertyName: "id", publicName: "id", isSignal: false, isRequired: false, transformFunction: null }, type: { classPropertyName: "type", publicName: "type", isSignal: false, isRequired: false, transformFunction: null }, look: { classPropertyName: "look", publicName: "look", isSignal: false, isRequired: false, transformFunction: null }, multiple: { classPropertyName: "multiple", publicName: "multiple", isSignal: false, isRequired: false, transformFunction: null }, valueField: { classPropertyName: "valueField", publicName: "valueField", isSignal: false, isRequired: false, transformFunction: null }, textField: { classPropertyName: "textField", publicName: "textField", isSignal: false, isRequired: false, transformFunction: null }, disabledField: { classPropertyName: "disabledField", publicName: "disabledField", isSignal: false, isRequired: false, transformFunction: null }, textTemplate: { classPropertyName: "textTemplate", publicName: "textTemplate", isSignal: false, isRequired: false, transformFunction: null }, selectedItems: { classPropertyName: "selectedItems", publicName: "selectedItems", isSignal: false, isRequired: false, transformFunction: null }, items: { classPropertyName: "items", publicName: "items", isSignal: true, isRequired: false, transformFunction: null }, placeholder: { classPropertyName: "placeholder", publicName: "placeholder", isSignal: true, isRequired: false, transformFunction: null }, minRecordsForSearch: { classPropertyName: "minRecordsForSearch", publicName: "minRecordsForSearch", isSignal: true, isRequired: false, transformFunction: null }, caption: { classPropertyName: "caption", publicName: "caption", 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 }, maxVisibleItems: { classPropertyName: "maxVisibleItems", publicName: "maxVisibleItems", isSignal: true, isRequired: false, transformFunction: null }, dropdownWidth: { classPropertyName: "dropdownWidth", publicName: "dropdownWidth", isSignal: true, isRequired: false, transformFunction: null }, searchBoxAutoFocus: { classPropertyName: "searchBoxAutoFocus", publicName: "searchBoxAutoFocus", isSignal: true, isRequired: false, transformFunction: null } }, outputs: { valueChange: "valueChange", stateChange: "stateChange", onValueChanged: "onValueChanged", onBlur: "onBlur", onFocus: "onFocus", readonlyChange: "readonlyChange", disabledChange: "disabledChange", onOpened: "onOpened", onClosed: "onClosed", onItemSelected: "onItemSelected", onItemClick: "onItemClick" }, host: { attributes: { "ngSkipHydration": "true" }, listeners: { "click": "toggle()", "keydown": "_handleKeydown($event)" } }, providers: [
480
+ static { this.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "22.0.8", type: AXSelectBoxComponent, isStandalone: true, selector: "ax-select-box", inputs: { disabled: { classPropertyName: "disabled", publicName: "disabled", isSignal: false, isRequired: false, transformFunction: null }, readonly: { classPropertyName: "readonly", publicName: "readonly", isSignal: false, isRequired: false, transformFunction: null }, tabIndex: { classPropertyName: "tabIndex", publicName: "tabIndex", isSignal: false, isRequired: false, transformFunction: null }, placeholder: { classPropertyName: "placeholder", publicName: "placeholder", isSignal: false, isRequired: false, transformFunction: null }, minValue: { classPropertyName: "minValue", publicName: "minValue", isSignal: false, isRequired: false, transformFunction: null }, maxValue: { classPropertyName: "maxValue", publicName: "maxValue", isSignal: false, isRequired: false, transformFunction: null }, value: { classPropertyName: "value", publicName: "value", isSignal: false, isRequired: false, transformFunction: null }, state: { classPropertyName: "state", publicName: "state", isSignal: false, isRequired: false, transformFunction: null }, name: { classPropertyName: "name", publicName: "name", isSignal: false, isRequired: false, transformFunction: null }, id: { classPropertyName: "id", publicName: "id", isSignal: false, isRequired: false, transformFunction: null }, type: { classPropertyName: "type", publicName: "type", isSignal: false, isRequired: false, transformFunction: null }, look: { classPropertyName: "look", publicName: "look", isSignal: false, isRequired: false, transformFunction: null }, multiple: { classPropertyName: "multiple", publicName: "multiple", isSignal: false, isRequired: false, transformFunction: null }, valueField: { classPropertyName: "valueField", publicName: "valueField", isSignal: false, isRequired: false, transformFunction: null }, textField: { classPropertyName: "textField", publicName: "textField", isSignal: false, isRequired: false, transformFunction: null }, disabledField: { classPropertyName: "disabledField", publicName: "disabledField", isSignal: false, isRequired: false, transformFunction: null }, textTemplate: { classPropertyName: "textTemplate", publicName: "textTemplate", isSignal: false, isRequired: false, transformFunction: null }, selectedItems: { classPropertyName: "selectedItems", publicName: "selectedItems", isSignal: false, isRequired: false, transformFunction: null }, isItemTruncated: { classPropertyName: "isItemTruncated", publicName: "isItemTruncated", isSignal: true, isRequired: false, transformFunction: null }, showItemTooltip: { classPropertyName: "showItemTooltip", publicName: "showItemTooltip", 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 }, dataSource: { classPropertyName: "dataSource", publicName: "dataSource", isSignal: false, isRequired: false, transformFunction: null }, minRecordsForSearch: { classPropertyName: "minRecordsForSearch", publicName: "minRecordsForSearch", isSignal: false, isRequired: false, transformFunction: null }, caption: { classPropertyName: "caption", publicName: "caption", isSignal: false, isRequired: false, transformFunction: null }, itemTemplate: { classPropertyName: "itemTemplate", publicName: "itemTemplate", isSignal: false, isRequired: false, transformFunction: null }, selectedTemplate: { classPropertyName: "selectedTemplate", publicName: "selectedTemplate", isSignal: false, isRequired: false, transformFunction: null }, emptyTemplate: { classPropertyName: "emptyTemplate", publicName: "emptyTemplate", isSignal: false, isRequired: false, transformFunction: null }, loadingTemplate: { classPropertyName: "loadingTemplate", publicName: "loadingTemplate", isSignal: false, isRequired: false, transformFunction: null }, dropdownWidth: { classPropertyName: "dropdownWidth", publicName: "dropdownWidth", isSignal: true, isRequired: false, transformFunction: null }, searchBoxAutoFocus: { classPropertyName: "searchBoxAutoFocus", publicName: "searchBoxAutoFocus", isSignal: true, isRequired: false, transformFunction: null } }, outputs: { valueChange: "valueChange", stateChange: "stateChange", onValueChanged: "onValueChanged", onBlur: "onBlur", onFocus: "onFocus", readonlyChange: "readonlyChange", disabledChange: "disabledChange", onOpened: "onOpened", onClosed: "onClosed", onItemSelected: "onItemSelected", onItemClick: "onItemClick" }, host: { attributes: { "ngSkipHydration": "true" }, listeners: { "keydown": "_handleKeydown($event)", "click": "hostClickListener()" } }, providers: [
253
481
  { provide: AXComponent, useExisting: AXSelectBoxComponent },
254
482
  { provide: AXFocusableComponent, useExisting: AXSelectBoxComponent },
255
483
  { provide: AXValuableComponent, useExisting: AXSelectBoxComponent },
256
484
  { provide: AXClearableComponent, useExisting: AXSelectBoxComponent },
257
485
  { provide: AXClosableComponent, useExisting: AXSelectBoxComponent },
258
486
  { provide: AXSearchableComponent, useExisting: AXSelectBoxComponent },
259
- { provide: NG_VALUE_ACCESSOR, useExisting: forwardRef(() => AXSelectBoxComponent), multi: true },
260
- { provide: AX_SELECTION_DATA_TOKEN, useClass: MXSelectionBridgeService },
487
+ {
488
+ provide: NG_VALUE_ACCESSOR,
489
+ useExisting: forwardRef(() => AXSelectBoxComponent),
490
+ multi: true,
491
+ },
492
+ {
493
+ provide: AX_SELECTION_DATA_TOKEN,
494
+ useClass: MXSelectionBridgeService,
495
+ },
261
496
  AXUnsubscriber,
262
- ], queries: [{ propertyName: "searchBox", first: true, predicate: AXSearchBoxComponent, descendants: true, isSignal: true }], viewQueries: [{ propertyName: "panel", first: true, predicate: ["panel"], descendants: true, isSignal: true }, { propertyName: "selectionList", first: true, predicate: AXSelectionListComponent, descendants: true, isSignal: true }, { propertyName: "dropdownRef", first: true, predicate: AXDropdownBoxComponent, descendants: true, isSignal: true }], usesInheritance: true, ngImport: i0, template: "<ax-dropdown-box\n [class.ax-state-multiple]=\"multiple\"\n (onOpened)=\"_handleOnOpenedEvent($event)\"\n (onClosed)=\"_handleOnClosedEvent($event)\"\n (focus)=\"emitOnFocusEvent($event)\"\n (blur)=\"emitOnBlurEvent($event)\"\n [disabled]=\"disabled\"\n [look]=\"look\"\n [popoverWidth]=\"dropdownWidth()\"\n>\n <ng-container input>\n <ng-content select=\"ax-prefix\"></ng-content>\n <div\n class=\"ax-editor ax-chips-container ax-content ax-input\"\n [class.ax-state-multiple]=\"multiple\"\n [tabindex]=\"tabIndex\"\n >\n @if (selectedItems.length === 0) {\n <div class=\"ax-placeholder\" role=\"textbox\" area-readonly=\"true\">\n {{ placeholder() | translate | async }}\n </div>\n }\n @for (item of selectedItems; track $index) {\n @if (selectedTemplate(); as selectedTpl) {\n <ng-template\n [ngTemplateOutlet]=\"selectedTpl\"\n [ngTemplateOutletContext]=\"{ $implicit: { data: item } }\"\n ></ng-template>\n } @else if (multiple) {\n <ax-tag [text]=\"getDisplayText(item) | translate | async\" look=\"twotone\">\n @if (!disabled && !readonly) {\n <ax-suffix>\n <span class=\"ax-icon ax-icon-close\" (click)=\"_handleBadgeRemove($event, item)\"></span>\n </ax-suffix>\n }\n </ax-tag>\n } @else {\n {{ getDisplayText(item) | translate | async }}\n }\n }\n </div>\n @if (selectedItems?.length && !disabled && !readonly) {\n <ng-content select=\"ax-clear-button\"></ng-content>\n }\n <button type=\"button\" [disabled]=\"disabled\" [tabIndex]=\"-1\" class=\"ax-general-button-icon\">\n <span class=\"ax-icon\" [class.ax-icon-chevron-down]=\"!isOpen\" [class.ax-icon-chevron-up]=\"isOpen\"></span>\n </button>\n <ng-content select=\"ax-suffix\"></ng-content>\n <ng-template #search>\n <ng-content select=\"ax-search-box\"></ng-content>\n </ng-template>\n </ng-container>\n\n <ng-container panel>\n <div #panel class=\"ax-select-box-panel\" [style.min-width]=\"_dropdownWidth()\">\n @if (dropdown.isActionsheetStyle) {\n <ax-header class=\"ax-solid\">\n <ax-title>\n {{ caption() || placeholder() || '@acorex:selectbox.popover.title' | translate | async }}\n </ax-title>\n <ax-close-button [icon]=\"multiple ? 'ax-icon ax-icon-check' : 'ax-icon ax-icon-close'\"></ax-close-button>\n </ax-header>\n }\n\n @if (\n searchBox() && (!minRecordsForSearch() || visibleItems().length >= minRecordsForSearch()! || searchValue())\n ) {\n <div class=\"ax-search-container\">\n <ng-template [ngTemplateOutlet]=\"search\"></ng-template>\n </div>\n }\n\n @if (renderList()) {\n @if (visibleItems().length) {\n <div class=\"ax-select-box-list\" [style.max-height]=\"_dropdownHeight()\">\n <ax-selection-list\n [name]=\"name\"\n [ngModel]=\"value\"\n [readonly]=\"readonly\"\n [disabled]=\"disabled\"\n [multiple]=\"multiple\"\n [textField]=\"textField\"\n [valueField]=\"valueField\"\n [disabledField]=\"disabledField\"\n [items]=\"visibleItems()\"\n [showControl]=\"true\"\n [customTemplate]=\"itemTemplate()\"\n direction=\"vertical\"\n look=\"solid\"\n (onValueChanged)=\"_handleValueChanged($event)\"\n ></ax-selection-list>\n </div>\n } @else {\n <div class=\"ax-select-box-empty\">\n @if (emptyTemplate(); as emptyTpl) {\n <ng-template [ngTemplateOutlet]=\"emptyTpl\"></ng-template>\n } @else {\n {{ '@acorex:common.general.no-result-found' | translate | async }}\n }\n </div>\n }\n }\n\n <ng-content select=\"ax-footer\"></ng-content>\n </div>\n </ng-container>\n</ax-dropdown-box>\n<ng-content select=\"ax-validation-rule\"></ng-content>\n", styles: ["@layer properties;@layer components{ax-select-box .ax-editor-container{padding-block:calc(var(--spacing, .25rem) * 0)}ax-select-box .ax-editor-container.ax-state-multiple{padding-inline:calc(var(--spacing, .25rem) * 1)}ax-select-box .ax-editor-container.ax-state-multiple .ax-placeholder{padding-inline-start:calc(var(--spacing, .25rem) * 2)}ax-select-box .ax-editor-container .ax-input,ax-select-box .ax-editor-container .ax-editor{padding-block:calc(var(--spacing, .25rem) * 1)}ax-select-box ax-dropdown-box.ax-state-multiple{height:auto!important;min-height:var(--ax-comp-editor-height);--ax-comp-editor-space-start-size: 0}ax-select-box .ax-chips-container{display:flex;min-height:var(--ax-sys-size-base);min-width:calc(var(--spacing, .25rem) * 0);flex:1;cursor:pointer!important;flex-wrap:wrap;align-items:center;justify-content:flex-start;gap:var(--ax-comp-select-box-chips-gap,.25rem);outline-style:var(--tw-outline-style);outline-width:0px;outline-color:transparent;-webkit-user-select:none;user-select:none}ax-select-box .ax-chips-container.ax-state-multiple:has(.ax-chips){padding:var(--ax-comp-select-box-chips-container-padding, .25rem)}ax-select-box .ax-chips-container ax-tag ax-prefix,ax-select-box .ax-chips-container ax-tag ax-suffix{padding:calc(var(--spacing, .25rem) * 0)!important}.ax-select-box-panel{display:flex;height:fit-content;max-height:100%;flex-direction:column;overflow:hidden}.ax-select-box-panel .ax-select-box-list{min-height:calc(var(--spacing, .25rem) * 0);overflow:auto}.ax-select-box-panel .ax-select-box-empty{padding-inline:calc(var(--spacing, .25rem) * 3);padding-block:calc(var(--spacing, .25rem) * 4);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-lightest-surface))}@supports (color: color-mix(in lab,red,red)){.ax-select-box-panel .ax-select-box-empty{color:color-mix(in oklab,rgba(var(--ax-sys-color-on-lightest-surface)) 75%,transparent)}}.ax-select-box-panel ax-selection-list{display:block;width:100%}.ax-select-box-panel ax-selection-list ul.ax-vertical{flex-wrap:nowrap}.ax-select-box-panel ax-selection-list li.ax-state-selected>label{background-color:rgba(var(--ax-sys-color-primary-lightest-surface))}.ax-select-box-panel ax-selection-list li.ax-state-selected>label: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)){.ax-select-box-panel ax-selection-list li.ax-state-selected>label: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-select-box-panel>ax-header .ax-icon-check{color:rgba(var(--ax-sys-color-primary-surface))}.ax-select-box-panel>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-select-box-panel>ax-header.ax-solid ax-title{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)}}@property --tw-outline-style{syntax: \"*\"; inherits: false; initial-value: solid;}@property --tw-border-style{syntax: \"*\"; inherits: false; initial-value: solid;}@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-outline-style: solid;--tw-border-style: solid;--tw-leading: initial;--tw-font-weight: initial}}}\n/*! tailwindcss v4.1.16 | MIT License | https://tailwindcss.com */\n"], dependencies: [{ kind: "component", type: AXDropdownBoxComponent, selector: "ax-dropdown-box", inputs: ["disabled", "look", "hasInput", "popoverWidth"], outputs: ["disabledChange", "onBlur", "onFocus", "onClick", "onOpened", "onClosed"] }, { kind: "directive", type: NgTemplateOutlet, selector: "[ngTemplateOutlet]", inputs: ["ngTemplateOutletContext", "ngTemplateOutlet", "ngTemplateOutletInjector"] }, { kind: "component", type: 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: AXDecoratorCloseButtonComponent, selector: "ax-close-button", inputs: ["closeAll", "icon"] }, { kind: "component", type: AXSelectionListComponent, selector: "ax-selection-list", inputs: ["id", "name", "disabled", "readonly", "tabIndex", "size", "value", "valueField", "textField", "disabledField", "readonlyField", "multiple", "direction", "customTemplate", "showControl", "items", "look"], outputs: ["onValueChanged", "onBlur", "onFocus"] }, { kind: "ngmodule", type: FormsModule }, { kind: "directive", type: i1.NgControlStatus, selector: "[formControlName],[ngModel],[formControl]" }, { kind: "directive", type: i1.NgModel, selector: "[ngModel]:not([formControlName]):not([formControl])", inputs: ["name", "disabled", "ngModel", "ngModelOptions"], outputs: ["ngModelChange"], exportAs: ["ngModel"] }, { kind: "component", type: AXTagComponent, selector: "ax-tag", inputs: ["color", "look", "text"], outputs: ["onClick", "onDblClick", "onContextMenu"] }, { kind: "pipe", type: AsyncPipe, name: "async" }, { kind: "pipe", type: AXTranslatorPipe, name: "translate" }], encapsulation: i0.ViewEncapsulation.None }); }
497
+ ], queries: [{ propertyName: "searchBox", first: true, predicate: AXSearchBoxComponent, descendants: true }], viewQueries: [{ propertyName: "panel", first: true, predicate: ["panel"], descendants: true }, { propertyName: "list", first: true, predicate: AXListComponent, descendants: true }, { propertyName: "dropdown", first: true, predicate: AXDropdownBoxComponent, descendants: true, static: true }], usesInheritance: true, ngImport: i0, template: "<ax-dropdown-box\n [class.ax-state-multiple]=\"multiple\"\n (onOpened)=\"_handleOnOpenedEvent($event)\"\n (onClosed)=\"_handleOnClosedEvent($event)\"\n (focus)=\"emitOnFocusEvent($event)\"\n (blur)=\"emitOnBlurEvent($event)\"\n [disabled]=\"disabled\"\n [look]=\"look\"\n [popoverWidth]=\"dropdownWidth()\"\n>\n <ng-container input>\n <ng-content select=\"ax-prefix\"> </ng-content>\n <div\n class=\"ax-editor ax-chips-container ax-content ax-input\"\n [class.ax-state-multiple]=\"multiple\"\n [tabindex]=\"tabIndex\"\n >\n @if (selectedItems.length === 0) {\n <div class=\"ax-placeholder\" role=\"textbox\" area-readonly=\"true\">\n {{ placeholder | translate | async }}\n </div>\n }\n @for (item of selectedItems; track $index) {\n @if (selectedTemplate) {\n <ng-template\n [ngTemplateOutlet]=\"selectedTemplate\"\n [ngTemplateOutletContext]=\"{ $implicit: { data: item } }\"\n ></ng-template>\n } @else {\n @if (multiple) {\n <!-- <div class=\"bg-surface border-surface flex items-center justify-center gap-2 rounded-full border px-2 py-1\">\n <ax-text>{{ getDisplayText(item) | translate | async }}</ax-text>\n @if (!disabled && !readonly && multiple) {\n <span class=\"ax-icon ax-icon-close\" (click)=\"_handleBadgeRemove($event, item)\"></span>\n }\n </div> -->\n <ax-tag [text]=\"getDisplayText(item) | translate | async\" look=\"twotone\">\n @if (!disabled && !readonly && multiple) {\n <ax-suffix>\n <span class=\"ax-icon ax-icon-close\" (click)=\"_handleBadgeRemove($event, item)\"></span>\n </ax-suffix>\n }\n </ax-tag>\n } @else {\n {{ getDisplayText(item) | translate | async }}\n }\n }\n }\n </div>\n @if (selectedItems?.length && !disabled && !readonly) {\n <ng-content select=\"ax-clear-button\"></ng-content>\n }\n <button type=\"button\" [disabled]=\"disabled\" [tabIndex]=\"-1\" class=\"ax-general-button-icon\">\n @if (isLoading()) {\n <ax-loading-spinner [size]=\"16\" [stroke]=\"1\"></ax-loading-spinner>\n } @else {\n <span\n class=\"ax-icon\"\n [ngClass]=\"{\n 'ax-icon-chevron-down': !isOpen,\n 'ax-icon-chevron-up': isOpen,\n }\"\n ></span>\n }\n </button>\n <ng-content select=\"ax-suffix\"> </ng-content>\n <ng-template #search>\n <ng-content select=\"ax-search-box\"> </ng-content>\n </ng-template>\n </ng-container>\n <ng-container panel>\n <div\n #panel\n class=\"ax-select-box-panel\"\n [class.ax-no-truncate]=\"!isItemTruncated()\"\n [style.min-width]=\"_dropdownWidth()\"\n >\n @if (dropdown.isActionsheetStyle) {\n <ax-header class=\"ax-solid\">\n <ax-title>{{ caption || placeholder || '@acorex:selectbox.popover.title' | translate | async }}</ax-title>\n <ax-close-button [icon]=\"multiple ? 'ax-icon ax-icon-check' : 'ax-icon ax-icon-close'\"></ax-close-button>\n </ax-header>\n }\n @if (searchBox && (!minRecordsForSearch || _listDataSource.totalCount >= minRecordsForSearch || searchValue())) {\n <div class=\"ax-search-container\">\n <ng-template [ngTemplateOutlet]=\"search\"></ng-template>\n </div>\n }\n @if (renderList()) {\n <ax-list\n [name]=\"name\"\n [ngModel]=\"value\"\n [readonly]=\"readonly\"\n [multiple]=\"multiple\"\n [textField]=\"textField\"\n [selectionMode]=\"'item'\"\n [valueField]=\"valueField\"\n [itemHeight]=\"itemHeight()\"\n [itemTemplate]=\"itemTemplate\"\n [textTemplate]=\"textTemplate\"\n [dataSource]=\"_listDataSource\"\n [style.height]=\"_dropdownHeight()\"\n [loadingTemplate]=\"loadingTemplate\"\n [isItemTruncated]=\"isItemTruncated()\"\n [showItemTooltip]=\"showItemTooltip()\"\n (onItemClick)=\"_handleItemClick($event)\"\n [emptyTemplate]=\"emptyTemplate ?? empty\"\n (onValueChanged)=\"_handleValueChanged($event)\"\n (onItemSelected)=\"_handleItemSelected($event)\"\n >\n </ax-list>\n <ng-template #empty>\n {{ '@acorex:common.general.no-result-found' | translate | async }}\n </ng-template>\n }\n\n @if (isLoading()) {\n @if (loadingTemplate) {\n <ng-template [ngTemplateOutlet]=\"loadingTemplate\"></ng-template>\n }\n }\n\n <ng-content select=\"ax-footer\"> </ng-content>\n </div>\n </ng-container>\n</ax-dropdown-box>\n<ng-content select=\"ax-validation-rule\"> </ng-content>\n", styles: ["@layer properties;@layer components{ax-select-box .ax-editor-container{padding-block:calc(var(--spacing, .25rem) * 0)}ax-select-box .ax-editor-container.ax-state-multiple{padding-inline:calc(var(--spacing, .25rem) * 1)}ax-select-box .ax-editor-container.ax-state-multiple .ax-placeholder{padding-inline-start:calc(var(--spacing, .25rem) * 2)}ax-select-box .ax-editor-container .ax-input,ax-select-box .ax-editor-container .ax-editor{padding-block:calc(var(--spacing, .25rem) * 1)}ax-select-box ax-dropdown-box.ax-state-multiple{height:auto!important;min-height:var(--ax-comp-editor-height);--ax-comp-editor-space-start-size: 0}ax-select-box .ax-chips-container{display:flex;min-height:var(--ax-sys-size-base);min-width:calc(var(--spacing, .25rem) * 0);flex:1;cursor:pointer!important;flex-wrap:wrap;align-items:center;justify-content:flex-start;gap:var(--ax-comp-select-box-chips-gap,.25rem);outline-style:var(--tw-outline-style);outline-width:0px;outline-color:transparent;-webkit-user-select:none;user-select:none}ax-select-box .ax-chips-container .ax-selectbox-input{width:calc(var(--spacing, .25rem) * 0);opacity:0%}ax-select-box .ax-chips-container.ax-state-multiple:has(.ax-chips){padding:var(--ax-comp-select-box-chips-container-padding, .25rem)}ax-select-box .ax-chips-container ax-tag ax-prefix,ax-select-box .ax-chips-container ax-tag ax-suffix{padding:calc(var(--spacing, .25rem) * 0)!important}.ax-select-box-panel{display:flex;height:fit-content;max-height:100%;flex-direction:column;overflow:hidden}.ax-select-box-panel.ax-no-truncate .ax-label-container span:not(.ax-truncated){white-space:nowrap}.ax-select-box-panel .ax-select-box-loading-container{display:flex;align-items:center;justify-content:center;padding:calc(var(--spacing, .25rem) * 4)}.ax-select-box-panel ax-list{min-height:calc(var(--spacing, .25rem) * 0);flex:1 1 auto}.ax-select-box-panel>ax-header .ax-icon-check{color:rgba(var(--ax-sys-color-primary-surface))}.ax-select-box-panel>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-select-box-panel>ax-header.ax-solid ax-title{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)}@media(max-width:40rem){.ax-select-box-panel .list-item{padding-inline:1rem}}}@property --tw-outline-style{syntax: \"*\"; inherits: false; initial-value: solid;}@property --tw-border-style{syntax: \"*\"; inherits: false; initial-value: solid;}@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-outline-style: solid;--tw-border-style: solid;--tw-leading: initial;--tw-font-weight: initial}}}\n/*! tailwindcss v4.1.16 | MIT License | https://tailwindcss.com */\n"], dependencies: [{ kind: "component", type: AXDropdownBoxComponent, selector: "ax-dropdown-box", inputs: ["disabled", "look", "hasInput", "popoverWidth"], outputs: ["disabledChange", "onBlur", "onFocus", "onClick", "onOpened", "onClosed"] }, { kind: "directive", type: NgTemplateOutlet, selector: "[ngTemplateOutlet]", inputs: ["ngTemplateOutletContext", "ngTemplateOutlet", "ngTemplateOutletInjector"] }, { kind: "directive", type: NgClass, selector: "[ngClass]", inputs: ["class", "ngClass"] }, { kind: "component", type: 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: AXDecoratorCloseButtonComponent, selector: "ax-close-button", inputs: ["closeAll", "icon"] }, { kind: "component", type: AXListComponent, selector: "ax-list", inputs: ["id", "name", "disabled", "readonly", "valueField", "textField", "textTemplate", "disabledField", "multiple", "selectionMode", "isItemTruncated", "showItemTooltip", "dataSource", "itemHeight", "itemTemplate", "emptyTemplate", "loadingTemplate", "checkbox"], outputs: ["onValueChanged", "disabledChange", "readonlyChange", "onBlur", "onFocus", "onItemClick", "onItemSelected", "onScrolledIndexChanged"] }, { kind: "ngmodule", type: FormsModule }, { kind: "directive", type: i1.NgControlStatus, selector: "[formControlName],[ngModel],[formControl]" }, { kind: "directive", type: i1.NgModel, selector: "[ngModel]:not([formControlName]):not([formControl])", inputs: ["name", "disabled", "ngModel", "ngModelOptions"], outputs: ["ngModelChange"], exportAs: ["ngModel"] }, { kind: "component", type: AXTagComponent, selector: "ax-tag", inputs: ["color", "look", "text"], outputs: ["onClick", "onDblClick", "onContextMenu"] }, { kind: "component", type: AXLoadingSpinnerComponent, selector: "ax-loading-spinner", inputs: ["text", "color", "size", "stroke"] }, { kind: "pipe", type: AsyncPipe, name: "async" }, { kind: "pipe", type: AXTranslatorPipe, name: "translate" }], encapsulation: i0.ViewEncapsulation.None }); }
263
498
  }
264
499
  i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "22.0.8", ngImport: i0, type: AXSelectBoxComponent, decorators: [{
265
500
  type: Component,
@@ -267,6 +502,7 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "22.0.8", ngImpor
267
502
  'disabled',
268
503
  'readonly',
269
504
  'tabIndex',
505
+ 'placeholder',
270
506
  'minValue',
271
507
  'maxValue',
272
508
  'value',
@@ -300,25 +536,64 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "22.0.8", ngImpor
300
536
  { provide: AXClearableComponent, useExisting: AXSelectBoxComponent },
301
537
  { provide: AXClosableComponent, useExisting: AXSelectBoxComponent },
302
538
  { provide: AXSearchableComponent, useExisting: AXSelectBoxComponent },
303
- { provide: NG_VALUE_ACCESSOR, useExisting: forwardRef(() => AXSelectBoxComponent), multi: true },
304
- { provide: AX_SELECTION_DATA_TOKEN, useClass: MXSelectionBridgeService },
539
+ {
540
+ provide: NG_VALUE_ACCESSOR,
541
+ useExisting: forwardRef(() => AXSelectBoxComponent),
542
+ multi: true,
543
+ },
544
+ {
545
+ provide: AX_SELECTION_DATA_TOKEN,
546
+ useClass: MXSelectionBridgeService,
547
+ },
305
548
  AXUnsubscriber,
306
- ], host: {
307
- ngSkipHydration: 'true',
308
- '(click)': 'toggle()',
309
- '(keydown)': '_handleKeydown($event)',
310
- }, imports: [
549
+ ], host: { ngSkipHydration: 'true' }, imports: [
311
550
  AXDropdownBoxComponent,
312
551
  NgTemplateOutlet,
552
+ NgClass,
313
553
  AXDecoratorGenericComponent,
314
554
  AXDecoratorCloseButtonComponent,
315
- AXSelectionListComponent,
555
+ AXListComponent,
316
556
  FormsModule,
317
557
  AsyncPipe,
318
558
  AXTranslatorPipe,
319
559
  AXTagComponent,
320
- ], template: "<ax-dropdown-box\n [class.ax-state-multiple]=\"multiple\"\n (onOpened)=\"_handleOnOpenedEvent($event)\"\n (onClosed)=\"_handleOnClosedEvent($event)\"\n (focus)=\"emitOnFocusEvent($event)\"\n (blur)=\"emitOnBlurEvent($event)\"\n [disabled]=\"disabled\"\n [look]=\"look\"\n [popoverWidth]=\"dropdownWidth()\"\n>\n <ng-container input>\n <ng-content select=\"ax-prefix\"></ng-content>\n <div\n class=\"ax-editor ax-chips-container ax-content ax-input\"\n [class.ax-state-multiple]=\"multiple\"\n [tabindex]=\"tabIndex\"\n >\n @if (selectedItems.length === 0) {\n <div class=\"ax-placeholder\" role=\"textbox\" area-readonly=\"true\">\n {{ placeholder() | translate | async }}\n </div>\n }\n @for (item of selectedItems; track $index) {\n @if (selectedTemplate(); as selectedTpl) {\n <ng-template\n [ngTemplateOutlet]=\"selectedTpl\"\n [ngTemplateOutletContext]=\"{ $implicit: { data: item } }\"\n ></ng-template>\n } @else if (multiple) {\n <ax-tag [text]=\"getDisplayText(item) | translate | async\" look=\"twotone\">\n @if (!disabled && !readonly) {\n <ax-suffix>\n <span class=\"ax-icon ax-icon-close\" (click)=\"_handleBadgeRemove($event, item)\"></span>\n </ax-suffix>\n }\n </ax-tag>\n } @else {\n {{ getDisplayText(item) | translate | async }}\n }\n }\n </div>\n @if (selectedItems?.length && !disabled && !readonly) {\n <ng-content select=\"ax-clear-button\"></ng-content>\n }\n <button type=\"button\" [disabled]=\"disabled\" [tabIndex]=\"-1\" class=\"ax-general-button-icon\">\n <span class=\"ax-icon\" [class.ax-icon-chevron-down]=\"!isOpen\" [class.ax-icon-chevron-up]=\"isOpen\"></span>\n </button>\n <ng-content select=\"ax-suffix\"></ng-content>\n <ng-template #search>\n <ng-content select=\"ax-search-box\"></ng-content>\n </ng-template>\n </ng-container>\n\n <ng-container panel>\n <div #panel class=\"ax-select-box-panel\" [style.min-width]=\"_dropdownWidth()\">\n @if (dropdown.isActionsheetStyle) {\n <ax-header class=\"ax-solid\">\n <ax-title>\n {{ caption() || placeholder() || '@acorex:selectbox.popover.title' | translate | async }}\n </ax-title>\n <ax-close-button [icon]=\"multiple ? 'ax-icon ax-icon-check' : 'ax-icon ax-icon-close'\"></ax-close-button>\n </ax-header>\n }\n\n @if (\n searchBox() && (!minRecordsForSearch() || visibleItems().length >= minRecordsForSearch()! || searchValue())\n ) {\n <div class=\"ax-search-container\">\n <ng-template [ngTemplateOutlet]=\"search\"></ng-template>\n </div>\n }\n\n @if (renderList()) {\n @if (visibleItems().length) {\n <div class=\"ax-select-box-list\" [style.max-height]=\"_dropdownHeight()\">\n <ax-selection-list\n [name]=\"name\"\n [ngModel]=\"value\"\n [readonly]=\"readonly\"\n [disabled]=\"disabled\"\n [multiple]=\"multiple\"\n [textField]=\"textField\"\n [valueField]=\"valueField\"\n [disabledField]=\"disabledField\"\n [items]=\"visibleItems()\"\n [showControl]=\"true\"\n [customTemplate]=\"itemTemplate()\"\n direction=\"vertical\"\n look=\"solid\"\n (onValueChanged)=\"_handleValueChanged($event)\"\n ></ax-selection-list>\n </div>\n } @else {\n <div class=\"ax-select-box-empty\">\n @if (emptyTemplate(); as emptyTpl) {\n <ng-template [ngTemplateOutlet]=\"emptyTpl\"></ng-template>\n } @else {\n {{ '@acorex:common.general.no-result-found' | translate | async }}\n }\n </div>\n }\n }\n\n <ng-content select=\"ax-footer\"></ng-content>\n </div>\n </ng-container>\n</ax-dropdown-box>\n<ng-content select=\"ax-validation-rule\"></ng-content>\n", styles: ["@layer properties;@layer components{ax-select-box .ax-editor-container{padding-block:calc(var(--spacing, .25rem) * 0)}ax-select-box .ax-editor-container.ax-state-multiple{padding-inline:calc(var(--spacing, .25rem) * 1)}ax-select-box .ax-editor-container.ax-state-multiple .ax-placeholder{padding-inline-start:calc(var(--spacing, .25rem) * 2)}ax-select-box .ax-editor-container .ax-input,ax-select-box .ax-editor-container .ax-editor{padding-block:calc(var(--spacing, .25rem) * 1)}ax-select-box ax-dropdown-box.ax-state-multiple{height:auto!important;min-height:var(--ax-comp-editor-height);--ax-comp-editor-space-start-size: 0}ax-select-box .ax-chips-container{display:flex;min-height:var(--ax-sys-size-base);min-width:calc(var(--spacing, .25rem) * 0);flex:1;cursor:pointer!important;flex-wrap:wrap;align-items:center;justify-content:flex-start;gap:var(--ax-comp-select-box-chips-gap,.25rem);outline-style:var(--tw-outline-style);outline-width:0px;outline-color:transparent;-webkit-user-select:none;user-select:none}ax-select-box .ax-chips-container.ax-state-multiple:has(.ax-chips){padding:var(--ax-comp-select-box-chips-container-padding, .25rem)}ax-select-box .ax-chips-container ax-tag ax-prefix,ax-select-box .ax-chips-container ax-tag ax-suffix{padding:calc(var(--spacing, .25rem) * 0)!important}.ax-select-box-panel{display:flex;height:fit-content;max-height:100%;flex-direction:column;overflow:hidden}.ax-select-box-panel .ax-select-box-list{min-height:calc(var(--spacing, .25rem) * 0);overflow:auto}.ax-select-box-panel .ax-select-box-empty{padding-inline:calc(var(--spacing, .25rem) * 3);padding-block:calc(var(--spacing, .25rem) * 4);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-lightest-surface))}@supports (color: color-mix(in lab,red,red)){.ax-select-box-panel .ax-select-box-empty{color:color-mix(in oklab,rgba(var(--ax-sys-color-on-lightest-surface)) 75%,transparent)}}.ax-select-box-panel ax-selection-list{display:block;width:100%}.ax-select-box-panel ax-selection-list ul.ax-vertical{flex-wrap:nowrap}.ax-select-box-panel ax-selection-list li.ax-state-selected>label{background-color:rgba(var(--ax-sys-color-primary-lightest-surface))}.ax-select-box-panel ax-selection-list li.ax-state-selected>label: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)){.ax-select-box-panel ax-selection-list li.ax-state-selected>label: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-select-box-panel>ax-header .ax-icon-check{color:rgba(var(--ax-sys-color-primary-surface))}.ax-select-box-panel>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-select-box-panel>ax-header.ax-solid ax-title{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)}}@property --tw-outline-style{syntax: \"*\"; inherits: false; initial-value: solid;}@property --tw-border-style{syntax: \"*\"; inherits: false; initial-value: solid;}@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-outline-style: solid;--tw-border-style: solid;--tw-leading: initial;--tw-font-weight: initial}}}\n/*! tailwindcss v4.1.16 | MIT License | https://tailwindcss.com */\n"] }]
321
- }], propDecorators: { items: [{ type: i0.Input, args: [{ isSignal: true, alias: "items", required: false }] }], placeholder: [{ type: i0.Input, args: [{ isSignal: true, alias: "placeholder", required: false }] }], minRecordsForSearch: [{ type: i0.Input, args: [{ isSignal: true, alias: "minRecordsForSearch", required: false }] }], caption: [{ type: i0.Input, args: [{ isSignal: true, alias: "caption", 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 }] }], maxVisibleItems: [{ type: i0.Input, args: [{ isSignal: true, alias: "maxVisibleItems", required: false }] }], dropdownWidth: [{ type: i0.Input, args: [{ isSignal: true, alias: "dropdownWidth", required: false }] }], searchBoxAutoFocus: [{ type: i0.Input, args: [{ isSignal: true, alias: "searchBoxAutoFocus", required: false }] }], panel: [{ type: i0.ViewChild, args: ['panel', { isSignal: true }] }], selectionList: [{ type: i0.ViewChild, args: [i0.forwardRef(() => AXSelectionListComponent), { isSignal: true }] }], searchBox: [{ type: i0.ContentChild, args: [i0.forwardRef(() => AXSearchBoxComponent), { isSignal: true }] }], dropdownRef: [{ type: i0.ViewChild, args: [i0.forwardRef(() => AXDropdownBoxComponent), { isSignal: true }] }] } });
560
+ AXLoadingSpinnerComponent,
561
+ ], template: "<ax-dropdown-box\n [class.ax-state-multiple]=\"multiple\"\n (onOpened)=\"_handleOnOpenedEvent($event)\"\n (onClosed)=\"_handleOnClosedEvent($event)\"\n (focus)=\"emitOnFocusEvent($event)\"\n (blur)=\"emitOnBlurEvent($event)\"\n [disabled]=\"disabled\"\n [look]=\"look\"\n [popoverWidth]=\"dropdownWidth()\"\n>\n <ng-container input>\n <ng-content select=\"ax-prefix\"> </ng-content>\n <div\n class=\"ax-editor ax-chips-container ax-content ax-input\"\n [class.ax-state-multiple]=\"multiple\"\n [tabindex]=\"tabIndex\"\n >\n @if (selectedItems.length === 0) {\n <div class=\"ax-placeholder\" role=\"textbox\" area-readonly=\"true\">\n {{ placeholder | translate | async }}\n </div>\n }\n @for (item of selectedItems; track $index) {\n @if (selectedTemplate) {\n <ng-template\n [ngTemplateOutlet]=\"selectedTemplate\"\n [ngTemplateOutletContext]=\"{ $implicit: { data: item } }\"\n ></ng-template>\n } @else {\n @if (multiple) {\n <!-- <div class=\"bg-surface border-surface flex items-center justify-center gap-2 rounded-full border px-2 py-1\">\n <ax-text>{{ getDisplayText(item) | translate | async }}</ax-text>\n @if (!disabled && !readonly && multiple) {\n <span class=\"ax-icon ax-icon-close\" (click)=\"_handleBadgeRemove($event, item)\"></span>\n }\n </div> -->\n <ax-tag [text]=\"getDisplayText(item) | translate | async\" look=\"twotone\">\n @if (!disabled && !readonly && multiple) {\n <ax-suffix>\n <span class=\"ax-icon ax-icon-close\" (click)=\"_handleBadgeRemove($event, item)\"></span>\n </ax-suffix>\n }\n </ax-tag>\n } @else {\n {{ getDisplayText(item) | translate | async }}\n }\n }\n }\n </div>\n @if (selectedItems?.length && !disabled && !readonly) {\n <ng-content select=\"ax-clear-button\"></ng-content>\n }\n <button type=\"button\" [disabled]=\"disabled\" [tabIndex]=\"-1\" class=\"ax-general-button-icon\">\n @if (isLoading()) {\n <ax-loading-spinner [size]=\"16\" [stroke]=\"1\"></ax-loading-spinner>\n } @else {\n <span\n class=\"ax-icon\"\n [ngClass]=\"{\n 'ax-icon-chevron-down': !isOpen,\n 'ax-icon-chevron-up': isOpen,\n }\"\n ></span>\n }\n </button>\n <ng-content select=\"ax-suffix\"> </ng-content>\n <ng-template #search>\n <ng-content select=\"ax-search-box\"> </ng-content>\n </ng-template>\n </ng-container>\n <ng-container panel>\n <div\n #panel\n class=\"ax-select-box-panel\"\n [class.ax-no-truncate]=\"!isItemTruncated()\"\n [style.min-width]=\"_dropdownWidth()\"\n >\n @if (dropdown.isActionsheetStyle) {\n <ax-header class=\"ax-solid\">\n <ax-title>{{ caption || placeholder || '@acorex:selectbox.popover.title' | translate | async }}</ax-title>\n <ax-close-button [icon]=\"multiple ? 'ax-icon ax-icon-check' : 'ax-icon ax-icon-close'\"></ax-close-button>\n </ax-header>\n }\n @if (searchBox && (!minRecordsForSearch || _listDataSource.totalCount >= minRecordsForSearch || searchValue())) {\n <div class=\"ax-search-container\">\n <ng-template [ngTemplateOutlet]=\"search\"></ng-template>\n </div>\n }\n @if (renderList()) {\n <ax-list\n [name]=\"name\"\n [ngModel]=\"value\"\n [readonly]=\"readonly\"\n [multiple]=\"multiple\"\n [textField]=\"textField\"\n [selectionMode]=\"'item'\"\n [valueField]=\"valueField\"\n [itemHeight]=\"itemHeight()\"\n [itemTemplate]=\"itemTemplate\"\n [textTemplate]=\"textTemplate\"\n [dataSource]=\"_listDataSource\"\n [style.height]=\"_dropdownHeight()\"\n [loadingTemplate]=\"loadingTemplate\"\n [isItemTruncated]=\"isItemTruncated()\"\n [showItemTooltip]=\"showItemTooltip()\"\n (onItemClick)=\"_handleItemClick($event)\"\n [emptyTemplate]=\"emptyTemplate ?? empty\"\n (onValueChanged)=\"_handleValueChanged($event)\"\n (onItemSelected)=\"_handleItemSelected($event)\"\n >\n </ax-list>\n <ng-template #empty>\n {{ '@acorex:common.general.no-result-found' | translate | async }}\n </ng-template>\n }\n\n @if (isLoading()) {\n @if (loadingTemplate) {\n <ng-template [ngTemplateOutlet]=\"loadingTemplate\"></ng-template>\n }\n }\n\n <ng-content select=\"ax-footer\"> </ng-content>\n </div>\n </ng-container>\n</ax-dropdown-box>\n<ng-content select=\"ax-validation-rule\"> </ng-content>\n", styles: ["@layer properties;@layer components{ax-select-box .ax-editor-container{padding-block:calc(var(--spacing, .25rem) * 0)}ax-select-box .ax-editor-container.ax-state-multiple{padding-inline:calc(var(--spacing, .25rem) * 1)}ax-select-box .ax-editor-container.ax-state-multiple .ax-placeholder{padding-inline-start:calc(var(--spacing, .25rem) * 2)}ax-select-box .ax-editor-container .ax-input,ax-select-box .ax-editor-container .ax-editor{padding-block:calc(var(--spacing, .25rem) * 1)}ax-select-box ax-dropdown-box.ax-state-multiple{height:auto!important;min-height:var(--ax-comp-editor-height);--ax-comp-editor-space-start-size: 0}ax-select-box .ax-chips-container{display:flex;min-height:var(--ax-sys-size-base);min-width:calc(var(--spacing, .25rem) * 0);flex:1;cursor:pointer!important;flex-wrap:wrap;align-items:center;justify-content:flex-start;gap:var(--ax-comp-select-box-chips-gap,.25rem);outline-style:var(--tw-outline-style);outline-width:0px;outline-color:transparent;-webkit-user-select:none;user-select:none}ax-select-box .ax-chips-container .ax-selectbox-input{width:calc(var(--spacing, .25rem) * 0);opacity:0%}ax-select-box .ax-chips-container.ax-state-multiple:has(.ax-chips){padding:var(--ax-comp-select-box-chips-container-padding, .25rem)}ax-select-box .ax-chips-container ax-tag ax-prefix,ax-select-box .ax-chips-container ax-tag ax-suffix{padding:calc(var(--spacing, .25rem) * 0)!important}.ax-select-box-panel{display:flex;height:fit-content;max-height:100%;flex-direction:column;overflow:hidden}.ax-select-box-panel.ax-no-truncate .ax-label-container span:not(.ax-truncated){white-space:nowrap}.ax-select-box-panel .ax-select-box-loading-container{display:flex;align-items:center;justify-content:center;padding:calc(var(--spacing, .25rem) * 4)}.ax-select-box-panel ax-list{min-height:calc(var(--spacing, .25rem) * 0);flex:1 1 auto}.ax-select-box-panel>ax-header .ax-icon-check{color:rgba(var(--ax-sys-color-primary-surface))}.ax-select-box-panel>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-select-box-panel>ax-header.ax-solid ax-title{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)}@media(max-width:40rem){.ax-select-box-panel .list-item{padding-inline:1rem}}}@property --tw-outline-style{syntax: \"*\"; inherits: false; initial-value: solid;}@property --tw-border-style{syntax: \"*\"; inherits: false; initial-value: solid;}@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-outline-style: solid;--tw-border-style: solid;--tw-leading: initial;--tw-font-weight: initial}}}\n/*! tailwindcss v4.1.16 | MIT License | https://tailwindcss.com */\n"] }]
562
+ }], propDecorators: { isItemTruncated: [{ type: i0.Input, args: [{ isSignal: true, alias: "isItemTruncated", required: false }] }], showItemTooltip: [{ type: i0.Input, args: [{ isSignal: true, alias: "showItemTooltip", required: false }] }], itemHeight: [{ type: i0.Input, args: [{ isSignal: true, alias: "itemHeight", required: false }] }], maxVisibleItems: [{ type: i0.Input, args: [{ isSignal: true, alias: "maxVisibleItems", required: false }] }], dataSource: [{
563
+ type: Input
564
+ }], placeholder: [{
565
+ type: Input
566
+ }], minRecordsForSearch: [{
567
+ type: Input
568
+ }], caption: [{
569
+ type: Input
570
+ }], itemTemplate: [{
571
+ type: Input
572
+ }], selectedTemplate: [{
573
+ type: Input
574
+ }], emptyTemplate: [{
575
+ type: Input
576
+ }], loadingTemplate: [{
577
+ type: Input
578
+ }], dropdownWidth: [{ type: i0.Input, args: [{ isSignal: true, alias: "dropdownWidth", required: false }] }], panel: [{
579
+ type: ViewChild,
580
+ args: ['panel']
581
+ }], list: [{
582
+ type: ViewChild,
583
+ args: [AXListComponent]
584
+ }], searchBox: [{
585
+ type: ContentChild,
586
+ args: [AXSearchBoxComponent]
587
+ }], searchBoxAutoFocus: [{ type: i0.Input, args: [{ isSignal: true, alias: "searchBoxAutoFocus", required: false }] }], dropdown: [{
588
+ type: ViewChild,
589
+ args: [AXDropdownBoxComponent, { static: true }]
590
+ }], _handleKeydown: [{
591
+ type: HostListener,
592
+ args: ['keydown', ['$event']]
593
+ }], hostClickListener: [{
594
+ type: HostListener,
595
+ args: ['click']
596
+ }] } });
322
597
 
323
598
  class AXSelectBoxModule {
324
599
  static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "22.0.8", ngImport: i0, type: AXSelectBoxModule, deps: [], target: i0.ɵɵFactoryTarget.NgModule }); }
@@ -334,7 +609,7 @@ class AXSelectBoxModule {
334
609
  A11yModule,
335
610
  AXTextBoxModule,
336
611
  AXDropdownModule,
337
- AXSelectionListModule,
612
+ AXListModule,
338
613
  AXSelectBoxComponent], exports: [AXSelectBoxComponent] }); }
339
614
  static { this.ɵinj = i0.ɵɵngDeclareInjector({ minVersion: "12.0.0", version: "22.0.8", ngImport: i0, type: AXSelectBoxModule, imports: [CommonModule,
340
615
  AXCommonModule,
@@ -348,7 +623,7 @@ class AXSelectBoxModule {
348
623
  A11yModule,
349
624
  AXTextBoxModule,
350
625
  AXDropdownModule,
351
- AXSelectionListModule,
626
+ AXListModule,
352
627
  AXSelectBoxComponent] }); }
353
628
  }
354
629
  i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "22.0.8", ngImport: i0, type: AXSelectBoxModule, decorators: [{
@@ -367,7 +642,7 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "22.0.8", ngImpor
367
642
  A11yModule,
368
643
  AXTextBoxModule,
369
644
  AXDropdownModule,
370
- AXSelectionListModule,
645
+ AXListModule,
371
646
  AXSelectBoxComponent,
372
647
  ],
373
648
  exports: [AXSelectBoxComponent],