quang 19.3.16-1 → 19.4.0

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.
@@ -1,6 +1,6 @@
1
1
  import { NgClass } from '@angular/common';
2
2
  import * as i0 from '@angular/core';
3
- import { input, viewChild, computed, signal, inject, effect, forwardRef, Optional, ChangeDetectionStrategy, Component } from '@angular/core';
3
+ import { inject, NgZone, ChangeDetectorRef, ApplicationRef, input, viewChild, computed, signal, effect, forwardRef, ChangeDetectionStrategy, Component } from '@angular/core';
4
4
  import { takeUntilDestroyed } from '@angular/core/rxjs-interop';
5
5
  import { NG_VALUE_ACCESSOR } from '@angular/forms';
6
6
  import { TranslocoPipe } from '@jsverse/transloco';
@@ -28,6 +28,10 @@ import { QuangBaseComponent } from 'quang/components/shared';
28
28
  class QuangDateComponent extends QuangBaseComponent {
29
29
  constructor() {
30
30
  super();
31
+ this._ngZone = inject(NgZone);
32
+ this._cdr = inject(ChangeDetectorRef);
33
+ this._appRef = inject(ApplicationRef);
34
+ this._tickScheduled = false;
31
35
  /**
32
36
  * Format to use to show on the input field.
33
37
  * The format is based on the standard {@link https://www.unicode.org/reports/tr35/tr35-dates.html#Date_Field_Symbol_Table}
@@ -70,7 +74,7 @@ class QuangDateComponent extends QuangBaseComponent {
70
74
  this._inputForDate = viewChild('inputForDate');
71
75
  this.contentTemplate = viewChild.required('calendarButton');
72
76
  this.hasNoContent = computed(() => this.contentTemplate()?.nativeElement.children.length === 0);
73
- this._quangTranslationService = signal(inject(QuangTranslationService));
77
+ this._quangTranslationService = signal(inject(QuangTranslationService, { optional: true }) ?? undefined);
74
78
  this._quangTranslationActiveLang = computed(() => this._quangTranslationService()?.activeLang() ?? null);
75
79
  this.multipleDatesSeparator = input(' - ');
76
80
  this.rangeSelection = input(false);
@@ -84,6 +88,9 @@ class QuangDateComponent extends QuangBaseComponent {
84
88
  return navigator.language;
85
89
  });
86
90
  this._airDatepickerInstance = signal(undefined);
91
+ // AirDatepicker doesn't reliably support toggling `inline` at runtime via `update()`.
92
+ // Track the mode used to create the current instance and recreate when it changes.
93
+ this._airDatepickerInlineMode = signal(null);
87
94
  this.searchTextDebounce = input(500);
88
95
  this.targetPosition = signal('bottom left');
89
96
  this._generateAirDatepickerEffect = effect(() => {
@@ -96,6 +103,7 @@ class QuangDateComponent extends QuangBaseComponent {
96
103
  this.showTimepicker = computed(() => !this.rangeSelection() && (this.timepicker() || this.showOnlyTimepicker()));
97
104
  this.isMouseInsideCalendar = signal(false);
98
105
  this.isMouseOutsideCalendar = computed(() => !this.isMouseInsideCalendar());
106
+ this._shouldRefocusInputOnHide = signal(false);
99
107
  fromEvent(document, 'scroll', { capture: true })
100
108
  .pipe(takeUntilDestroyed(), debounceTime(250))
101
109
  .subscribe(() => {
@@ -105,111 +113,147 @@ class QuangDateComponent extends QuangBaseComponent {
105
113
  });
106
114
  }
107
115
  setupCalendar() {
108
- if (this._inputForDate()?.nativeElement) {
109
- let currentValue = this._value();
110
- let targetDate;
111
- if (currentValue && typeof currentValue === 'string') {
112
- if (!this.showTimepicker()) {
113
- currentValue = currentValue.split('T')[0];
114
- }
115
- targetDate = [currentValue];
116
+ if (!this._inputForDate()?.nativeElement)
117
+ return;
118
+ const desiredInlineMode = this.showInline();
119
+ const existingInstance = this._airDatepickerInstance();
120
+ const existingInlineMode = this._airDatepickerInlineMode();
121
+ if (existingInstance && existingInlineMode !== null && existingInlineMode !== desiredInlineMode) {
122
+ const maybeDestroy = existingInstance;
123
+ maybeDestroy.destroy?.();
124
+ this._airDatepickerInstance.set(undefined);
125
+ }
126
+ let currentValue = this._value();
127
+ let targetDate;
128
+ if (currentValue && typeof currentValue === 'string') {
129
+ if (!this.showTimepicker()) {
130
+ currentValue = currentValue.split('T')[0];
116
131
  }
117
- else if (currentValue && typeof currentValue === 'object') {
118
- targetDate = [];
119
- if (currentValue.dateFrom) {
120
- let targetDateFrom = currentValue.dateFrom;
121
- if (!this.showTimepicker()) {
122
- targetDateFrom = currentValue.dateFrom.split('T')[0];
123
- }
124
- targetDate.push(targetDateFrom);
125
- }
126
- if (currentValue.dateTo) {
127
- let targetDateTo = currentValue.dateTo;
128
- if (!this.showTimepicker()) {
129
- targetDateTo = currentValue.dateTo.split('T')[0];
130
- }
131
- targetDate.push(targetDateTo);
132
- }
132
+ targetDate = [currentValue];
133
+ }
134
+ else if (currentValue && typeof currentValue === 'object') {
135
+ targetDate = [];
136
+ if (currentValue.dateFrom) {
137
+ const targetDateFrom = this.showTimepicker()
138
+ ? currentValue.dateFrom
139
+ : currentValue.dateFrom.split('T')[0];
140
+ targetDate.push(targetDateFrom);
133
141
  }
134
- this.setCalendarPosition();
135
- const airDatepickerOpts = {
136
- autoClose: true,
137
- classes: this.calendarClasses(),
138
- dateFormat: this.dateFormat(),
139
- inline: this.showInline(),
140
- isMobile: false,
141
- multipleDatesSeparator: this.multipleDatesSeparator(),
142
- range: this.rangeSelection(),
143
- timepicker: this.showTimepicker(),
144
- onlyTimepicker: this.showOnlyTimepicker(),
145
- timeFormat: this.timeFormat(),
146
- minHours: this.minHour(),
147
- maxHours: this.maxHour(),
148
- minMinutes: this.minMinute(),
149
- maxMinutes: this.maxMinute(),
150
- minDate: this.minDate(),
151
- maxDate: this.maxDate(),
152
- toggleSelected: false,
153
- multipleDates: false,
154
- selectedDates: targetDate,
155
- position: this.targetPosition(),
156
- locale: this.getLocale(),
157
- onSelect: ({ date }) => {
158
- if (!Array.isArray(date)) {
159
- let selectTargetDate = date;
160
- if (!this.showTimepicker()) {
161
- selectTargetDate = this.dateToUtc(date);
142
+ if (currentValue.dateTo) {
143
+ const targetDateTo = this.showTimepicker() ? currentValue.dateTo : currentValue.dateTo.split('T')[0];
144
+ targetDate.push(targetDateTo);
145
+ }
146
+ }
147
+ this.setCalendarPosition();
148
+ const userDatepickerOptions = this.datepickerOptions() ?? {};
149
+ const userOnSelect = userDatepickerOptions.onSelect;
150
+ const userOnHide = userDatepickerOptions.onHide;
151
+ const userOnShow = userDatepickerOptions.onShow;
152
+ const airDatepickerOpts = {
153
+ ...userDatepickerOptions,
154
+ autoClose: !this.showInline(),
155
+ showEvent: 'click',
156
+ classes: this.calendarClasses(),
157
+ dateFormat: this.dateFormat(),
158
+ inline: this.showInline(),
159
+ isMobile: false,
160
+ multipleDatesSeparator: this.multipleDatesSeparator(),
161
+ range: this.rangeSelection(),
162
+ timepicker: this.showTimepicker(),
163
+ onlyTimepicker: this.showOnlyTimepicker(),
164
+ timeFormat: this.timeFormat(),
165
+ minHours: this.minHour(),
166
+ maxHours: this.maxHour(),
167
+ minMinutes: this.minMinute(),
168
+ maxMinutes: this.maxMinute(),
169
+ minDate: this.minDate(),
170
+ maxDate: this.maxDate(),
171
+ toggleSelected: false,
172
+ multipleDates: false,
173
+ selectedDates: targetDate,
174
+ position: this.targetPosition(),
175
+ locale: this.getLocale(),
176
+ onSelect: (args) => {
177
+ const { date } = args;
178
+ // AirDatepicker callbacks may fire outside Angular's zone in some app setups.
179
+ // Ensure CVA propagation happens inside the zone so the connected FormControl updates reliably.
180
+ this._ngZone.run(() => {
181
+ this._shouldRefocusInputOnHide.set(true);
182
+ if (Array.isArray(date)) {
183
+ // Range selection: AirDatepicker emits partial selections too (only start date).
184
+ // Committing `_value` for partial selections can trigger `setupCalendar()` re-sync and
185
+ // break the second click. Only commit once the range is complete.
186
+ const [from, to] = date;
187
+ if (!from || !to) {
188
+ return;
162
189
  }
190
+ const value = {
191
+ dateFrom: (this.showTimepicker() ? from : this.dateToUtc(from)).toISOString(),
192
+ dateTo: (this.showTimepicker() ? to : this.dateToUtc(to)).toISOString(),
193
+ };
194
+ this.onChangedHandler(value);
195
+ }
196
+ else if (date) {
197
+ const selectTargetDate = this.showTimepicker() ? date : this.dateToUtc(date);
163
198
  this.onChangedHandler(selectTargetDate.toISOString());
164
199
  }
165
200
  if (this.showInline()) {
166
- this.onHideCalendar();
167
- }
168
- },
169
- onHide: (isAnimationComplete) => {
170
- if (isAnimationComplete) {
171
- this.onHideCalendar();
201
+ // Inline mode should update the connected control immediately.
202
+ // Do not rely on `onHideCalendar()` because inline never hides and the input may be visually hidden.
203
+ this.propagateValueToControl();
172
204
  }
173
- },
174
- ...(this.datepickerOptions() ?? {}),
175
- onShow: (isAnimationComplete) => {
176
- const datepicker = this._airDatepickerInstance()?.$datepicker;
177
- if (datepicker) {
178
- datepicker.onmouseenter = () => {
179
- this.isMouseInsideCalendar.set(true);
180
- };
181
- datepicker.onmouseleave = () => {
182
- this.isMouseInsideCalendar.set(false);
183
- };
184
- }
185
- if (isAnimationComplete || !this.showTimepicker()) {
186
- return;
187
- }
188
- this.setupTimepicker();
189
- },
190
- };
191
- if (this._airDatepickerInstance()) {
192
- if (this._airDatepickerInstance()?.visible) {
193
- this._airDatepickerInstance()?.update(airDatepickerOpts);
205
+ });
206
+ userOnSelect?.(args);
207
+ },
208
+ onHide: (isAnimationComplete) => {
209
+ if (isAnimationComplete) {
210
+ this.onHideCalendar();
194
211
  }
195
- else {
196
- this._airDatepickerInstance()?.update(airDatepickerOpts, { silent: true });
212
+ userOnHide?.(isAnimationComplete);
213
+ },
214
+ onShow: (isAnimationComplete) => {
215
+ const datepicker = this._airDatepickerInstance()?.$datepicker;
216
+ if (datepicker) {
217
+ datepicker.onmouseenter = () => {
218
+ this.isMouseInsideCalendar.set(true);
219
+ };
220
+ datepicker.onmouseleave = () => {
221
+ this.isMouseInsideCalendar.set(false);
222
+ };
197
223
  }
198
- if (!targetDate) {
199
- this._airDatepickerInstance()?.setFocusDate(false);
200
- this._airDatepickerInstance()?.clear({ silent: true });
201
- }
202
- else {
203
- this._airDatepickerInstance()?.selectDate(targetDate, { updateTime: true });
224
+ if (isAnimationComplete || !this.showTimepicker()) {
225
+ return;
204
226
  }
227
+ this.setupTimepicker();
228
+ userOnShow?.(isAnimationComplete);
229
+ },
230
+ };
231
+ if (this._airDatepickerInstance()) {
232
+ if (this._airDatepickerInstance()?.visible) {
233
+ this._airDatepickerInstance()?.update(airDatepickerOpts);
205
234
  }
206
235
  else {
207
- this._airDatepickerInstance.set(new AirDatepicker(this._inputForDate()?.nativeElement, airDatepickerOpts));
236
+ this._airDatepickerInstance()?.update(airDatepickerOpts, { silent: true });
208
237
  }
209
- if (this.showInline()) {
210
- this.setupTimepicker();
238
+ if (targetDate) {
239
+ this._airDatepickerInstance()?.selectDate(targetDate, { updateTime: true, silent: true });
240
+ }
241
+ else {
242
+ this._airDatepickerInstance()?.setFocusDate(false);
243
+ this._airDatepickerInstance()?.clear({ silent: true });
211
244
  }
212
245
  }
246
+ else {
247
+ this._airDatepickerInstance.set(new AirDatepicker(this._inputForDate()?.nativeElement, airDatepickerOpts));
248
+ }
249
+ this._airDatepickerInlineMode.set(desiredInlineMode);
250
+ if (desiredInlineMode) {
251
+ // Ensure inline calendar is visible after re-creation/update.
252
+ this._airDatepickerInstance()?.show?.();
253
+ }
254
+ if (this.showInline()) {
255
+ this.setupTimepicker();
256
+ }
213
257
  }
214
258
  onChangeText($event) {
215
259
  const value = $event.target?.value;
@@ -217,14 +261,23 @@ class QuangDateComponent extends QuangBaseComponent {
217
261
  // TODO: check format for DateRange
218
262
  if (value.length === this.valueFormat().length && isMatch(value, this.valueFormat())) {
219
263
  this.onChangedHandler(this.setupInputStringToDate(value).toISOString());
264
+ if (this.showInline()) {
265
+ this.propagateValueToControl();
266
+ }
220
267
  }
221
268
  }
222
269
  else {
223
270
  this.onChangedHandler(value);
271
+ if (this.showInline()) {
272
+ this.propagateValueToControl();
273
+ }
224
274
  }
225
275
  }
226
276
  onBlurHandler() {
227
277
  super.onBlurHandler();
278
+ if (this.showInline()) {
279
+ return;
280
+ }
228
281
  if (this.isMouseOutsideCalendar() && this._airDatepickerInstance()?.visible) {
229
282
  this._airDatepickerInstance()?.hide();
230
283
  }
@@ -234,9 +287,9 @@ class QuangDateComponent extends QuangBaseComponent {
234
287
  if (value.length !== targetValueFormat.length) {
235
288
  targetValueFormat = targetValueFormat.replace('yyyy', 'yy');
236
289
  }
237
- let targetDate = parse(value, targetValueFormat, new Date());
290
+ const targetDate = parse(value, targetValueFormat, new Date());
238
291
  if (!this.showTimepicker()) {
239
- targetDate = this.dateToUtc(targetDate);
292
+ return this.dateToUtc(targetDate);
240
293
  }
241
294
  return targetDate;
242
295
  }
@@ -275,6 +328,42 @@ class QuangDateComponent extends QuangBaseComponent {
275
328
  }
276
329
  this._value.set(targetDate);
277
330
  }
331
+ propagateValueToControl() {
332
+ if (this.formControl()?.getRawValue() !== this._value()) {
333
+ super.onChangedHandler(this._value());
334
+ }
335
+ else if (this.onTouched) {
336
+ this.onTouched();
337
+ }
338
+ this.requestRender();
339
+ }
340
+ requestRender() {
341
+ // Inline datepicker interactions can happen outside Angular-managed events.
342
+ // Marking the view dirty is not always enough in zoneless/event-coalesced setups,
343
+ // so we coalesce a manual tick.
344
+ this._cdr.markForCheck();
345
+ if (this._tickScheduled) {
346
+ return;
347
+ }
348
+ this._tickScheduled = true;
349
+ queueMicrotask(() => {
350
+ this._tickScheduled = false;
351
+ this._appRef.tick();
352
+ });
353
+ }
354
+ syncValueFromDatepickerSelection() {
355
+ if (!this.showInline()) {
356
+ return;
357
+ }
358
+ const datepickerInstance = this._airDatepickerInstance();
359
+ const selectedDate = datepickerInstance?.selectedDates?.[0];
360
+ if (!(selectedDate instanceof Date)) {
361
+ return;
362
+ }
363
+ const targetDate = this.showTimepicker() ? selectedDate : this.dateToUtc(selectedDate);
364
+ this.onChangedHandler(targetDate.toISOString());
365
+ this.propagateValueToControl();
366
+ }
278
367
  onHideCalendar() {
279
368
  const valueInput = this._inputForDate()?.nativeElement.value;
280
369
  let value = valueInput;
@@ -283,18 +372,14 @@ class QuangDateComponent extends QuangBaseComponent {
283
372
  const [dateFrom, dateTo] = valueInput.split(this.multipleDatesSeparator());
284
373
  value.dateFrom = dateFrom ?? '';
285
374
  value.dateTo = dateTo ?? '';
286
- if (!value.dateFrom || !this.checkDateMatch(value.dateFrom)) {
287
- value.dateFrom = null;
288
- }
289
- else {
290
- value.dateFrom = this.setupInputStringToDate(value.dateFrom).toISOString();
291
- }
292
- if (!value.dateTo || !this.checkDateMatch(value.dateTo)) {
293
- value.dateTo = null;
294
- }
295
- else {
296
- value.dateTo = this.setupInputStringToDate(value.dateTo).toISOString();
297
- }
375
+ value.dateFrom =
376
+ !value.dateFrom || !this.checkDateMatch(value.dateFrom)
377
+ ? null
378
+ : this.setupInputStringToDate(value.dateFrom).toISOString();
379
+ value.dateTo =
380
+ !value.dateTo || !this.checkDateMatch(value.dateTo)
381
+ ? null
382
+ : this.setupInputStringToDate(value.dateTo).toISOString();
298
383
  this.onChangedHandler(value);
299
384
  }
300
385
  else if (this.checkDateMatch(value)) {
@@ -303,20 +388,19 @@ class QuangDateComponent extends QuangBaseComponent {
303
388
  else {
304
389
  this.onChangedHandler(null);
305
390
  }
306
- if (this.formControl()?.getRawValue() !== this._value()) {
307
- super.onChangedHandler(this._value());
308
- }
309
- else if (this.onTouched) {
310
- this.onTouched();
391
+ this.propagateValueToControl();
392
+ if (this.showInline()) {
393
+ return;
311
394
  }
312
- // Only focus the input if the active element is still within this component
313
- // (e.g., user selected a date via keyboard or mouse click on the calendar).
395
+ // Only focus the input when the user actually interacted with the calendar.
314
396
  // Avoids infinite focus loop when tabbing between multiple datepickers.
315
397
  const activeElement = document.activeElement;
316
398
  const calendarElement = this._airDatepickerInstance()?.$datepicker;
317
399
  const inputElement = this._inputForDate()?.nativeElement;
318
400
  const isCalendarFocused = calendarElement?.contains(activeElement);
319
- if (isCalendarFocused || this.isMouseInsideCalendar()) {
401
+ const shouldRefocus = this._shouldRefocusInputOnHide() || isCalendarFocused || this.isMouseInsideCalendar();
402
+ this._shouldRefocusInputOnHide.set(false);
403
+ if (shouldRefocus) {
320
404
  inputElement?.focus();
321
405
  }
322
406
  this.onBlurHandler();
@@ -326,6 +410,9 @@ class QuangDateComponent extends QuangBaseComponent {
326
410
  return format(val, this.valueFormat());
327
411
  }
328
412
  if (val && typeof val === 'object') {
413
+ if (!val.dateFrom && !val.dateTo) {
414
+ return '';
415
+ }
329
416
  let dateFromFormat = '';
330
417
  let dateToFormat = '';
331
418
  if (val.dateFrom) {
@@ -339,8 +426,29 @@ class QuangDateComponent extends QuangBaseComponent {
339
426
  return '';
340
427
  }
341
428
  openDatePicker() {
342
- if (this._inputForDate()?.nativeElement) {
343
- this._inputForDate()?.nativeElement.focus();
429
+ const inputEl = this._inputForDate()?.nativeElement;
430
+ if (!inputEl || this._isDisabled()) {
431
+ return;
432
+ }
433
+ inputEl.focus();
434
+ if (!this._airDatepickerInstance()) {
435
+ this.setupCalendar();
436
+ }
437
+ this._airDatepickerInstance()?.show();
438
+ }
439
+ onInputKeydown(event) {
440
+ if (this._isDisabled()) {
441
+ return;
442
+ }
443
+ const datepickerInstance = this._airDatepickerInstance();
444
+ if (event.key === 'Escape' && datepickerInstance?.visible) {
445
+ event.preventDefault();
446
+ datepickerInstance.hide();
447
+ return;
448
+ }
449
+ if (event.key === 'Enter' || event.key === 'ArrowDown') {
450
+ event.preventDefault();
451
+ this.openDatePicker();
344
452
  }
345
453
  }
346
454
  interceptInputInteraction($event) {
@@ -353,13 +461,13 @@ class QuangDateComponent extends QuangBaseComponent {
353
461
  getLocale() {
354
462
  switch (this._activeLanguage()?.toLowerCase()) {
355
463
  case 'en':
356
- return en.default || en;
464
+ return en.default ?? en;
357
465
  case 'it':
358
- return it.default || it;
466
+ return it.default ?? it;
359
467
  case 'fr':
360
- return fr.default || fr;
468
+ return fr.default ?? fr;
361
469
  default:
362
- return en.default || en;
470
+ return en.default ?? en;
363
471
  }
364
472
  }
365
473
  onCancel() {
@@ -369,10 +477,6 @@ class QuangDateComponent extends QuangBaseComponent {
369
477
  // convert to UTC time removing the timezone
370
478
  return new Date(date.getTime() - date.getTimezoneOffset() * 60000);
371
479
  }
372
- dateToLocal(date) {
373
- // convert to local time adding the timezone
374
- return new Date(date.getTime() + date.getTimezoneOffset() * 60000);
375
- }
376
480
  setCalendarPosition() {
377
481
  const windowInnerHeight = window.innerHeight;
378
482
  const inputBoundingClientRect = this._inputForDate()?.nativeElement.getBoundingClientRect();
@@ -385,8 +489,23 @@ class QuangDateComponent extends QuangBaseComponent {
385
489
  }
386
490
  }
387
491
  setupTimepicker() {
388
- const timepicker = document.getElementsByClassName('air-datepicker-time')?.[0];
389
- if (timepicker) {
492
+ const datepickerRoot = this._airDatepickerInstance()?.$datepicker;
493
+ if (!datepickerRoot) {
494
+ return;
495
+ }
496
+ // AirDatepicker may re-render time inputs; use delegated listeners so we don't lose handlers.
497
+ if (!datepickerRoot.dataset['quangTimepickerListeners']) {
498
+ datepickerRoot.dataset['quangTimepickerListeners'] = 'true';
499
+ datepickerRoot.addEventListener('input', () => {
500
+ if (!this.showInline()) {
501
+ return;
502
+ }
503
+ // Let AirDatepicker update its internal selection first.
504
+ setTimeout(() => this._ngZone.run(() => this.syncValueFromDatepickerSelection()), 0);
505
+ }, { capture: true });
506
+ }
507
+ const timepickers = datepickerRoot.getElementsByClassName('air-datepicker-time');
508
+ for (const timepicker of Array.from(timepickers)) {
390
509
  const inputs = timepicker.getElementsByTagName('input');
391
510
  for (const input of Array.from(inputs)) {
392
511
  input.setAttribute('type', 'number');
@@ -396,7 +515,7 @@ class QuangDateComponent extends QuangBaseComponent {
396
515
  evt.stopImmediatePropagation();
397
516
  };
398
517
  input.onblur = () => {
399
- if (this.isMouseOutsideCalendar()) {
518
+ if (!this.showInline() && this.isMouseOutsideCalendar()) {
400
519
  this._airDatepickerInstance()?.hide();
401
520
  }
402
521
  };
@@ -407,14 +526,12 @@ class QuangDateComponent extends QuangBaseComponent {
407
526
  return isMatch(date, this.valueFormat()) || isMatch(date, this.valueFormat().replace('yyyy', 'yy'));
408
527
  }
409
528
  static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "19.2.15", ngImport: i0, type: QuangDateComponent, deps: [], target: i0.ɵɵFactoryTarget.Component }); }
410
- static { this.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "19.2.15", type: QuangDateComponent, isStandalone: true, selector: "quang-date", inputs: { dateFormat: { classPropertyName: "dateFormat", publicName: "dateFormat", isSignal: true, isRequired: false, transformFunction: null }, timeFormat: { classPropertyName: "timeFormat", publicName: "timeFormat", isSignal: true, isRequired: false, transformFunction: null }, activeLanguageOverride: { classPropertyName: "activeLanguageOverride", publicName: "activeLanguageOverride", isSignal: true, isRequired: false, transformFunction: null }, timepicker: { classPropertyName: "timepicker", publicName: "timepicker", isSignal: true, isRequired: false, transformFunction: null }, invalidDateMessage: { classPropertyName: "invalidDateMessage", publicName: "invalidDateMessage", isSignal: true, isRequired: false, transformFunction: null }, showOnlyTimepicker: { classPropertyName: "showOnlyTimepicker", publicName: "showOnlyTimepicker", isSignal: true, isRequired: false, transformFunction: null }, minHour: { classPropertyName: "minHour", publicName: "minHour", isSignal: true, isRequired: false, transformFunction: null }, maxHour: { classPropertyName: "maxHour", publicName: "maxHour", isSignal: true, isRequired: false, transformFunction: null }, minMinute: { classPropertyName: "minMinute", publicName: "minMinute", isSignal: true, isRequired: false, transformFunction: null }, maxMinute: { classPropertyName: "maxMinute", publicName: "maxMinute", isSignal: true, isRequired: false, transformFunction: null }, minDate: { classPropertyName: "minDate", publicName: "minDate", isSignal: true, isRequired: false, transformFunction: null }, maxDate: { classPropertyName: "maxDate", publicName: "maxDate", isSignal: true, isRequired: false, transformFunction: null }, showInline: { classPropertyName: "showInline", publicName: "showInline", isSignal: true, isRequired: false, transformFunction: null }, calendarClasses: { classPropertyName: "calendarClasses", publicName: "calendarClasses", isSignal: true, isRequired: false, transformFunction: null }, buttonClass: { classPropertyName: "buttonClass", publicName: "buttonClass", isSignal: true, isRequired: false, transformFunction: null }, datepickerOptions: { classPropertyName: "datepickerOptions", publicName: "datepickerOptions", isSignal: true, isRequired: false, transformFunction: null }, multipleDatesSeparator: { classPropertyName: "multipleDatesSeparator", publicName: "multipleDatesSeparator", isSignal: true, isRequired: false, transformFunction: null }, rangeSelection: { classPropertyName: "rangeSelection", publicName: "rangeSelection", isSignal: true, isRequired: false, transformFunction: null }, searchTextDebounce: { classPropertyName: "searchTextDebounce", publicName: "searchTextDebounce", isSignal: true, isRequired: false, transformFunction: null } }, providers: [{ provide: NG_VALUE_ACCESSOR, useExisting: forwardRef(() => QuangDateComponent), multi: true }], viewQueries: [{ propertyName: "_inputForDate", first: true, predicate: ["inputForDate"], descendants: true, isSignal: true }, { propertyName: "contentTemplate", first: true, predicate: ["calendarButton"], descendants: true, isSignal: true }], usesInheritance: true, ngImport: i0, template: "<div class=\"mb-3\">\n @if (componentLabel()) {\n <label\n [htmlFor]=\"componentId()\"\n class=\"form-label\"\n >\n {{ componentLabel() | transloco }}\n <span [hidden]=\"!_isRequired()\">*</span>\n </label>\n }\n <div\n [class.is-invalid]=\"_showErrors()\"\n [class.is-valid]=\"_showSuccess()\"\n class=\"input-date-container\"\n >\n <input\n [attr.required]=\"getIsRequiredControl()\"\n [autocomplete]=\"'off'\"\n [class.is-invalid]=\"_showErrors()\"\n [class.is-valid]=\"_showSuccess()\"\n [class.with-button-calendar]=\"!hasNoContent()\"\n [disabled]=\"_isDisabled()\"\n [hidden]=\"showInline()\"\n [id]=\"componentId()\"\n [ngClass]=\"componentClass()\"\n [placeholder]=\"componentPlaceholder() | transloco\"\n [readOnly]=\"isReadonly()\"\n [tabIndex]=\"componentTabIndex()\"\n [value]=\"inputValueString()\"\n (blur)=\"onBlurHandler()\"\n (focus)=\"interceptInputInteraction($event)\"\n (input)=\"onChangeText($event)\"\n (mouseenter)=\"isMouseInsideCalendar.set(true)\"\n (mouseleave)=\"isMouseInsideCalendar.set(false)\"\n (search)=\"onCancel()\"\n #inputForDate\n class=\"form-control\"\n type=\"search\"\n />\n <button\n [attr.required]=\"getIsRequiredControl()\"\n [class.border-danger]=\"_showErrors()\"\n [class.border-success]=\"_showSuccess()\"\n [hidden]=\"showInline() || hasNoContent() || _isDisabled()\"\n [ngClass]=\"buttonClass()\"\n (click)=\"_ngControl()?.disabled ? null : openDatePicker()\"\n #calendarButton\n aria-label=\"calendar-button\"\n class=\"btn btn-outline-secondary btn-outline-calendar\"\n type=\"button\"\n >\n <ng-content></ng-content>\n </button>\n </div>\n <div class=\"valid-feedback\">\n {{ successMessage() | transloco }}\n </div>\n <div class=\"invalid-feedback\">\n {{ _currentErrorMessage() | transloco: _currentErrorMessageExtraData() }}\n </div>\n @if (helpMessage()) {\n <small\n [hidden]=\"_showSuccess() || _showErrors()\"\n aria-live=\"assertive\"\n class=\"form-text text-muted\"\n >\n {{ helpMessage() | transloco }}\n </small>\n }\n</div>\n", styles: ["input::-webkit-search-cancel-button{-webkit-appearance:none;height:.75rem;width:.75rem;background-image:url(\"data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 3 1024 1024' width='12' height='12' fill='currentColor'%3E%3Cpath d='M9 1018q5 4 10.5 6.5 5.5 2.5 11.5 2.5 6 0 11.5-2.5 5.5-2.5 10.5-6.5l459-459 459 459q5 4 10.5 6.5 5.5 2.5 11.5 2.5 6 0 11.5-2.5 5.5-2.5 10.5-6.5 9-9 9-22 0-13-9-22l-459-459 459-459q9-9 9-22 0-13-9-22-9-9-22-9-13 0-22 9l-459 459-459-459q-9-9-22-9-13 0-22 9-9 9-9 22 0 13 9 22l459 459-459 459q-9 9-9 22 0 13 9 22l0 0z'/%3E%3C/svg%3E%0A\");cursor:pointer}::ng-deep .air-datepicker{z-index:99999}::ng-deep .air-datepicker.-inline-{z-index:unset}::ng-deep .air-datepicker .air-datepicker--pointer{display:none}::ng-deep .air-datepicker .air-datepicker-time{display:block}::ng-deep .air-datepicker .air-datepicker-time .air-datepicker-time--current{display:none}::ng-deep .air-datepicker .air-datepicker-time .air-datepicker-time--sliders{display:flex;justify-content:center;padding-top:.25rem;gap:1rem}::ng-deep .air-datepicker .air-datepicker-time .air-datepicker-time--sliders .air-datepicker-time--row{width:100%;position:relative}::ng-deep .air-datepicker .air-datepicker-time .air-datepicker-time--sliders .air-datepicker-time--row:first-child:after{content:\":\";display:inline;font-size:1rem;position:absolute;right:-.65rem}::ng-deep .air-datepicker .air-datepicker-time .air-datepicker-time--sliders .air-datepicker-time--row input{width:100%;text-align:center;padding:0;padding-left:1rem;border-color:var(--bs-border-color)}::ng-deep .air-datepicker .air-datepicker-time .air-datepicker-time--sliders .air-datepicker-time--row .form-control:focus{box-shadow:unset!important}::ng-deep .air-datepicker.-inline-.-only-timepicker-{border:0}::ng-deep .air-datepicker.-inline-.-only-timepicker- .air-datepicker--time{border:0}:host{display:block}:host .input-date-container{display:flex}:host input{flex:1}:host input.with-button-calendar{border-top-right-radius:0;border-bottom-right-radius:0}:host input:disabled{border-radius:var(--bs-border-radius)}:host .btn-outline-calendar{border-left:0;border-top-left-radius:0;border-bottom-left-radius:0;min-width:unset;display:flex;border-color:var(--bs-border-color)}:host .border-danger{border-color:var(--bs-form-invalid-border-color)}:host .border-success{border-color:var(--bs-form-valid-border-color)}\n"], dependencies: [{ kind: "pipe", type: TranslocoPipe, name: "transloco" }, { kind: "directive", type: NgClass, selector: "[ngClass]", inputs: ["class", "ngClass"] }], changeDetection: i0.ChangeDetectionStrategy.OnPush }); }
529
+ static { this.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "19.2.15", type: QuangDateComponent, isStandalone: true, selector: "quang-date", inputs: { dateFormat: { classPropertyName: "dateFormat", publicName: "dateFormat", isSignal: true, isRequired: false, transformFunction: null }, timeFormat: { classPropertyName: "timeFormat", publicName: "timeFormat", isSignal: true, isRequired: false, transformFunction: null }, activeLanguageOverride: { classPropertyName: "activeLanguageOverride", publicName: "activeLanguageOverride", isSignal: true, isRequired: false, transformFunction: null }, timepicker: { classPropertyName: "timepicker", publicName: "timepicker", isSignal: true, isRequired: false, transformFunction: null }, invalidDateMessage: { classPropertyName: "invalidDateMessage", publicName: "invalidDateMessage", isSignal: true, isRequired: false, transformFunction: null }, showOnlyTimepicker: { classPropertyName: "showOnlyTimepicker", publicName: "showOnlyTimepicker", isSignal: true, isRequired: false, transformFunction: null }, minHour: { classPropertyName: "minHour", publicName: "minHour", isSignal: true, isRequired: false, transformFunction: null }, maxHour: { classPropertyName: "maxHour", publicName: "maxHour", isSignal: true, isRequired: false, transformFunction: null }, minMinute: { classPropertyName: "minMinute", publicName: "minMinute", isSignal: true, isRequired: false, transformFunction: null }, maxMinute: { classPropertyName: "maxMinute", publicName: "maxMinute", isSignal: true, isRequired: false, transformFunction: null }, minDate: { classPropertyName: "minDate", publicName: "minDate", isSignal: true, isRequired: false, transformFunction: null }, maxDate: { classPropertyName: "maxDate", publicName: "maxDate", isSignal: true, isRequired: false, transformFunction: null }, showInline: { classPropertyName: "showInline", publicName: "showInline", isSignal: true, isRequired: false, transformFunction: null }, calendarClasses: { classPropertyName: "calendarClasses", publicName: "calendarClasses", isSignal: true, isRequired: false, transformFunction: null }, buttonClass: { classPropertyName: "buttonClass", publicName: "buttonClass", isSignal: true, isRequired: false, transformFunction: null }, datepickerOptions: { classPropertyName: "datepickerOptions", publicName: "datepickerOptions", isSignal: true, isRequired: false, transformFunction: null }, multipleDatesSeparator: { classPropertyName: "multipleDatesSeparator", publicName: "multipleDatesSeparator", isSignal: true, isRequired: false, transformFunction: null }, rangeSelection: { classPropertyName: "rangeSelection", publicName: "rangeSelection", isSignal: true, isRequired: false, transformFunction: null }, searchTextDebounce: { classPropertyName: "searchTextDebounce", publicName: "searchTextDebounce", isSignal: true, isRequired: false, transformFunction: null } }, providers: [{ provide: NG_VALUE_ACCESSOR, useExisting: forwardRef(() => QuangDateComponent), multi: true }], viewQueries: [{ propertyName: "_inputForDate", first: true, predicate: ["inputForDate"], descendants: true, isSignal: true }, { propertyName: "contentTemplate", first: true, predicate: ["calendarButton"], descendants: true, isSignal: true }], usesInheritance: true, ngImport: i0, template: "<div class=\"mb-3\">\n @if (componentLabel()) {\n <label\n [htmlFor]=\"componentId()\"\n class=\"form-label\"\n >\n {{ componentLabel() | transloco }}\n <span [hidden]=\"!_isRequired()\">*</span>\n </label>\n }\n <div\n [class.is-invalid]=\"_showErrors()\"\n [class.is-valid]=\"_showSuccess()\"\n class=\"input-date-container\"\n >\n <input\n [attr.aria-hidden]=\"showInline() ? 'true' : null\"\n [attr.required]=\"getIsRequiredControl()\"\n [autocomplete]=\"'off'\"\n [class.is-invalid]=\"_showErrors()\"\n [class.is-valid]=\"_showSuccess()\"\n [class.quang-date-inline-hidden]=\"showInline()\"\n [class.with-button-calendar]=\"!hasNoContent()\"\n [disabled]=\"_isDisabled()\"\n [id]=\"componentId()\"\n [ngClass]=\"componentClass()\"\n [placeholder]=\"componentPlaceholder() | transloco\"\n [readOnly]=\"isReadonly()\"\n [tabIndex]=\"componentTabIndex()\"\n [value]=\"inputValueString()\"\n (blur)=\"onBlurHandler()\"\n (focus)=\"interceptInputInteraction($event)\"\n (input)=\"onChangeText($event)\"\n (keydown)=\"onInputKeydown($event)\"\n (mouseenter)=\"isMouseInsideCalendar.set(true)\"\n (mouseleave)=\"isMouseInsideCalendar.set(false)\"\n (search)=\"onCancel()\"\n #inputForDate\n class=\"form-control\"\n type=\"search\"\n />\n <button\n [attr.aria-hidden]=\"showInline() ? 'true' : null\"\n [attr.required]=\"getIsRequiredControl()\"\n [class.border-danger]=\"_showErrors()\"\n [class.border-success]=\"_showSuccess()\"\n [class.quang-date-inline-hidden]=\"showInline()\"\n [hidden]=\"hasNoContent() || _isDisabled()\"\n [ngClass]=\"buttonClass()\"\n (click)=\"_ngControl()?.disabled ? null : openDatePicker()\"\n #calendarButton\n aria-label=\"calendar-button\"\n class=\"btn btn-outline-secondary btn-outline-calendar\"\n type=\"button\"\n >\n <ng-content></ng-content>\n </button>\n </div>\n <div class=\"valid-feedback\">\n {{ successMessage() | transloco }}\n </div>\n <div class=\"invalid-feedback\">\n {{ _currentErrorMessage() | transloco: _currentErrorMessageExtraData() }}\n </div>\n @if (helpMessage()) {\n <small\n [hidden]=\"_showSuccess() || _showErrors()\"\n aria-live=\"assertive\"\n class=\"form-text text-muted\"\n >\n {{ helpMessage() | transloco }}\n </small>\n }\n</div>\n", styles: ["input::-webkit-search-cancel-button{-webkit-appearance:none;height:.75rem;width:.75rem;background-image:url(\"data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 3 1024 1024' width='12' height='12' fill='currentColor'%3E%3Cpath d='M9 1018q5 4 10.5 6.5 5.5 2.5 11.5 2.5 6 0 11.5-2.5 5.5-2.5 10.5-6.5l459-459 459 459q5 4 10.5 6.5 5.5 2.5 11.5 2.5 6 0 11.5-2.5 5.5-2.5 10.5-6.5 9-9 9-22 0-13-9-22l-459-459 459-459q9-9 9-22 0-13-9-22-9-9-22-9-13 0-22 9l-459 459-459-459q-9-9-22-9-13 0-22 9-9 9-9 22 0 13 9 22l459 459-459 459q-9 9-9 22 0 13 9 22l0 0z'/%3E%3C/svg%3E%0A\");cursor:pointer}::ng-deep .air-datepicker{z-index:99999}::ng-deep .air-datepicker.-inline-{z-index:unset}::ng-deep .air-datepicker .air-datepicker--pointer{display:none}::ng-deep .air-datepicker .air-datepicker-time{display:block}::ng-deep .air-datepicker .air-datepicker-time .air-datepicker-time--current{display:none}::ng-deep .air-datepicker .air-datepicker-time .air-datepicker-time--sliders{display:flex;justify-content:center;padding-top:.25rem;gap:1rem}::ng-deep .air-datepicker .air-datepicker-time .air-datepicker-time--sliders .air-datepicker-time--row{width:100%;position:relative}::ng-deep .air-datepicker .air-datepicker-time .air-datepicker-time--sliders .air-datepicker-time--row:first-child:after{content:\":\";display:inline;font-size:1rem;position:absolute;right:-.65rem}::ng-deep .air-datepicker .air-datepicker-time .air-datepicker-time--sliders .air-datepicker-time--row input{width:100%;text-align:center;padding:0;padding-left:1rem;border-color:var(--bs-border-color)}::ng-deep .air-datepicker .air-datepicker-time .air-datepicker-time--sliders .air-datepicker-time--row .form-control:focus{box-shadow:unset!important}::ng-deep .air-datepicker.-inline-.-only-timepicker-{border:0;padding:0!important}::ng-deep .air-datepicker.-inline-.-only-timepicker- .air-datepicker--time{border:0;padding:0!important}::ng-deep .air-datepicker.-inline-.-only-timepicker- .air-datepicker-time{padding:0!important}:host{display:block}:host .quang-date-inline-hidden{position:absolute!important;width:1px!important;height:1px!important;padding:0!important;margin:0!important;border:0!important;opacity:0!important;pointer-events:none!important;overflow:hidden!important;white-space:nowrap!important;clip:rect(0 0 0 0)!important;clip-path:inset(50%)!important}:host .input-date-container{display:flex}:host input{flex:1}:host input.with-button-calendar{border-top-right-radius:0;border-bottom-right-radius:0}:host input:disabled{border-radius:var(--bs-border-radius)}:host .btn-outline-calendar{border-left:0;border-top-left-radius:0;border-bottom-left-radius:0;min-width:unset;display:flex;border-color:var(--bs-border-color)}:host .border-danger{border-color:var(--bs-form-invalid-border-color)}:host .border-success{border-color:var(--bs-form-valid-border-color)}\n"], dependencies: [{ kind: "pipe", type: TranslocoPipe, name: "transloco" }, { kind: "directive", type: NgClass, selector: "[ngClass]", inputs: ["class", "ngClass"] }], changeDetection: i0.ChangeDetectionStrategy.OnPush }); }
411
530
  }
412
531
  i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "19.2.15", ngImport: i0, type: QuangDateComponent, decorators: [{
413
532
  type: Component,
414
- args: [{ selector: 'quang-date', providers: [{ provide: NG_VALUE_ACCESSOR, useExisting: forwardRef(() => QuangDateComponent), multi: true }], imports: [TranslocoPipe, NgClass], changeDetection: ChangeDetectionStrategy.OnPush, template: "<div class=\"mb-3\">\n @if (componentLabel()) {\n <label\n [htmlFor]=\"componentId()\"\n class=\"form-label\"\n >\n {{ componentLabel() | transloco }}\n <span [hidden]=\"!_isRequired()\">*</span>\n </label>\n }\n <div\n [class.is-invalid]=\"_showErrors()\"\n [class.is-valid]=\"_showSuccess()\"\n class=\"input-date-container\"\n >\n <input\n [attr.required]=\"getIsRequiredControl()\"\n [autocomplete]=\"'off'\"\n [class.is-invalid]=\"_showErrors()\"\n [class.is-valid]=\"_showSuccess()\"\n [class.with-button-calendar]=\"!hasNoContent()\"\n [disabled]=\"_isDisabled()\"\n [hidden]=\"showInline()\"\n [id]=\"componentId()\"\n [ngClass]=\"componentClass()\"\n [placeholder]=\"componentPlaceholder() | transloco\"\n [readOnly]=\"isReadonly()\"\n [tabIndex]=\"componentTabIndex()\"\n [value]=\"inputValueString()\"\n (blur)=\"onBlurHandler()\"\n (focus)=\"interceptInputInteraction($event)\"\n (input)=\"onChangeText($event)\"\n (mouseenter)=\"isMouseInsideCalendar.set(true)\"\n (mouseleave)=\"isMouseInsideCalendar.set(false)\"\n (search)=\"onCancel()\"\n #inputForDate\n class=\"form-control\"\n type=\"search\"\n />\n <button\n [attr.required]=\"getIsRequiredControl()\"\n [class.border-danger]=\"_showErrors()\"\n [class.border-success]=\"_showSuccess()\"\n [hidden]=\"showInline() || hasNoContent() || _isDisabled()\"\n [ngClass]=\"buttonClass()\"\n (click)=\"_ngControl()?.disabled ? null : openDatePicker()\"\n #calendarButton\n aria-label=\"calendar-button\"\n class=\"btn btn-outline-secondary btn-outline-calendar\"\n type=\"button\"\n >\n <ng-content></ng-content>\n </button>\n </div>\n <div class=\"valid-feedback\">\n {{ successMessage() | transloco }}\n </div>\n <div class=\"invalid-feedback\">\n {{ _currentErrorMessage() | transloco: _currentErrorMessageExtraData() }}\n </div>\n @if (helpMessage()) {\n <small\n [hidden]=\"_showSuccess() || _showErrors()\"\n aria-live=\"assertive\"\n class=\"form-text text-muted\"\n >\n {{ helpMessage() | transloco }}\n </small>\n }\n</div>\n", styles: ["input::-webkit-search-cancel-button{-webkit-appearance:none;height:.75rem;width:.75rem;background-image:url(\"data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 3 1024 1024' width='12' height='12' fill='currentColor'%3E%3Cpath d='M9 1018q5 4 10.5 6.5 5.5 2.5 11.5 2.5 6 0 11.5-2.5 5.5-2.5 10.5-6.5l459-459 459 459q5 4 10.5 6.5 5.5 2.5 11.5 2.5 6 0 11.5-2.5 5.5-2.5 10.5-6.5 9-9 9-22 0-13-9-22l-459-459 459-459q9-9 9-22 0-13-9-22-9-9-22-9-13 0-22 9l-459 459-459-459q-9-9-22-9-13 0-22 9-9 9-9 22 0 13 9 22l459 459-459 459q-9 9-9 22 0 13 9 22l0 0z'/%3E%3C/svg%3E%0A\");cursor:pointer}::ng-deep .air-datepicker{z-index:99999}::ng-deep .air-datepicker.-inline-{z-index:unset}::ng-deep .air-datepicker .air-datepicker--pointer{display:none}::ng-deep .air-datepicker .air-datepicker-time{display:block}::ng-deep .air-datepicker .air-datepicker-time .air-datepicker-time--current{display:none}::ng-deep .air-datepicker .air-datepicker-time .air-datepicker-time--sliders{display:flex;justify-content:center;padding-top:.25rem;gap:1rem}::ng-deep .air-datepicker .air-datepicker-time .air-datepicker-time--sliders .air-datepicker-time--row{width:100%;position:relative}::ng-deep .air-datepicker .air-datepicker-time .air-datepicker-time--sliders .air-datepicker-time--row:first-child:after{content:\":\";display:inline;font-size:1rem;position:absolute;right:-.65rem}::ng-deep .air-datepicker .air-datepicker-time .air-datepicker-time--sliders .air-datepicker-time--row input{width:100%;text-align:center;padding:0;padding-left:1rem;border-color:var(--bs-border-color)}::ng-deep .air-datepicker .air-datepicker-time .air-datepicker-time--sliders .air-datepicker-time--row .form-control:focus{box-shadow:unset!important}::ng-deep .air-datepicker.-inline-.-only-timepicker-{border:0}::ng-deep .air-datepicker.-inline-.-only-timepicker- .air-datepicker--time{border:0}:host{display:block}:host .input-date-container{display:flex}:host input{flex:1}:host input.with-button-calendar{border-top-right-radius:0;border-bottom-right-radius:0}:host input:disabled{border-radius:var(--bs-border-radius)}:host .btn-outline-calendar{border-left:0;border-top-left-radius:0;border-bottom-left-radius:0;min-width:unset;display:flex;border-color:var(--bs-border-color)}:host .border-danger{border-color:var(--bs-form-invalid-border-color)}:host .border-success{border-color:var(--bs-form-valid-border-color)}\n"] }]
415
- }], ctorParameters: () => [], propDecorators: { _quangTranslationService: [{
416
- type: Optional
417
- }] } });
533
+ args: [{ selector: 'quang-date', providers: [{ provide: NG_VALUE_ACCESSOR, useExisting: forwardRef(() => QuangDateComponent), multi: true }], imports: [TranslocoPipe, NgClass], changeDetection: ChangeDetectionStrategy.OnPush, template: "<div class=\"mb-3\">\n @if (componentLabel()) {\n <label\n [htmlFor]=\"componentId()\"\n class=\"form-label\"\n >\n {{ componentLabel() | transloco }}\n <span [hidden]=\"!_isRequired()\">*</span>\n </label>\n }\n <div\n [class.is-invalid]=\"_showErrors()\"\n [class.is-valid]=\"_showSuccess()\"\n class=\"input-date-container\"\n >\n <input\n [attr.aria-hidden]=\"showInline() ? 'true' : null\"\n [attr.required]=\"getIsRequiredControl()\"\n [autocomplete]=\"'off'\"\n [class.is-invalid]=\"_showErrors()\"\n [class.is-valid]=\"_showSuccess()\"\n [class.quang-date-inline-hidden]=\"showInline()\"\n [class.with-button-calendar]=\"!hasNoContent()\"\n [disabled]=\"_isDisabled()\"\n [id]=\"componentId()\"\n [ngClass]=\"componentClass()\"\n [placeholder]=\"componentPlaceholder() | transloco\"\n [readOnly]=\"isReadonly()\"\n [tabIndex]=\"componentTabIndex()\"\n [value]=\"inputValueString()\"\n (blur)=\"onBlurHandler()\"\n (focus)=\"interceptInputInteraction($event)\"\n (input)=\"onChangeText($event)\"\n (keydown)=\"onInputKeydown($event)\"\n (mouseenter)=\"isMouseInsideCalendar.set(true)\"\n (mouseleave)=\"isMouseInsideCalendar.set(false)\"\n (search)=\"onCancel()\"\n #inputForDate\n class=\"form-control\"\n type=\"search\"\n />\n <button\n [attr.aria-hidden]=\"showInline() ? 'true' : null\"\n [attr.required]=\"getIsRequiredControl()\"\n [class.border-danger]=\"_showErrors()\"\n [class.border-success]=\"_showSuccess()\"\n [class.quang-date-inline-hidden]=\"showInline()\"\n [hidden]=\"hasNoContent() || _isDisabled()\"\n [ngClass]=\"buttonClass()\"\n (click)=\"_ngControl()?.disabled ? null : openDatePicker()\"\n #calendarButton\n aria-label=\"calendar-button\"\n class=\"btn btn-outline-secondary btn-outline-calendar\"\n type=\"button\"\n >\n <ng-content></ng-content>\n </button>\n </div>\n <div class=\"valid-feedback\">\n {{ successMessage() | transloco }}\n </div>\n <div class=\"invalid-feedback\">\n {{ _currentErrorMessage() | transloco: _currentErrorMessageExtraData() }}\n </div>\n @if (helpMessage()) {\n <small\n [hidden]=\"_showSuccess() || _showErrors()\"\n aria-live=\"assertive\"\n class=\"form-text text-muted\"\n >\n {{ helpMessage() | transloco }}\n </small>\n }\n</div>\n", styles: ["input::-webkit-search-cancel-button{-webkit-appearance:none;height:.75rem;width:.75rem;background-image:url(\"data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 3 1024 1024' width='12' height='12' fill='currentColor'%3E%3Cpath d='M9 1018q5 4 10.5 6.5 5.5 2.5 11.5 2.5 6 0 11.5-2.5 5.5-2.5 10.5-6.5l459-459 459 459q5 4 10.5 6.5 5.5 2.5 11.5 2.5 6 0 11.5-2.5 5.5-2.5 10.5-6.5 9-9 9-22 0-13-9-22l-459-459 459-459q9-9 9-22 0-13-9-22-9-9-22-9-13 0-22 9l-459 459-459-459q-9-9-22-9-13 0-22 9-9 9-9 22 0 13 9 22l459 459-459 459q-9 9-9 22 0 13 9 22l0 0z'/%3E%3C/svg%3E%0A\");cursor:pointer}::ng-deep .air-datepicker{z-index:99999}::ng-deep .air-datepicker.-inline-{z-index:unset}::ng-deep .air-datepicker .air-datepicker--pointer{display:none}::ng-deep .air-datepicker .air-datepicker-time{display:block}::ng-deep .air-datepicker .air-datepicker-time .air-datepicker-time--current{display:none}::ng-deep .air-datepicker .air-datepicker-time .air-datepicker-time--sliders{display:flex;justify-content:center;padding-top:.25rem;gap:1rem}::ng-deep .air-datepicker .air-datepicker-time .air-datepicker-time--sliders .air-datepicker-time--row{width:100%;position:relative}::ng-deep .air-datepicker .air-datepicker-time .air-datepicker-time--sliders .air-datepicker-time--row:first-child:after{content:\":\";display:inline;font-size:1rem;position:absolute;right:-.65rem}::ng-deep .air-datepicker .air-datepicker-time .air-datepicker-time--sliders .air-datepicker-time--row input{width:100%;text-align:center;padding:0;padding-left:1rem;border-color:var(--bs-border-color)}::ng-deep .air-datepicker .air-datepicker-time .air-datepicker-time--sliders .air-datepicker-time--row .form-control:focus{box-shadow:unset!important}::ng-deep .air-datepicker.-inline-.-only-timepicker-{border:0;padding:0!important}::ng-deep .air-datepicker.-inline-.-only-timepicker- .air-datepicker--time{border:0;padding:0!important}::ng-deep .air-datepicker.-inline-.-only-timepicker- .air-datepicker-time{padding:0!important}:host{display:block}:host .quang-date-inline-hidden{position:absolute!important;width:1px!important;height:1px!important;padding:0!important;margin:0!important;border:0!important;opacity:0!important;pointer-events:none!important;overflow:hidden!important;white-space:nowrap!important;clip:rect(0 0 0 0)!important;clip-path:inset(50%)!important}:host .input-date-container{display:flex}:host input{flex:1}:host input.with-button-calendar{border-top-right-radius:0;border-bottom-right-radius:0}:host input:disabled{border-radius:var(--bs-border-radius)}:host .btn-outline-calendar{border-left:0;border-top-left-radius:0;border-bottom-left-radius:0;min-width:unset;display:flex;border-color:var(--bs-border-color)}:host .border-danger{border-color:var(--bs-form-invalid-border-color)}:host .border-success{border-color:var(--bs-form-valid-border-color)}\n"] }]
534
+ }], ctorParameters: () => [] });
418
535
 
419
536
  /**
420
537
  * Generated bundle index. Do not edit.