@nanahoshi/mona-ui 0.24.4 → 0.24.5

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 (66) hide show
  1. package/README.md +1 -0
  2. package/fesm2022/nanahoshi-mona-ui-auto-complete.mjs +95 -70
  3. package/fesm2022/nanahoshi-mona-ui-combo-box.mjs +136 -89
  4. package/fesm2022/nanahoshi-mona-ui-dropdown-list.mjs +108 -56
  5. package/fesm2022/nanahoshi-mona-ui-dropdowns.mjs +68 -59
  6. package/fesm2022/nanahoshi-mona-ui-editor.mjs +3 -3
  7. package/fesm2022/nanahoshi-mona-ui-filter.mjs +1 -1
  8. package/fesm2022/{nanahoshi-mona-ui-grid-grid-footer-row.component-DLOPRuFv.mjs → nanahoshi-mona-ui-grid-grid-footer-row.component-BMCM0W8s.mjs} +2 -2
  9. package/fesm2022/{nanahoshi-mona-ui-grid-grid-list.component-Dw5U9H0a.mjs → nanahoshi-mona-ui-grid-grid-list.component-BSlV8Sua.mjs} +4 -4
  10. package/fesm2022/{nanahoshi-mona-ui-grid-grid-row.component-D1kyAzD8.mjs → nanahoshi-mona-ui-grid-grid-row.component-CTOdnH29.mjs} +2 -2
  11. package/fesm2022/{nanahoshi-mona-ui-grid-grid-virtual-list.component-ECK1_smx.mjs → nanahoshi-mona-ui-grid-grid-virtual-list.component-C2kf5MwO.mjs} +4 -4
  12. package/fesm2022/{nanahoshi-mona-ui-grid-nanahoshi-mona-ui-grid-D4lUDbfx.mjs → nanahoshi-mona-ui-grid-nanahoshi-mona-ui-grid-Dh42tUui.mjs} +8 -8
  13. package/fesm2022/nanahoshi-mona-ui-grid.mjs +1 -1
  14. package/fesm2022/nanahoshi-mona-ui-i18n-icu.mjs +2 -1
  15. package/fesm2022/nanahoshi-mona-ui-internal-indicator-icon.mjs +2 -2
  16. package/fesm2022/nanahoshi-mona-ui-internal.mjs +4 -2
  17. package/fesm2022/nanahoshi-mona-ui-locales-ar-sa.mjs +2 -1
  18. package/fesm2022/nanahoshi-mona-ui-locales-de-de.mjs +4 -1
  19. package/fesm2022/nanahoshi-mona-ui-locales-es-es.mjs +4 -1
  20. package/fesm2022/nanahoshi-mona-ui-locales-fr-fr.mjs +4 -1
  21. package/fesm2022/nanahoshi-mona-ui-locales-id-id.mjs +2 -1
  22. package/fesm2022/nanahoshi-mona-ui-locales-it-it.mjs +2 -1
  23. package/fesm2022/nanahoshi-mona-ui-locales-ja-jp.mjs +2 -1
  24. package/fesm2022/nanahoshi-mona-ui-locales-ko-kr.mjs +2 -1
  25. package/fesm2022/nanahoshi-mona-ui-locales-pt-br.mjs +2 -1
  26. package/fesm2022/nanahoshi-mona-ui-locales-ru-ru.mjs +2 -1
  27. package/fesm2022/nanahoshi-mona-ui-locales-tr-tr.mjs +2 -1
  28. package/fesm2022/nanahoshi-mona-ui-locales-zh-cn.mjs +2 -1
  29. package/fesm2022/nanahoshi-mona-ui-locales-zh-tw.mjs +2 -1
  30. package/fesm2022/nanahoshi-mona-ui-multi-select.mjs +118 -66
  31. package/fesm2022/nanahoshi-mona-ui-pager.mjs +1 -1
  32. package/i18n/catalogs/en-US.messages.json +2 -1
  33. package/locales/ar-sa/ar-sa.messages.json +2 -1
  34. package/locales/de-de/de-de.messages.json +2 -1
  35. package/locales/es-es/es-es.messages.json +2 -1
  36. package/locales/fr-fr/fr-fr.messages.json +2 -1
  37. package/locales/id-id/id-id.messages.json +2 -1
  38. package/locales/it-it/it-it.messages.json +2 -1
  39. package/locales/ja-jp/ja-jp.messages.json +2 -1
  40. package/locales/ko-kr/ko-kr.messages.json +2 -1
  41. package/locales/pt-br/pt-br.messages.json +2 -1
  42. package/locales/ru-ru/ru-ru.messages.json +2 -1
  43. package/locales/tr-tr/tr-tr.messages.json +2 -1
  44. package/locales/zh-cn/zh-cn.messages.json +2 -1
  45. package/locales/zh-tw/zh-tw.messages.json +2 -1
  46. package/package.json +1 -1
  47. package/types/nanahoshi-mona-ui-auto-complete.d.ts +34 -20
  48. package/types/nanahoshi-mona-ui-combo-box.d.ts +42 -23
  49. package/types/nanahoshi-mona-ui-dropdown-list.d.ts +29 -15
  50. package/types/nanahoshi-mona-ui-dropdowns.d.ts +30 -19
  51. package/types/nanahoshi-mona-ui-i18n.d.ts +1 -0
  52. package/types/nanahoshi-mona-ui-internal.d.ts +3 -1
  53. package/types/nanahoshi-mona-ui-locales-ar-sa.d.ts +1 -0
  54. package/types/nanahoshi-mona-ui-locales-de-de.d.ts +1 -0
  55. package/types/nanahoshi-mona-ui-locales-es-es.d.ts +1 -0
  56. package/types/nanahoshi-mona-ui-locales-fr-fr.d.ts +1 -0
  57. package/types/nanahoshi-mona-ui-locales-id-id.d.ts +1 -0
  58. package/types/nanahoshi-mona-ui-locales-it-it.d.ts +1 -0
  59. package/types/nanahoshi-mona-ui-locales-ja-jp.d.ts +1 -0
  60. package/types/nanahoshi-mona-ui-locales-ko-kr.d.ts +1 -0
  61. package/types/nanahoshi-mona-ui-locales-pt-br.d.ts +1 -0
  62. package/types/nanahoshi-mona-ui-locales-ru-ru.d.ts +1 -0
  63. package/types/nanahoshi-mona-ui-locales-tr-tr.d.ts +1 -0
  64. package/types/nanahoshi-mona-ui-locales-zh-cn.d.ts +1 -0
  65. package/types/nanahoshi-mona-ui-locales-zh-tw.d.ts +1 -0
  66. package/types/nanahoshi-mona-ui-multi-select.d.ts +45 -21
@@ -1,14 +1,15 @@
1
1
  import { NgTemplateOutlet } from '@angular/common';
2
2
  import * as i0 from '@angular/core';
3
- import { Directive, inject, DestroyRef, ElementRef, linkedSignal, computed, contentChild, TemplateRef, viewChild, input, output, model, effect, untracked, afterNextRender, forwardRef, Component } from '@angular/core';
3
+ import { Directive, inject, DestroyRef, ElementRef, linkedSignal, computed, contentChild, TemplateRef, viewChild, input, output, booleanAttribute, model, effect, untracked, afterNextRender, forwardRef, Component } from '@angular/core';
4
4
  import { takeUntilDestroyed } from '@angular/core/rxjs-interop';
5
5
  import * as i1 from '@nanahoshi/mona-ui/dropdowns';
