@nanahoshi/mona-ui 0.24.4 → 0.24.6

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 (80) hide show
  1. package/README.md +3 -0
  2. package/fesm2022/nanahoshi-mona-ui-auto-complete.mjs +95 -70
  3. package/fesm2022/nanahoshi-mona-ui-calendar.mjs +196 -137
  4. package/fesm2022/nanahoshi-mona-ui-combo-box.mjs +136 -89
  5. package/fesm2022/nanahoshi-mona-ui-date-input.mjs +164 -3
  6. package/fesm2022/nanahoshi-mona-ui-date-picker.mjs +124 -140
  7. package/fesm2022/nanahoshi-mona-ui-datetime-picker.mjs +205 -202
  8. package/fesm2022/nanahoshi-mona-ui-dropdown-list.mjs +108 -56
  9. package/fesm2022/nanahoshi-mona-ui-dropdowns.mjs +68 -59
  10. package/fesm2022/nanahoshi-mona-ui-editor.mjs +3 -3
  11. package/fesm2022/nanahoshi-mona-ui-filter.mjs +1 -1
  12. package/fesm2022/{nanahoshi-mona-ui-grid-grid-footer-row.component-DLOPRuFv.mjs → nanahoshi-mona-ui-grid-grid-footer-row.component-CD_ODHpU.mjs} +2 -2
  13. package/fesm2022/{nanahoshi-mona-ui-grid-grid-list.component-Dw5U9H0a.mjs → nanahoshi-mona-ui-grid-grid-list.component-0jN7I1jo.mjs} +4 -4
  14. package/fesm2022/{nanahoshi-mona-ui-grid-grid-row.component-D1kyAzD8.mjs → nanahoshi-mona-ui-grid-grid-row.component-BI_iE7pl.mjs} +3 -3
  15. package/fesm2022/{nanahoshi-mona-ui-grid-grid-virtual-list.component-ECK1_smx.mjs → nanahoshi-mona-ui-grid-grid-virtual-list.component-Sa1aAtJ-.mjs} +4 -4
  16. package/fesm2022/{nanahoshi-mona-ui-grid-nanahoshi-mona-ui-grid-D4lUDbfx.mjs → nanahoshi-mona-ui-grid-nanahoshi-mona-ui-grid-BvUM9nPt.mjs} +8 -8
  17. package/fesm2022/nanahoshi-mona-ui-grid.mjs +1 -1
  18. package/fesm2022/nanahoshi-mona-ui-i18n-icu.mjs +2 -1
  19. package/fesm2022/nanahoshi-mona-ui-internal-indicator-icon.mjs +2 -2
  20. package/fesm2022/nanahoshi-mona-ui-internal.mjs +4 -2
  21. package/fesm2022/nanahoshi-mona-ui-locales-ar-sa.mjs +2 -1
  22. package/fesm2022/nanahoshi-mona-ui-locales-de-de.mjs +4 -1
  23. package/fesm2022/nanahoshi-mona-ui-locales-es-es.mjs +4 -1
  24. package/fesm2022/nanahoshi-mona-ui-locales-fr-fr.mjs +4 -1
  25. package/fesm2022/nanahoshi-mona-ui-locales-id-id.mjs +2 -1
  26. package/fesm2022/nanahoshi-mona-ui-locales-it-it.mjs +2 -1
  27. package/fesm2022/nanahoshi-mona-ui-locales-ja-jp.mjs +2 -1
  28. package/fesm2022/nanahoshi-mona-ui-locales-ko-kr.mjs +2 -1
  29. package/fesm2022/nanahoshi-mona-ui-locales-pt-br.mjs +2 -1
  30. package/fesm2022/nanahoshi-mona-ui-locales-ru-ru.mjs +2 -1
  31. package/fesm2022/nanahoshi-mona-ui-locales-tr-tr.mjs +2 -1
  32. package/fesm2022/nanahoshi-mona-ui-locales-zh-cn.mjs +2 -1
  33. package/fesm2022/nanahoshi-mona-ui-locales-zh-tw.mjs +2 -1
  34. package/fesm2022/nanahoshi-mona-ui-multi-select.mjs +118 -66
  35. package/fesm2022/nanahoshi-mona-ui-numeric-text-box.mjs +195 -122
  36. package/fesm2022/nanahoshi-mona-ui-pager.mjs +1 -1
  37. package/fesm2022/nanahoshi-mona-ui-time-picker.mjs +149 -167
  38. package/fesm2022/nanahoshi-mona-ui-time-selector.mjs +182 -137
  39. package/i18n/catalogs/en-US.messages.json +2 -1
  40. package/locales/ar-sa/ar-sa.messages.json +2 -1
  41. package/locales/de-de/de-de.messages.json +2 -1
  42. package/locales/es-es/es-es.messages.json +2 -1
  43. package/locales/fr-fr/fr-fr.messages.json +2 -1
  44. package/locales/id-id/id-id.messages.json +2 -1
  45. package/locales/it-it/it-it.messages.json +2 -1
  46. package/locales/ja-jp/ja-jp.messages.json +2 -1
  47. package/locales/ko-kr/ko-kr.messages.json +2 -1
  48. package/locales/pt-br/pt-br.messages.json +2 -1
  49. package/locales/ru-ru/ru-ru.messages.json +2 -1
  50. package/locales/tr-tr/tr-tr.messages.json +2 -1
  51. package/locales/zh-cn/zh-cn.messages.json +2 -1
  52. package/locales/zh-tw/zh-tw.messages.json +2 -1
  53. package/package.json +2 -2
  54. package/types/nanahoshi-mona-ui-auto-complete.d.ts +34 -20
  55. package/types/nanahoshi-mona-ui-calendar.d.ts +30 -11
  56. package/types/nanahoshi-mona-ui-combo-box.d.ts +42 -23
  57. package/types/nanahoshi-mona-ui-date-input.d.ts +74 -3
  58. package/types/nanahoshi-mona-ui-date-picker.d.ts +61 -33
  59. package/types/nanahoshi-mona-ui-datetime-picker.d.ts +79 -38
  60. package/types/nanahoshi-mona-ui-dropdown-list.d.ts +29 -15
  61. package/types/nanahoshi-mona-ui-dropdowns.d.ts +30 -19
  62. package/types/nanahoshi-mona-ui-i18n.d.ts +1 -0
  63. package/types/nanahoshi-mona-ui-internal.d.ts +3 -1
  64. package/types/nanahoshi-mona-ui-locales-ar-sa.d.ts +1 -0
  65. package/types/nanahoshi-mona-ui-locales-de-de.d.ts +1 -0
  66. package/types/nanahoshi-mona-ui-locales-es-es.d.ts +1 -0
  67. package/types/nanahoshi-mona-ui-locales-fr-fr.d.ts +1 -0
  68. package/types/nanahoshi-mona-ui-locales-id-id.d.ts +1 -0
  69. package/types/nanahoshi-mona-ui-locales-it-it.d.ts +1 -0
  70. package/types/nanahoshi-mona-ui-locales-ja-jp.d.ts +1 -0
  71. package/types/nanahoshi-mona-ui-locales-ko-kr.d.ts +1 -0
  72. package/types/nanahoshi-mona-ui-locales-pt-br.d.ts +1 -0
  73. package/types/nanahoshi-mona-ui-locales-ru-ru.d.ts +1 -0
  74. package/types/nanahoshi-mona-ui-locales-tr-tr.d.ts +1 -0
  75. package/types/nanahoshi-mona-ui-locales-zh-cn.d.ts +1 -0
  76. package/types/nanahoshi-mona-ui-locales-zh-tw.d.ts +1 -0
  77. package/types/nanahoshi-mona-ui-multi-select.d.ts +45 -21
  78. package/types/nanahoshi-mona-ui-numeric-text-box.d.ts +57 -16
  79. package/types/nanahoshi-mona-ui-time-picker.d.ts +72 -42
  80. package/types/nanahoshi-mona-ui-time-selector.d.ts +78 -46
