@nanahoshi/mona-ui 0.24.2 → 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 (85) hide show
  1. package/README.md +3 -0
  2. package/fesm2022/nanahoshi-mona-ui-auto-complete.mjs +96 -71
  3. package/fesm2022/nanahoshi-mona-ui-check-box.mjs +1 -1
  4. package/fesm2022/nanahoshi-mona-ui-color-gradient.mjs +1 -1
  5. package/fesm2022/nanahoshi-mona-ui-color-picker.mjs +1 -1
  6. package/fesm2022/nanahoshi-mona-ui-combo-box.mjs +140 -91
  7. package/fesm2022/nanahoshi-mona-ui-date-input.mjs +1 -1
  8. package/fesm2022/nanahoshi-mona-ui-date-picker.mjs +8 -4
  9. package/fesm2022/nanahoshi-mona-ui-datetime-picker.mjs +8 -4
  10. package/fesm2022/nanahoshi-mona-ui-dropdown-list.mjs +112 -58
  11. package/fesm2022/nanahoshi-mona-ui-dropdowns.mjs +80 -61
  12. package/fesm2022/nanahoshi-mona-ui-editor.mjs +4 -4
  13. package/fesm2022/nanahoshi-mona-ui-filter.mjs +1 -1
  14. package/fesm2022/{nanahoshi-mona-ui-grid-grid-footer-row.component-x_euoNnS.mjs → nanahoshi-mona-ui-grid-grid-footer-row.component-BMCM0W8s.mjs} +2 -2
  15. package/fesm2022/{nanahoshi-mona-ui-grid-grid-list.component-C1_6vq77.mjs → nanahoshi-mona-ui-grid-grid-list.component-BSlV8Sua.mjs} +4 -4
  16. package/fesm2022/{nanahoshi-mona-ui-grid-grid-row.component-BhukVWIy.mjs → nanahoshi-mona-ui-grid-grid-row.component-CTOdnH29.mjs} +3 -3
  17. package/fesm2022/{nanahoshi-mona-ui-grid-grid-virtual-list.component-XQKOPPVs.mjs → nanahoshi-mona-ui-grid-grid-virtual-list.component-C2kf5MwO.mjs} +4 -4
  18. package/fesm2022/{nanahoshi-mona-ui-grid-nanahoshi-mona-ui-grid-Iw-wvKGl.mjs → nanahoshi-mona-ui-grid-nanahoshi-mona-ui-grid-Dh42tUui.mjs} +10 -15
  19. package/fesm2022/nanahoshi-mona-ui-grid.mjs +1 -1
  20. package/fesm2022/nanahoshi-mona-ui-i18n-icu.mjs +2 -1
  21. package/fesm2022/nanahoshi-mona-ui-internal-filter-input.mjs +2 -2
  22. package/fesm2022/nanahoshi-mona-ui-internal-indicator-icon.mjs +2 -2
  23. package/fesm2022/nanahoshi-mona-ui-internal-tree.mjs +1 -1
  24. package/fesm2022/nanahoshi-mona-ui-internal.mjs +18 -2
  25. package/fesm2022/nanahoshi-mona-ui-locales-ar-sa.mjs +2 -1
  26. package/fesm2022/nanahoshi-mona-ui-locales-de-de.mjs +4 -1
  27. package/fesm2022/nanahoshi-mona-ui-locales-es-es.mjs +4 -1
  28. package/fesm2022/nanahoshi-mona-ui-locales-fr-fr.mjs +4 -1
  29. package/fesm2022/nanahoshi-mona-ui-locales-id-id.mjs +2 -1
  30. package/fesm2022/nanahoshi-mona-ui-locales-it-it.mjs +2 -1
  31. package/fesm2022/nanahoshi-mona-ui-locales-ja-jp.mjs +2 -1
  32. package/fesm2022/nanahoshi-mona-ui-locales-ko-kr.mjs +2 -1
  33. package/fesm2022/nanahoshi-mona-ui-locales-pt-br.mjs +2 -1
  34. package/fesm2022/nanahoshi-mona-ui-locales-ru-ru.mjs +2 -1
  35. package/fesm2022/nanahoshi-mona-ui-locales-tr-tr.mjs +2 -1
  36. package/fesm2022/nanahoshi-mona-ui-locales-zh-cn.mjs +2 -1
  37. package/fesm2022/nanahoshi-mona-ui-locales-zh-tw.mjs +2 -1
  38. package/fesm2022/nanahoshi-mona-ui-menubar.mjs +3 -3
  39. package/fesm2022/nanahoshi-mona-ui-multi-select.mjs +119 -67
  40. package/fesm2022/nanahoshi-mona-ui-numeric-text-box.mjs +1 -1
  41. package/fesm2022/nanahoshi-mona-ui-otp-input.mjs +1 -1
  42. package/fesm2022/nanahoshi-mona-ui-pager.mjs +1 -1
  43. package/fesm2022/nanahoshi-mona-ui-popup-menu.mjs +2 -2
  44. package/fesm2022/nanahoshi-mona-ui-popup.mjs +269 -182
  45. package/fesm2022/nanahoshi-mona-ui-switch.mjs +1 -1
  46. package/fesm2022/nanahoshi-mona-ui-text-box.mjs +95 -58
  47. package/fesm2022/nanahoshi-mona-ui-time-picker.mjs +7 -5
  48. package/fesm2022/nanahoshi-mona-ui-time-selector.mjs +1 -1
  49. package/i18n/catalogs/en-US.messages.json +2 -1
  50. package/locales/ar-sa/ar-sa.messages.json +2 -1
  51. package/locales/de-de/de-de.messages.json +2 -1
  52. package/locales/es-es/es-es.messages.json +2 -1
  53. package/locales/fr-fr/fr-fr.messages.json +2 -1
  54. package/locales/id-id/id-id.messages.json +2 -1
  55. package/locales/it-it/it-it.messages.json +2 -1
  56. package/locales/ja-jp/ja-jp.messages.json +2 -1
  57. package/locales/ko-kr/ko-kr.messages.json +2 -1
  58. package/locales/pt-br/pt-br.messages.json +2 -1
  59. package/locales/ru-ru/ru-ru.messages.json +2 -1
  60. package/locales/tr-tr/tr-tr.messages.json +2 -1
  61. package/locales/zh-cn/zh-cn.messages.json +2 -1
  62. package/locales/zh-tw/zh-tw.messages.json +2 -1
  63. package/package.json +1 -1
  64. package/types/nanahoshi-mona-ui-auto-complete.d.ts +34 -20
  65. package/types/nanahoshi-mona-ui-combo-box.d.ts +42 -23
  66. package/types/nanahoshi-mona-ui-dropdown-list.d.ts +29 -15
  67. package/types/nanahoshi-mona-ui-dropdowns.d.ts +36 -19
  68. package/types/nanahoshi-mona-ui-i18n.d.ts +1 -0
  69. package/types/nanahoshi-mona-ui-internal.d.ts +11 -1
  70. package/types/nanahoshi-mona-ui-locales-ar-sa.d.ts +1 -0
  71. package/types/nanahoshi-mona-ui-locales-de-de.d.ts +1 -0
  72. package/types/nanahoshi-mona-ui-locales-es-es.d.ts +1 -0
  73. package/types/nanahoshi-mona-ui-locales-fr-fr.d.ts +1 -0
  74. package/types/nanahoshi-mona-ui-locales-id-id.d.ts +1 -0
  75. package/types/nanahoshi-mona-ui-locales-it-it.d.ts +1 -0
  76. package/types/nanahoshi-mona-ui-locales-ja-jp.d.ts +1 -0
  77. package/types/nanahoshi-mona-ui-locales-ko-kr.d.ts +1 -0
  78. package/types/nanahoshi-mona-ui-locales-pt-br.d.ts +1 -0
  79. package/types/nanahoshi-mona-ui-locales-ru-ru.d.ts +1 -0
  80. package/types/nanahoshi-mona-ui-locales-tr-tr.d.ts +1 -0
  81. package/types/nanahoshi-mona-ui-locales-zh-cn.d.ts +1 -0
  82. package/types/nanahoshi-mona-ui-locales-zh-tw.d.ts +1 -0
  83. package/types/nanahoshi-mona-ui-multi-select.d.ts +45 -21
  84. package/types/nanahoshi-mona-ui-popup.d.ts +97 -36
  85. package/types/nanahoshi-mona-ui-text-box.d.ts +62 -14