6
- import { DropdownListService, DropdownService, DropdownFooterTemplateDirective, DropdownGroupHeaderTemplateDirective, DropdownHeaderTemplateDirective, DropdownItemTemplateDirective, dropdownPopupThemeVariants, DropdownNoDataTemplateDirective, DropdownPrefixTemplateDirective, DropdownLiveRegionDirective, DropdownDataInputToken, DROPDOWN_POPUP_INPUT_TOKEN, DropdownDataHandlerDirective, DropdownListPopupHandlerDirective } from '@nanahoshi/mona-ui/dropdowns';
7
- import { themeControlSurfaceClasses, createElementControlId, isTypeaheadKey, setupTypeahead } from '@nanahoshi/mona-ui/internal';
6
+ import { DropdownListService, DropdownService, DropdownFooterTemplateDirective, DropdownGroupHeaderTemplateDirective, DropdownHeaderTemplateDirective, DropdownItemTemplateDirective, dropdownPopupThemeVariants, DropdownNoDataTemplateDirective, DropdownPrefixTemplateDirective, DROPDOWN_DATA_INPUT_TOKEN, DROPDOWN_POPUP_INPUT_TOKEN, DropdownDataHandlerDirective, DropdownListPopupHandlerDirective, DropdownLiveRegionDirective } from '@nanahoshi/mona-ui/dropdowns';
7
+ import { themeControlSurfaceClasses, createElementControlId, isTypeaheadKey, TYPEAHEAD_RESET_DELAY, setupTypeahead } from '@nanahoshi/mona-ui/internal';
8
8
  import { IndicatorIconComponent } from '@nanahoshi/mona-ui/internal/indicator-icon';
9
9
  import { ListService, ListComponent, ListItemTemplateDirective, ListGroupHeaderTemplateDirective, ListFooterTemplateDirective, ListHeaderTemplateDirective, ListNoDataTemplateDirective } from '@nanahoshi/mona-ui/internal/list';
10
+ import { PopupCloseSource } from '@nanahoshi/mona-ui/popup';
10
11
  import { MonaI18nService } from '@nanahoshi/mona-ui/i18n';
11
- import { Subject } from 'rxjs';
12
+ import { Subject, filter } from 'rxjs';
12
13
  import { twMerge } from 'tailwind-merge';
13
14
  import { cva } from 'class-variance-authority';
14
15
 