package/README.md CHANGED
@@ -21,6 +21,9 @@ A modern, high-performance, accessible UI component library built for Angular an
21
21
  - [Buttons](docs/button.md)
22
22
  - [Popups](docs/popup.md)
23
23
  - [Text Boxes](docs/text-box.md)
24
+ - [Dropdowns](docs/dropdowns.md)
25
+ - [Numeric Text Boxes](docs/numeric-text-box.md)
26
+ - [Dates and Times](docs/dates.md)
24
27
  - [Patch Stores & Merge Utilities](docs/patch-store.md)
25
28
  - [Component Migration Inventory](docs/internal/i18n-rtl-migration-inventory.md)
26
29
 
@@ -1,15 +1,13 @@
1
1
  import { NgTemplateOutlet } from '@angular/common';
2
2
  import * as i0 from '@angular/core';
3
- import { inject, DestroyRef, ElementRef, computed, linkedSignal, contentChild, TemplateRef, viewChild, input, output, model, afterNextRender, effect, untracked, forwardRef, Component } from '@angular/core';
3
+ import { inject, DestroyRef, ElementRef, computed, linkedSignal, contentChild, TemplateRef, viewChild, input, output, booleanAttribute, model, afterNextRender, effect, untracked, forwardRef, Component } from '@angular/core';
4
4
  import { takeUntilDestroyed } from '@angular/core/rxjs-interop';
5
- import * as i2 from '@angular/forms';
6
- import { FormsModule } from '@angular/forms';
7
5
  import { themeControlSurfaceClasses, createElementControlId, rxTimeout } from '@nanahoshi/mona-ui/internal';
8
6
  import { FilterChangeEvent } from '@nanahoshi/mona-ui/common';
9
7
  import { IndicatorIconComponent } from '@nanahoshi/mona-ui/internal/indicator-icon';
10
8
  import { ListService, ListComponent, ListGroupHeaderTemplateDirective, ListFooterTemplateDirective, ListHeaderTemplateDirective, ListNoDataTemplateDirective, ListItemTemplateDirective } from '@nanahoshi/mona-ui/internal/list';
11
9
  import * as i1 from '@nanahoshi/mona-ui/dropdowns';
12
- import { DropdownService, DropdownFooterTemplateDirective, DropdownGroupHeaderTemplateDirective, DropdownHeaderTemplateDirective, DropdownItemTemplateDirective, dropdownPopupThemeVariants, DropdownNoDataTemplateDirective, DropdownPrefixTemplateDirective, DropdownSuffixTemplateDirective, DropdownLiveRegionDirective, DropdownDataInputToken, DROPDOWN_POPUP_INPUT_TOKEN, DropdownDataHandlerDirective, DropdownListPopupHandlerDirective } from '@nanahoshi/mona-ui/dropdowns';
10
+ import { DropdownService, DropdownFooterTemplateDirective, DropdownGroupHeaderTemplateDirective, DropdownHeaderTemplateDirective, DropdownItemTemplateDirective, dropdownPopupThemeVariants, DropdownNoDataTemplateDirective, DropdownPrefixTemplateDirective, DropdownSuffixTemplateDirective, DROPDOWN_DATA_INPUT_TOKEN, DROPDOWN_POPUP_INPUT_TOKEN, DropdownDataHandlerDirective, DropdownListPopupHandlerDirective, DropdownLiveRegionDirective } from '@nanahoshi/mona-ui/dropdowns';
13
11
  import { TextBoxDirective } from '@nanahoshi/mona-ui/text-box';
