@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
@@ -1,22 +1,20 @@
1
1
  import { CdkTrapFocus } from '@angular/cdk/a11y';
2
2
  import { NgTemplateOutlet } from '@angular/common';
3
3
  import * as i0 from '@angular/core';
4
- import { inject, DestroyRef, ElementRef, signal, computed, linkedSignal, contentChild, viewChild, TemplateRef, output, input, model, effect, untracked, afterNextRender, forwardRef, Component } from '@angular/core';
4
+ import { inject, DestroyRef, ElementRef, signal, computed, contentChild, linkedSignal, viewChild, TemplateRef, input, output, booleanAttribute, model, effect, untracked, afterNextRender, forwardRef, Component } from '@angular/core';
5
5
  import { takeUntilDestroyed } from '@angular/core/rxjs-interop';
6
- import { any } from '@mirei/ts-collections';
7
6
  import { LucideCalendar } from '@lucide/angular';
8
7
  import { ButtonDirective } from '@nanahoshi/mona-ui/button';
9
- import { ButtonGroupComponent } from '@nanahoshi/mona-ui/button-group';
10
8
  import { CalendarDecadeCellTemplateDirective, CalendarMonthCellTemplateDirective, CalendarYearCellTemplateDirective, CalendarComponent } from '@nanahoshi/mona-ui/calendar';
11
- import { CalendarService, TimeSelectorService, datePopupThemeVariants, DateInputPrefixTemplateDirective } from '@nanahoshi/mona-ui/date-input';
9
+ import { CalendarService, TimeSelectorService, getLocaleHourFormat, datePopupThemeVariants, DateInputPrefixTemplateDirective, createTypedDateInput } from '@nanahoshi/mona-ui/date-input';
12
10
  import * as i1 from '@nanahoshi/mona-ui/dropdowns';
13
11
  import { DropdownService, DROPDOWN_POPUP_INPUT_TOKEN, DropdownPopupHandlerDirective } from '@nanahoshi/mona-ui/dropdowns';
14
- import { injectComponentDirection, MonaI18nService, gregorianDateTime, getLocaleDateTimeInputFormat, parseGregorianDate } from '@nanahoshi/mona-ui/i18n';
12
+ import { injectComponentDirection, MonaI18nService, getLocaleDateTimeInputFormat } from '@nanahoshi/mona-ui/i18n';
15
13
  import { themeControlSurfaceClasses, createElementControlId } from '@nanahoshi/mona-ui/internal';
16
14
  import { TextBoxComponent, TextBoxSuffixTemplateDirective, TextBoxPrefixTemplateDirective } from '@nanahoshi/mona-ui/text-box';
17
15
  import { TimeSelectorComponent } from '@nanahoshi/mona-ui/time-selector';
18
16
  import { DateTime } from 'luxon';
19
- import { fromEvent, mergeWith } from 'rxjs';
17
+ import { mergeWith } from 'rxjs';
20
18
  import { twMerge } from 'tailwind-merge';
21
19
  import { cva } from 'class-variance-authority';
22
20
 