@@ -89,6 +90,12 @@ const dropdownListValueContainerThemeVariants = cva(`flex h-full w-full items-ce
89
90
  });
90
91
  const dropdownListAffixContainerThemeVariants = cva(`flex h-full flex-none items-center justify-center`);
91
92
 
93
+ const cancellingCloseSources = new Set([
94
+ PopupCloseSource.BackdropClick,
95
+ PopupCloseSource.Escape,
96
+ PopupCloseSource.OutsideClick,
97
+ PopupCloseSource.Scroll
98
+ ]);
92
99
  class DropdownListComponent {
93
100
  #destroyRef;
94
101
  #dropdownListService;
@@ -98,6 +105,7 @@ class DropdownListComponent {
98
105
  #listService;
99
106
  #navigatedItem;
100
107
  #typeaheadKey;
108
+ #lastTypeaheadKeyTime;
101
109
  constructor() {
102
110
  this.#destroyRef = inject(DestroyRef);
103
111
  this.#dropdownListService = inject(DropdownListService);
@@ -108,6 +116,7 @@ class DropdownListComponent {
108
116
  this.#navigatedItem = linkedSignal(() => this.selectedDataItem(), /* @ts-ignore */
109
117
  ...(ngDevMode ? [{ debugName: "#navigatedItem" }] : /* istanbul ignore next */ []));
110
118
  this.#typeaheadKey = new Subject();
119
+ this.#lastTypeaheadKeyTime = Number.NEGATIVE_INFINITY;
111
120
  this.activeDescendant = computed(() => {
112
121
  const highlightedItem = this.#listService.highlightedItem();
113
122
  return highlightedItem ? highlightedItem.uid : null;
@@ -136,6 +145,12 @@ class DropdownListComponent {
136
145
  return twMerge(classes, userClass);
137
146
  }, /* @ts-ignore */
138
147
  ...(ngDevMode ? [{ debugName: "baseClass" }] : /* istanbul ignore next */ []));
148
+ this.clearButtonVisible = computed(() => this.showClearButton() &&
149
+ this.selectedListItem() != null &&
150
+ !this.loading() &&
151
+ !this.disabled() &&
152
+ !this.readonly(), /* @ts-ignore */
153
+ ...(ngDevMode ? [{ debugName: "clearButtonVisible" }] : /* istanbul ignore next */ []));
139
154
  this.effectiveAriaLabel = computed(() => this.ariaLabel() || (this.ariaLabelledBy() ? "" : this.placeholder()), /* @ts-ignore */
140
155
  ...(ngDevMode ? [{ debugName: "effectiveAriaLabel" }] : /* istanbul ignore next */ []));
141
156
  this.expanded = computed(() => this.#dropdownService.popupRef() !== null, /* @ts-ignore */
@@ -154,7 +169,9 @@ class DropdownListComponent {
154
169
  const size = this.size();
155
170
  const userClass = this.popupClass();
156
171
  const variantClass = dropdownPopupThemeVariants({ rounded, size });
157
- return twMerge(variantClass, userClass);
172
+ // With a popupHeight, the overlay sets the limit; the default max-h-64 would cut a taller popup short.
173
+ const heightClass = this.popupHeight() ? "max-h-none" : "";
174
+ return twMerge(variantClass, heightClass, userClass);
158
175
  }, /* @ts-ignore */
159
176
  ...(ngDevMode ? [{ debugName: "listPopupClass" }] : /* istanbul ignore next */ []));
160
177
  this.messages = this.#i18n.componentMessages("dropdownList", DROPDOWN_LIST_DEFAULT_MESSAGES);
@@ -189,6 +206,11 @@ class DropdownListComponent {
189
206
  return this.#listService.getItemText(listItem);
190
207
  }, /* @ts-ignore */
191
208
  ...(ngDevMode ? [{ debugName: "valueText" }] : /* istanbul ignore next */ []));
209
+ /**
210
+ * @description ID of an element that describes the dropdown list, such as help text or an error message.
211
+ * @default ""
212
+ */
213
+ this.ariaDescribedBy = input("", { ...(ngDevMode ? { debugName: "ariaDescribedBy" } : /* istanbul ignore next */ {}), alias: "aria-describedby" });
192
214
  /**
193
215
  * @description Accessible name for the host element. Describe what the component represents.
194
216
  * When empty, falls back to the placeholder text.
@@ -203,6 +225,7 @@ class DropdownListComponent {
203
225
  /**
204
226
  * @description Emitted when the popup is about to close. This event is preventable.
205
227
  */
228
+ // eslint-disable-next-line @angular-eslint/no-output-native -- renaming the output would break existing (close) bindings
206
229
  this.close = output();
207
230
  /**
208
231
  * @description Emitted after the popup closes.
@@ -218,14 +241,12 @@ class DropdownListComponent {
218
241
  * @description Renders the component with reduced visual emphasis and removes pointer interaction.
219
242
  * @default false
220
243
  */
221
- this.disabled = model(false, /* @ts-ignore */
222
- ...(ngDevMode ? [{ debugName: "disabled" }] : /* istanbul ignore next */ []));
244
+ this.disabled = input(false, { ...(ngDevMode ? { debugName: "disabled" } : /* istanbul ignore next */ {}), transform: booleanAttribute });
223
245
  /**
224
246
  * @description Marks the field as invalid. Set automatically by the `FormField` directive when bound via `[formField]`.
225
247
  * @default false
226
248
  */
227
- this.invalid = input(false, /* @ts-ignore */
228
- ...(ngDevMode ? [{ debugName: "invalid" }] : /* istanbul ignore next */ []));
249
+ this.invalid = input(false, { ...(ngDevMode ? { debugName: "invalid" } : /* istanbul ignore next */ {}), transform: booleanAttribute });
229
250
  /**
230
251
  * @description Predicate or field name used to determine whether an individual item is disabled.
231
252
  * @default undefined
@@ -233,11 +254,11 @@ class DropdownListComponent {
233
254
  this.itemDisabled = input(/* @ts-ignore */
234
255
  ...(ngDevMode ? [undefined, { debugName: "itemDisabled" }] : /* istanbul ignore next */ []));
235
256
  /**
236
- * @description Displays a loading indicator and prevents interaction while an operation is in progress.
257
+ * @description Shows a loading indicator, in place of the clear button, and marks the field busy. It doesn't
258
+ * block interaction: the field stays usable while data loads.
237
259
  * @default false
238
260
  */
239
- this.loading = input(false, /* @ts-ignore */
240
- ...(ngDevMode ? [{ debugName: "loading" }] : /* istanbul ignore next */ []));
261
+ this.loading = input(false, { ...(ngDevMode ? { debugName: "loading" } : /* istanbul ignore next */ {}), transform: booleanAttribute });
241
262
  /**
242
263
  * @description Emitted when the popup is about to open. This event is preventable.
243
264
  */
@@ -259,7 +280,8 @@ class DropdownListComponent {
259
280
  this.popupClass = input("", /* @ts-ignore */
260
281
  ...(ngDevMode ? [{ debugName: "popupClass" }] : /* istanbul ignore next */ []));
261
282
  /**
262
- * @description Height of the popup element.
283
+ * @description Maximum height of the popup, in pixels or as a CSS length. Shorter lists shrink to fit. When
284
+ * unset, the popup is at most 200 pixels tall.
263
285
  * @default null
264
286
  */
265
287
  this.popupHeight = input(null, /* @ts-ignore */
@@ -274,14 +296,12 @@ class DropdownListComponent {
274
296
  * @description Prevents value changes while preserving the component's visual state.
275
297
  * @default false
276
298
  */
277
- this.readonly = input(false, /* @ts-ignore */
278
- ...(ngDevMode ? [{ debugName: "readonly" }] : /* istanbul ignore next */ []));
299
+ this.readonly = input(false, { ...(ngDevMode ? { debugName: "readonly" } : /* istanbul ignore next */ {}), transform: booleanAttribute });
279
300
  /**
280
301
  * @description Marks the field as required for form validation.
281
302
  * @default false
282
303
  */
283
- this.required = input(false, /* @ts-ignore */
284
- ...(ngDevMode ? [{ debugName: "required" }] : /* istanbul ignore next */ []));
304
+ this.required = input(false, { ...(ngDevMode ? { debugName: "required" } : /* istanbul ignore next */ {}), transform: booleanAttribute });
285
305
  /**
286
306
  * @description Border-radius preset applied to the component.
287
307
  * @default "medium"
@@ -292,8 +312,7 @@ class DropdownListComponent {
292
312
  * @description Shows a clear button that resets the selected value when clicked.
293
313
  * @default false
294
314
  */
295
- this.showClearButton = input(false, /* @ts-ignore */
296
- ...(ngDevMode ? [{ debugName: "showClearButton" }] : /* istanbul ignore next */ []));
315
+ this.showClearButton = input(false, { ...(ngDevMode ? { debugName: "showClearButton" } : /* istanbul ignore next */ {}), transform: booleanAttribute });
297
316
  /**
298
317
  * @description Size preset controlling the component's dimensions.
299
318
  * @default "medium"
@@ -308,16 +327,15 @@ class DropdownListComponent {
308
327
  this.textField = input(/* @ts-ignore */
309
328
  ...(ngDevMode ? [undefined, { debugName: "textField" }] : /* istanbul ignore next */ []));
310
329
  /**
311
- * @description Emitted when the control is interacted with via blur, selection, or clear.
312
- * The `FormField` directive listens to this to mark the field as touched.
330
+ * @description Emitted when focus leaves the dropdown list. Moving between it, its clear button and its popup
331
+ * doesn't count. The `FormField` directive listens to this to mark the field as touched.
313
332
  */
314
333
  this.touch = output();
315
334
  /**
316
335
  * @description Marks the control as touched. Set automatically by the `FormField` directive when bound via `[formField]`.
317
336
  * @default false
318
337
  */
319
- this.touched = input(false, /* @ts-ignore */
320
- ...(ngDevMode ? [{ debugName: "touched" }] : /* istanbul ignore next */ []));
338
+ this.touched = input(false, { ...(ngDevMode ? { debugName: "touched" } : /* istanbul ignore next */ {}), transform: booleanAttribute });
321
339
  /**
322
340
  * @description Additional CSS classes merged onto the host element via `tailwind-merge`.
323
341
  * @default ""
@@ -350,8 +368,7 @@ class DropdownListComponent {
350
368
  *
351
369
  * @default false
352
370
  */
353
- this.valuePrimitive = input(false, /* @ts-ignore */
354
- ...(ngDevMode ? [{ debugName: "valuePrimitive" }] : /* istanbul ignore next */ []));
371
+ this.valuePrimitive = input(false, { ...(ngDevMode ? { debugName: "valuePrimitive" } : /* istanbul ignore next */ {}), transform: booleanAttribute });
355
372
  effect(() => {
356
373
  const value = this.value();
357
374
  const valueField = this.valueField();
@@ -383,17 +400,28 @@ class DropdownListComponent {
383
400
  });
384
401
  });
385
402
  }
386
- focus() {
387
- this.#hostElementRef.nativeElement?.focus();
403
+ /**
404
+ * @description Moves focus to the dropdown list.
405
+ * @param options Passed to `HTMLElement.focus()`, for example `{ preventScroll: true }`.
406
+ */
407
+ focus(options) {
408
+ this.#hostElementRef.nativeElement?.focus(options);
388
409
  }
389
410
  setValue(value) {
390
411
  this.updateValue(value);
391
412
  }
392
- onBlur(event) {
393
- const popupElement = this.#dropdownService.popupRef()?.overlayRef.overlayElement;
394
- if (popupElement && event?.relatedTarget instanceof Node && popupElement.contains(event.relatedTarget)) {
413
+ onFocusOut(event) {
414
+ // Removing a focused dropdown from the page fires focusout after it is destroyed.
415
+ if (this.#destroyRef.destroyed) {
395
416
  return;
396
417
  }
418
+ const nextTarget = event.relatedTarget;
419
+ if (nextTarget instanceof Node) {
420
+ const popupElement = this.#dropdownService.popupRef()?.overlayRef.overlayElement;
421
+ if (this.#hostElementRef.nativeElement.contains(nextTarget) || popupElement?.contains(nextTarget)) {
422
+ return;
423
+ }
424
+ }
397
425
  this.touch.emit();
398
426
  }
399
427
  onItemSelect(event) {
@@ -403,7 +431,7 @@ class DropdownListComponent {
403
431
  this.#navigatedItem.set(event.item.data);
404
432
  return;
405
433
  }
406
- this.updateValue(this.getControlValue(event.item.data), true);
434
+ this.updateValue(this.getControlValue(event.item.data));
407
435
  if (event.source.via === "mouse" || event.source.key === "Enter" || event.source.key === "NumpadEnter") {
408
436
  this.closePopup();
409
437
  }
@@ -415,7 +443,9 @@ class DropdownListComponent {
415
443
  }
416
444
  }
417
445
  onValueClear(event) {
418
- if (this.readonly() || (event instanceof KeyboardEvent && event.key !== "Enter" && event.key !== " ")) {
446
+ if (this.disabled() ||
447
+ this.readonly() ||
448
+ (event instanceof KeyboardEvent && event.key !== "Enter" && event.key !== " ")) {
419
449
  return;
420
450
  }
421
451
  event.stopImmediatePropagation();
@@ -439,7 +469,7 @@ class DropdownListComponent {
439
469
  this.#listService.selectItem(nextItem);
440
470
  const expanded = this.expanded();
441
471
  if (!expanded) {
442
- this.updateValue(this.getControlValue(nextItem.data), true);
472
+ this.updateValue(this.getControlValue(nextItem.data));
443
473
  }
444
474
  else {
445
475
  this.scrollToSelectedItem();
@@ -457,7 +487,7 @@ class DropdownListComponent {
457
487
  }
458
488
  const navigatedItem = this.#navigatedItem();
459
489
  if (navigatedItem && this.value() !== this.getControlValue(navigatedItem)) {
460
- this.updateValue(this.getControlValue(navigatedItem), true);
490
+ this.updateValue(this.getControlValue(navigatedItem));
461
491
  }
462
492
  this.closePopup();
463
493
  }
@@ -470,7 +500,7 @@ class DropdownListComponent {
470
500
  }
471
501
  this.#listService.selectItem(itemToSelect, true, false);
472
502
  if (!this.expanded()) {
473
- this.updateValue(this.getControlValue(itemToSelect.data), true);
503
+ this.updateValue(this.getControlValue(itemToSelect.data));
474
504
  }
475
505
  else {
476
506
  this.#navigatedItem.set(itemToSelect.data);
@@ -480,6 +510,10 @@ class DropdownListComponent {
480
510
  this.#listService.setNavigableOptions({ enabled: true, mode: "select" });
481
511
  this.#listService.setSelectableOptions(this.selectableOptions);
482
512
  }
513
+ pushTypeaheadKey(key) {
514
+ this.#lastTypeaheadKeyTime = Date.now();
515
+ this.#typeaheadKey.next(key);
516
+ }
483
517
  scrollToSelectedItem() {
484
518
  const item = this.selectedListItem();
485
519
  if (!item) {
@@ -490,7 +524,7 @@ class DropdownListComponent {
490
524
  setArrowKeyNavigationSubscription() {
491
525
  this.#dropdownListService.navigate$.pipe(takeUntilDestroyed(this.#destroyRef)).subscribe(({ item }) => {
492
526
  if (!this.expanded()) {
493
- this.updateValue(this.getControlValue(item.data), true);
527
+ this.updateValue(this.getControlValue(item.data));
494
528
  }
495
529
  else {
496
530
  this.#navigatedItem.set(item.data);
@@ -518,17 +552,28 @@ class DropdownListComponent {
518
552
  this.handleHomeEndKeys(event);
519
553
  }
520
554
  else if (isTypeaheadKey(event.key, event)) {
521
- this.#typeaheadKey.next(event.key);
555
+ this.pushTypeaheadKey(event.key);
522
556
  }
523
557
  });
524
558
  }
525
559
  setPopupCloseSubscriptions() {
526
- this.#dropdownService.popupCloseComplete$.pipe(takeUntilDestroyed(this.#destroyRef)).subscribe(() => {
527
- const navigatedItem = this.#navigatedItem();
528
- this.updateValue(navigatedItem ? this.getControlValue(navigatedItem) : null, true);
560
+ this.#dropdownService.popupCloseComplete$.pipe(takeUntilDestroyed(this.#destroyRef)).subscribe(event => {
561
+ if (cancellingCloseSources.has(event.via)) {
562
+ // Escape, an outside click or a scroll cancels: drop the option the arrow keys reached.
563
+ this.synchronizeSelection(this.value());
564
+ this.#navigatedItem.set(this.selectedDataItem());
565
+ }
566
+ else {
567
+ const navigatedItem = this.#navigatedItem();
568
+ this.updateValue(navigatedItem ? this.getControlValue(navigatedItem) : null);
569
+ }
529
570
  if (this.#dropdownService.focusCanReturn()) {
530
571
  window.setTimeout(() => this.focus());
531
572
  }
573
+ else if (!this.#destroyRef.destroyed) {
574
+ // Focus left from inside the popup (its filter box), so the host never saw a focusout.
575
+ this.touch.emit();
576
+ }
532
577
  });
533
578
  }
534
579
  setSubscriptions() {
@@ -536,8 +581,19 @@ class DropdownListComponent {
536
581
  this.setKeydownSubscription();
537
582
  this.setFilterChangeSubscription();
538
583
  this.setPopupCloseSubscriptions();
584
+ this.setTypeaheadSpaceSubscription();
539
585
  this.setTypeaheadSubscription();
540
586
  }
587
+ setTypeaheadSpaceSubscription() {
588
+ // While a typeahead search is under way, Space is part of it ("New York"), not the popup toggle.
589
+ this.#dropdownService.beforeKeydown$
590
+ .pipe(takeUntilDestroyed(this.#destroyRef), filter(e => e.originalEvent?.key === " " && Date.now() - this.#lastTypeaheadKeyTime < TYPEAHEAD_RESET_DELAY))
591
+ .subscribe(event => {
592
+ event.preventDefault();
593
+ event.originalEvent?.preventDefault();
594
+ this.pushTypeaheadKey(" ");
595
+ });
596
+ }
541
597
  setTypeaheadSubscription() {
542
598
  setupTypeahead(this.#typeaheadKey)
543
599
  .pipe(takeUntilDestroyed(this.#destroyRef))
@@ -555,22 +611,18 @@ class DropdownListComponent {
555
611
  this.#listService.setSelectedDataItems([value]);
556
612
  }
557
613
  }
558
- updateValue(value, notify = true) {
559
- const oldValue = this.value();
560
- if (oldValue !== value) {
614
+ updateValue(value) {
615
+ if (this.value() !== value) {
561
616
  this.value.set(value);
562
617
  }
563
- if (notify && oldValue !== value) {
564
- this.touch.emit();
565
- }
566
618
  }
567
619
  static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "22.0.6", ngImport: i0, type: DropdownListComponent, deps: [], target: i0.ɵɵFactoryTarget.Component }); }
568
- static { this.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "22.0.6", type: DropdownListComponent, isStandalone: true, selector: "mona-dropdown-list", inputs: { ariaLabel: { classPropertyName: "ariaLabel", publicName: "aria-label", isSignal: true, isRequired: false, transformFunction: null }, ariaLabelledBy: { classPropertyName: "ariaLabelledBy", publicName: "aria-labelledby", isSignal: true, isRequired: false, transformFunction: null }, data: { classPropertyName: "data", publicName: "data", isSignal: true, isRequired: false, transformFunction: null }, disabled: { classPropertyName: "disabled", publicName: "disabled", isSignal: true, isRequired: false, transformFunction: null }, invalid: { classPropertyName: "invalid", publicName: "invalid", isSignal: true, isRequired: false, transformFunction: null }, itemDisabled: { classPropertyName: "itemDisabled", publicName: "itemDisabled", isSignal: true, isRequired: false, transformFunction: null }, loading: { classPropertyName: "loading", publicName: "loading", isSignal: true, isRequired: false, transformFunction: null }, placeholder: { classPropertyName: "placeholder", publicName: "placeholder", isSignal: true, isRequired: false, transformFunction: null }, popupClass: { classPropertyName: "popupClass", publicName: "popupClass", isSignal: true, isRequired: false, transformFunction: null }, popupHeight: { classPropertyName: "popupHeight", publicName: "popupHeight", isSignal: true, isRequired: false, transformFunction: null }, popupWidth: { classPropertyName: "popupWidth", publicName: "popupWidth", isSignal: true, isRequired: false, transformFunction: null }, readonly: { classPropertyName: "readonly", publicName: "readonly", isSignal: true, isRequired: false, transformFunction: null }, required: { classPropertyName: "required", publicName: "required", isSignal: true, isRequired: false, transformFunction: null }, rounded: { classPropertyName: "rounded", publicName: "rounded", isSignal: true, isRequired: false, transformFunction: null }, showClearButton: { classPropertyName: "showClearButton", publicName: "showClearButton", isSignal: true, isRequired: false, transformFunction: null }, size: { classPropertyName: "size", publicName: "size", isSignal: true, isRequired: false, transformFunction: null }, textField: { classPropertyName: "textField", publicName: "textField", isSignal: true, isRequired: false, transformFunction: null }, touched: { classPropertyName: "touched", publicName: "touched", isSignal: true, isRequired: false, transformFunction: null }, userClass: { classPropertyName: "userClass", publicName: "class", isSignal: true, isRequired: false, transformFunction: null }, value: { classPropertyName: "value", publicName: "value", isSignal: true, isRequired: false, transformFunction: null }, valueField: { classPropertyName: "valueField", publicName: "valueField", isSignal: true, isRequired: false, transformFunction: null }, valuePrimitive: { classPropertyName: "valuePrimitive", publicName: "valuePrimitive", isSignal: true, isRequired: false, transformFunction: null } }, outputs: { close: "close", closed: "closed", disabled: "disabledChange", open: "open", opened: "opened", touch: "touch", value: "valueChange" }, host: { listeners: { "blur": "onBlur($event)" }, properties: { "attr.aria-activedescendant": "activeDescendant()", "attr.aria-busy": "loading() ? 'true' : undefined", "attr.aria-controls": "listId", "attr.aria-disabled": "disabled() ? true : undefined", "attr.aria-expanded": "expanded()", "attr.aria-haspopup": "'listbox'", "attr.aria-invalid": "invalidState() ? true : undefined", "attr.aria-label": "effectiveAriaLabel() || null", "attr.aria-labelledby": "ariaLabelledBy()", "attr.aria-readonly": "readonly() ? true : undefined", "attr.aria-required": "required() ? true : undefined", "attr.data-disabled": "disabled() || null", "attr.data-invalid": "invalidState() || null", "attr.data-readonly": "readonly() || null", "attr.role": "'combobox'", "attr.tabindex": "disabled() ? null : 0", "class": "baseClass()" } }, providers: [
620
+ static { this.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "22.0.6", type: DropdownListComponent, isStandalone: true, selector: "mona-dropdown-list", inputs: { ariaDescribedBy: { classPropertyName: "ariaDescribedBy", publicName: "aria-describedby", isSignal: true, isRequired: false, transformFunction: null }, ariaLabel: { classPropertyName: "ariaLabel", publicName: "aria-label", isSignal: true, isRequired: false, transformFunction: null }, ariaLabelledBy: { classPropertyName: "ariaLabelledBy", publicName: "aria-labelledby", isSignal: true, isRequired: false, transformFunction: null }, data: { classPropertyName: "data", publicName: "data", isSignal: true, isRequired: false, transformFunction: null }, disabled: { classPropertyName: "disabled", publicName: "disabled", isSignal: true, isRequired: false, transformFunction: null }, invalid: { classPropertyName: "invalid", publicName: "invalid", isSignal: true, isRequired: false, transformFunction: null }, itemDisabled: { classPropertyName: "itemDisabled", publicName: "itemDisabled", isSignal: true, isRequired: false, transformFunction: null }, loading: { classPropertyName: "loading", publicName: "loading", isSignal: true, isRequired: false, transformFunction: null }, placeholder: { classPropertyName: "placeholder", publicName: "placeholder", isSignal: true, isRequired: false, transformFunction: null }, popupClass: { classPropertyName: "popupClass", publicName: "popupClass", isSignal: true, isRequired: false, transformFunction: null }, popupHeight: { classPropertyName: "popupHeight", publicName: "popupHeight", isSignal: true, isRequired: false, transformFunction: null }, popupWidth: { classPropertyName: "popupWidth", publicName: "popupWidth", isSignal: true, isRequired: false, transformFunction: null }, readonly: { classPropertyName: "readonly", publicName: "readonly", isSignal: true, isRequired: false, transformFunction: null }, required: { classPropertyName: "required", publicName: "required", isSignal: true, isRequired: false, transformFunction: null }, rounded: { classPropertyName: "rounded", publicName: "rounded", isSignal: true, isRequired: false, transformFunction: null }, showClearButton: { classPropertyName: "showClearButton", publicName: "showClearButton", isSignal: true, isRequired: false, transformFunction: null }, size: { classPropertyName: "size", publicName: "size", isSignal: true, isRequired: false, transformFunction: null }, textField: { classPropertyName: "textField", publicName: "textField", isSignal: true, isRequired: false, transformFunction: null }, touched: { classPropertyName: "touched", publicName: "touched", isSignal: true, isRequired: false, transformFunction: null }, userClass: { classPropertyName: "userClass", publicName: "class", isSignal: true, isRequired: false, transformFunction: null }, value: { classPropertyName: "value", publicName: "value", isSignal: true, isRequired: false, transformFunction: null }, valueField: { classPropertyName: "valueField", publicName: "valueField", isSignal: true, isRequired: false, transformFunction: null }, valuePrimitive: { classPropertyName: "valuePrimitive", publicName: "valuePrimitive", isSignal: true, isRequired: false, transformFunction: null } }, outputs: { close: "close", closed: "closed", open: "open", opened: "opened", touch: "touch", value: "valueChange" }, host: { listeners: { "focusout": "onFocusOut($event)" }, properties: { "attr.aria-activedescendant": "activeDescendant()", "attr.aria-busy": "loading() ? 'true' : undefined", "attr.aria-controls": "listId", "attr.aria-describedby": "ariaDescribedBy() || null", "attr.aria-disabled": "disabled() ? true : undefined", "attr.aria-expanded": "expanded()", "attr.aria-haspopup": "'listbox'", "attr.aria-invalid": "invalidState() ? true : undefined", "attr.aria-label": "effectiveAriaLabel() || null", "attr.aria-labelledby": "ariaLabelledBy() || null", "attr.aria-readonly": "readonly() ? true : undefined", "attr.aria-required": "required() ? true : undefined", "attr.data-disabled": "disabled() || null", "attr.data-invalid": "invalidState() || null", "attr.data-readonly": "readonly() || null", "attr.role": "'combobox'", "attr.tabindex": "disabled() ? null : 0", "class": "baseClass()" } }, providers: [
569
621
  ListService,
570
622
  DropdownService,
571
623
  DropdownListService,
572
624
  {
573
- provide: DropdownDataInputToken,
625
+ provide: DROPDOWN_DATA_INPUT_TOKEN,
574
626
  useExisting: forwardRef(() => DropdownListComponent),
575
627
  multi: false
576
628
  },
@@ -579,16 +631,16 @@ class DropdownListComponent {
579
631
  useExisting: forwardRef(() => DropdownListComponent),
580
632
  multi: false
581
633
  }
582
- ], queries: [{ propertyName: "footerTemplate", first: true, predicate: DropdownFooterTemplateDirective, descendants: true, read: TemplateRef, isSignal: true }, { propertyName: "groupHeaderTemplate", first: true, predicate: DropdownGroupHeaderTemplateDirective, descendants: true, read: TemplateRef, isSignal: true }, { propertyName: "headerTemplate", first: true, predicate: DropdownHeaderTemplateDirective, descendants: true, read: TemplateRef, isSignal: true }, { propertyName: "itemTemplate", first: true, predicate: DropdownItemTemplateDirective, descendants: true, read: TemplateRef, isSignal: true }, { propertyName: "noDataTemplate", first: true, predicate: DropdownNoDataTemplateDirective, descendants: true, read: TemplateRef, isSignal: true }, { propertyName: "prefixTemplate", first: true, predicate: DropdownPrefixTemplateDirective, descendants: true, read: TemplateRef, isSignal: true }, { propertyName: "valueTemplate", first: true, predicate: DropdownListValueTemplateDirective, descendants: true, read: TemplateRef, isSignal: true }], viewQueries: [{ propertyName: "popupTemplate", first: true, predicate: ["popupTemplate"], descendants: true, isSignal: true }], hostDirectives: [{ directive: i1.DropdownDataHandlerDirective }, { directive: i1.DropdownListPopupHandlerDirective }], ngImport: i0, template: "@if (prefixTemplate()) {\n <span [class]=\"affixClass()\">\n <ng-container [ngTemplateOutlet]=\"prefixTemplate()\"></ng-container>\n </span>\n}\n\n<span [class]=\"valueContainerClass()\">\n @if (!valueTemplate()) {\n <span>\n @if (selectedListItem()) {\n <span>{{ valueText() }}</span>\n } @else {\n <span>{{ placeholder() }}</span>\n }\n </span>\n } @else {\n <ng-container\n [ngTemplateOutlet]=\"valueTemplate()\"\n [ngTemplateOutletContext]=\"{ $implicit: selectedDataItem() }\"></ng-container>\n }\n</span>\n\n@if (selectedListItem() && showClearButton() && !loading()) {\n <mona-indicator-icon\n preset=\"clear\"\n [interactive]=\"true\"\n [label]=\"messages().clear\"\n (activate)=\"onValueClear($event)\"></mona-indicator-icon>\n}\n\n@if (loading()) {\n <mona-indicator-icon preset=\"loading\" [size]=\"12\"></mona-indicator-icon>\n}\n\n<mona-indicator-icon preset=\"dropdown\" [size]=\"18\"></mona-indicator-icon>\n\n<span monaDropdownLiveRegion></span>\n\n<ng-template #popupTemplate>\n <div [class]=\"listPopupClass()\" (pointerdown)=\"onPopupPointerDown($event)\">\n <mona-list [listId]=\"listId\" [focusOnMount]=\"false\" [size]=\"size()\" (itemSelect)=\"onItemSelect($event)\">\n @if (footerTemplate()) {\n <ng-template monaListFooterTemplate>\n <ng-container [ngTemplateOutlet]=\"footerTemplate()\"></ng-container>\n </ng-template>\n }\n @if (groupHeaderTemplate()) {\n <ng-template monaListGroupHeaderTemplate let-group>\n <ng-container\n [ngTemplateOutlet]=\"groupHeaderTemplate()\"\n [ngTemplateOutletContext]=\"{ $implicit: group }\"></ng-container>\n </ng-template>\n }\n @if (headerTemplate()) {\n <ng-template monaListHeaderTemplate>\n <ng-container [ngTemplateOutlet]=\"headerTemplate()\"></ng-container>\n </ng-template>\n }\n @if (itemTemplate()) {\n <ng-template monaListItemTemplate let-dataItem>\n <ng-container\n [ngTemplateOutlet]=\"itemTemplate()\"\n [ngTemplateOutletContext]=\"{ $implicit: dataItem }\"></ng-container>\n </ng-template>\n }\n @if (noDataTemplate()) {\n <ng-template monaListNoDataTemplate>\n <ng-container [ngTemplateOutlet]=\"noDataTemplate()\"></ng-container>\n </ng-template>\n }\n </mona-list>\n </div>\n</ng-template>\n", dependencies: [{ kind: "directive", type: NgTemplateOutlet, selector: "[ngTemplateOutlet]", inputs: ["ngTemplateOutletContext", "ngTemplateOutlet", "ngTemplateOutletInjector"] }, { kind: "component", type: ListComponent, selector: "mona-list", inputs: ["ariaLabel", "data", "focusOnMount", "height", "listClass", "listId", "listItemClass", "listItemStyle", "listStyle", "maxHeight", "maxWidth", "size", "textField", "width"], outputs: ["itemSelect"] }, { kind: "directive", type: ListItemTemplateDirective, selector: "ng-template[monaListItemTemplate]" }, { kind: "directive", type: ListGroupHeaderTemplateDirective, selector: "ng-template[monaListGroupHeaderTemplate]" }, { kind: "directive", type: ListFooterTemplateDirective, selector: "ng-template[monaListFooterTemplate]" }, { kind: "directive", type: ListHeaderTemplateDirective, selector: "ng-template[monaListHeaderTemplate]" }, { kind: "directive", type: ListNoDataTemplateDirective, selector: "ng-template[monaListNoDataTemplate]" }, { kind: "directive", type: DropdownLiveRegionDirective, selector: "span[monaDropdownLiveRegion]" }, { kind: "component", type: IndicatorIconComponent, selector: "mona-indicator-icon", inputs: ["icon", "interactive", "label", "preset", "size", "class"], outputs: ["activate"] }] }); }
634
+ ], queries: [{ propertyName: "footerTemplate", first: true, predicate: DropdownFooterTemplateDirective, descendants: true, read: TemplateRef, isSignal: true }, { propertyName: "groupHeaderTemplate", first: true, predicate: DropdownGroupHeaderTemplateDirective, descendants: true, read: TemplateRef, isSignal: true }, { propertyName: "headerTemplate", first: true, predicate: DropdownHeaderTemplateDirective, descendants: true, read: TemplateRef, isSignal: true }, { propertyName: "itemTemplate", first: true, predicate: DropdownItemTemplateDirective, descendants: true, read: TemplateRef, isSignal: true }, { propertyName: "noDataTemplate", first: true, predicate: DropdownNoDataTemplateDirective, descendants: true, read: TemplateRef, isSignal: true }, { propertyName: "prefixTemplate", first: true, predicate: DropdownPrefixTemplateDirective, descendants: true, read: TemplateRef, isSignal: true }, { propertyName: "valueTemplate", first: true, predicate: DropdownListValueTemplateDirective, descendants: true, read: TemplateRef, isSignal: true }], viewQueries: [{ propertyName: "popupTemplate", first: true, predicate: ["popupTemplate"], descendants: true, isSignal: true }], hostDirectives: [{ directive: i1.DropdownDataHandlerDirective }, { directive: i1.DropdownListPopupHandlerDirective }, { directive: i1.DropdownLiveRegionDirective }], ngImport: i0, template: "@if (prefixTemplate()) {\n <span [class]=\"affixClass()\">\n <ng-container [ngTemplateOutlet]=\"prefixTemplate()\"></ng-container>\n </span>\n}\n\n<span [class]=\"valueContainerClass()\">\n @if (!valueTemplate()) {\n <span>\n @if (selectedListItem()) {\n <span>{{ valueText() }}</span>\n } @else {\n <span>{{ placeholder() }}</span>\n }\n </span>\n } @else {\n <ng-container\n [ngTemplateOutlet]=\"valueTemplate()\"\n [ngTemplateOutletContext]=\"{ $implicit: selectedDataItem() }\"></ng-container>\n }\n</span>\n\n@if (clearButtonVisible()) {\n <mona-indicator-icon\n preset=\"clear\"\n [interactive]=\"true\"\n [label]=\"messages().clear\"\n (activate)=\"onValueClear($event)\"></mona-indicator-icon>\n}\n\n@if (loading()) {\n <mona-indicator-icon preset=\"loading\" [size]=\"12\"></mona-indicator-icon>\n}\n\n<mona-indicator-icon preset=\"dropdown\" [size]=\"18\"></mona-indicator-icon>\n\n<ng-template #popupTemplate>\n <div [class]=\"listPopupClass()\" (pointerdown)=\"onPopupPointerDown($event)\">\n <mona-list [listId]=\"listId\" [focusOnMount]=\"false\" [size]=\"size()\" (itemSelect)=\"onItemSelect($event)\">\n @if (footerTemplate()) {\n <ng-template monaListFooterTemplate>\n <ng-container [ngTemplateOutlet]=\"footerTemplate()\"></ng-container>\n </ng-template>\n }\n @if (groupHeaderTemplate()) {\n <ng-template monaListGroupHeaderTemplate let-group>\n <ng-container\n [ngTemplateOutlet]=\"groupHeaderTemplate()\"\n [ngTemplateOutletContext]=\"{ $implicit: group }\"></ng-container>\n </ng-template>\n }\n @if (headerTemplate()) {\n <ng-template monaListHeaderTemplate>\n <ng-container [ngTemplateOutlet]=\"headerTemplate()\"></ng-container>\n </ng-template>\n }\n @if (itemTemplate()) {\n <ng-template monaListItemTemplate let-dataItem>\n <ng-container\n [ngTemplateOutlet]=\"itemTemplate()\"\n [ngTemplateOutletContext]=\"{ $implicit: dataItem }\"></ng-container>\n </ng-template>\n }\n @if (noDataTemplate()) {\n <ng-template monaListNoDataTemplate>\n <ng-container [ngTemplateOutlet]=\"noDataTemplate()\"></ng-container>\n </ng-template>\n }\n </mona-list>\n </div>\n</ng-template>\n", dependencies: [{ kind: "directive", type: NgTemplateOutlet, selector: "[ngTemplateOutlet]", inputs: ["ngTemplateOutletContext", "ngTemplateOutlet", "ngTemplateOutletInjector"] }, { kind: "component", type: ListComponent, selector: "mona-list", inputs: ["ariaLabel", "data", "focusOnMount", "height", "listClass", "listId", "listItemClass", "listItemStyle", "listStyle", "maxHeight", "maxWidth", "size", "textField", "width"], outputs: ["itemSelect"] }, { kind: "directive", type: ListItemTemplateDirective, selector: "ng-template[monaListItemTemplate]" }, { kind: "directive", type: ListGroupHeaderTemplateDirective, selector: "ng-template[monaListGroupHeaderTemplate]" }, { kind: "directive", type: ListFooterTemplateDirective, selector: "ng-template[monaListFooterTemplate]" }, { kind: "directive", type: ListHeaderTemplateDirective, selector: "ng-template[monaListHeaderTemplate]" }, { kind: "directive", type: ListNoDataTemplateDirective, selector: "ng-template[monaListNoDataTemplate]" }, { kind: "component", type: IndicatorIconComponent, selector: "mona-indicator-icon", inputs: ["icon", "interactive", "label", "preset", "size", "class"], outputs: ["activate"] }] }); }
583
635
  }
584
636
  i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "22.0.6", ngImport: i0, type: DropdownListComponent, decorators: [{
585
637
  type: Component,
586
- args: [{ selector: "mona-dropdown-list", hostDirectives: [DropdownDataHandlerDirective, DropdownListPopupHandlerDirective], providers: [
638
+ args: [{ selector: "mona-dropdown-list", hostDirectives: [DropdownDataHandlerDirective, DropdownListPopupHandlerDirective, DropdownLiveRegionDirective], providers: [
587
639
  ListService,
588
640
  DropdownService,
589
641
  DropdownListService,
590
642
  {
591
- provide: DropdownDataInputToken,
643
+ provide: DROPDOWN_DATA_INPUT_TOKEN,
592
644
  useExisting: forwardRef(() => DropdownListComponent),
593
645
  multi: false
594
646
  },
@@ -605,18 +657,18 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "22.0.6", ngImpor
605
657
  ListFooterTemplateDirective,
606
658
  ListHeaderTemplateDirective,
607
659
  ListNoDataTemplateDirective,
608
- DropdownLiveRegionDirective,
609
660
  IndicatorIconComponent
610
661
  ], host: {
611
662
  "[attr.aria-activedescendant]": "activeDescendant()",
612
663
  "[attr.aria-busy]": "loading() ? 'true' : undefined",
613
664
  "[attr.aria-controls]": "listId",
665
+ "[attr.aria-describedby]": "ariaDescribedBy() || null",
614
666
  "[attr.aria-disabled]": "disabled() ? true : undefined",
615
667
  "[attr.aria-expanded]": "expanded()",
616
668
  "[attr.aria-haspopup]": "'listbox'",
617
669
  "[attr.aria-invalid]": "invalidState() ? true : undefined",
618
670
  "[attr.aria-label]": "effectiveAriaLabel() || null",
619
- "[attr.aria-labelledby]": "ariaLabelledBy()",
671
+ "[attr.aria-labelledby]": "ariaLabelledBy() || null",
620
672
  "[attr.aria-readonly]": "readonly() ? true : undefined",
621
673
  "[attr.aria-required]": "required() ? true : undefined",
622
674
  "[attr.data-disabled]": "disabled() || null",
@@ -625,11 +677,11 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "22.0.6", ngImpor
625
677
  "[attr.role]": "'combobox'",
626
678
  "[attr.tabindex]": "disabled() ? null : 0",
627
679
  "[class]": "baseClass()",
628
- "(blur)": "onBlur($event)"
629
- }, template: "@if (prefixTemplate()) {\n <span [class]=\"affixClass()\">\n <ng-container [ngTemplateOutlet]=\"prefixTemplate()\"></ng-container>\n </span>\n}\n\n<span [class]=\"valueContainerClass()\">\n @if (!valueTemplate()) {\n <span>\n @if (selectedListItem()) {\n <span>{{ valueText() }}</span>\n } @else {\n <span>{{ placeholder() }}</span>\n }\n </span>\n } @else {\n <ng-container\n [ngTemplateOutlet]=\"valueTemplate()\"\n [ngTemplateOutletContext]=\"{ $implicit: selectedDataItem() }\"></ng-container>\n }\n</span>\n\n@if (selectedListItem() && showClearButton() && !loading()) {\n <mona-indicator-icon\n preset=\"clear\"\n [interactive]=\"true\"\n [label]=\"messages().clear\"\n (activate)=\"onValueClear($event)\"></mona-indicator-icon>\n}\n\n@if (loading()) {\n <mona-indicator-icon preset=\"loading\" [size]=\"12\"></mona-indicator-icon>\n}\n\n<mona-indicator-icon preset=\"dropdown\" [size]=\"18\"></mona-indicator-icon>\n\n<span monaDropdownLiveRegion></span>\n\n<ng-template #popupTemplate>\n <div [class]=\"listPopupClass()\" (pointerdown)=\"onPopupPointerDown($event)\">\n <mona-list [listId]=\"listId\" [focusOnMount]=\"false\" [size]=\"size()\" (itemSelect)=\"onItemSelect($event)\">\n @if (footerTemplate()) {\n <ng-template monaListFooterTemplate>\n <ng-container [ngTemplateOutlet]=\"footerTemplate()\"></ng-container>\n </ng-template>\n }\n @if (groupHeaderTemplate()) {\n <ng-template monaListGroupHeaderTemplate let-group>\n <ng-container\n [ngTemplateOutlet]=\"groupHeaderTemplate()\"\n [ngTemplateOutletContext]=\"{ $implicit: group }\"></ng-container>\n </ng-template>\n }\n @if (headerTemplate()) {\n <ng-template monaListHeaderTemplate>\n <ng-container [ngTemplateOutlet]=\"headerTemplate()\"></ng-container>\n </ng-template>\n }\n @if (itemTemplate()) {\n <ng-template monaListItemTemplate let-dataItem>\n <ng-container\n [ngTemplateOutlet]=\"itemTemplate()\"\n [ngTemplateOutletContext]=\"{ $implicit: dataItem }\"></ng-container>\n </ng-template>\n }\n @if (noDataTemplate()) {\n <ng-template monaListNoDataTemplate>\n <ng-container [ngTemplateOutlet]=\"noDataTemplate()\"></ng-container>\n </ng-template>\n }\n </mona-list>\n </div>\n</ng-template>\n" }]
680
+ "(focusout)": "onFocusOut($event)"
681
+ }, template: "@if (prefixTemplate()) {\n <span [class]=\"affixClass()\">\n <ng-container [ngTemplateOutlet]=\"prefixTemplate()\"></ng-container>\n </span>\n}\n\n<span [class]=\"valueContainerClass()\">\n @if (!valueTemplate()) {\n <span>\n @if (selectedListItem()) {\n <span>{{ valueText() }}</span>\n } @else {\n <span>{{ placeholder() }}</span>\n }\n </span>\n } @else {\n <ng-container\n [ngTemplateOutlet]=\"valueTemplate()\"\n [ngTemplateOutletContext]=\"{ $implicit: selectedDataItem() }\"></ng-container>\n }\n</span>\n\n@if (clearButtonVisible()) {\n <mona-indicator-icon\n preset=\"clear\"\n [interactive]=\"true\"\n [label]=\"messages().clear\"\n (activate)=\"onValueClear($event)\"></mona-indicator-icon>\n}\n\n@if (loading()) {\n <mona-indicator-icon preset=\"loading\" [size]=\"12\"></mona-indicator-icon>\n}\n\n<mona-indicator-icon preset=\"dropdown\" [size]=\"18\"></mona-indicator-icon>\n\n<ng-template #popupTemplate>\n <div [class]=\"listPopupClass()\" (pointerdown)=\"onPopupPointerDown($event)\">\n <mona-list [listId]=\"listId\" [focusOnMount]=\"false\" [size]=\"size()\" (itemSelect)=\"onItemSelect($event)\">\n @if (footerTemplate()) {\n <ng-template monaListFooterTemplate>\n <ng-container [ngTemplateOutlet]=\"footerTemplate()\"></ng-container>\n </ng-template>\n }\n @if (groupHeaderTemplate()) {\n <ng-template monaListGroupHeaderTemplate let-group>\n <ng-container\n [ngTemplateOutlet]=\"groupHeaderTemplate()\"\n [ngTemplateOutletContext]=\"{ $implicit: group }\"></ng-container>\n </ng-template>\n }\n @if (headerTemplate()) {\n <ng-template monaListHeaderTemplate>\n <ng-container [ngTemplateOutlet]=\"headerTemplate()\"></ng-container>\n </ng-template>\n }\n @if (itemTemplate()) {\n <ng-template monaListItemTemplate let-dataItem>\n <ng-container\n [ngTemplateOutlet]=\"itemTemplate()\"\n [ngTemplateOutletContext]=\"{ $implicit: dataItem }\"></ng-container>\n </ng-template>\n }\n @if (noDataTemplate()) {\n <ng-template monaListNoDataTemplate>\n <ng-container [ngTemplateOutlet]=\"noDataTemplate()\"></ng-container>\n </ng-template>\n }\n </mona-list>\n </div>\n</ng-template>\n" }]
630
682
  }], ctorParameters: () => [], propDecorators: { footerTemplate: [{ type: i0.ContentChild, args: [i0.forwardRef(() => DropdownFooterTemplateDirective), { ...{ read: TemplateRef }, isSignal: true }] }], groupHeaderTemplate: [{ type: i0.ContentChild, args: [i0.forwardRef(() => DropdownGroupHeaderTemplateDirective), { ...{
631
683
  read: TemplateRef
632
- }, isSignal: true }] }], headerTemplate: [{ type: i0.ContentChild, args: [i0.forwardRef(() => DropdownHeaderTemplateDirective), { ...{ read: TemplateRef }, isSignal: true }] }], itemTemplate: [{ type: i0.ContentChild, args: [i0.forwardRef(() => DropdownItemTemplateDirective), { ...{ read: TemplateRef }, isSignal: true }] }], noDataTemplate: [{ type: i0.ContentChild, args: [i0.forwardRef(() => DropdownNoDataTemplateDirective), { ...{ read: TemplateRef }, isSignal: true }] }], popupTemplate: [{ type: i0.ViewChild, args: ["popupTemplate", { isSignal: true }] }], prefixTemplate: [{ type: i0.ContentChild, args: [i0.forwardRef(() => DropdownPrefixTemplateDirective), { ...{ read: TemplateRef }, isSignal: true }] }], valueTemplate: [{ type: i0.ContentChild, args: [i0.forwardRef(() => DropdownListValueTemplateDirective), { ...{ read: TemplateRef }, isSignal: true }] }], ariaLabel: [{ type: i0.Input, args: [{ isSignal: true, alias: "aria-label", required: false }] }], ariaLabelledBy: [{ type: i0.Input, args: [{ isSignal: true, alias: "aria-labelledby", required: false }] }], close: [{ type: i0.Output, args: ["close"] }], closed: [{ type: i0.Output, args: ["closed"] }], data: [{ type: i0.Input, args: [{ isSignal: true, alias: "data", required: false }] }], disabled: [{ type: i0.Input, args: [{ isSignal: true, alias: "disabled", required: false }] }, { type: i0.Output, args: ["disabledChange"] }], invalid: [{ type: i0.Input, args: [{ isSignal: true, alias: "invalid", required: false }] }], itemDisabled: [{ type: i0.Input, args: [{ isSignal: true, alias: "itemDisabled", required: false }] }], loading: [{ type: i0.Input, args: [{ isSignal: true, alias: "loading", required: false }] }], open: [{ type: i0.Output, args: ["open"] }], opened: [{ type: i0.Output, args: ["opened"] }], placeholder: [{ type: i0.Input, args: [{ isSignal: true, alias: "placeholder", required: false }] }], popupClass: [{ type: i0.Input, args: [{ isSignal: true, alias: "popupClass", required: false }] }], popupHeight: [{ type: i0.Input, args: [{ isSignal: true, alias: "popupHeight", required: false }] }], popupWidth: [{ type: i0.Input, args: [{ isSignal: true, alias: "popupWidth", required: false }] }], readonly: [{ type: i0.Input, args: [{ isSignal: true, alias: "readonly", required: false }] }], required: [{ type: i0.Input, args: [{ isSignal: true, alias: "required", required: false }] }], rounded: [{ type: i0.Input, args: [{ isSignal: true, alias: "rounded", required: false }] }], showClearButton: [{ type: i0.Input, args: [{ isSignal: true, alias: "showClearButton", required: false }] }], size: [{ type: i0.Input, args: [{ isSignal: true, alias: "size", required: false }] }], textField: [{ type: i0.Input, args: [{ isSignal: true, alias: "textField", required: false }] }], touch: [{ type: i0.Output, args: ["touch"] }], touched: [{ type: i0.Input, args: [{ isSignal: true, alias: "touched", required: false }] }], userClass: [{ type: i0.Input, args: [{ isSignal: true, alias: "class", required: false }] }], value: [{ type: i0.Input, args: [{ isSignal: true, alias: "value", required: false }] }, { type: i0.Output, args: ["valueChange"] }], valueField: [{ type: i0.Input, args: [{ isSignal: true, alias: "valueField", required: false }] }], valuePrimitive: [{ type: i0.Input, args: [{ isSignal: true, alias: "valuePrimitive", required: false }] }] } });
684
+ }, isSignal: true }] }], headerTemplate: [{ type: i0.ContentChild, args: [i0.forwardRef(() => DropdownHeaderTemplateDirective), { ...{ read: TemplateRef }, isSignal: true }] }], itemTemplate: [{ type: i0.ContentChild, args: [i0.forwardRef(() => DropdownItemTemplateDirective), { ...{ read: TemplateRef }, isSignal: true }] }], noDataTemplate: [{ type: i0.ContentChild, args: [i0.forwardRef(() => DropdownNoDataTemplateDirective), { ...{ read: TemplateRef }, isSignal: true }] }], popupTemplate: [{ type: i0.ViewChild, args: ["popupTemplate", { isSignal: true }] }], prefixTemplate: [{ type: i0.ContentChild, args: [i0.forwardRef(() => DropdownPrefixTemplateDirective), { ...{ read: TemplateRef }, isSignal: true }] }], valueTemplate: [{ type: i0.ContentChild, args: [i0.forwardRef(() => DropdownListValueTemplateDirective), { ...{ read: TemplateRef }, isSignal: true }] }], ariaDescribedBy: [{ type: i0.Input, args: [{ isSignal: true, alias: "aria-describedby", required: false }] }], ariaLabel: [{ type: i0.Input, args: [{ isSignal: true, alias: "aria-label", required: false }] }], ariaLabelledBy: [{ type: i0.Input, args: [{ isSignal: true, alias: "aria-labelledby", required: false }] }], close: [{ type: i0.Output, args: ["close"] }], closed: [{ type: i0.Output, args: ["closed"] }], data: [{ type: i0.Input, args: [{ isSignal: true, alias: "data", required: false }] }], disabled: [{ type: i0.Input, args: [{ isSignal: true, alias: "disabled", required: false }] }], invalid: [{ type: i0.Input, args: [{ isSignal: true, alias: "invalid", required: false }] }], itemDisabled: [{ type: i0.Input, args: [{ isSignal: true, alias: "itemDisabled", required: false }] }], loading: [{ type: i0.Input, args: [{ isSignal: true, alias: "loading", required: false }] }], open: [{ type: i0.Output, args: ["open"] }], opened: [{ type: i0.Output, args: ["opened"] }], placeholder: [{ type: i0.Input, args: [{ isSignal: true, alias: "placeholder", required: false }] }], popupClass: [{ type: i0.Input, args: [{ isSignal: true, alias: "popupClass", required: false }] }], popupHeight: [{ type: i0.Input, args: [{ isSignal: true, alias: "popupHeight", required: false }] }], popupWidth: [{ type: i0.Input, args: [{ isSignal: true, alias: "popupWidth", required: false }] }], readonly: [{ type: i0.Input, args: [{ isSignal: true, alias: "readonly", required: false }] }], required: [{ type: i0.Input, args: [{ isSignal: true, alias: "required", required: false }] }], rounded: [{ type: i0.Input, args: [{ isSignal: true, alias: "rounded", required: false }] }], showClearButton: [{ type: i0.Input, args: [{ isSignal: true, alias: "showClearButton", required: false }] }], size: [{ type: i0.Input, args: [{ isSignal: true, alias: "size", required: false }] }], textField: [{ type: i0.Input, args: [{ isSignal: true, alias: "textField", required: false }] }], touch: [{ type: i0.Output, args: ["touch"] }], touched: [{ type: i0.Input, args: [{ isSignal: true, alias: "touched", required: false }] }], userClass: [{ type: i0.Input, args: [{ isSignal: true, alias: "class", required: false }] }], value: [{ type: i0.Input, args: [{ isSignal: true, alias: "value", required: false }] }, { type: i0.Output, args: ["valueChange"] }], valueField: [{ type: i0.Input, args: [{ isSignal: true, alias: "valueField", required: false }] }], valuePrimitive: [{ type: i0.Input, args: [{ isSignal: true, alias: "valuePrimitive", required: false }] }] } });
633
685
 
634
686
  /*
635
687
  * Public API Surface of @nanahoshi/mona-ui/dropdown-list