@nanahoshi/mona-ui 0.24.5 → 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 (23) hide show
  1. package/README.md +2 -0
  2. package/fesm2022/nanahoshi-mona-ui-calendar.mjs +196 -137
  3. package/fesm2022/nanahoshi-mona-ui-date-input.mjs +164 -3
  4. package/fesm2022/nanahoshi-mona-ui-date-picker.mjs +124 -140
  5. package/fesm2022/nanahoshi-mona-ui-datetime-picker.mjs +205 -202
  6. package/fesm2022/nanahoshi-mona-ui-filter.mjs +1 -1
  7. package/fesm2022/{nanahoshi-mona-ui-grid-grid-footer-row.component-BMCM0W8s.mjs → nanahoshi-mona-ui-grid-grid-footer-row.component-CD_ODHpU.mjs} +2 -2
  8. package/fesm2022/{nanahoshi-mona-ui-grid-grid-list.component-BSlV8Sua.mjs → nanahoshi-mona-ui-grid-grid-list.component-0jN7I1jo.mjs} +4 -4
  9. package/fesm2022/{nanahoshi-mona-ui-grid-grid-row.component-CTOdnH29.mjs → nanahoshi-mona-ui-grid-grid-row.component-BI_iE7pl.mjs} +3 -3
  10. package/fesm2022/{nanahoshi-mona-ui-grid-grid-virtual-list.component-C2kf5MwO.mjs → nanahoshi-mona-ui-grid-grid-virtual-list.component-Sa1aAtJ-.mjs} +4 -4
  11. package/fesm2022/{nanahoshi-mona-ui-grid-nanahoshi-mona-ui-grid-Dh42tUui.mjs → nanahoshi-mona-ui-grid-nanahoshi-mona-ui-grid-BvUM9nPt.mjs} +8 -8
  12. package/fesm2022/nanahoshi-mona-ui-grid.mjs +1 -1
  13. package/fesm2022/nanahoshi-mona-ui-numeric-text-box.mjs +195 -122
  14. package/fesm2022/nanahoshi-mona-ui-time-picker.mjs +149 -167
  15. package/fesm2022/nanahoshi-mona-ui-time-selector.mjs +182 -137
  16. package/package.json +2 -2
  17. package/types/nanahoshi-mona-ui-calendar.d.ts +30 -11
  18. package/types/nanahoshi-mona-ui-date-input.d.ts +74 -3
  19. package/types/nanahoshi-mona-ui-date-picker.d.ts +61 -33
  20. package/types/nanahoshi-mona-ui-datetime-picker.d.ts +79 -38
  21. package/types/nanahoshi-mona-ui-numeric-text-box.d.ts +57 -16
  22. package/types/nanahoshi-mona-ui-time-picker.d.ts +72 -42
  23. package/types/nanahoshi-mona-ui-time-selector.d.ts +78 -46
@@ -1,17 +1,16 @@
1
1
  import { CdkTrapFocus } from '@angular/cdk/a11y';
2
2
  import * as i0 from '@angular/core';
3
- import { inject, DestroyRef, ElementRef, computed, linkedSignal, signal, viewChild, output, input, model, afterNextRender, effect, untracked, forwardRef, Component } from '@angular/core';
3
+ import { inject, DestroyRef, ElementRef, computed, viewChild, input, output, booleanAttribute, model, afterNextRender, effect, untracked, forwardRef, Component } from '@angular/core';
4
4
  import { takeUntilDestroyed } from '@angular/core/rxjs-interop';
5
5
  import { LucideClock } from '@lucide/angular';
6
6
  import { ButtonDirective } from '@nanahoshi/mona-ui/button';
7
+ import { getLocaleHourFormat, createTypedDateInput } from '@nanahoshi/mona-ui/date-input';
7
8
  import * as i1 from '@nanahoshi/mona-ui/dropdowns';
8
9
  import { DropdownService, dropdownPopupThemeVariants, DROPDOWN_POPUP_INPUT_TOKEN, DropdownPopupHandlerDirective } from '@nanahoshi/mona-ui/dropdowns';
9
- import { MonaI18nService, gregorianDateTime, getLocaleTimeInputFormat, parseGregorianDate } from '@nanahoshi/mona-ui/i18n';
10
+ import { MonaI18nService, getLocaleTimeInputFormat } from '@nanahoshi/mona-ui/i18n';
10
11
  import { themeControlSurfaceClasses, createElementControlId } from '@nanahoshi/mona-ui/internal';
11
12
  import { TextBoxComponent, TextBoxSuffixTemplateDirective } from '@nanahoshi/mona-ui/text-box';
12
13
  import { TimeSelectorComponent } from '@nanahoshi/mona-ui/time-selector';
13
- import { DateTime } from 'luxon';
14
- import { fromEvent, filter } from 'rxjs';
15
14
  import { twMerge } from 'tailwind-merge';
16
15
  import { cva } from 'class-variance-authority';
17
16
 