14
12
  import { MonaI18nService } from '@nanahoshi/mona-ui/i18n';
15
13
  import { Subject, filter, debounceTime, identity, take, tap } from 'rxjs';
@@ -143,14 +141,17 @@ class AutoCompleteComponent {
143
141
  return twMerge(variantClass, userClass);
144
142
  }, /* @ts-ignore */
145
143
  ...(ngDevMode ? [{ debugName: "baseClass" }] : /* istanbul ignore next */ []));
146
- this.effectiveAriaLabel = computed(() => this.ariaLabel() || (this.ariaLabelledBy() ? "" : this.placeholder()), /* @ts-ignore */
147
- ...(ngDevMode ? [{ debugName: "effectiveAriaLabel" }] : /* istanbul ignore next */ []));
144
+ this.clearButtonVisible = computed(() => this.showClearButton() &&
145
+ !!this.autoCompleteValue() &&
146
+ !this.loading() &&
147
+ !this.disabled() &&
148
+ !this.readonly(), /* @ts-ignore */
149
+ ...(ngDevMode ? [{ debugName: "clearButtonVisible" }] : /* istanbul ignore next */ []));
148
150
  this.expanded = computed(() => this.#popupRef() !== null, /* @ts-ignore */
149
151
  ...(ngDevMode ? [{ debugName: "expanded" }] : /* istanbul ignore next */ []));
150
152
  this.footerTemplate = contentChild(DropdownFooterTemplateDirective, { ...(ngDevMode ? { debugName: "footerTemplate" } : /* istanbul ignore next */ {}), read: TemplateRef });
151
153
  this.groupHeaderTemplate = contentChild(DropdownGroupHeaderTemplateDirective, { ...(ngDevMode ? { debugName: "groupHeaderTemplate" } : /* istanbul ignore next */ {}), read: TemplateRef });
152
154
  this.headerTemplate = contentChild(DropdownHeaderTemplateDirective, { ...(ngDevMode ? { debugName: "headerTemplate" } : /* istanbul ignore next */ {}), read: TemplateRef });