@@ -107,7 +105,6 @@ class DateTimePickerComponent {
107
105
  #dropdownService;
108
106
  #hostElementRef;
109
107
  #i18n;
110
- #id;
111
108
  #timeSelectorService;
112
109
  constructor() {
113
110
  this.#calendarService = inject(CalendarService);
@@ -116,7 +113,6 @@ class DateTimePickerComponent {
116
113
  this.#dropdownService = inject(DropdownService);
117
114
  this.#hostElementRef = inject(ElementRef);
118
115
  this.#i18n = inject(MonaI18nService);
119
- this.#id = createElementControlId();
120
116
  this.#timeSelectorService = inject(TimeSelectorService);
121
117
  this.activeView = signal("date", /* @ts-ignore */
122
118
  ...(ngDevMode ? [{ debugName: "activeView" }] : /* istanbul ignore next */ []));
@@ -129,28 +125,24 @@ class DateTimePickerComponent {
129
125
  return twMerge(variantClass, userClass);
130
126
  }, /* @ts-ignore */
131
127
  ...(ngDevMode ? [{ debugName: "baseClass" }] : /* istanbul ignore next */ []));
132
- this.currentDateString = linkedSignal(() => {
133
- const value = this.value();
134
- const format = this.effectiveFormat();
135
- const locale = this.#i18n.localeId();
136
- if (!value) {
137
- return "";
138
- }
139
- return gregorianDateTime(value, locale).toFormat(format);
140
- }, /* @ts-ignore */
141
- ...(ngDevMode ? [{ debugName: "currentDateString" }] : /* istanbul ignore next */ []));
128
+ this.dateTabId = createElementControlId();
142
129
  this.decadeCellTemplate = contentChild(CalendarDecadeCellTemplateDirective, /* @ts-ignore */
143
130
  ...(ngDevMode ? [{ debugName: "decadeCellTemplate" }] : /* istanbul ignore next */ []));
144
131
  this.effectiveFormat = computed(() => {
145
132
  return (this.format() ??
146
133
  getLocaleDateTimeInputFormat(this.#i18n.localeId(), {
147
- hourFormat: this.hourFormat(),
134
+ hourFormat: this.effectiveHourFormat(),
148
135
  showSeconds: this.showSeconds()
149
136
  }));
150
137
  }, /* @ts-ignore */
151
138
  ...(ngDevMode ? [{ debugName: "effectiveFormat" }] : /* istanbul ignore next */ []));
139
+ this.effectiveHourFormat = computed(() => this.hourFormat() ?? getLocaleHourFormat(this.#i18n.localeId()), /* @ts-ignore */
140
+ ...(ngDevMode ? [{ debugName: "effectiveHourFormat" }] : /* istanbul ignore next */ []));
152
141
  this.expanded = computed(() => this.#dropdownService.popupRef() !== null, /* @ts-ignore */
153
142
  ...(ngDevMode ? [{ debugName: "expanded" }] : /* istanbul ignore next */ []));
143
+ /** Whether the view shown next takes focus: yes after picking a day, no when a tab is chosen. */
144
+ this.focusViewOnMount = signal(true, /* @ts-ignore */
145
+ ...(ngDevMode ? [{ debugName: "focusViewOnMount" }] : /* istanbul ignore next */ []));
154
146
  this.footerClass = computed(() => {
155
147
  return dateTimePickerFooterThemeVariants();
156
148
  }, /* @ts-ignore */
@@ -160,24 +152,20 @@ class DateTimePickerComponent {
160
152
  }, /* @ts-ignore */
161
153
  ...(ngDevMode ? [{ debugName: "headerClass" }] : /* istanbul ignore next */ []));
162
154
  this.inputAttributes = computed(() => {
163
- const controls = this.popupId;
164
- const expanded = this.#dropdownService.popupRef() != null;
165
- const hasPopup = "dialog";
166
- const invalid = this.invalidState();
167
155
  return {
168
156
  "aria-autocomplete": "none",
169
- "aria-controls": controls,
170
- "aria-expanded": expanded,
171
- "aria-haspopup": hasPopup,
172
- "aria-invalid": invalid,
173
- id: this.#id,
157
+ "aria-controls": this.popupId,
158
+ // The binder drops `false`, and a combobox must always say whether it's expanded.
159
+ "aria-expanded": this.expanded() ? "true" : "false",
160
+ "aria-haspopup": "dialog",
174
161
  // The text box hides its clear button when read-only, so typing is blocked here instead.
175
162
  readonly: this.readonly() || this.readonlyInput(),
176
- role: "group"
163
+ role: "combobox"
177
164
  };
178
165
  }, /* @ts-ignore */
179
166
  ...(ngDevMode ? [{ debugName: "inputAttributes" }] : /* istanbul ignore next */ []));
180
- this.invalidState = computed(() => this.touched() && (this.invalid() || (this.required() && !this.value())), /* @ts-ignore */
167
+ this.invalidState = computed(() => this.typedInput.errors().length > 0 ||
168
+ (this.touched() && (this.invalid() || (this.required() && !this.value()))), /* @ts-ignore */
181
169
  ...(ngDevMode ? [{ debugName: "invalidState" }] : /* istanbul ignore next */ []));
182
170
  this.isRtl = computed(() => this.#direction() === "rtl", /* @ts-ignore */
183
171
  ...(ngDevMode ? [{ debugName: "isRtl" }] : /* istanbul ignore next */ []));
@@ -186,6 +174,7 @@ class DateTimePickerComponent {
186
174
  ...(ngDevMode ? [{ debugName: "monthCellTemplate" }] : /* istanbul ignore next */ []));
187
175
  this.navigatedDate = linkedSignal(() => this.value() ?? new Date(), /* @ts-ignore */
188
176
  ...(ngDevMode ? [{ debugName: "navigatedDate" }] : /* istanbul ignore next */ []));
177
+ this.panelId = createElementControlId();
189
178
  this.pickerPopupClass = computed(() => {
190
179
  const rounded = this.rounded();
191
180
  const size = this.size();
@@ -226,8 +215,25 @@ class DateTimePickerComponent {
226
215
  return null;
227
216
  }, /* @ts-ignore */
228
217
  ...(ngDevMode ? [{ debugName: "timePickerMin" }] : /* istanbul ignore next */ []));
218
+ this.timeTabId = createElementControlId();
229
219
  this.yearCellTemplate = contentChild(CalendarYearCellTemplateDirective, /* @ts-ignore */
230
220
  ...(ngDevMode ? [{ debugName: "yearCellTemplate" }] : /* istanbul ignore next */ []));
221
+ /**
222
+ * @description Id of an element that describes the input, such as a hint or an error message.
223
+ * @default ""
224
+ */
225
+ this.ariaDescribedBy = input("", { ...(ngDevMode ? { debugName: "ariaDescribedBy" } : /* istanbul ignore next */ {}), alias: "aria-describedby" });
226
+ /**
227
+ * @description Accessible name of the input. Prefer a visible label, linked through {@link inputId} or
228
+ * {@link ariaLabelledBy}; the placeholder is not a label.
229
+ * @default ""
230
+ */
231
+ this.ariaLabel = input("", { ...(ngDevMode ? { debugName: "ariaLabel" } : /* istanbul ignore next */ {}), alias: "aria-label" });
232
+ /**
233
+ * @description Id of the element that labels the input.
234
+ * @default ""
235
+ */
236
+ this.ariaLabelledBy = input("", { ...(ngDevMode ? { debugName: "ariaLabelledBy" } : /* istanbul ignore next */ {}), alias: "aria-labelledby" });
231
237
  /**
232
238
  * @description Emits when the popup is about to close. This event is preventable.
233
239
  */
@@ -239,12 +245,13 @@ class DateTimePickerComponent {
239
245
  this.closed = output();
240
246
  /**
241
247
  * @description Sets the disabled state of the date time picker.
248
+ * @default false
242
249
  */
243
- this.disabled = input(false, /* @ts-ignore */
244
- ...(ngDevMode ? [{ debugName: "disabled" }] : /* istanbul ignore next */ []));
250
+ this.disabled = input(false, { ...(ngDevMode ? { debugName: "disabled" } : /* istanbul ignore next */ {}), transform: booleanAttribute });
245
251
  /**
246
252
  * @description Sets the disabled dates of the date time picker.
247
- * Accepts either an iterable of Date objects or a predicate function.
253
+ * Accepts either an iterable of Date objects or a predicate function. Typing a disabled date is reported as a
254
+ * `disabledDate` error instead of setting the value.
248
255
  */
249
256
  this.disabledDates = input(/* @ts-ignore */
250
257
  ...(ngDevMode ? [undefined, { debugName: "disabledDates" }] : /* istanbul ignore next */ []));
@@ -255,16 +262,18 @@ class DateTimePickerComponent {
255
262
  this.firstDay = input(null, /* @ts-ignore */
256
263
  ...(ngDevMode ? [{ debugName: "firstDay" }] : /* istanbul ignore next */ []));
257
264
  /**
258
- * @description Sets the date format of the date time picker. If not specified, derives from the active locale, hourFormat, and showSeconds.
265
+ * @description Sets the date format of the date time picker. If not specified, derives from the active locale,
266
+ * hourFormat, and showSeconds. Typed text is also accepted with one-digit parts and a two-digit year.
259
267
  * @default null
260
268
  */
261
269
  this.format = input(null, /* @ts-ignore */
262
270
  ...(ngDevMode ? [{ debugName: "format" }] : /* istanbul ignore next */ []));
263
271
  /**
264
- * @description Sets the hour format of the time picker.
265
- * @default 24
272
+ * @description Sets the hour format of the date time picker. When null, the active locale's clock is used: 12-hour
273
+ * for en-US, 24-hour for de-DE.
274
+ * @default null
266
275
  */
267
- this.hourFormat = input("24", /* @ts-ignore */
276
+ this.hourFormat = input(null, /* @ts-ignore */
268
277
  ...(ngDevMode ? [{ debugName: "hourFormat" }] : /* istanbul ignore next */ []));
269
278
  /**
270
279
  * @description Sets the hour step of the time picker.
@@ -272,19 +281,26 @@ class DateTimePickerComponent {
272
281
  */
273
282
  this.hourStep = input(1, /* @ts-ignore */
274
283
  ...(ngDevMode ? [{ debugName: "hourStep" }] : /* istanbul ignore next */ []));
284
+ /**
285
+ * @description Id of the inner `<input>` element. Point a `<label for>` or `<mona-label for>` at it to label the
286
+ * date time picker. A unique id is generated when it isn't set.
287
+ * @default generated
288
+ */
289
+ this.inputId = input(createElementControlId(), /* @ts-ignore */
290
+ ...(ngDevMode ? [{ debugName: "inputId" }] : /* istanbul ignore next */ []));
275
291
  /**
276
292
  * @description Marks the date time picker as invalid. When bound to a signal form field via `[formField]`,
277
293
  * this is written by the `FormField` directive.
278
294
  * @default false
279
295
  */
280
- this.invalid = input(false, /* @ts-ignore */
281
- ...(ngDevMode ? [{ debugName: "invalid" }] : /* istanbul ignore next */ []));
296
+ this.invalid = input(false, { ...(ngDevMode ? { debugName: "invalid" } : /* istanbul ignore next */ {}), transform: booleanAttribute });
282
297
  /**
283
- * @description Sets the maximum date of the date time picker.
298
+ * @description Sets the maximum date of the date time picker. A later typed date is reported as a `maxDate` error.
284
299
  */
285
300
  this.max = input(undefined, { ...(ngDevMode ? { debugName: "max" } : /* istanbul ignore next */ {}), transform: value => (value instanceof Date ? value : undefined) });
286
301
  /**
287
- * @description Sets the minimum date of the date time picker.
302
+ * @description Sets the minimum date of the date time picker. An earlier typed date is reported as a `minDate`
303
+ * error.
288
304
  */
289
305
  this.min = input(undefined, { ...(ngDevMode ? { debugName: "min" } : /* istanbul ignore next */ {}), transform: value => (value instanceof Date ? value : undefined) });
290
306
  /**
@@ -313,35 +329,33 @@ class DateTimePickerComponent {
313
329
  this.popupClass = input("", /* @ts-ignore */
314
330
  ...(ngDevMode ? [{ debugName: "popupClass" }] : /* istanbul ignore next */ []));
315
331
  /**
316
- * @description Sets the height of the popup element.
317
- * @default 200
332
+ * @description Sets the height of the popup element. When not set, the popup fits its content.
333
+ * @default undefined
318
334
  */
319
335
  this.popupHeight = input(/* @ts-ignore */
320
336
  ...(ngDevMode ? [undefined, { debugName: "popupHeight" }] : /* istanbul ignore next */ []));
321
337
  /**
322
- * @description Sets the width of the popup element.
323
- * @default null
338
+ * @description Sets the width of the popup element. When not set, the popup is at least as wide as the input.
339
+ * @default undefined
324
340
  */
325
341
  this.popupWidth = input(/* @ts-ignore */
326
342
  ...(ngDevMode ? [undefined, { debugName: "popupWidth" }] : /* istanbul ignore next */ []));
327
343
  /**
328
344
  * @description Sets the readonly state of the date time picker.
345
+ * @default false
329
346
  */
330
- this.readonly = input(false, /* @ts-ignore */
331
- ...(ngDevMode ? [{ debugName: "readonly" }] : /* istanbul ignore next */ []));
347
+ this.readonly = input(false, { ...(ngDevMode ? { debugName: "readonly" } : /* istanbul ignore next */ {}), transform: booleanAttribute });
332
348
  /**
333
349
  * @description When true, the input is readonly but the popup button remains enabled.
334
350
  * @default false
335
351
  */
336
- this.readonlyInput = input(false, /* @ts-ignore */
337
- ...(ngDevMode ? [{ debugName: "readonlyInput" }] : /* istanbul ignore next */ []));
352
+ this.readonlyInput = input(false, { ...(ngDevMode ? { debugName: "readonlyInput" } : /* istanbul ignore next */ {}), transform: booleanAttribute });
338
353
  /**
339
354
  * @description Sets the required state of the date time picker.
340
355
  * When bound to a signal form field via `[formField]`, this is written by the `FormField` directive.
341
356
  * @default false
342
357
  */
343
- this.required = input(false, /* @ts-ignore */
344
- ...(ngDevMode ? [{ debugName: "required" }] : /* istanbul ignore next */ []));
358
+ this.required = input(false, { ...(ngDevMode ? { debugName: "required" } : /* istanbul ignore next */ {}), transform: booleanAttribute });
345
359
  /**
346
360
  * @description Sets the border radius of the date time picker.
347
361
  */
@@ -354,22 +368,22 @@ class DateTimePickerComponent {
354
368
  this.secondStep = input(1, /* @ts-ignore */
355
369
  ...(ngDevMode ? [{ debugName: "secondStep" }] : /* istanbul ignore next */ []));
356
370
  /**
357
- * @description Sets the visibility of the clear button.
371
+ * @description Sets the visibility of the clear button. Clearing empties the value at once.
372
+ * @default false
358
373
  */
359
- this.showClearButton = input(false, /* @ts-ignore */
360
- ...(ngDevMode ? [{ debugName: "showClearButton" }] : /* istanbul ignore next */ []));
374
+ this.showClearButton = input(false, { ...(ngDevMode ? { debugName: "showClearButton" } : /* istanbul ignore next */ {}), transform: booleanAttribute });
361
375
  /**
362
376
  * @description Sets the visibility of the second selector.
377
+ * @default false
363
378
  */
364
- this.showSeconds = input(false, /* @ts-ignore */
365
- ...(ngDevMode ? [{ debugName: "showSeconds" }] : /* istanbul ignore next */ []));
379
+ this.showSeconds = input(false, { ...(ngDevMode ? { debugName: "showSeconds" } : /* istanbul ignore next */ {}), transform: booleanAttribute });
366
380
  /**
367
381
  * @description Sets the size of the date time picker.
368
382
  */
369
383
  this.size = input("medium", /* @ts-ignore */
370
384
  ...(ngDevMode ? [{ debugName: "size" }] : /* istanbul ignore next */ []));
371
385
  /**
372
- * @description Emitted when the date time picker is interacted with via blur, selection, or clear.
386
+ * @description Emitted when focus leaves the date time picker and its popup.
373
387
  * The `FormField` directive listens to this to mark the field as touched.
374
388
  */
375
389
  this.touch = output();
@@ -378,11 +392,11 @@ class DateTimePickerComponent {
378
392
  * this is written by the `FormField` directive.
379
393
  * @default false
380
394
  */
381
- this.touched = input(false, /* @ts-ignore */
382
- ...(ngDevMode ? [{ debugName: "touched" }] : /* istanbul ignore next */ []));
395
+ this.touched = input(false, { ...(ngDevMode ? { debugName: "touched" } : /* istanbul ignore next */ {}), transform: booleanAttribute });
383
396
  this.userClass = input("", { ...(ngDevMode ? { debugName: "userClass" } : /* istanbul ignore next */ {}), alias: "class" });
384
397
  /**
385
- * @description Two-way bindable current date time value.
398
+ * @description Two-way bindable current date time value. Typed text is written on Enter and when the input loses
399
+ * focus; text that isn't a valid date and time keeps the previous value and marks the field invalid.
386
400
  * @default null
387
401
  */
388
402
  this.value = model(null, /* @ts-ignore */
@@ -391,68 +405,55 @@ class DateTimePickerComponent {
391
405
  * @description Enables the display of week numbers in the calendar.
392
406
  * @default false
393
407
  */
394
- this.weekNumber = input(false, /* @ts-ignore */
395
- ...(ngDevMode ? [{ debugName: "weekNumber" }] : /* istanbul ignore next */ []));
408
+ this.weekNumber = input(false, { ...(ngDevMode ? { debugName: "weekNumber" } : /* istanbul ignore next */ {}), transform: booleanAttribute });
409
+ this.typedInput = createTypedDateInput({
410
+ constraints: () => ({
411
+ disabledDates: this.disabledDates(),
412
+ max: this.max(),
413
+ min: this.min(),
414
+ unit: "datetime"
415
+ }),
416
+ format: () => this.effectiveFormat(),
417
+ localeId: () => this.#i18n.localeId(),
418
+ value: this.value
419
+ });
396
420
  effect(() => {
397
421
  const popupTemplate = this.popupTemplate();
398
422
  untracked(() => this.#dropdownService.popupTemplate.set(popupTemplate));
399
423
  });
400
424
  afterNextRender({
401
425
  read: () => {
402
- this.setSubscriptions();
403
- this.setPopupCloseSubscriptions();
426
+ this.setPopupKeyboardSubscription();
427
+ this.setPopupCloseSubscription();
404
428
  }
405
429
  });
406
430
  }
407
- focus() {
431
+ /**
432
+ * Focuses the input and places the caret after the text. Read-only pickers take focus too.
433
+ * @param options Options passed to the native `focus()` call, such as `preventScroll`.
434
+ */
435
+ focus(options) {
408
436
  const input = this.#hostElementRef.nativeElement.querySelector("input");
409
- if (input && !this.readonly()) {
410
- input.focus();
437
+ if (input) {
438
+ input.focus(options);
411
439
  input.setSelectionRange(input.value.length, input.value.length);
412
440
  }
413
441
  }
414
442
  onCalendarValueChange(date) {
415
443
  const singleDate = Array.isArray(date) ? null : date;
416
444
  if (singleDate) {
417
- const inRangeDate = this.updateDateIfNotInRange(singleDate);
418
- this.navigatedDate.set(inRangeDate);
445
+ // The calendar gives midnight; keep the time already chosen.
446
+ const current = this.navigatedDate();
447
+ const withTime = new Date(singleDate);
448
+ withTime.setHours(current.getHours(), current.getMinutes(), current.getSeconds(), 0);
449
+ this.navigatedDate.set(this.updateDateIfNotInRange(withTime));
419
450
  }
451
+ this.focusViewOnMount.set(true);
420
452
  this.activeView.set("time");
421
453
  }
422
454
  onCancelClick() {
423
455
  this.navigatedDate.set(this.value() ?? new Date());
424
- this.#dropdownService.popupRef()?.close();
425
- this.touch.emit();
426
- }
427
- onDateInputBlur() {
428
- if (this.#dropdownService.popupRef()) {
429
- this.touch.emit();
430
- return;
431
- }
432
- if (!this.currentDateString() && this.value()) {
433
- this.setCurrentDate(null);
434
- this.touch.emit();
435
- return;
436
- }
437
- const locale = this.#i18n.localeId();
438
- const dateTime = parseGregorianDate(this.currentDateString(), this.effectiveFormat(), locale);
439
- if (this.dateStringEquals(this.value(), dateTime.toJSDate())) {
440
- this.touch.emit();
441
- return;
442
- }
443
- if (dateTime.isValid) {
444
- const value = this.value();
445
- if (value && gregorianDateTime(value, locale).equals(dateTime)) {
446
- this.touch.emit();
447
- return;
448
- }
449
- this.setCurrentDate(dateTime.toJSDate());
450
- }
451
- else {
452
- this.setCurrentDate(null);
453
- this.currentDateString.set("");
454
- }
455
- this.touch.emit();
456
+ this.closePopup();
456
457
  }
457
458
  onDateInputButtonClick() {
458
459
  if (this.disabled() || this.readonly()) {
@@ -465,90 +466,104 @@ class DateTimePickerComponent {
465
466
  this.openPopup();
466
467
  }
467
468
  }
468
- onDateStringEdit(dateString) {
469
- this.currentDateString.set(dateString);
470
- }
471
- onSetDateClick() {
472
- this.value.set(this.navigatedDate());
473
- this.#dropdownService.popupRef()?.close();
474
- this.touch.emit();
475
- }
476
- onTimeSelectorValueChange(date) {
477
- if (date) {
478
- const inRangeDate = this.updateDateIfNotInRange(date);
479
- this.navigatedDate.set(inRangeDate);
469
+ onFocusIn(event) {
470
+ // The host is focusable only to pass focus on; focus inside it, such as a click in the text, stays put.
471
+ if (event.target === this.#hostElementRef.nativeElement) {
472
+ this.focus();
480
473
  }
481
474
  }
482
- closePopup() {
483
- this.#dropdownService.popupRef()?.close();
484
- }
485
- compareDatesEqual(date1, date2) {
486
- return (date1.getFullYear() === date2.getFullYear() &&
487
- date1.getMonth() === date2.getMonth() &&
488
- date1.getDate() === date2.getDate());
489
- }
490
- dateStringEquals(date1, date2) {
491
- if (date1 && date2) {
492
- const locale = this.#i18n.localeId();
493
- return (gregorianDateTime(date1, locale).toFormat(this.effectiveFormat()) ===
494
- gregorianDateTime(date2, locale).toFormat(this.effectiveFormat()));
475
+ onFocusOut(event) {
476
+ // Removing a focused picker from the page fires focusout after it is destroyed.
477
+ if (this.#destroyRef.destroyed) {
478
+ return;
479
+ }
480
+ const nextTarget = event.relatedTarget;
481
+ if (nextTarget instanceof Node) {
482
+ const popupElement = this.#dropdownService.popupRef()?.overlayRef.overlayElement;
483
+ if (this.#hostElementRef.nativeElement.contains(nextTarget) || popupElement?.contains(nextTarget)) {
484
+ return;
485
+ }
495
486
  }
496
- return date1 === date2;
487
+ this.touch.emit();
488
+ }
489
+ onInputBlur() {
490
+ this.typedInput.commit();
497
491
  }
498
- handleKeydown(event) {
492
+ onKeydown(event) {
499
493
  if (this.disabled() || this.readonly()) {
500
494
  return;
501
495
  }
502
- const popupOpen = this.#dropdownService.popupRef() !== null;
496
+ const popupOpen = this.expanded();
503
497
  if (event.altKey && event.key === "ArrowDown") {
504
498
  event.preventDefault();
505
499
  this.openPopup();
506
- return;
507
500
  }
508
- if (event.altKey && event.key === "ArrowUp") {
509
- event.preventDefault();
510
- console.warn("ArrowUp is not supported yet");
511
- this.closePopup();
512
- return;
501
+ else if (event.altKey && event.key === "ArrowUp") {
502
+ if (popupOpen) {
503
+ event.preventDefault();
504
+ this.closePopup();
505
+ }
513
506
  }
514
- if (event.key === "Escape" && popupOpen) {
515
- event.preventDefault();
516
- this.onCancelClick();
517
- return;
507
+ else if (event.key === "Escape") {
508
+ if (popupOpen) {
509
+ event.preventDefault();
510
+ this.onCancelClick();
511
+ }
518
512
  }
519
- if (event.altKey && event.key === "ArrowRight" && popupOpen) {
520
- event.preventDefault();
521
- this.activeView.set(this.isRtl() ? "date" : "time");
522
- return;
513
+ else if (event.altKey && (event.key === "ArrowRight" || event.key === "ArrowLeft")) {
514
+ if (popupOpen) {
515
+ event.preventDefault();
516
+ const towardsTime = (event.key === "ArrowRight") !== this.isRtl();
517
+ this.activeView.set(towardsTime ? "time" : "date");
518
+ }
523
519
  }
524
- if (event.altKey && event.key === "ArrowLeft" && popupOpen) {
525
- event.preventDefault();
526
- this.activeView.set(this.isRtl() ? "time" : "date");
520
+ else if (event.key === "Enter" && event.target instanceof HTMLInputElement) {
521
+ // Committed before a surrounding form submits; an IME uses Enter to confirm its text.
522
+ if (!event.isComposing && event.keyCode !== 229) {
523
+ this.typedInput.commit();
524
+ }
525
+ }
526
+ }
527
+ onSetDateClick() {
528
+ this.value.set(this.navigatedDate());
529
+ this.closePopup();
530
+ }
531
+ /** Arrow keys, Home and End move between the Date and Time tabs, as in the APG tabs pattern. */
532
+ onTabKeydown(event) {
533
+ if (event.altKey) {
527
534
  return;
528
535
  }
529
- if (event.key === "Enter" && popupOpen) {
530
- const target = event.target;
531
- if (target.tagName === "BUTTON" || target.closest("button")) {
532
- return;
533
- }
534
- event.preventDefault();
535
- if (this.activeView() === "date") {
536
- this.activeView.set("time");
537
- }
538
- else {
539
- this.onSetDateClick();
540
- }
536
+ const forward = this.isRtl() ? "ArrowLeft" : "ArrowRight";
537
+ const backward = this.isRtl() ? "ArrowRight" : "ArrowLeft";
538
+ let view = null;
539
+ if (event.key === "Home" || event.key === backward) {
540
+ view = "date";
541
+ }
542
+ else if (event.key === "End" || event.key === forward) {
543
+ view = "time";
544
+ }
545
+ if (!view) {
541
546
  return;
542
547
  }
548
+ event.preventDefault();
549
+ this.selectTab(view);
550
+ const tabId = view === "date" ? this.dateTabId : this.timeTabId;
551
+ const tablist = event.currentTarget;
552
+ tablist.querySelector(`[id="${tabId}"]`)?.focus();
543
553
  }
544
- isDateDisabledByInput(date, disabledDates) {
545
- if (typeof disabledDates === "function") {
546
- return disabledDates(date);
547
- }
548
- else if (disabledDates) {
549
- return any(disabledDates, d => this.compareDatesEqual(date, d));
554
+ onTimeSelectorValueChange(date) {
555
+ if (date) {
556
+ const inRangeDate = this.updateDateIfNotInRange(date);
557
+ this.navigatedDate.set(inRangeDate);
550
558
  }
551
- return false;
559
+ }
560
+ /** Shows a view from its tab; focus stays on the tab, as in the APG tabs pattern. */
561
+ selectTab(view) {
562
+ this.focusViewOnMount.set(false);
563
+ this.activeView.set(view);
564
+ }
565
+ closePopup() {
566
+ this.#dropdownService.popupRef()?.close();
552
567
  }
553
568
  openPopup() {
554
569
  if (!this.#dropdownService.popupRef()) {
@@ -561,15 +576,21 @@ class DateTimePickerComponent {
561
576
  });
562
577
  }
563
578
  }
564
- setCurrentDate(date) {
565
- this.value.set(date);
566
- this.updateCurrentDateString(date, this.effectiveFormat());
567
- this.touch.emit();
579
+ setPopupCloseSubscription() {
580
+ this.#dropdownService.popupCloseComplete$.pipe(takeUntilDestroyed(this.#destroyRef)).subscribe(() => {
581
+ if (this.#dropdownService.focusCanReturn()) {
582
+ this.focus();
583
+ }
584
+ else if (!this.#destroyRef.destroyed) {
585
+ // Focus left from inside the popup, which the host's focusout doesn't see.
586
+ this.touch.emit();
587
+ }
588
+ this.activeView.set("date");
589
+ this.focusViewOnMount.set(true);
590
+ this.navigatedDate.set(this.value() ?? new Date());
591
+ });
568
592
  }
569
- setKeyboardSubscriptions() {
570
- fromEvent(this.#hostElementRef.nativeElement, "keydown")
571
- .pipe(takeUntilDestroyed(this.#destroyRef))
572
- .subscribe(event => this.handleKeydown(event));
593
+ setPopupKeyboardSubscription() {
573
594
  this.#calendarService.keydown$
574
595
  .pipe(mergeWith(this.#timeSelectorService.keydown$), takeUntilDestroyed(this.#destroyRef))
575
596
  .subscribe(e => {
@@ -603,29 +624,6 @@ class DateTimePickerComponent {
603
624
  }
604
625
  });
605
626
  }
606
- setPopupCloseSubscriptions() {
607
- this.#dropdownService.popupCloseComplete$.pipe(takeUntilDestroyed(this.#destroyRef)).subscribe(() => {
608
- if (this.#dropdownService.focusCanReturn()) {
609
- this.focus();
610
- }
611
- this.activeView.set("date");
612
- this.navigatedDate.set(this.value() ?? new Date());
613
- });
614
- }
615
- setSubscriptions() {
616
- fromEvent(this.#hostElementRef.nativeElement, "focusin")
617
- .pipe(takeUntilDestroyed(this.#destroyRef))
618
- .subscribe(() => this.focus());
619
- this.setKeyboardSubscriptions();
620
- }
621
- updateCurrentDateString(date, format) {
622
- if (!date) {
623
- this.currentDateString.set("");
624
- return;
625
- }
626
- const dateString = gregorianDateTime(date, this.#i18n.localeId()).toFormat(format);
627
- this.currentDateString.set(dateString);
628
- }
629
627
  updateDateIfNotInRange(date) {
630
628
  const maxDate = this.max();
631
629
  const minDate = this.min();
@@ -638,7 +636,7 @@ class DateTimePickerComponent {
638
636
  return date;
639
637
  }
640
638
  static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "22.0.6", ngImport: i0, type: DateTimePickerComponent, deps: [], target: i0.ɵɵFactoryTarget.Component }); }
641
- static { this.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "22.0.6", type: DateTimePickerComponent, isStandalone: true, selector: "mona-datetime-picker", inputs: { disabled: { classPropertyName: "disabled", publicName: "disabled", isSignal: true, isRequired: false, transformFunction: null }, disabledDates: { classPropertyName: "disabledDates", publicName: "disabledDates", isSignal: true, isRequired: false, transformFunction: null }, firstDay: { classPropertyName: "firstDay", publicName: "firstDay", isSignal: true, isRequired: false, transformFunction: null }, format: { classPropertyName: "format", publicName: "format", isSignal: true, isRequired: false, transformFunction: null }, hourFormat: { classPropertyName: "hourFormat", publicName: "hourFormat", isSignal: true, isRequired: false, transformFunction: null }, hourStep: { classPropertyName: "hourStep", publicName: "hourStep", isSignal: true, isRequired: false, transformFunction: null }, invalid: { classPropertyName: "invalid", publicName: "invalid", isSignal: true, isRequired: false, transformFunction: null }, max: { classPropertyName: "max", publicName: "max", isSignal: true, isRequired: false, transformFunction: null }, min: { classPropertyName: "min", publicName: "min", isSignal: true, isRequired: false, transformFunction: null }, minuteStep: { classPropertyName: "minuteStep", publicName: "minuteStep", 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 }, readonlyInput: { classPropertyName: "readonlyInput", publicName: "readonlyInput", 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 }, secondStep: { classPropertyName: "secondStep", publicName: "secondStep", isSignal: true, isRequired: false, transformFunction: null }, showClearButton: { classPropertyName: "showClearButton", publicName: "showClearButton", isSignal: true, isRequired: false, transformFunction: null }, showSeconds: { classPropertyName: "showSeconds", publicName: "showSeconds", isSignal: true, isRequired: false, transformFunction: null }, size: { classPropertyName: "size", publicName: "size", 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 }, weekNumber: { classPropertyName: "weekNumber", publicName: "weekNumber", isSignal: true, isRequired: false, transformFunction: null } }, outputs: { close: "close", closed: "closed", open: "open", opened: "opened", touch: "touch", value: "valueChange" }, host: { listeners: { "blur": "onDateInputBlur()" }, properties: { "attr.tabindex": "disabled() ? null : -1", "attr.aria-invalid": "invalidState() ? 'true' : null", "attr.data-disabled": "disabled() || null", "attr.data-expanded": "expanded()", "attr.data-invalid": "invalidState() || null", "attr.data-readonly": "readonly() || null", "class": "baseClass()" } }, providers: [
639
+ static { this.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "22.0.6", type: DateTimePickerComponent, isStandalone: true, selector: "mona-datetime-picker", 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 }, disabled: { classPropertyName: "disabled", publicName: "disabled", isSignal: true, isRequired: false, transformFunction: null }, disabledDates: { classPropertyName: "disabledDates", publicName: "disabledDates", isSignal: true, isRequired: false, transformFunction: null }, firstDay: { classPropertyName: "firstDay", publicName: "firstDay", isSignal: true, isRequired: false, transformFunction: null }, format: { classPropertyName: "format", publicName: "format", isSignal: true, isRequired: false, transformFunction: null }, hourFormat: { classPropertyName: "hourFormat", publicName: "hourFormat", isSignal: true, isRequired: false, transformFunction: null }, hourStep: { classPropertyName: "hourStep", publicName: "hourStep", 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 }, max: { classPropertyName: "max", publicName: "max", isSignal: true, isRequired: false, transformFunction: null }, min: { classPropertyName: "min", publicName: "min", isSignal: true, isRequired: false, transformFunction: null }, minuteStep: { classPropertyName: "minuteStep", publicName: "minuteStep", 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 }, readonlyInput: { classPropertyName: "readonlyInput", publicName: "readonlyInput", 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 }, secondStep: { classPropertyName: "secondStep", publicName: "secondStep", isSignal: true, isRequired: false, transformFunction: null }, showClearButton: { classPropertyName: "showClearButton", publicName: "showClearButton", isSignal: true, isRequired: false, transformFunction: null }, showSeconds: { classPropertyName: "showSeconds", publicName: "showSeconds", isSignal: true, isRequired: false, transformFunction: null }, size: { classPropertyName: "size", publicName: "size", 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 }, weekNumber: { classPropertyName: "weekNumber", publicName: "weekNumber", isSignal: true, isRequired: false, transformFunction: null } }, outputs: { close: "close", closed: "closed", open: "open", opened: "opened", touch: "touch", value: "valueChange" }, host: { listeners: { "focusin": "onFocusIn($event)", "focusout": "onFocusOut($event)", "keydown": "onKeydown($event)" }, properties: { "attr.aria-describedby": "null", "attr.aria-label": "null", "attr.aria-labelledby": "null", "attr.tabindex": "disabled() ? null : -1", "attr.aria-invalid": "invalidState() ? 'true' : null", "attr.data-disabled": "disabled() || null", "attr.data-expanded": "expanded()", "attr.data-invalid": "invalidState() || null", "attr.data-readonly": "readonly() || null", "class": "baseClass()" } }, providers: [
642
640
  CalendarService,
643
641
  DropdownService,
644
642
  TimeSelectorService,
@@ -647,7 +645,7 @@ class DateTimePickerComponent {
647
645
  useExisting: forwardRef(() => DateTimePickerComponent),
648
646
  multi: false
649
647
  }
650
- ], queries: [{ propertyName: "decadeCellTemplate", first: true, predicate: CalendarDecadeCellTemplateDirective, descendants: true, isSignal: true }, { propertyName: "monthCellTemplate", first: true, predicate: CalendarMonthCellTemplateDirective, descendants: true, isSignal: true }, { propertyName: "prefixTemplate", first: true, predicate: DateInputPrefixTemplateDirective, descendants: true, read: TemplateRef, isSignal: true }, { propertyName: "yearCellTemplate", first: true, predicate: CalendarYearCellTemplateDirective, descendants: true, isSignal: true }], viewQueries: [{ propertyName: "popupTemplate", first: true, predicate: ["datePopupTemplate"], descendants: true, isSignal: true }], hostDirectives: [{ directive: i1.DropdownPopupHandlerDirective }], ngImport: i0, template: "<mona-text-box\n (inputBlur)=\"onDateInputBlur()\"\n (valueChange)=\"onDateStringEdit($event)\"\n [clearButton]=\"showClearButton()\"\n [disabled]=\"disabled()\"\n [inputAttributes]=\"inputAttributes()\"\n [invalid]=\"invalid()\"\n [placeholder]=\"placeholder()\"\n [readonly]=\"readonly()\"\n [required]=\"required()\"\n [rounded]=\"rounded()\"\n [size]=\"size()\"\n [touched]=\"touched()\"\n [value]=\"currentDateString()\">\n @if (prefixTemplate()) {\n <ng-template monaTextBoxPrefixTemplate>\n <ng-container [ngTemplateOutlet]=\"prefixTemplate()\"></ng-container>\n </ng-template>\n }\n <ng-template monaTextBoxSuffixTemplate>\n <button\n monaButton\n look=\"ghost\"\n [iconOnly]=\"true\"\n [size]=\"size()\"\n [rounded]=\"'none'\"\n class=\"aspect-square h-full w-auto\"\n [attr.aria-label]=\"messages().openDateTimePicker\"\n [attr.aria-expanded]=\"expanded()\"\n [attr.aria-controls]=\"popupId\"\n (click)=\"onDateInputButtonClick()\"\n [disabled]=\"disabled() || readonly()\"\n [tabindex]=\"-1\">\n <svg lucideCalendar [size]=\"16\" aria-hidden=\"true\"></svg>\n </button>\n </ng-template>\n</mona-text-box>\n\n<ng-template #datePopupTemplate>\n <div\n [class]=\"pickerPopupClass()\"\n [id]=\"popupId\"\n class=\"flex h-68 flex-col\"\n aria-modal=\"true\"\n role=\"dialog\"\n [attr.aria-label]=\"messages().dateTimePicker\"\n cdkTrapFocus>\n <div [class]=\"headerClass()\">\n <mona-button-group\n selection=\"single\"\n [allowEmpty]=\"false\"\n class=\"w-full\"\n [disabled]=\"disabled()\"\n [size]=\"size()\"\n [rounded]=\"rounded()\"\n role=\"tablist\">\n <button monaButton [selected]=\"activeView() === 'date'\" (click)=\"activeView.set('date')\" role=\"tab\">\n {{ messages().date }}\n </button>\n <button monaButton [selected]=\"activeView() === 'time'\" (click)=\"activeView.set('time')\" role=\"tab\">\n {{ messages().time }}\n </button>\n </mona-button-group>\n </div>\n <div class=\"overflow-hidden\">\n @if (activeView() === \"date\") {\n <div class=\"flex h-full items-center justify-center\" [attr.aria-label]=\"messages().calendar\">\n <mona-calendar\n [disabledDates]=\"disabledDates()\"\n [minDate]=\"min()\"\n [maxDate]=\"max()\"\n [firstDay]=\"firstDay()\"\n [weekNumber]=\"weekNumber()\"\n [value]=\"navigatedDate()\"\n [disabled]=\"disabled()\"\n [readonly]=\"readonly()\"\n [rounded]=\"rounded()\"\n (valueChange)=\"onCalendarValueChange($event)\"\n class=\"flex-1 border-none shadow-none\">\n @if (decadeCellTemplate()) {\n <ng-template monaCalendarDecadeCellTemplate let-year>\n <ng-container\n [ngTemplateOutlet]=\"decadeCellTemplate()?.templateRef\"\n [ngTemplateOutletContext]=\"{ $implicit: year }\"></ng-container>\n </ng-template>\n }\n @if (monthCellTemplate()) {\n <ng-template monaCalendarMonthCellTemplate let-day let-date=\"date\">\n <ng-container\n [ngTemplateOutlet]=\"monthCellTemplate()?.templateRef\"\n [ngTemplateOutletContext]=\"{ $implicit: day, date }\"></ng-container>\n </ng-template>\n }\n @if (yearCellTemplate()) {\n <ng-template monaCalendarYearCellTemplate let-year let-text=\"text\">\n <ng-container\n [ngTemplateOutlet]=\"yearCellTemplate()?.templateRef\"\n [ngTemplateOutletContext]=\"{ $implicit: year, text }\"></ng-container>\n </ng-template>\n }\n </mona-calendar>\n </div>\n }\n @if (activeView() === \"time\") {\n <div class=\"flex h-full max-h-64 items-center justify-center\" [attr.aria-label]=\"messages().timePicker\">\n <mona-time-selector\n [value]=\"navigatedDate()\"\n (valueChange)=\"onTimeSelectorValueChange($event)\"\n [disabled]=\"disabled()\"\n [readonly]=\"readonly()\"\n [max]=\"timePickerMax()\"\n [min]=\"timePickerMin()\"\n [footer]=\"false\"\n [size]=\"size()\"\n [rounded]=\"rounded()\"\n [hourStep]=\"hourStep()\"\n [minuteStep]=\"minuteStep()\"\n [secondStep]=\"secondStep()\"\n [hourFormat]=\"hourFormat()\"\n [showSeconds]=\"showSeconds()\"></mona-time-selector>\n </div>\n }\n </div>\n <div [class]=\"footerClass()\">\n <button\n monaButton\n look=\"primary\"\n [disabled]=\"disabled()\"\n [rounded]=\"rounded()\"\n [size]=\"size()\"\n (click)=\"onSetDateClick()\">\n {{ messages().set }}\n </button>\n <button\n monaButton\n look=\"default\"\n [disabled]=\"disabled()\"\n [rounded]=\"rounded()\"\n [size]=\"size()\"\n (click)=\"onCancelClick()\">\n {{ messages().cancel }}\n </button>\n </div>\n </div>\n</ng-template>\n", dependencies: [{ kind: "component", type: LucideCalendar, selector: "svg[lucideCalendar]" }, { kind: "directive", type: ButtonDirective, selector: "button[monaButton]", inputs: ["aria-haspopup", "disabled", "iconOnly", "loading", "look", "rounded", "selected", "size", "tabindex", "toggleable", "type", "class"], outputs: ["lookChange", "selectedChange"] }, { kind: "component", type: CalendarComponent, selector: "mona-calendar", inputs: ["disabled", "disabledDates", "firstDay", "invalid", "maxDate", "minDate", "readonly", "required", "rounded", "selection", "touched", "class", "value", "weekNumber"], outputs: ["disabledChange", "touch", "valueChange"] }, { kind: "component", type: TimeSelectorComponent, selector: "mona-time-selector", inputs: ["aria-label", "disabled", "focusOnMount", "footer", "hourFormat", "hourStep", "invalid", "max", "min", "minuteStep", "readonly", "required", "rounded", "secondStep", "showSeconds", "size", "touched", "value"], outputs: ["touch", "valueChange"] }, { kind: "component", type: TextBoxComponent, selector: "mona-text-box", inputs: ["aria-describedby", "aria-label", "aria-labelledby", "clearButton", "disabled", "inputAttributes", "inputClass", "inputId", "inputStyle", "invalid", "maxLength", "minLength", "name", "placeholder", "readonly", "required", "rounded", "size", "touched", "type", "class", "value"], outputs: ["inputBlur", "inputFocus", "touch", "valueChange"] }, { kind: "directive", type: TextBoxSuffixTemplateDirective, selector: "ng-template[monaTextBoxSuffixTemplate]" }, { kind: "component", type: ButtonGroupComponent, selector: "mona-button-group", inputs: ["allowEmpty", "aria-label", "disabled", "look", "rounded", "selection", "size", "class"], outputs: ["buttonClick", "disabledChange", "selectionChange"] }, { kind: "directive", type: CdkTrapFocus, selector: "[cdkTrapFocus]", inputs: ["cdkTrapFocus", "cdkTrapFocusAutoCapture"], exportAs: ["cdkTrapFocus"] }, { kind: "directive", type: CalendarDecadeCellTemplateDirective, selector: "ng-template[monaCalendarDecadeCellTemplate]" }, { kind: "directive", type: CalendarMonthCellTemplateDirective, selector: "ng-template[monaCalendarMonthCellTemplate]" }, { kind: "directive", type: CalendarYearCellTemplateDirective, selector: "ng-template[monaCalendarYearCellTemplate]" }, { kind: "directive", type: NgTemplateOutlet, selector: "[ngTemplateOutlet]", inputs: ["ngTemplateOutletContext", "ngTemplateOutlet", "ngTemplateOutletInjector"] }, { kind: "directive", type: TextBoxPrefixTemplateDirective, selector: "ng-template[monaTextBoxPrefixTemplate]" }] }); }
648
+ ], queries: [{ propertyName: "decadeCellTemplate", first: true, predicate: CalendarDecadeCellTemplateDirective, descendants: true, isSignal: true }, { propertyName: "monthCellTemplate", first: true, predicate: CalendarMonthCellTemplateDirective, descendants: true, isSignal: true }, { propertyName: "prefixTemplate", first: true, predicate: DateInputPrefixTemplateDirective, descendants: true, read: TemplateRef, isSignal: true }, { propertyName: "yearCellTemplate", first: true, predicate: CalendarYearCellTemplateDirective, descendants: true, isSignal: true }], viewQueries: [{ propertyName: "popupTemplate", first: true, predicate: ["datePopupTemplate"], descendants: true, isSignal: true }], hostDirectives: [{ directive: i1.DropdownPopupHandlerDirective }], ngImport: i0, template: "<mona-text-box\n (inputBlur)=\"onInputBlur()\"\n (valueChange)=\"typedInput.edit($event)\"\n [aria-describedby]=\"ariaDescribedBy()\"\n [aria-label]=\"ariaLabel()\"\n [aria-labelledby]=\"ariaLabelledBy()\"\n [clearButton]=\"showClearButton()\"\n [disabled]=\"disabled()\"\n [inputAttributes]=\"inputAttributes()\"\n [inputId]=\"inputId()\"\n [invalid]=\"invalidState()\"\n [placeholder]=\"placeholder()\"\n [readonly]=\"readonly()\"\n [required]=\"required()\"\n [rounded]=\"rounded()\"\n [size]=\"size()\"\n [touched]=\"invalidState() || touched()\"\n [value]=\"typedInput.text()\">\n @if (prefixTemplate()) {\n <ng-template monaTextBoxPrefixTemplate>\n <ng-container [ngTemplateOutlet]=\"prefixTemplate()\"></ng-container>\n </ng-template>\n }\n <ng-template monaTextBoxSuffixTemplate>\n <button\n monaButton\n look=\"ghost\"\n [iconOnly]=\"true\"\n [size]=\"size()\"\n [rounded]=\"'none'\"\n class=\"aspect-square h-full w-auto\"\n [attr.aria-label]=\"messages().openDateTimePicker\"\n [attr.aria-expanded]=\"expanded()\"\n [attr.aria-controls]=\"popupId\"\n (click)=\"onDateInputButtonClick()\"\n [disabled]=\"disabled() || readonly()\"\n [tabindex]=\"-1\">\n <svg lucideCalendar [size]=\"16\" aria-hidden=\"true\"></svg>\n </button>\n </ng-template>\n</mona-text-box>\n\n<ng-template #datePopupTemplate>\n <div\n [class]=\"pickerPopupClass()\"\n [id]=\"popupId\"\n class=\"flex h-68 flex-col\"\n aria-modal=\"true\"\n role=\"dialog\"\n [attr.aria-label]=\"messages().dateTimePicker\"\n cdkTrapFocus>\n <div [class]=\"headerClass()\">\n <div class=\"flex w-full gap-1\" role=\"tablist\" (keydown)=\"onTabKeydown($event)\">\n <button\n monaButton\n type=\"button\"\n role=\"tab\"\n class=\"flex-1\"\n [id]=\"dateTabId\"\n [attr.aria-controls]=\"panelId\"\n [attr.aria-selected]=\"activeView() === 'date'\"\n [disabled]=\"disabled()\"\n [rounded]=\"rounded()\"\n [selected]=\"activeView() === 'date'\"\n [size]=\"size()\"\n [tabindex]=\"activeView() === 'date' ? 0 : -1\"\n (click)=\"selectTab('date')\">\n {{ messages().date }}\n </button>\n <button\n monaButton\n type=\"button\"\n role=\"tab\"\n class=\"flex-1\"\n [id]=\"timeTabId\"\n [attr.aria-controls]=\"panelId\"\n [attr.aria-selected]=\"activeView() === 'time'\"\n [disabled]=\"disabled()\"\n [rounded]=\"rounded()\"\n [selected]=\"activeView() === 'time'\"\n [size]=\"size()\"\n [tabindex]=\"activeView() === 'time' ? 0 : -1\"\n (click)=\"selectTab('time')\">\n {{ messages().time }}\n </button>\n </div>\n </div>\n <div\n class=\"overflow-hidden\"\n role=\"tabpanel\"\n [id]=\"panelId\"\n [attr.aria-labelledby]=\"activeView() === 'date' ? dateTabId : timeTabId\">\n @if (activeView() === \"date\") {\n <div class=\"flex h-full items-center justify-center\">\n <mona-calendar\n [focusOnMount]=\"focusViewOnMount()\"\n [disabledDates]=\"disabledDates()\"\n [minDate]=\"min()\"\n [maxDate]=\"max()\"\n [firstDay]=\"firstDay()\"\n [weekNumber]=\"weekNumber()\"\n [value]=\"navigatedDate()\"\n [disabled]=\"disabled()\"\n [readonly]=\"readonly()\"\n [rounded]=\"rounded()\"\n (valueChange)=\"onCalendarValueChange($event)\"\n class=\"flex-1 border-none shadow-none\">\n @if (decadeCellTemplate()) {\n <ng-template monaCalendarDecadeCellTemplate let-year>\n <ng-container\n [ngTemplateOutlet]=\"decadeCellTemplate()?.templateRef\"\n [ngTemplateOutletContext]=\"{ $implicit: year }\"></ng-container>\n </ng-template>\n }\n @if (monthCellTemplate()) {\n <ng-template monaCalendarMonthCellTemplate let-day let-date=\"date\">\n <ng-container\n [ngTemplateOutlet]=\"monthCellTemplate()?.templateRef\"\n [ngTemplateOutletContext]=\"{ $implicit: day, date }\"></ng-container>\n </ng-template>\n }\n @if (yearCellTemplate()) {\n <ng-template monaCalendarYearCellTemplate let-year let-text=\"text\">\n <ng-container\n [ngTemplateOutlet]=\"yearCellTemplate()?.templateRef\"\n [ngTemplateOutletContext]=\"{ $implicit: year, text }\"></ng-container>\n </ng-template>\n }\n </mona-calendar>\n </div>\n }\n @if (activeView() === \"time\") {\n <div class=\"flex h-full max-h-64 items-center justify-center\">\n <mona-time-selector\n [focusOnMount]=\"focusViewOnMount()\"\n [value]=\"navigatedDate()\"\n (valueChange)=\"onTimeSelectorValueChange($event)\"\n [disabled]=\"disabled()\"\n [readonly]=\"readonly()\"\n [max]=\"timePickerMax()\"\n [min]=\"timePickerMin()\"\n [footer]=\"false\"\n [size]=\"size()\"\n [rounded]=\"rounded()\"\n [hourStep]=\"hourStep()\"\n [minuteStep]=\"minuteStep()\"\n [secondStep]=\"secondStep()\"\n [hourFormat]=\"effectiveHourFormat()\"\n [showSeconds]=\"showSeconds()\"></mona-time-selector>\n </div>\n }\n </div>\n <div [class]=\"footerClass()\">\n <button\n monaButton\n look=\"primary\"\n [disabled]=\"disabled()\"\n [rounded]=\"rounded()\"\n [size]=\"size()\"\n (click)=\"onSetDateClick()\">\n {{ messages().set }}\n </button>\n <button\n monaButton\n look=\"default\"\n [disabled]=\"disabled()\"\n [rounded]=\"rounded()\"\n [size]=\"size()\"\n (click)=\"onCancelClick()\">\n {{ messages().cancel }}\n </button>\n </div>\n </div>\n</ng-template>\n", dependencies: [{ kind: "component", type: LucideCalendar, selector: "svg[lucideCalendar]" }, { kind: "directive", type: ButtonDirective, selector: "button[monaButton]", inputs: ["aria-haspopup", "disabled", "iconOnly", "loading", "look", "rounded", "selected", "size", "tabindex", "toggleable", "type", "class"], outputs: ["lookChange", "selectedChange"] }, { kind: "component", type: CalendarComponent, selector: "mona-calendar", inputs: ["disabled", "disabledDates", "firstDay", "focusOnMount", "invalid", "maxDate", "minDate", "readonly", "required", "rounded", "selection", "touched", "class", "value", "weekNumber"], outputs: ["touch", "valueChange"] }, { kind: "component", type: TimeSelectorComponent, selector: "mona-time-selector", inputs: ["aria-label", "disabled", "focusOnMount", "footer", "hourFormat", "hourStep", "invalid", "max", "min", "minuteStep", "readonly", "required", "rounded", "secondStep", "showSeconds", "size", "touched", "value"], outputs: ["touch", "valueChange"] }, { kind: "component", type: TextBoxComponent, selector: "mona-text-box", inputs: ["aria-describedby", "aria-label", "aria-labelledby", "clearButton", "disabled", "inputAttributes", "inputClass", "inputId", "inputStyle", "invalid", "maxLength", "minLength", "name", "placeholder", "readonly", "required", "rounded", "size", "touched", "type", "class", "value"], outputs: ["inputBlur", "inputFocus", "touch", "valueChange"] }, { kind: "directive", type: TextBoxSuffixTemplateDirective, selector: "ng-template[monaTextBoxSuffixTemplate]" }, { kind: "directive", type: CdkTrapFocus, selector: "[cdkTrapFocus]", inputs: ["cdkTrapFocus", "cdkTrapFocusAutoCapture"], exportAs: ["cdkTrapFocus"] }, { kind: "directive", type: CalendarDecadeCellTemplateDirective, selector: "ng-template[monaCalendarDecadeCellTemplate]" }, { kind: "directive", type: CalendarMonthCellTemplateDirective, selector: "ng-template[monaCalendarMonthCellTemplate]" }, { kind: "directive", type: CalendarYearCellTemplateDirective, selector: "ng-template[monaCalendarYearCellTemplate]" }, { kind: "directive", type: NgTemplateOutlet, selector: "[ngTemplateOutlet]", inputs: ["ngTemplateOutletContext", "ngTemplateOutlet", "ngTemplateOutletInjector"] }, { kind: "directive", type: TextBoxPrefixTemplateDirective, selector: "ng-template[monaTextBoxPrefixTemplate]" }] }); }
651
649
  }
652
650
  i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "22.0.6", ngImport: i0, type: DateTimePickerComponent, decorators: [{
653
651
  type: Component,
@@ -667,7 +665,6 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "22.0.6", ngImpor
667
665
  TimeSelectorComponent,
668
666
  TextBoxComponent,
669
667
  TextBoxSuffixTemplateDirective,
670
- ButtonGroupComponent,
671
668
  CdkTrapFocus,
672
669
  CalendarDecadeCellTemplateDirective,
673
670
  CalendarMonthCellTemplateDirective,
@@ -675,6 +672,10 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "22.0.6", ngImpor
675
672
  NgTemplateOutlet,
676
673
  TextBoxPrefixTemplateDirective
677
674
  ], hostDirectives: [DropdownPopupHandlerDirective], host: {
675
+ // The ARIA inputs below are applied to the inner input, so the host must not keep the static attributes.
676
+ "[attr.aria-describedby]": "null",
677
+ "[attr.aria-label]": "null",
678
+ "[attr.aria-labelledby]": "null",
678
679
  "[attr.tabindex]": "disabled() ? null : -1",
679
680
  "[attr.aria-invalid]": "invalidState() ? 'true' : null",
680
681
  "[attr.data-disabled]": "disabled() || null",
@@ -682,9 +683,11 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "22.0.6", ngImpor
682
683
  "[attr.data-invalid]": "invalidState() || null",
683
684
  "[attr.data-readonly]": "readonly() || null",
684
685
  "[class]": "baseClass()",
685
- "(blur)": "onDateInputBlur()"
686
- }, template: "<mona-text-box\n (inputBlur)=\"onDateInputBlur()\"\n (valueChange)=\"onDateStringEdit($event)\"\n [clearButton]=\"showClearButton()\"\n [disabled]=\"disabled()\"\n [inputAttributes]=\"inputAttributes()\"\n [invalid]=\"invalid()\"\n [placeholder]=\"placeholder()\"\n [readonly]=\"readonly()\"\n [required]=\"required()\"\n [rounded]=\"rounded()\"\n [size]=\"size()\"\n [touched]=\"touched()\"\n [value]=\"currentDateString()\">\n @if (prefixTemplate()) {\n <ng-template monaTextBoxPrefixTemplate>\n <ng-container [ngTemplateOutlet]=\"prefixTemplate()\"></ng-container>\n </ng-template>\n }\n <ng-template monaTextBoxSuffixTemplate>\n <button\n monaButton\n look=\"ghost\"\n [iconOnly]=\"true\"\n [size]=\"size()\"\n [rounded]=\"'none'\"\n class=\"aspect-square h-full w-auto\"\n [attr.aria-label]=\"messages().openDateTimePicker\"\n [attr.aria-expanded]=\"expanded()\"\n [attr.aria-controls]=\"popupId\"\n (click)=\"onDateInputButtonClick()\"\n [disabled]=\"disabled() || readonly()\"\n [tabindex]=\"-1\">\n <svg lucideCalendar [size]=\"16\" aria-hidden=\"true\"></svg>\n </button>\n </ng-template>\n</mona-text-box>\n\n<ng-template #datePopupTemplate>\n <div\n [class]=\"pickerPopupClass()\"\n [id]=\"popupId\"\n class=\"flex h-68 flex-col\"\n aria-modal=\"true\"\n role=\"dialog\"\n [attr.aria-label]=\"messages().dateTimePicker\"\n cdkTrapFocus>\n <div [class]=\"headerClass()\">\n <mona-button-group\n selection=\"single\"\n [allowEmpty]=\"false\"\n class=\"w-full\"\n [disabled]=\"disabled()\"\n [size]=\"size()\"\n [rounded]=\"rounded()\"\n role=\"tablist\">\n <button monaButton [selected]=\"activeView() === 'date'\" (click)=\"activeView.set('date')\" role=\"tab\">\n {{ messages().date }}\n </button>\n <button monaButton [selected]=\"activeView() === 'time'\" (click)=\"activeView.set('time')\" role=\"tab\">\n {{ messages().time }}\n </button>\n </mona-button-group>\n </div>\n <div class=\"overflow-hidden\">\n @if (activeView() === \"date\") {\n <div class=\"flex h-full items-center justify-center\" [attr.aria-label]=\"messages().calendar\">\n <mona-calendar\n [disabledDates]=\"disabledDates()\"\n [minDate]=\"min()\"\n [maxDate]=\"max()\"\n [firstDay]=\"firstDay()\"\n [weekNumber]=\"weekNumber()\"\n [value]=\"navigatedDate()\"\n [disabled]=\"disabled()\"\n [readonly]=\"readonly()\"\n [rounded]=\"rounded()\"\n (valueChange)=\"onCalendarValueChange($event)\"\n class=\"flex-1 border-none shadow-none\">\n @if (decadeCellTemplate()) {\n <ng-template monaCalendarDecadeCellTemplate let-year>\n <ng-container\n [ngTemplateOutlet]=\"decadeCellTemplate()?.templateRef\"\n [ngTemplateOutletContext]=\"{ $implicit: year }\"></ng-container>\n </ng-template>\n }\n @if (monthCellTemplate()) {\n <ng-template monaCalendarMonthCellTemplate let-day let-date=\"date\">\n <ng-container\n [ngTemplateOutlet]=\"monthCellTemplate()?.templateRef\"\n [ngTemplateOutletContext]=\"{ $implicit: day, date }\"></ng-container>\n </ng-template>\n }\n @if (yearCellTemplate()) {\n <ng-template monaCalendarYearCellTemplate let-year let-text=\"text\">\n <ng-container\n [ngTemplateOutlet]=\"yearCellTemplate()?.templateRef\"\n [ngTemplateOutletContext]=\"{ $implicit: year, text }\"></ng-container>\n </ng-template>\n }\n </mona-calendar>\n </div>\n }\n @if (activeView() === \"time\") {\n <div class=\"flex h-full max-h-64 items-center justify-center\" [attr.aria-label]=\"messages().timePicker\">\n <mona-time-selector\n [value]=\"navigatedDate()\"\n (valueChange)=\"onTimeSelectorValueChange($event)\"\n [disabled]=\"disabled()\"\n [readonly]=\"readonly()\"\n [max]=\"timePickerMax()\"\n [min]=\"timePickerMin()\"\n [footer]=\"false\"\n [size]=\"size()\"\n [rounded]=\"rounded()\"\n [hourStep]=\"hourStep()\"\n [minuteStep]=\"minuteStep()\"\n [secondStep]=\"secondStep()\"\n [hourFormat]=\"hourFormat()\"\n [showSeconds]=\"showSeconds()\"></mona-time-selector>\n </div>\n }\n </div>\n <div [class]=\"footerClass()\">\n <button\n monaButton\n look=\"primary\"\n [disabled]=\"disabled()\"\n [rounded]=\"rounded()\"\n [size]=\"size()\"\n (click)=\"onSetDateClick()\">\n {{ messages().set }}\n </button>\n <button\n monaButton\n look=\"default\"\n [disabled]=\"disabled()\"\n [rounded]=\"rounded()\"\n [size]=\"size()\"\n (click)=\"onCancelClick()\">\n {{ messages().cancel }}\n </button>\n </div>\n </div>\n</ng-template>\n" }]
687
- }], ctorParameters: () => [], propDecorators: { decadeCellTemplate: [{ type: i0.ContentChild, args: [i0.forwardRef(() => CalendarDecadeCellTemplateDirective), { isSignal: true }] }], monthCellTemplate: [{ type: i0.ContentChild, args: [i0.forwardRef(() => CalendarMonthCellTemplateDirective), { isSignal: true }] }], popupTemplate: [{ type: i0.ViewChild, args: ["datePopupTemplate", { isSignal: true }] }], prefixTemplate: [{ type: i0.ContentChild, args: [i0.forwardRef(() => DateInputPrefixTemplateDirective), { ...{ read: TemplateRef }, isSignal: true }] }], yearCellTemplate: [{ type: i0.ContentChild, args: [i0.forwardRef(() => CalendarYearCellTemplateDirective), { isSignal: true }] }], close: [{ type: i0.Output, args: ["close"] }], closed: [{ type: i0.Output, args: ["closed"] }], disabled: [{ type: i0.Input, args: [{ isSignal: true, alias: "disabled", required: false }] }], disabledDates: [{ type: i0.Input, args: [{ isSignal: true, alias: "disabledDates", required: false }] }], firstDay: [{ type: i0.Input, args: [{ isSignal: true, alias: "firstDay", required: false }] }], format: [{ type: i0.Input, args: [{ isSignal: true, alias: "format", required: false }] }], hourFormat: [{ type: i0.Input, args: [{ isSignal: true, alias: "hourFormat", required: false }] }], hourStep: [{ type: i0.Input, args: [{ isSignal: true, alias: "hourStep", required: false }] }], invalid: [{ type: i0.Input, args: [{ isSignal: true, alias: "invalid", required: false }] }], max: [{ type: i0.Input, args: [{ isSignal: true, alias: "max", required: false }] }], min: [{ type: i0.Input, args: [{ isSignal: true, alias: "min", required: false }] }], minuteStep: [{ type: i0.Input, args: [{ isSignal: true, alias: "minuteStep", 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 }] }], readonlyInput: [{ type: i0.Input, args: [{ isSignal: true, alias: "readonlyInput", required: false }] }], required: [{ type: i0.Input, args: [{ isSignal: true, alias: "required", required: false }] }], rounded: [{ type: i0.Input, args: [{ isSignal: true, alias: "rounded", required: false }] }], secondStep: [{ type: i0.Input, args: [{ isSignal: true, alias: "secondStep", required: false }] }], showClearButton: [{ type: i0.Input, args: [{ isSignal: true, alias: "showClearButton", required: false }] }], showSeconds: [{ type: i0.Input, args: [{ isSignal: true, alias: "showSeconds", required: false }] }], size: [{ type: i0.Input, args: [{ isSignal: true, alias: "size", 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"] }], weekNumber: [{ type: i0.Input, args: [{ isSignal: true, alias: "weekNumber", required: false }] }] } });
686
+ "(focusin)": "onFocusIn($event)",
687
+ "(focusout)": "onFocusOut($event)",
688
+ "(keydown)": "onKeydown($event)"
689
+ }, template: "<mona-text-box\n (inputBlur)=\"onInputBlur()\"\n (valueChange)=\"typedInput.edit($event)\"\n [aria-describedby]=\"ariaDescribedBy()\"\n [aria-label]=\"ariaLabel()\"\n [aria-labelledby]=\"ariaLabelledBy()\"\n [clearButton]=\"showClearButton()\"\n [disabled]=\"disabled()\"\n [inputAttributes]=\"inputAttributes()\"\n [inputId]=\"inputId()\"\n [invalid]=\"invalidState()\"\n [placeholder]=\"placeholder()\"\n [readonly]=\"readonly()\"\n [required]=\"required()\"\n [rounded]=\"rounded()\"\n [size]=\"size()\"\n [touched]=\"invalidState() || touched()\"\n [value]=\"typedInput.text()\">\n @if (prefixTemplate()) {\n <ng-template monaTextBoxPrefixTemplate>\n <ng-container [ngTemplateOutlet]=\"prefixTemplate()\"></ng-container>\n </ng-template>\n }\n <ng-template monaTextBoxSuffixTemplate>\n <button\n monaButton\n look=\"ghost\"\n [iconOnly]=\"true\"\n [size]=\"size()\"\n [rounded]=\"'none'\"\n class=\"aspect-square h-full w-auto\"\n [attr.aria-label]=\"messages().openDateTimePicker\"\n [attr.aria-expanded]=\"expanded()\"\n [attr.aria-controls]=\"popupId\"\n (click)=\"onDateInputButtonClick()\"\n [disabled]=\"disabled() || readonly()\"\n [tabindex]=\"-1\">\n <svg lucideCalendar [size]=\"16\" aria-hidden=\"true\"></svg>\n </button>\n </ng-template>\n</mona-text-box>\n\n<ng-template #datePopupTemplate>\n <div\n [class]=\"pickerPopupClass()\"\n [id]=\"popupId\"\n class=\"flex h-68 flex-col\"\n aria-modal=\"true\"\n role=\"dialog\"\n [attr.aria-label]=\"messages().dateTimePicker\"\n cdkTrapFocus>\n <div [class]=\"headerClass()\">\n <div class=\"flex w-full gap-1\" role=\"tablist\" (keydown)=\"onTabKeydown($event)\">\n <button\n monaButton\n type=\"button\"\n role=\"tab\"\n class=\"flex-1\"\n [id]=\"dateTabId\"\n [attr.aria-controls]=\"panelId\"\n [attr.aria-selected]=\"activeView() === 'date'\"\n [disabled]=\"disabled()\"\n [rounded]=\"rounded()\"\n [selected]=\"activeView() === 'date'\"\n [size]=\"size()\"\n [tabindex]=\"activeView() === 'date' ? 0 : -1\"\n (click)=\"selectTab('date')\">\n {{ messages().date }}\n </button>\n <button\n monaButton\n type=\"button\"\n role=\"tab\"\n class=\"flex-1\"\n [id]=\"timeTabId\"\n [attr.aria-controls]=\"panelId\"\n [attr.aria-selected]=\"activeView() === 'time'\"\n [disabled]=\"disabled()\"\n [rounded]=\"rounded()\"\n [selected]=\"activeView() === 'time'\"\n [size]=\"size()\"\n [tabindex]=\"activeView() === 'time' ? 0 : -1\"\n (click)=\"selectTab('time')\">\n {{ messages().time }}\n </button>\n </div>\n </div>\n <div\n class=\"overflow-hidden\"\n role=\"tabpanel\"\n [id]=\"panelId\"\n [attr.aria-labelledby]=\"activeView() === 'date' ? dateTabId : timeTabId\">\n @if (activeView() === \"date\") {\n <div class=\"flex h-full items-center justify-center\">\n <mona-calendar\n [focusOnMount]=\"focusViewOnMount()\"\n [disabledDates]=\"disabledDates()\"\n [minDate]=\"min()\"\n [maxDate]=\"max()\"\n [firstDay]=\"firstDay()\"\n [weekNumber]=\"weekNumber()\"\n [value]=\"navigatedDate()\"\n [disabled]=\"disabled()\"\n [readonly]=\"readonly()\"\n [rounded]=\"rounded()\"\n (valueChange)=\"onCalendarValueChange($event)\"\n class=\"flex-1 border-none shadow-none\">\n @if (decadeCellTemplate()) {\n <ng-template monaCalendarDecadeCellTemplate let-year>\n <ng-container\n [ngTemplateOutlet]=\"decadeCellTemplate()?.templateRef\"\n [ngTemplateOutletContext]=\"{ $implicit: year }\"></ng-container>\n </ng-template>\n }\n @if (monthCellTemplate()) {\n <ng-template monaCalendarMonthCellTemplate let-day let-date=\"date\">\n <ng-container\n [ngTemplateOutlet]=\"monthCellTemplate()?.templateRef\"\n [ngTemplateOutletContext]=\"{ $implicit: day, date }\"></ng-container>\n </ng-template>\n }\n @if (yearCellTemplate()) {\n <ng-template monaCalendarYearCellTemplate let-year let-text=\"text\">\n <ng-container\n [ngTemplateOutlet]=\"yearCellTemplate()?.templateRef\"\n [ngTemplateOutletContext]=\"{ $implicit: year, text }\"></ng-container>\n </ng-template>\n }\n </mona-calendar>\n </div>\n }\n @if (activeView() === \"time\") {\n <div class=\"flex h-full max-h-64 items-center justify-center\">\n <mona-time-selector\n [focusOnMount]=\"focusViewOnMount()\"\n [value]=\"navigatedDate()\"\n (valueChange)=\"onTimeSelectorValueChange($event)\"\n [disabled]=\"disabled()\"\n [readonly]=\"readonly()\"\n [max]=\"timePickerMax()\"\n [min]=\"timePickerMin()\"\n [footer]=\"false\"\n [size]=\"size()\"\n [rounded]=\"rounded()\"\n [hourStep]=\"hourStep()\"\n [minuteStep]=\"minuteStep()\"\n [secondStep]=\"secondStep()\"\n [hourFormat]=\"effectiveHourFormat()\"\n [showSeconds]=\"showSeconds()\"></mona-time-selector>\n </div>\n }\n </div>\n <div [class]=\"footerClass()\">\n <button\n monaButton\n look=\"primary\"\n [disabled]=\"disabled()\"\n [rounded]=\"rounded()\"\n [size]=\"size()\"\n (click)=\"onSetDateClick()\">\n {{ messages().set }}\n </button>\n <button\n monaButton\n look=\"default\"\n [disabled]=\"disabled()\"\n [rounded]=\"rounded()\"\n [size]=\"size()\"\n (click)=\"onCancelClick()\">\n {{ messages().cancel }}\n </button>\n </div>\n </div>\n</ng-template>\n" }]
690
+ }], ctorParameters: () => [], propDecorators: { decadeCellTemplate: [{ type: i0.ContentChild, args: [i0.forwardRef(() => CalendarDecadeCellTemplateDirective), { isSignal: true }] }], monthCellTemplate: [{ type: i0.ContentChild, args: [i0.forwardRef(() => CalendarMonthCellTemplateDirective), { isSignal: true }] }], popupTemplate: [{ type: i0.ViewChild, args: ["datePopupTemplate", { isSignal: true }] }], prefixTemplate: [{ type: i0.ContentChild, args: [i0.forwardRef(() => DateInputPrefixTemplateDirective), { ...{ read: TemplateRef }, isSignal: true }] }], yearCellTemplate: [{ type: i0.ContentChild, args: [i0.forwardRef(() => CalendarYearCellTemplateDirective), { 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"] }], disabled: [{ type: i0.Input, args: [{ isSignal: true, alias: "disabled", required: false }] }], disabledDates: [{ type: i0.Input, args: [{ isSignal: true, alias: "disabledDates", required: false }] }], firstDay: [{ type: i0.Input, args: [{ isSignal: true, alias: "firstDay", required: false }] }], format: [{ type: i0.Input, args: [{ isSignal: true, alias: "format", required: false }] }], hourFormat: [{ type: i0.Input, args: [{ isSignal: true, alias: "hourFormat", required: false }] }], hourStep: [{ type: i0.Input, args: [{ isSignal: true, alias: "hourStep", required: false }] }], inputId: [{ type: i0.Input, args: [{ isSignal: true, alias: "inputId", required: false }] }], invalid: [{ type: i0.Input, args: [{ isSignal: true, alias: "invalid", required: false }] }], max: [{ type: i0.Input, args: [{ isSignal: true, alias: "max", required: false }] }], min: [{ type: i0.Input, args: [{ isSignal: true, alias: "min", required: false }] }], minuteStep: [{ type: i0.Input, args: [{ isSignal: true, alias: "minuteStep", 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 }] }], readonlyInput: [{ type: i0.Input, args: [{ isSignal: true, alias: "readonlyInput", required: false }] }], required: [{ type: i0.Input, args: [{ isSignal: true, alias: "required", required: false }] }], rounded: [{ type: i0.Input, args: [{ isSignal: true, alias: "rounded", required: false }] }], secondStep: [{ type: i0.Input, args: [{ isSignal: true, alias: "secondStep", required: false }] }], showClearButton: [{ type: i0.Input, args: [{ isSignal: true, alias: "showClearButton", required: false }] }], showSeconds: [{ type: i0.Input, args: [{ isSignal: true, alias: "showSeconds", required: false }] }], size: [{ type: i0.Input, args: [{ isSignal: true, alias: "size", 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"] }], weekNumber: [{ type: i0.Input, args: [{ isSignal: true, alias: "weekNumber", required: false }] }] } });
688
691
 
689
692
  /*
690
693
  * Public API Surface of @nanahoshi/mona-ui/datetime-picker