@@ -81,13 +80,11 @@ class TimePickerComponent {
81
80
  #dropdownService;
82
81
  #hostElementRef;
83
82
  #i18n;
84
- #id;
85
83
  constructor() {
86
84
  this.#destroyRef = inject(DestroyRef);
87
85
  this.#dropdownService = inject(DropdownService);
88
86
  this.#hostElementRef = inject(ElementRef);
89
87
  this.#i18n = inject(MonaI18nService);
90
- this.#id = createElementControlId();
91
88
  this.baseClass = computed(() => {
92
89
  const focused = this.#dropdownService.popupRef() != null;
93
90
  const rounded = this.rounded();
@@ -97,49 +94,35 @@ class TimePickerComponent {
97
94
  return twMerge(variantClass, userClass);
98
95
  }, /* @ts-ignore */
99
96
  ...(ngDevMode ? [{ debugName: "baseClass" }] : /* istanbul ignore next */ []));
100
- this.currentDateString = linkedSignal(() => {
101
- const value = this.value();
102
- const format = this.effectiveFormat();
103
- const locale = this.#i18n.localeId();
104
- if (!value) {
105
- return "";
106
- }
107
- return gregorianDateTime(value, locale).toFormat(format);
108
- }, /* @ts-ignore */
109
- ...(ngDevMode ? [{ debugName: "currentDateString" }] : /* istanbul ignore next */ []));
110
97
  this.effectiveFormat = computed(() => {
111
98
  return (this.format() ??
112
99
  getLocaleTimeInputFormat(this.#i18n.localeId(), {
113
- hourFormat: this.hourFormat(),
100
+ hourFormat: this.effectiveHourFormat(),
114
101
  showSeconds: this.showSeconds()
115
102
  }));
116
103
  }, /* @ts-ignore */
117
104
  ...(ngDevMode ? [{ debugName: "effectiveFormat" }] : /* istanbul ignore next */ []));
105
+ this.effectiveHourFormat = computed(() => this.hourFormat() ?? getLocaleHourFormat(this.#i18n.localeId()), /* @ts-ignore */
106
+ ...(ngDevMode ? [{ debugName: "effectiveHourFormat" }] : /* istanbul ignore next */ []));
118
107
  this.expanded = computed(() => this.#dropdownService.popupRef() != null, /* @ts-ignore */
119
108
  ...(ngDevMode ? [{ debugName: "expanded" }] : /* istanbul ignore next */ []));
120
109
  this.inputAttributes = computed(() => {
121
- const controls = this.popupId;
122
- const expanded = this.#dropdownService.popupRef() != null;
123
- const hasPopup = "dialog";
124
- const invalid = this.invalidState();
125
110
  return {
126
111
  "aria-autocomplete": "none",
127
- "aria-controls": controls,
128
- "aria-expanded": expanded,
129
- "aria-haspopup": hasPopup,
130
- "aria-invalid": invalid,
131
- id: this.#id,
112
+ "aria-controls": this.popupId,
113
+ // The binder drops `false`, and a combobox must always say whether it's expanded.
114
+ "aria-expanded": this.expanded() ? "true" : "false",
115
+ "aria-haspopup": "dialog",
132
116
  // The text box hides its clear button when read-only, so typing is blocked here instead.
133
117
  readonly: this.readonly() || this.readonlyInput(),
134
118
  role: "combobox"
135
119
  };
136
120
  }, /* @ts-ignore */
137
121
  ...(ngDevMode ? [{ debugName: "inputAttributes" }] : /* istanbul ignore next */ []));
138
- this.invalidState = computed(() => this.touched() && (this.invalid() || (this.required() && !this.value())), /* @ts-ignore */
122
+ this.invalidState = computed(() => this.typedInput.errors().length > 0 ||
123
+ (this.touched() && (this.invalid() || (this.required() && !this.value()))), /* @ts-ignore */
139
124
  ...(ngDevMode ? [{ debugName: "invalidState" }] : /* istanbul ignore next */ []));
140
125
  this.messages = this.#i18n.componentMessages("timePicker", TIME_PICKER_DEFAULT_MESSAGES);
141
- this.navigatedDate = signal(new Date(), /* @ts-ignore */
142
- ...(ngDevMode ? [{ debugName: "navigatedDate" }] : /* istanbul ignore next */ []));
143
126
  this.pickerPopupClass = computed(() => {
144
127
  const rounded = this.rounded();
145
128
  const size = this.size();
@@ -151,6 +134,22 @@ class TimePickerComponent {
151
134
  this.popupId = createElementControlId();
152
135
  this.timePopupTemplateRef = viewChild.required("timePopupTemplate", /* @ts-ignore */
153
136
  ...(ngDevMode ? [{ debugName: "timePopupTemplateRef" }] : /* istanbul ignore next */ []));
137
+ /**
138
+ * @description Id of an element that describes the input, such as a hint or an error message.
139
+ * @default ""
140
+ */
141
+ this.ariaDescribedBy = input("", { ...(ngDevMode ? { debugName: "ariaDescribedBy" } : /* istanbul ignore next */ {}), alias: "aria-describedby" });
142
+ /**
143
+ * @description Accessible name of the input. Prefer a visible label, linked through {@link inputId} or
144
+ * {@link ariaLabelledBy}; the placeholder is not a label.
145
+ * @default ""
146
+ */
147
+ this.ariaLabel = input("", { ...(ngDevMode ? { debugName: "ariaLabel" } : /* istanbul ignore next */ {}), alias: "aria-label" });
148
+ /**
149
+ * @description Id of the element that labels the input.
150
+ * @default ""
151
+ */
152
+ this.ariaLabelledBy = input("", { ...(ngDevMode ? { debugName: "ariaLabelledBy" } : /* istanbul ignore next */ {}), alias: "aria-labelledby" });
154
153
  /**
155
154
  * @description Emits when the popup is about to close. This event is preventable.
156
155
  */
@@ -162,20 +161,22 @@ class TimePickerComponent {
162
161
  this.closed = output();
163
162
  /**
164
163
  * @description Sets the disabled state of the time picker.
164
+ * @default false
165
165
  */
166
- this.disabled = input(false, /* @ts-ignore */
167
- ...(ngDevMode ? [{ debugName: "disabled" }] : /* istanbul ignore next */ []));
166
+ this.disabled = input(false, { ...(ngDevMode ? { debugName: "disabled" } : /* istanbul ignore next */ {}), transform: booleanAttribute });
168
167
  /**
169
- * @description Sets the format of the time picker. If not specified, derives from the active locale, hourFormat, and showSeconds.
168
+ * @description Sets the format of the time picker. If not specified, derives from the active locale, hourFormat,
169
+ * and showSeconds. Typed text is also accepted with one-digit hours, minutes and seconds.
170
170
  * @default null
171
171
  */
172
172
  this.format = input(null, /* @ts-ignore */
173
173
  ...(ngDevMode ? [{ debugName: "format" }] : /* istanbul ignore next */ []));
174
174
  /**
175
- * @description Sets the hour format of the time picker.
176
- * @default 24
175
+ * @description Sets the hour format of the time picker. When null, the active locale's clock is used: 12-hour for
176
+ * en-US, 24-hour for de-DE.
177
+ * @default null
177
178
  */
178
- this.hourFormat = input("24", /* @ts-ignore */
179
+ this.hourFormat = input(null, /* @ts-ignore */
179
180
  ...(ngDevMode ? [{ debugName: "hourFormat" }] : /* istanbul ignore next */ []));
180
181
  /**
181
182
  * @description Sets the hour step of the time picker.
@@ -183,21 +184,29 @@ class TimePickerComponent {
183
184
  */
184
185
  this.hourStep = input(1, /* @ts-ignore */
185
186
  ...(ngDevMode ? [{ debugName: "hourStep" }] : /* istanbul ignore next */ []));
187
+ /**
188
+ * @description Id of the inner `<input>` element. Point a `<label for>` or `<mona-label for>` at it to label the
189
+ * time picker. A unique id is generated when it isn't set.
190
+ * @default generated
191
+ */
192
+ this.inputId = input(createElementControlId(), /* @ts-ignore */
193
+ ...(ngDevMode ? [{ debugName: "inputId" }] : /* istanbul ignore next */ []));
186
194
  /**
187
195
  * @description Marks the time picker as invalid. When bound to a signal form field via `[formField]`,
188
196
  * this is written by the `FormField` directive.
189
197
  * @default false
190
198
  */
191
- this.invalid = input(false, /* @ts-ignore */
192
- ...(ngDevMode ? [{ debugName: "invalid" }] : /* istanbul ignore next */ []));
199
+ this.invalid = input(false, { ...(ngDevMode ? { debugName: "invalid" } : /* istanbul ignore next */ {}), transform: booleanAttribute });
193
200
  /**
194
- * @description Sets the maximum date of the time picker.
195
- * @default null
201
+ * @description Sets the latest time of the time picker. Only the time of day is compared; a later typed time is
202
+ * reported as a `maxDate` error.
203
+ * @default undefined
196
204
  */
197
205
  this.max = input(undefined, { ...(ngDevMode ? { debugName: "max" } : /* istanbul ignore next */ {}), transform: value => (value instanceof Date ? value : undefined) });
198
206
  /**
199
- * @description Sets the minimum date of the time picker.
200
- * @default null
207
+ * @description Sets the earliest time of the time picker. Only the time of day is compared; an earlier typed time
208
+ * is reported as a `minDate` error.
209
+ * @default undefined
201
210
  */
202
211
  this.min = input(undefined, { ...(ngDevMode ? { debugName: "min" } : /* istanbul ignore next */ {}), transform: value => (value instanceof Date ? value : undefined) });
203
212
  /**
@@ -226,35 +235,33 @@ class TimePickerComponent {
226
235
  this.popupClass = input("", /* @ts-ignore */
227
236
  ...(ngDevMode ? [{ debugName: "popupClass" }] : /* istanbul ignore next */ []));
228
237
  /**
229
- * @description Sets the height of the popup element.
230
- * @default 200
238
+ * @description Sets the height of the popup element. When not set, the popup fits the time selector.
239
+ * @default undefined
231
240
  */
232
241
  this.popupHeight = input(/* @ts-ignore */
233
242
  ...(ngDevMode ? [undefined, { debugName: "popupHeight" }] : /* istanbul ignore next */ []));
234
243
  /**
235
- * @description Sets the width of the popup element.
236
- * @default null
244
+ * @description Sets the width of the popup element. When not set, the popup fits the time selector.
245
+ * @default undefined
237
246
  */
238
247
  this.popupWidth = input(/* @ts-ignore */
239
248
  ...(ngDevMode ? [undefined, { debugName: "popupWidth" }] : /* istanbul ignore next */ []));
240
249
  /**
241
250
  * @description Sets the readonly state of the time picker.
251
+ * @default false
242
252
  */
243
- this.readonly = input(false, /* @ts-ignore */
244
- ...(ngDevMode ? [{ debugName: "readonly" }] : /* istanbul ignore next */ []));
253
+ this.readonly = input(false, { ...(ngDevMode ? { debugName: "readonly" } : /* istanbul ignore next */ {}), transform: booleanAttribute });
245
254
  /**
246
255
  * @description When true, the input is readonly but the popup button remains enabled.
247
256
  * @default false
248
257
  */
249
- this.readonlyInput = input(false, /* @ts-ignore */
250
- ...(ngDevMode ? [{ debugName: "readonlyInput" }] : /* istanbul ignore next */ []));
258
+ this.readonlyInput = input(false, { ...(ngDevMode ? { debugName: "readonlyInput" } : /* istanbul ignore next */ {}), transform: booleanAttribute });
251
259
  /**
252
260
  * @description Sets the required state of the time picker.
253
261
  * When bound to a signal form field via `[formField]`, this is written by the `FormField` directive.
254
262
  * @default false
255
263
  */
256
- this.required = input(false, /* @ts-ignore */
257
- ...(ngDevMode ? [{ debugName: "required" }] : /* istanbul ignore next */ []));
264
+ this.required = input(false, { ...(ngDevMode ? { debugName: "required" } : /* istanbul ignore next */ {}), transform: booleanAttribute });
258
265
  /**
259
266
  * @description Sets the border radius of the time picker.
260
267
  */
@@ -267,22 +274,22 @@ class TimePickerComponent {
267
274
  this.secondStep = input(1, /* @ts-ignore */
268
275
  ...(ngDevMode ? [{ debugName: "secondStep" }] : /* istanbul ignore next */ []));
269
276
  /**
270
- * @description Sets the visibility of the clear button.
277
+ * @description Sets the visibility of the clear button. Clearing empties the value at once.
278
+ * @default false
271
279
  */
272
- this.showClearButton = input(false, /* @ts-ignore */
273
- ...(ngDevMode ? [{ debugName: "showClearButton" }] : /* istanbul ignore next */ []));
280
+ this.showClearButton = input(false, { ...(ngDevMode ? { debugName: "showClearButton" } : /* istanbul ignore next */ {}), transform: booleanAttribute });
274
281
  /**
275
282
  * @description Sets the visibility of the second selector.
283
+ * @default false
276
284
  */
277
- this.showSeconds = input(false, /* @ts-ignore */
278
- ...(ngDevMode ? [{ debugName: "showSeconds" }] : /* istanbul ignore next */ []));
285
+ this.showSeconds = input(false, { ...(ngDevMode ? { debugName: "showSeconds" } : /* istanbul ignore next */ {}), transform: booleanAttribute });
279
286
  /**
280
287
  * @description Sets the size of the time picker.
281
288
  */
282
289
  this.size = input("medium", /* @ts-ignore */
283
290
  ...(ngDevMode ? [{ debugName: "size" }] : /* istanbul ignore next */ []));
284
291
  /**
285
- * @description Emitted when the time picker is interacted with via blur, selection, or clear.
292
+ * @description Emitted when focus leaves the time picker and its popup.
286
293
  * The `FormField` directive listens to this to mark the field as touched.
287
294
  */
288
295
  this.touch = output();
@@ -291,90 +298,104 @@ class TimePickerComponent {
291
298
  * this is written by the `FormField` directive.
292
299
  * @default false
293
300
  */
294
- this.touched = input(false, /* @ts-ignore */
295
- ...(ngDevMode ? [{ debugName: "touched" }] : /* istanbul ignore next */ []));
301
+ this.touched = input(false, { ...(ngDevMode ? { debugName: "touched" } : /* istanbul ignore next */ {}), transform: booleanAttribute });
296
302
  this.userClass = input("", { ...(ngDevMode ? { debugName: "userClass" } : /* istanbul ignore next */ {}), alias: "class" });
297
303
  /**
298
- * @description Two-way bindable current time value.
304
+ * @description Two-way bindable current time value. Typed text is written on Enter and when the input loses
305
+ * focus, on the current value's day (today when empty); text that isn't a valid time keeps the previous value
306
+ * and marks the field invalid.
299
307
  * @default null
300
308
  */
301
309
  this.value = model(null, /* @ts-ignore */
302
310
  ...(ngDevMode ? [{ debugName: "value" }] : /* istanbul ignore next */ []));
311
+ this.typedInput = createTypedDateInput({
312
+ constraints: () => ({ max: this.max(), min: this.min(), unit: "time" }),
313
+ format: () => this.effectiveFormat(),
314
+ localeId: () => this.#i18n.localeId(),
315
+ resolve: (parsed, current) => {
316
+ const day = current ?? new Date();
317
+ return parsed
318
+ .set({ year: day.getFullYear(), month: day.getMonth() + 1, day: day.getDate() })
319
+ .toJSDate();
320
+ },
321
+ value: this.value
322
+ });
303
323
  afterNextRender({
304
- read: () => {
305
- this.setDateValues();
306
- this.setSubscriptions();
307
- }
324
+ read: () => this.setPopupCloseSubscription()
308
325
  });
309
326
  effect(() => {
310
327
  const popupTemplate = this.timePopupTemplateRef();
311
328
  untracked(() => this.#dropdownService.popupTemplate.set(popupTemplate));
312
329
  });
313
330
  }
314
- focus() {
331
+ /**
332
+ * Focuses the input and places the caret after the text. Read-only pickers take focus too.
333
+ * @param options Options passed to the native `focus()` call, such as `preventScroll`.
334
+ */
335
+ focus(options) {
315
336
  const input = this.#hostElementRef.nativeElement.querySelector("input");
316
- if (input && !this.readonly()) {
317
- input.focus();
337
+ if (input) {
338
+ input.focus(options);
318
339
  input.setSelectionRange(input.value.length, input.value.length);
319
340
  }
320
341
  }
321
- onDateStringEdit(dateString) {
322
- this.currentDateString.set(dateString);
342
+ onFocusIn(event) {
343
+ // The host is focusable only to pass focus on; focus inside it, such as a click in the text, stays put.
344
+ if (event.target === this.#hostElementRef.nativeElement) {
345
+ this.focus();
346
+ }
323
347
  }
324
- onTimeInputBlur() {
325
- if (this.#dropdownService.popupRef()) {
326
- this.touch.emit();
348
+ onFocusOut(event) {
349
+ // Removing a focused picker from the page fires focusout after it is destroyed.
350
+ if (this.#destroyRef.destroyed) {
327
351
  return;
328
352
  }
329
- this.processTimeInput(this.currentDateString());
353
+ const nextTarget = event.relatedTarget;
354
+ if (nextTarget instanceof Node) {
355
+ const popupElement = this.#dropdownService.popupRef()?.overlayRef.overlayElement;
356
+ if (this.#hostElementRef.nativeElement.contains(nextTarget) || popupElement?.contains(nextTarget)) {
357
+ return;
358
+ }
359
+ }
330
360
  this.touch.emit();
331
361
  }
332
- onTimeInputButtonClick() {
362
+ onInputBlur() {
363
+ this.typedInput.commit();
364
+ }
365
+ onKeydown(event) {
333
366
  if (this.disabled() || this.readonly()) {
334
367
  return;
335
368
  }
336
- this.openPopup();
337
- }
338
- onTimeSelectorValueChange(date) {
339
- this.setCurrentDate(date);
340
- this.#dropdownService.popupRef()?.close();
341
- this.focus();
342
- }
343
- dateStringEquals(date1, date2) {
344
- if (date1 && date2) {
345
- const locale = this.#i18n.localeId();
346
- return (gregorianDateTime(date1, locale).toFormat(this.effectiveFormat()) ===
347
- gregorianDateTime(date2, locale).toFormat(this.effectiveFormat()));
369
+ if (event.altKey && event.key === "ArrowDown") {
370
+ event.preventDefault();
371
+ this.openPopup();
348
372
  }
349
- return date1 === date2;
350
- }
351
- generateValidDateTime(dateString) {
352
- const value = this.value();
353
- const locale = this.#i18n.localeId();
354
- const valueDate = value ? gregorianDateTime(value, locale) : gregorianDateTime(new Date(), locale);
355
- let dateTime = parseGregorianDate(dateString, this.effectiveFormat(), locale);
356
- if (dateTime.isValid) {
357
- return dateTime.set({ year: valueDate.year, month: valueDate.month, day: valueDate.day });
373
+ else if ((event.altKey && event.key === "ArrowUp") || event.key === "Escape") {
374
+ if (this.expanded()) {
375
+ event.preventDefault();
376
+ this.#dropdownService.popupRef()?.close();
377
+ }
358
378
  }
359
- const maxDate = this.max();
360
- const minDate = this.min();
361
- const date = minDate ?? maxDate;
362
- if (date) {
363
- const newDate = gregorianDateTime(date, locale);
364
- dateTime = newDate.set({ year: valueDate.year, month: valueDate.month, day: valueDate.day });
365
- return dateTime;
379
+ else if (event.key === "Enter" && event.target instanceof HTMLInputElement) {
380
+ // Committed before a surrounding form submits; an IME uses Enter to confirm its text.
381
+ if (!event.isComposing && event.keyCode !== 229) {
382
+ this.typedInput.commit();
383
+ }
366
384
  }
367
- return null;
368
385
  }
369
- handleKeydown(e) {
386
+ onTimeInputButtonClick() {
370
387
  if (this.disabled() || this.readonly()) {
371
388
  return;
372
389
  }
373
- if (e.key === "ArrowDown" && e.altKey) {
374
- e.preventDefault();
375
- this.openPopup();
390
+ if (this.#dropdownService.popupRef()) {
391
+ this.#dropdownService.popupRef()?.close();
376
392
  return;
377
393
  }
394
+ this.openPopup();
395
+ }
396
+ onTimeSelectorValueChange(date) {
397
+ this.value.set(date);
398
+ this.#dropdownService.popupRef()?.close();
378
399
  }
379
400
  openPopup() {
380
401
  if (this.#dropdownService.popupRef()) {
@@ -385,71 +406,26 @@ class TimePickerComponent {
385
406
  width: this.popupWidth() || "auto"
386
407
  });
387
408
  }
388
- processTimeInput(inputText) {
389
- const dateTime = this.generateValidDateTime(inputText);
390
- if (!dateTime) {
391
- this.setCurrentDate(null);
392
- return;
393
- }
394
- if (this.dateStringEquals(dateTime.toJSDate(), this.value())) {
395
- this.setCurrentDateString(this.value());
396
- return;
397
- }
398
- if (dateTime.isValid) {
399
- this.setCurrentDate(dateTime.toJSDate());
400
- this.navigatedDate.set(dateTime.toJSDate());
401
- }
402
- else {
403
- this.setCurrentDate(null);
404
- }
405
- }
406
- setCurrentDate(date) {
407
- this.value.set(date);
408
- this.setCurrentDateString(date);
409
- this.touch.emit();
410
- }
411
- setCurrentDateString(date) {
412
- this.updateCurrentDateString(date, this.effectiveFormat());
413
- }
414
- setDateValues() {
415
- const value = this.value();
416
- const locale = this.#i18n.localeId();
417
- this.navigatedDate.set(value ?? DateTime.now().setLocale(locale).toJSDate());
418
- if (value) {
419
- this.updateCurrentDateString(value, this.effectiveFormat());
420
- }
421
- }
422
- setKeyboardNavigation() {
423
- fromEvent(this.#hostElementRef.nativeElement, "keydown")
424
- .pipe(takeUntilDestroyed(this.#destroyRef))
425
- .subscribe(e => this.handleKeydown(e));
426
- }
427
- setSubscriptions() {
428
- this.setKeyboardNavigation();
429
- fromEvent(this.#hostElementRef.nativeElement, "focusin")
430
- .pipe(takeUntilDestroyed(this.#destroyRef))
431
- .subscribe(() => this.focus());
432
- this.#dropdownService.popupCloseComplete$
433
- .pipe(filter(() => this.#dropdownService.focusCanReturn()), takeUntilDestroyed(this.#destroyRef))
434
- .subscribe(() => this.focus());
435
- }
436
- updateCurrentDateString(date, format) {
437
- if (!date) {
438
- this.currentDateString.set("");
439
- return;
440
- }
441
- const dateString = gregorianDateTime(date, this.#i18n.localeId()).toFormat(format);
442
- this.currentDateString.set(dateString);
409
+ setPopupCloseSubscription() {
410
+ this.#dropdownService.popupCloseComplete$.pipe(takeUntilDestroyed(this.#destroyRef)).subscribe(() => {
411
+ if (this.#dropdownService.focusCanReturn()) {
412
+ this.focus();
413
+ }
414
+ else if (!this.#destroyRef.destroyed) {
415
+ // Focus left from inside the popup, which the host's focusout doesn't see.
416
+ this.touch.emit();
417
+ }
418
+ });
443
419
  }
444
420
  static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "22.0.6", ngImport: i0, type: TimePickerComponent, deps: [], target: i0.ɵɵFactoryTarget.Component }); }
445
- static { this.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.2.0", version: "22.0.6", type: TimePickerComponent, isStandalone: true, selector: "mona-time-picker", inputs: { disabled: { classPropertyName: "disabled", publicName: "disabled", 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 } }, outputs: { close: "close", closed: "closed", open: "open", opened: "opened", touch: "touch", value: "valueChange" }, host: { listeners: { "blur": "onTimeInputBlur()" }, 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: [
421
+ static { this.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.2.0", version: "22.0.6", type: TimePickerComponent, isStandalone: true, selector: "mona-time-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 }, 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 } }, 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: [
446
422
  DropdownService,
447
423
  {
448
424
  provide: DROPDOWN_POPUP_INPUT_TOKEN,
449
425
  useExisting: forwardRef(() => TimePickerComponent),
450
426
  multi: false
451
427
  }
452
- ], viewQueries: [{ propertyName: "timePopupTemplateRef", first: true, predicate: ["timePopupTemplate"], descendants: true, isSignal: true }], hostDirectives: [{ directive: i1.DropdownPopupHandlerDirective }], ngImport: i0, template: "<mona-text-box\n [disabled]=\"disabled()\"\n [readonly]=\"readonly()\"\n [required]=\"required()\"\n [value]=\"currentDateString()\"\n [inputAttributes]=\"inputAttributes()\"\n [invalid]=\"invalid()\"\n [placeholder]=\"placeholder()\"\n [rounded]=\"rounded()\"\n [size]=\"size()\"\n [touched]=\"touched()\"\n [clearButton]=\"showClearButton()\"\n (valueChange)=\"onDateStringEdit($event)\"\n (inputBlur)=\"onTimeInputBlur()\">\n <ng-template monaTextBoxSuffixTemplate>\n <button\n monaButton\n look=\"ghost\"\n [iconOnly]=\"true\"\n [size]=\"size()\"\n [rounded]=\"'none'\"\n (click)=\"onTimeInputButtonClick()\"\n class=\"aspect-square h-full w-auto\"\n [attr.aria-label]=\"messages().openTimePicker\"\n [attr.aria-expanded]=\"expanded()\"\n [attr.aria-controls]=\"popupId\"\n [disabled]=\"disabled() || readonly()\"\n [tabindex]=\"-1\">\n <svg lucideClock [size]=\"16\" aria-hidden=\"true\"></svg>\n </button>\n </ng-template>\n</mona-text-box>\n\n<ng-template #timePopupTemplate>\n <div\n [class]=\"pickerPopupClass()\"\n [id]=\"popupId\"\n aria-modal=\"true\"\n role=\"dialog\"\n [attr.aria-label]=\"messages().timePicker\"\n cdkTrapFocus>\n <mona-time-selector\n [value]=\"value()\"\n (valueChange)=\"onTimeSelectorValueChange($event)\"\n [max]=\"max()\"\n [min]=\"min()\"\n [disabled]=\"disabled()\"\n [readonly]=\"readonly()\"\n [hourFormat]=\"hourFormat()\"\n [hourStep]=\"hourStep()\"\n [minuteStep]=\"minuteStep()\"\n [secondStep]=\"secondStep()\"\n [size]=\"size()\"\n [rounded]=\"rounded()\"\n [showSeconds]=\"showSeconds()\"></mona-time-selector>\n </div>\n</ng-template>\n", dependencies: [{ kind: "component", type: LucideClock, selector: "svg[lucideClock]" }, { 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: 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"] }] }); }
428
+ ], viewQueries: [{ propertyName: "timePopupTemplateRef", first: true, predicate: ["timePopupTemplate"], descendants: true, isSignal: true }], hostDirectives: [{ directive: i1.DropdownPopupHandlerDirective }], ngImport: i0, template: "<mona-text-box\n [aria-describedby]=\"ariaDescribedBy()\"\n [aria-label]=\"ariaLabel()\"\n [aria-labelledby]=\"ariaLabelledBy()\"\n [disabled]=\"disabled()\"\n [inputId]=\"inputId()\"\n [readonly]=\"readonly()\"\n [required]=\"required()\"\n [value]=\"typedInput.text()\"\n [inputAttributes]=\"inputAttributes()\"\n [invalid]=\"invalidState()\"\n [placeholder]=\"placeholder()\"\n [rounded]=\"rounded()\"\n [size]=\"size()\"\n [touched]=\"invalidState() || touched()\"\n [clearButton]=\"showClearButton()\"\n (valueChange)=\"typedInput.edit($event)\"\n (inputBlur)=\"onInputBlur()\">\n <ng-template monaTextBoxSuffixTemplate>\n <button\n monaButton\n look=\"ghost\"\n [iconOnly]=\"true\"\n [size]=\"size()\"\n [rounded]=\"'none'\"\n (click)=\"onTimeInputButtonClick()\"\n class=\"aspect-square h-full w-auto\"\n [attr.aria-label]=\"messages().openTimePicker\"\n [attr.aria-expanded]=\"expanded()\"\n [attr.aria-controls]=\"popupId\"\n [disabled]=\"disabled() || readonly()\"\n [tabindex]=\"-1\">\n <svg lucideClock [size]=\"16\" aria-hidden=\"true\"></svg>\n </button>\n </ng-template>\n</mona-text-box>\n\n<ng-template #timePopupTemplate>\n <div\n [class]=\"pickerPopupClass()\"\n [id]=\"popupId\"\n aria-modal=\"true\"\n role=\"dialog\"\n [attr.aria-label]=\"messages().timePicker\"\n cdkTrapFocus>\n <mona-time-selector\n focusOnMount\n [value]=\"value()\"\n (valueChange)=\"onTimeSelectorValueChange($event)\"\n [max]=\"max()\"\n [min]=\"min()\"\n [disabled]=\"disabled()\"\n [readonly]=\"readonly()\"\n [hourFormat]=\"effectiveHourFormat()\"\n [hourStep]=\"hourStep()\"\n [minuteStep]=\"minuteStep()\"\n [secondStep]=\"secondStep()\"\n [size]=\"size()\"\n [rounded]=\"rounded()\"\n [showSeconds]=\"showSeconds()\"></mona-time-selector>\n </div>\n</ng-template>\n", dependencies: [{ kind: "component", type: LucideClock, selector: "svg[lucideClock]" }, { 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: 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"] }] }); }
453
429
  }
454
430
  i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "22.0.6", ngImport: i0, type: TimePickerComponent, decorators: [{
455
431
  type: Component,
@@ -468,6 +444,10 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "22.0.6", ngImpor
468
444
  TextBoxSuffixTemplateDirective,
469
445
  CdkTrapFocus
470
446
  ], hostDirectives: [DropdownPopupHandlerDirective], host: {
447
+ // The ARIA inputs below are applied to the inner input, so the host must not keep the static attributes.
448
+ "[attr.aria-describedby]": "null",
449
+ "[attr.aria-label]": "null",
450
+ "[attr.aria-labelledby]": "null",
471
451
  "[attr.tabindex]": "disabled() ? null : -1",
472
452
  "[attr.aria-invalid]": "invalidState() ? 'true' : null",
473
453
  "[attr.data-disabled]": "disabled() || null",
@@ -475,9 +455,11 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "22.0.6", ngImpor
475
455
  "[attr.data-invalid]": "invalidState() || null",
476
456
  "[attr.data-readonly]": "readonly() || null",
477
457
  "[class]": "baseClass()",
478
- "(blur)": "onTimeInputBlur()"
479
- }, template: "<mona-text-box\n [disabled]=\"disabled()\"\n [readonly]=\"readonly()\"\n [required]=\"required()\"\n [value]=\"currentDateString()\"\n [inputAttributes]=\"inputAttributes()\"\n [invalid]=\"invalid()\"\n [placeholder]=\"placeholder()\"\n [rounded]=\"rounded()\"\n [size]=\"size()\"\n [touched]=\"touched()\"\n [clearButton]=\"showClearButton()\"\n (valueChange)=\"onDateStringEdit($event)\"\n (inputBlur)=\"onTimeInputBlur()\">\n <ng-template monaTextBoxSuffixTemplate>\n <button\n monaButton\n look=\"ghost\"\n [iconOnly]=\"true\"\n [size]=\"size()\"\n [rounded]=\"'none'\"\n (click)=\"onTimeInputButtonClick()\"\n class=\"aspect-square h-full w-auto\"\n [attr.aria-label]=\"messages().openTimePicker\"\n [attr.aria-expanded]=\"expanded()\"\n [attr.aria-controls]=\"popupId\"\n [disabled]=\"disabled() || readonly()\"\n [tabindex]=\"-1\">\n <svg lucideClock [size]=\"16\" aria-hidden=\"true\"></svg>\n </button>\n </ng-template>\n</mona-text-box>\n\n<ng-template #timePopupTemplate>\n <div\n [class]=\"pickerPopupClass()\"\n [id]=\"popupId\"\n aria-modal=\"true\"\n role=\"dialog\"\n [attr.aria-label]=\"messages().timePicker\"\n cdkTrapFocus>\n <mona-time-selector\n [value]=\"value()\"\n (valueChange)=\"onTimeSelectorValueChange($event)\"\n [max]=\"max()\"\n [min]=\"min()\"\n [disabled]=\"disabled()\"\n [readonly]=\"readonly()\"\n [hourFormat]=\"hourFormat()\"\n [hourStep]=\"hourStep()\"\n [minuteStep]=\"minuteStep()\"\n [secondStep]=\"secondStep()\"\n [size]=\"size()\"\n [rounded]=\"rounded()\"\n [showSeconds]=\"showSeconds()\"></mona-time-selector>\n </div>\n</ng-template>\n" }]
480
- }], ctorParameters: () => [], propDecorators: { timePopupTemplateRef: [{ type: i0.ViewChild, args: ["timePopupTemplate", { 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 }] }], 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"] }] } });
458
+ "(focusin)": "onFocusIn($event)",
459
+ "(focusout)": "onFocusOut($event)",
460
+ "(keydown)": "onKeydown($event)"
461
+ }, template: "<mona-text-box\n [aria-describedby]=\"ariaDescribedBy()\"\n [aria-label]=\"ariaLabel()\"\n [aria-labelledby]=\"ariaLabelledBy()\"\n [disabled]=\"disabled()\"\n [inputId]=\"inputId()\"\n [readonly]=\"readonly()\"\n [required]=\"required()\"\n [value]=\"typedInput.text()\"\n [inputAttributes]=\"inputAttributes()\"\n [invalid]=\"invalidState()\"\n [placeholder]=\"placeholder()\"\n [rounded]=\"rounded()\"\n [size]=\"size()\"\n [touched]=\"invalidState() || touched()\"\n [clearButton]=\"showClearButton()\"\n (valueChange)=\"typedInput.edit($event)\"\n (inputBlur)=\"onInputBlur()\">\n <ng-template monaTextBoxSuffixTemplate>\n <button\n monaButton\n look=\"ghost\"\n [iconOnly]=\"true\"\n [size]=\"size()\"\n [rounded]=\"'none'\"\n (click)=\"onTimeInputButtonClick()\"\n class=\"aspect-square h-full w-auto\"\n [attr.aria-label]=\"messages().openTimePicker\"\n [attr.aria-expanded]=\"expanded()\"\n [attr.aria-controls]=\"popupId\"\n [disabled]=\"disabled() || readonly()\"\n [tabindex]=\"-1\">\n <svg lucideClock [size]=\"16\" aria-hidden=\"true\"></svg>\n </button>\n </ng-template>\n</mona-text-box>\n\n<ng-template #timePopupTemplate>\n <div\n [class]=\"pickerPopupClass()\"\n [id]=\"popupId\"\n aria-modal=\"true\"\n role=\"dialog\"\n [attr.aria-label]=\"messages().timePicker\"\n cdkTrapFocus>\n <mona-time-selector\n focusOnMount\n [value]=\"value()\"\n (valueChange)=\"onTimeSelectorValueChange($event)\"\n [max]=\"max()\"\n [min]=\"min()\"\n [disabled]=\"disabled()\"\n [readonly]=\"readonly()\"\n [hourFormat]=\"effectiveHourFormat()\"\n [hourStep]=\"hourStep()\"\n [minuteStep]=\"minuteStep()\"\n [secondStep]=\"secondStep()\"\n [size]=\"size()\"\n [rounded]=\"rounded()\"\n [showSeconds]=\"showSeconds()\"></mona-time-selector>\n </div>\n</ng-template>\n" }]
462
+ }], ctorParameters: () => [], propDecorators: { timePopupTemplateRef: [{ type: i0.ViewChild, args: ["timePopupTemplate", { 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 }] }], 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"] }] } });
481
463
 
482
464
  /*
483
465
  * Public API Surface of @nanahoshi/mona-ui/time-picker