@@ -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
 
@@ -67,7 +68,7 @@ const dropdownListInputThemeVariants = cva(`
67
68
  full: "rounded-full px-3"
68
69
  },
69
70
  size: {
70
- large: "h-10 text-md",
71
+ large: "h-10 text-base",
71
72
  medium: "h-9 text-sm",
72
73
  small: "h-8 text-xs"
73
74
  }
@@ -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,15 +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);
529
- window.setTimeout(() => this.focus());
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
+ }
570
+ if (this.#dropdownService.focusCanReturn()) {
571
+ window.setTimeout(() => this.focus());
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
+ }
530
577
  });
531
578
  }
532
579
  setSubscriptions() {
@@ -534,8 +581,19 @@ class DropdownListComponent {
534
581
  this.setKeydownSubscription();
535
582
  this.setFilterChangeSubscription();
536
583
  this.setPopupCloseSubscriptions();
584
+ this.setTypeaheadSpaceSubscription();
537
585
  this.setTypeaheadSubscription();
538
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
+ }
539
597
  setTypeaheadSubscription() {
540
598
  setupTypeahead(this.#typeaheadKey)
541
599
  .pipe(takeUntilDestroyed(this.#destroyRef))
@@ -553,22 +611,18 @@ class DropdownListComponent {
553
611
  this.#listService.setSelectedDataItems([value]);
554
612
  }
555
613
  }
556
- updateValue(value, notify = true) {
557
- const oldValue = this.value();
558
- if (oldValue !== value) {
614
+ updateValue(value) {
615
+ if (this.value() !== value) {
559
616
  this.value.set(value);
560
617
  }
561
- if (notify && oldValue !== value) {
562
- this.touch.emit();
563
- }
564
618
  }
565
619
  static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "22.0.6", ngImport: i0, type: DropdownListComponent, deps: [], target: i0.ɵɵFactoryTarget.Component }); }
566
- 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: [
567
621
  ListService,
568
622
  DropdownService,
569
623
  DropdownListService,
570
624
  {
571
- provide: DropdownDataInputToken,
625
+ provide: DROPDOWN_DATA_INPUT_TOKEN,
572
626
  useExisting: forwardRef(() => DropdownListComponent),
573
627
  multi: false
574
628
  },
@@ -577,16 +631,16 @@ class DropdownListComponent {
577
631
  useExisting: forwardRef(() => DropdownListComponent),
578
632
  multi: false
579
633
  }
580
- ], 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"] }] }); }
581
635
  }
582
636
  i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "22.0.6", ngImport: i0, type: DropdownListComponent, decorators: [{
583
637
  type: Component,
584
- args: [{ selector: "mona-dropdown-list", hostDirectives: [DropdownDataHandlerDirective, DropdownListPopupHandlerDirective], providers: [
638
+ args: [{ selector: "mona-dropdown-list", hostDirectives: [DropdownDataHandlerDirective, DropdownListPopupHandlerDirective, DropdownLiveRegionDirective], providers: [
585
639
  ListService,
586
640
  DropdownService,
587
641
  DropdownListService,
588
642
  {
589
- provide: DropdownDataInputToken,
643
+ provide: DROPDOWN_DATA_INPUT_TOKEN,
590
644
  useExisting: forwardRef(() => DropdownListComponent),
591
645
  multi: false
592
646
  },
@@ -603,18 +657,18 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "22.0.6", ngImpor
603
657
  ListFooterTemplateDirective,
604
658
  ListHeaderTemplateDirective,
605
659
  ListNoDataTemplateDirective,
606
- DropdownLiveRegionDirective,
607
660
  IndicatorIconComponent
608
661
  ], host: {
609
662
  "[attr.aria-activedescendant]": "activeDescendant()",
610
663
  "[attr.aria-busy]": "loading() ? 'true' : undefined",
611
664
  "[attr.aria-controls]": "listId",
665
+ "[attr.aria-describedby]": "ariaDescribedBy() || null",
612
666
  "[attr.aria-disabled]": "disabled() ? true : undefined",
613
667
  "[attr.aria-expanded]": "expanded()",
614
668
  "[attr.aria-haspopup]": "'listbox'",
615
669
  "[attr.aria-invalid]": "invalidState() ? true : undefined",
616
670
  "[attr.aria-label]": "effectiveAriaLabel() || null",
617
- "[attr.aria-labelledby]": "ariaLabelledBy()",
671
+ "[attr.aria-labelledby]": "ariaLabelledBy() || null",
618
672
  "[attr.aria-readonly]": "readonly() ? true : undefined",
619
673
  "[attr.aria-required]": "required() ? true : undefined",
620
674
  "[attr.data-disabled]": "disabled() || null",
@@ -623,11 +677,11 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "22.0.6", ngImpor
623
677
  "[attr.role]": "'combobox'",
624
678
  "[attr.tabindex]": "disabled() ? null : 0",
625
679
  "[class]": "baseClass()",
626
- "(blur)": "onBlur($event)"
627
- }, 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" }]
628
682
  }], ctorParameters: () => [], propDecorators: { footerTemplate: [{ type: i0.ContentChild, args: [i0.forwardRef(() => DropdownFooterTemplateDirective), { ...{ read: TemplateRef }, isSignal: true }] }], groupHeaderTemplate: [{ type: i0.ContentChild, args: [i0.forwardRef(() => DropdownGroupHeaderTemplateDirective), { ...{
629
683
  read: TemplateRef
630
- }, 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 }] }] } });
631
685
 
632
686
  /*
633
687
  * Public API Surface of @nanahoshi/mona-ui/dropdown-list