153
- this.id = createElementControlId();
154
155
  this.inputClass = computed(() => {
155
156
  const rounded = this.rounded();
156
157
  return autoCompleteTextInputThemeVariants({ rounded });
@@ -167,7 +168,9 @@ class AutoCompleteComponent {
167
168
  const size = this.size();
168
169
  const userClass = this.popupClass();
169
170
  const variantClass = dropdownPopupThemeVariants({ rounded, size });
170
- return twMerge(variantClass, userClass);
171
+ // With a popupHeight, the overlay sets the limit; the default max-h-64 would cut a taller popup short.
172
+ const heightClass = this.popupHeight() ? "max-h-none" : "";
173
+ return twMerge(variantClass, heightClass, userClass);
171
174
  }, /* @ts-ignore */
172
175
  ...(ngDevMode ? [{ debugName: "listPopupClass" }] : /* istanbul ignore next */ []));
173
176
  this.messages = this.#i18n.componentMessages("autoComplete", AUTO_COMPLETE_DEFAULT_MESSAGES);
@@ -188,8 +191,9 @@ class AutoCompleteComponent {
188
191
  */
189
192
  this.ariaDescribedBy = input("", { ...(ngDevMode ? { debugName: "ariaDescribedBy" } : /* istanbul ignore next */ {}), alias: "aria-describedby" });
190
193
  /**
191
- * @description Accessible name for the input. Describe what the autocomplete represents.
192
- * Falls back to {@link placeholder} when neither this nor {@link ariaLabelledBy} is set.
194
+ * @description Accessible name for the input. Describe what the autocomplete represents. Prefer a visible label,
195
+ * linked through {@link inputId} or {@link ariaLabelledBy}; without any of them, browsers fall back to the
196
+ * {@link placeholder}.
193
197
  * @default ""
194
198
  */
195
199
  this.ariaLabel = input("", { ...(ngDevMode ? { debugName: "ariaLabel" } : /* istanbul ignore next */ {}), alias: "aria-label" });
@@ -201,6 +205,7 @@ class AutoCompleteComponent {
201
205
  /**
202
206
  * @description Emits when the popup is about to close. This event is preventable.
203
207
  */
208
+ // eslint-disable-next-line @angular-eslint/no-output-native -- renaming the output would break existing (close) bindings
204
209
  this.close = output();
205
210
  /**
206
211
  * @description Emits after the popup is closed.
@@ -216,21 +221,25 @@ class AutoCompleteComponent {
216
221
  * @description Renders the component with reduced visual emphasis and removes pointer interaction.
217
222
  * @default false
218
223
  */
219
- this.disabled = model(false, /* @ts-ignore */
220
- ...(ngDevMode ? [{ debugName: "disabled" }] : /* istanbul ignore next */ []));
224
+ this.disabled = input(false, { ...(ngDevMode ? { debugName: "disabled" } : /* istanbul ignore next */ {}), transform: booleanAttribute });
221
225
  /**
222
226
  * @description Defines whether the first matching item should be highlighted while typing.
223
227
  * @default true
224
228
  */
225
- this.highlightFirst = input(true, /* @ts-ignore */
226
- ...(ngDevMode ? [{ debugName: "highlightFirst" }] : /* istanbul ignore next */ []));
229
+ this.highlightFirst = input(true, { ...(ngDevMode ? { debugName: "highlightFirst" } : /* istanbul ignore next */ {}), transform: booleanAttribute });
230
+ /**
231
+ * @description Id of the inner `<input>` element. Point a `<label for>` or `<mona-label for>` at it to label the
232
+ * autocomplete. A unique id is generated when it isn't set.
233
+ * @default generated
234
+ */
235
+ this.inputId = input(createElementControlId(), /* @ts-ignore */
236
+ ...(ngDevMode ? [{ debugName: "inputId" }] : /* istanbul ignore next */ []));
227
237
  /**
228
238
  * @description Marks the autocomplete as invalid. When bound to a signal form field via `[formField]`,
229
239
  * this is written by the `FormField` directive.
230
240
  * @default false
231
241
  */
232
- this.invalid = input(false, /* @ts-ignore */
233
- ...(ngDevMode ? [{ debugName: "invalid" }] : /* istanbul ignore next */ []));
242
+ this.invalid = input(false, { ...(ngDevMode ? { debugName: "invalid" } : /* istanbul ignore next */ {}), transform: booleanAttribute });
234
243
  /**
235
244
  * @description Predicate or field name used to determine whether an individual item is disabled.
236
245
  * @default undefined
@@ -238,11 +247,11 @@ class AutoCompleteComponent {
238
247
  this.itemDisabled = input(/* @ts-ignore */
239
248
  ...(ngDevMode ? [undefined, { debugName: "itemDisabled" }] : /* istanbul ignore next */ []));
240
249
  /**
241
- * @description Displays a loading indicator and prevents interaction while an operation is in progress.
250
+ * @description Shows a loading indicator, in place of the clear button, and marks the field busy. It doesn't
251
+ * block interaction: the field stays usable while data loads.
242
252
  * @default false
243
253
  */
244
- this.loading = input(false, /* @ts-ignore */
245
- ...(ngDevMode ? [{ debugName: "loading" }] : /* istanbul ignore next */ []));
254
+ this.loading = input(false, { ...(ngDevMode ? { debugName: "loading" } : /* istanbul ignore next */ {}), transform: booleanAttribute });
246
255
  /**
247
256
  * @description Emits when the popup is about to open. This event is preventable.
248
257
  */
@@ -264,7 +273,8 @@ class AutoCompleteComponent {
264
273
  this.popupClass = input("", /* @ts-ignore */
265
274
  ...(ngDevMode ? [{ debugName: "popupClass" }] : /* istanbul ignore next */ []));
266
275
  /**
267
- * @description Height of the popup element.
276
+ * @description Maximum height of the popup, in pixels or as a CSS length. Shorter lists shrink to fit. When
277
+ * unset, the popup is at most 200 pixels tall.
268
278
  * @default null
269
279
  */
270
280
  this.popupHeight = input(null, /* @ts-ignore */
@@ -279,14 +289,12 @@ class AutoCompleteComponent {
279
289
  * @description Prevents value changes while preserving the component's visual state.
280
290
  * @default false
281
291
  */
282
- this.readonly = input(false, /* @ts-ignore */
283
- ...(ngDevMode ? [{ debugName: "readonly" }] : /* istanbul ignore next */ []));
292
+ this.readonly = input(false, { ...(ngDevMode ? { debugName: "readonly" } : /* istanbul ignore next */ {}), transform: booleanAttribute });
284
293
  /**
285
294
  * @description Marks the field as required for form validation.
286
295
  * @default false
287
296
  */
288
- this.required = input(false, /* @ts-ignore */
289
- ...(ngDevMode ? [{ debugName: "required" }] : /* istanbul ignore next */ []));
297
+ this.required = input(false, { ...(ngDevMode ? { debugName: "required" } : /* istanbul ignore next */ {}), transform: booleanAttribute });
290
298
  /**
291
299
  * @description Border-radius preset applied to the component.
292
300
  * @default "medium"
@@ -294,11 +302,11 @@ class AutoCompleteComponent {
294
302
  this.rounded = input("medium", /* @ts-ignore */
295
303
  ...(ngDevMode ? [{ debugName: "rounded" }] : /* istanbul ignore next */ []));
296
304
  /**
297
- * @description Displays a button that clears the current value when clicked.
305
+ * @description Displays a button that clears the current value when clicked. Unlike the other dropdowns, this
306
+ * defaults to `true`.
298
307
  * @default true
299
308
  */
300
- this.showClearButton = input(true, /* @ts-ignore */
301
- ...(ngDevMode ? [{ debugName: "showClearButton" }] : /* istanbul ignore next */ []));
309
+ this.showClearButton = input(true, { ...(ngDevMode ? { debugName: "showClearButton" } : /* istanbul ignore next */ {}), transform: booleanAttribute });
302
310
  /**
303
311
  * @description Size preset controlling the component's dimensions.
304
312
  * @default "medium"
@@ -313,8 +321,8 @@ class AutoCompleteComponent {
313
321
  this.textField = input(null, /* @ts-ignore */
314
322
  ...(ngDevMode ? [{ debugName: "textField" }] : /* istanbul ignore next */ []));
315
323
  /**
316
- * @description Emitted when the autocomplete is interacted with on blur, selection, clear, or committed input.
317
- * The `FormField` directive listens to this to mark the field as touched.
324
+ * @description Emitted when focus leaves the autocomplete. Moving between its input, clear button and popup
325
+ * doesn't count. The `FormField` directive listens to this to mark the field as touched.
318
326
  */
319
327
  this.touch = output();
320
328
  /**
@@ -322,8 +330,7 @@ class AutoCompleteComponent {
322
330
  * this is written by the `FormField` directive.
323
331
  * @default false
324
332
  */
325
- this.touched = input(false, /* @ts-ignore */
326
- ...(ngDevMode ? [{ debugName: "touched" }] : /* istanbul ignore next */ []));
333
+ this.touched = input(false, { ...(ngDevMode ? { debugName: "touched" } : /* istanbul ignore next */ {}), transform: booleanAttribute });
327
334
  /**
328
335
  * @description Additional CSS classes merged onto the host element via `tailwind-merge`.
329
336
  * @default ""
@@ -354,22 +361,39 @@ class AutoCompleteComponent {
354
361
  untracked(() => this.#dropdownService.popupTemplate.set(popupTemplate));
355
362
  });
356
363
  }
357
- focus() {
364
+ /**
365
+ * @description Moves focus to the inner input. The caret goes to the end of the text.
366
+ * @param options Passed to `HTMLElement.focus()`, for example `{ preventScroll: true }`.
367
+ */
368
+ focus(options) {
358
369
  const input = this.#hostElementRef.nativeElement.querySelector("input");
359
370
  if (input) {
360
- input.focus();
371
+ input.focus(options);
361
372
  input.setSelectionRange(input.value.length, input.value.length);
362
373
  }
363
374
  }
364
- onInputBlur(event) {
365
- const popupElement = this.#dropdownService.popupRef()?.overlayRef.overlayElement;
366
- if (popupElement && event?.relatedTarget instanceof Node && popupElement.contains(event.relatedTarget)) {
375
+ onFocusOut(event) {
376
+ // Removing a focused dropdown from the page fires focusout after it is destroyed.
377
+ if (this.#destroyRef.destroyed) {
367
378
  return;
368
379
  }
369
- this.touch.emit();
380
+ const nextTarget = event.relatedTarget;
381
+ if (nextTarget instanceof Node) {
382
+ const popupElement = this.#popupRef()?.overlayRef.overlayElement;
383
+ if (this.#hostElementRef.nativeElement.contains(nextTarget) || popupElement?.contains(nextTarget)) {
384
+ return;
385
+ }
386
+ }
370
387
  if (this.value() !== this.autoCompleteValue() && !this.#popupRef()) {
371
388
  this.updateValue(this.autoCompleteValue());
372
389
  }
390
+ this.touch.emit();
391
+ }
392
+ onInput(text) {
393
+ // Keep the signal in step with the input on every keystroke, so that writing the same text back still
394
+ // reaches the DOM through the [value] binding.
395
+ this.autoCompleteValue.set(text);
396
+ this.autoCompleteValue$.next(text);
373
397
  }
374
398
  onItemSelect(event) {
375
399
  const itemText = this.#listService.getItemText(event.item);
@@ -385,7 +409,9 @@ class AutoCompleteComponent {
385
409
  }
386
410
  }
387
411
  onValueClear(event) {
388
- if (this.readonly() || (event instanceof KeyboardEvent && event.key !== "Enter" && event.key !== " ")) {
412
+ if (this.disabled() ||
413
+ this.readonly() ||
414
+ (event instanceof KeyboardEvent && event.key !== "Enter" && event.key !== " ")) {
389
415
  return;
390
416
  }
391
417
  event.stopImmediatePropagation();
@@ -441,10 +467,15 @@ class AutoCompleteComponent {
441
467
  }
442
468
  }
443
469
  if (!value) {
444
- this.#popupRef()
445
- ?.closed.pipe(take(1))
446
- .subscribe(() => this.clear(false));
447
- this.closePopup();
470
+ const popupRef = this.#popupRef();
471
+ if (popupRef) {
472
+ popupRef.closed.pipe(take(1)).subscribe(() => this.clear(false));
473
+ this.closePopup();
474
+ }
475
+ else {
476
+ // Deleting the text with the popup closed still has to reach the value on blur.
477
+ this.clear(false);
478
+ }
448
479
  return;
449
480
  }
450
481
  if (!this.#popupRef()) {
@@ -482,16 +513,15 @@ class AutoCompleteComponent {
482
513
  }
483
514
  setEscapeKeySubscription() {
484
515
  this.#dropdownService.beforeKeydown$
485
- .pipe(filter(e => e.originalEvent?.key === "Escape"), takeUntilDestroyed(this.#destroyRef), tap(e => {
486
- e.preventDefault();
487
- e.originalEvent?.stopImmediatePropagation();
488
- }))
489
- .subscribe(() => {
516
+ .pipe(filter(e => e.originalEvent?.key === "Escape"), takeUntilDestroyed(this.#destroyRef), tap(e => e.preventDefault()))
517
+ .subscribe(event => {
490
518
  if (this.#popupRef()) {
491
519
  this.closePopup();
492
520
  return;
493
521
  }
494
522
  if (this.autoCompleteValue()) {
523
+ // This Escape was used to clear the text; a dialog or window around the field waits for the next.
524
+ event.originalEvent?.stopPropagation();
495
525
  this.clear(false);
496
526
  }
497
527
  });
@@ -514,22 +544,18 @@ class AutoCompleteComponent {
514
544
  this.setPopupCloseSubscriptions();
515
545
  this.setSpaceKeySubscription();
516
546
  }
517
- updateValue(value, notify = true) {
518
- const oldValue = this.value();
519
- if (notify && oldValue !== value) {
520
- const notifyValue = value === "" || value == null ? null : value;
521
- this.value.set(notifyValue);
522
- this.touch.emit();
523
- return;
547
+ updateValue(value) {
548
+ const nextValue = value || null;
549
+ if (this.value() !== nextValue) {
550
+ this.value.set(nextValue);
524
551
  }
525
- this.value.set(value);
526
552
  }
527
553
  static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "22.0.6", ngImport: i0, type: AutoCompleteComponent, deps: [], target: i0.ɵɵFactoryTarget.Component }); }
528
- static { this.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "22.0.6", type: AutoCompleteComponent, isStandalone: true, selector: "mona-auto-complete", 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 }, highlightFirst: { classPropertyName: "highlightFirst", publicName: "highlightFirst", 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 } }, outputs: { close: "close", closed: "closed", disabled: "disabledChange", open: "open", opened: "opened", touch: "touch", value: "valueChange" }, host: { properties: { "attr.aria-disabled": "disabled() ? true : undefined", "attr.aria-haspopup": "'listbox'", "attr.aria-invalid": "invalidState() ? true : undefined", "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.tabindex": "-1", "class": "baseClass()" } }, providers: [
554
+ static { this.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "22.0.6", type: AutoCompleteComponent, isStandalone: true, selector: "mona-auto-complete", 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 }, highlightFirst: { classPropertyName: "highlightFirst", publicName: "highlightFirst", isSignal: true, isRequired: false, transformFunction: null }, inputId: { classPropertyName: "inputId", publicName: "inputId", 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 } }, outputs: { close: "close", closed: "closed", open: "open", opened: "opened", touch: "touch", value: "valueChange" }, host: { listeners: { "focusout": "onFocusOut($event)" }, properties: { "attr.aria-describedby": "null", "attr.aria-label": "null", "attr.aria-labelledby": "null", "attr.data-disabled": "disabled() || null", "attr.data-invalid": "invalidState() || null", "attr.data-readonly": "readonly() || null", "attr.tabindex": "-1", "class": "baseClass()" } }, providers: [
529
555
  ListService,
530
556
  DropdownService,
531
557
  {
532
- provide: DropdownDataInputToken,
558
+ provide: DROPDOWN_DATA_INPUT_TOKEN,
533
559
  useExisting: forwardRef(() => AutoCompleteComponent),
534
560
  multi: false
535
561
  },
@@ -538,15 +564,15 @@ class AutoCompleteComponent {
538
564
  useExisting: forwardRef(() => AutoCompleteComponent),
539
565
  multi: false
540
566
  }
541
- ], 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: "suffixTemplate", first: true, predicate: DropdownSuffixTemplateDirective, 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<input\n monaTextBox\n role=\"combobox\"\n [class]=\"inputClass()\"\n [disabled]=\"disabled()\"\n [id]=\"id\"\n [placeholder]=\"placeholder()\"\n [readonly]=\"readonly()\"\n [rounded]=\"rounded()\"\n [size]=\"size()\"\n [ngModel]=\"autoCompleteValue()\"\n [attr.aria-activedescendant]=\"activeDescendant()\"\n [attr.aria-autocomplete]=\"'list'\"\n [attr.aria-busy]=\"loading()\"\n [attr.aria-controls]=\"listId\"\n [attr.aria-describedby]=\"ariaDescribedBy() || undefined\"\n [attr.aria-expanded]=\"expanded()\"\n [attr.aria-haspopup]=\"'listbox'\"\n [attr.aria-invalid]=\"invalidState() || undefined\"\n [attr.aria-label]=\"effectiveAriaLabel() || undefined\"\n [attr.aria-labelledby]=\"ariaLabelledBy() || undefined\"\n (ngModelChange)=\"autoCompleteValue$.next($event)\"\n (blur)=\"onInputBlur($event)\" />\n\n@if (showClearButton() && autoCompleteValue() && !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@if (suffixTemplate()) {\n <span [class]=\"affixClass()\">\n <ng-container [ngTemplateOutlet]=\"suffixTemplate()\"></ng-container>\n </span>\n}\n\n<span monaDropdownLiveRegion></span>\n\n<ng-template #popupTemplate>\n <div [class]=\"listPopupClass()\" (pointerdown)=\"onPopupPointerDown($event)\">\n <mona-list (itemSelect)=\"onItemSelect($event)\" [focusOnMount]=\"false\" [size]=\"size()\" [listId]=\"listId\">\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: TextBoxDirective, selector: "input[monaTextBox]", inputs: ["invalid", "rounded", "size", "touched", "class"] }, { kind: "ngmodule", type: FormsModule }, { kind: "directive", type: i2.DefaultValueAccessor, selector: "input:not([type=checkbox]):not([ngNoCva])[formControlName],textarea:not([ngNoCva])[formControlName],input:not([type=checkbox]):not([ngNoCva])[formControl],textarea:not([ngNoCva])[formControl],input:not([type=checkbox]):not([ngNoCva])[ngModel],textarea:not([ngNoCva])[ngModel],[ngDefaultControl]" }, { kind: "directive", type: i2.NgControlStatus, selector: "[formControlName],[ngModel],[formControl]" }, { kind: "directive", type: i2.NgModel, selector: "[ngModel]:not([formControlName]):not([formControl])", inputs: ["name", "disabled", "ngModel", "ngModelOptions"], outputs: ["ngModelChange"], exportAs: ["ngModel"] }, { 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: 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: ListItemTemplateDirective, selector: "ng-template[monaListItemTemplate]" }, { kind: "directive", type: DropdownLiveRegionDirective, selector: "span[monaDropdownLiveRegion]" }, { kind: "component", type: IndicatorIconComponent, selector: "mona-indicator-icon", inputs: ["icon", "interactive", "label", "preset", "size", "class"], outputs: ["activate"] }] }); }
567
+ ], 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: "suffixTemplate", first: true, predicate: DropdownSuffixTemplateDirective, 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<input\n monaTextBox\n role=\"combobox\"\n [class]=\"inputClass()\"\n [disabled]=\"disabled()\"\n [id]=\"inputId()\"\n [placeholder]=\"placeholder()\"\n [readonly]=\"readonly()\"\n [required]=\"required()\"\n [rounded]=\"rounded()\"\n [size]=\"size()\"\n [value]=\"autoCompleteValue()\"\n [attr.aria-activedescendant]=\"activeDescendant()\"\n [attr.aria-autocomplete]=\"'list'\"\n [attr.aria-busy]=\"loading()\"\n [attr.aria-controls]=\"listId\"\n [attr.aria-describedby]=\"ariaDescribedBy() || undefined\"\n [attr.aria-expanded]=\"expanded()\"\n [attr.aria-haspopup]=\"'listbox'\"\n [attr.aria-invalid]=\"invalidState() || undefined\"\n [attr.aria-label]=\"ariaLabel() || undefined\"\n [attr.aria-labelledby]=\"ariaLabelledBy() || undefined\"\n (input)=\"onInput(textInput.value)\"\n #textInput />\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@if (suffixTemplate()) {\n <span [class]=\"affixClass()\">\n <ng-container [ngTemplateOutlet]=\"suffixTemplate()\"></ng-container>\n </span>\n}\n\n<ng-template #popupTemplate>\n <div [class]=\"listPopupClass()\" (pointerdown)=\"onPopupPointerDown($event)\">\n <mona-list (itemSelect)=\"onItemSelect($event)\" [focusOnMount]=\"false\" [size]=\"size()\" [listId]=\"listId\">\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: TextBoxDirective, selector: "input[monaTextBox]", inputs: ["invalid", "rounded", "size", "touched", "class"] }, { 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: 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: ListItemTemplateDirective, selector: "ng-template[monaListItemTemplate]" }, { kind: "component", type: IndicatorIconComponent, selector: "mona-indicator-icon", inputs: ["icon", "interactive", "label", "preset", "size", "class"], outputs: ["activate"] }] }); }
542
568
  }
543
569
  i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "22.0.6", ngImport: i0, type: AutoCompleteComponent, decorators: [{
544
570
  type: Component,
545
- args: [{ selector: "mona-auto-complete", hostDirectives: [DropdownDataHandlerDirective, DropdownListPopupHandlerDirective], providers: [
571
+ args: [{ selector: "mona-auto-complete", hostDirectives: [DropdownDataHandlerDirective, DropdownListPopupHandlerDirective, DropdownLiveRegionDirective], providers: [
546
572
  ListService,
547
573
  DropdownService,
548
574
  {
549
- provide: DropdownDataInputToken,
575
+ provide: DROPDOWN_DATA_INPUT_TOKEN,
550
576
  useExisting: forwardRef(() => AutoCompleteComponent),
551
577
  multi: false
552
578
  },
@@ -557,7 +583,6 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "22.0.6", ngImpor
557
583
  }
558
584
  ], imports: [
559
585
  TextBoxDirective,
560
- FormsModule,
561
586
  NgTemplateOutlet,
562
587
  ListComponent,
563
588
  ListGroupHeaderTemplateDirective,
@@ -565,23 +590,23 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "22.0.6", ngImpor
565
590
  ListHeaderTemplateDirective,
566
591
  ListNoDataTemplateDirective,
567
592
  ListItemTemplateDirective,
568
- DropdownLiveRegionDirective,
569
593
  IndicatorIconComponent
570
594
  ], host: {
571
- "[attr.aria-disabled]": "disabled() ? true : undefined",
572
- "[attr.aria-haspopup]": "'listbox'",
573
- "[attr.aria-invalid]": "invalidState() ? true : undefined",
574
- "[attr.aria-readonly]": "readonly() ? true : undefined",
575
- "[attr.aria-required]": "required() ? true : undefined",
595
+ // The host has no role: the inner input is the combobox and carries the name, description and state. A static
596
+ // aria-* attribute written on <mona-auto-complete> would otherwise stay on the host as well.
597
+ "[attr.aria-describedby]": "null",
598
+ "[attr.aria-label]": "null",
599
+ "[attr.aria-labelledby]": "null",
576
600
  "[attr.data-disabled]": "disabled() || null",
577
601
  "[attr.data-invalid]": "invalidState() || null",
578
602
  "[attr.data-readonly]": "readonly() || null",
579
603
  "[attr.tabindex]": "-1",
580
- "[class]": "baseClass()"
581
- }, template: "@if (prefixTemplate()) {\n <span [class]=\"affixClass()\">\n <ng-container [ngTemplateOutlet]=\"prefixTemplate()\"></ng-container>\n </span>\n}\n\n<input\n monaTextBox\n role=\"combobox\"\n [class]=\"inputClass()\"\n [disabled]=\"disabled()\"\n [id]=\"id\"\n [placeholder]=\"placeholder()\"\n [readonly]=\"readonly()\"\n [rounded]=\"rounded()\"\n [size]=\"size()\"\n [ngModel]=\"autoCompleteValue()\"\n [attr.aria-activedescendant]=\"activeDescendant()\"\n [attr.aria-autocomplete]=\"'list'\"\n [attr.aria-busy]=\"loading()\"\n [attr.aria-controls]=\"listId\"\n [attr.aria-describedby]=\"ariaDescribedBy() || undefined\"\n [attr.aria-expanded]=\"expanded()\"\n [attr.aria-haspopup]=\"'listbox'\"\n [attr.aria-invalid]=\"invalidState() || undefined\"\n [attr.aria-label]=\"effectiveAriaLabel() || undefined\"\n [attr.aria-labelledby]=\"ariaLabelledBy() || undefined\"\n (ngModelChange)=\"autoCompleteValue$.next($event)\"\n (blur)=\"onInputBlur($event)\" />\n\n@if (showClearButton() && autoCompleteValue() && !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@if (suffixTemplate()) {\n <span [class]=\"affixClass()\">\n <ng-container [ngTemplateOutlet]=\"suffixTemplate()\"></ng-container>\n </span>\n}\n\n<span monaDropdownLiveRegion></span>\n\n<ng-template #popupTemplate>\n <div [class]=\"listPopupClass()\" (pointerdown)=\"onPopupPointerDown($event)\">\n <mona-list (itemSelect)=\"onItemSelect($event)\" [focusOnMount]=\"false\" [size]=\"size()\" [listId]=\"listId\">\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" }]
604
+ "[class]": "baseClass()",
605
+ "(focusout)": "onFocusOut($event)"
606
+ }, template: "@if (prefixTemplate()) {\n <span [class]=\"affixClass()\">\n <ng-container [ngTemplateOutlet]=\"prefixTemplate()\"></ng-container>\n </span>\n}\n\n<input\n monaTextBox\n role=\"combobox\"\n [class]=\"inputClass()\"\n [disabled]=\"disabled()\"\n [id]=\"inputId()\"\n [placeholder]=\"placeholder()\"\n [readonly]=\"readonly()\"\n [required]=\"required()\"\n [rounded]=\"rounded()\"\n [size]=\"size()\"\n [value]=\"autoCompleteValue()\"\n [attr.aria-activedescendant]=\"activeDescendant()\"\n [attr.aria-autocomplete]=\"'list'\"\n [attr.aria-busy]=\"loading()\"\n [attr.aria-controls]=\"listId\"\n [attr.aria-describedby]=\"ariaDescribedBy() || undefined\"\n [attr.aria-expanded]=\"expanded()\"\n [attr.aria-haspopup]=\"'listbox'\"\n [attr.aria-invalid]=\"invalidState() || undefined\"\n [attr.aria-label]=\"ariaLabel() || undefined\"\n [attr.aria-labelledby]=\"ariaLabelledBy() || undefined\"\n (input)=\"onInput(textInput.value)\"\n #textInput />\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@if (suffixTemplate()) {\n <span [class]=\"affixClass()\">\n <ng-container [ngTemplateOutlet]=\"suffixTemplate()\"></ng-container>\n </span>\n}\n\n<ng-template #popupTemplate>\n <div [class]=\"listPopupClass()\" (pointerdown)=\"onPopupPointerDown($event)\">\n <mona-list (itemSelect)=\"onItemSelect($event)\" [focusOnMount]=\"false\" [size]=\"size()\" [listId]=\"listId\">\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" }]
582
607
  }], ctorParameters: () => [], propDecorators: { footerTemplate: [{ type: i0.ContentChild, args: [i0.forwardRef(() => DropdownFooterTemplateDirective), { ...{ read: TemplateRef }, isSignal: true }] }], groupHeaderTemplate: [{ type: i0.ContentChild, args: [i0.forwardRef(() => DropdownGroupHeaderTemplateDirective), { ...{
583
608
  read: TemplateRef
584
- }, 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 }] }], suffixTemplate: [{ type: i0.ContentChild, args: [i0.forwardRef(() => DropdownSuffixTemplateDirective), { ...{ 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 }] }, { type: i0.Output, args: ["disabledChange"] }], highlightFirst: [{ type: i0.Input, args: [{ isSignal: true, alias: "highlightFirst", 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 }] }] } });
609
+ }, 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 }] }], suffixTemplate: [{ type: i0.ContentChild, args: [i0.forwardRef(() => DropdownSuffixTemplateDirective), { ...{ 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 }] }], highlightFirst: [{ type: i0.Input, args: [{ isSignal: true, alias: "highlightFirst", required: false }] }], inputId: [{ type: i0.Input, args: [{ isSignal: true, alias: "inputId", 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 }] }] } });
585
610
 
586
611
  /*
587
612
  * Public API Surface of @nanahoshi/mona-ui/auto-complete