quang 20.5.1 → 20.6.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.
- package/components/autocomplete/README.md +34 -0
- package/components/autocomplete/index.d.ts +2 -0
- package/components/date/index.d.ts +11 -1
- package/components/radio-group/README.md +75 -0
- package/components/radio-group/index.d.ts +31 -0
- package/components/select/README.md +34 -1
- package/components/select/index.d.ts +1 -0
- package/components/shared/index.d.ts +11 -3
- package/fesm2022/quang-components-autocomplete.mjs +9 -3
- package/fesm2022/quang-components-autocomplete.mjs.map +1 -1
- package/fesm2022/quang-components-checkbox.mjs +2 -2
- package/fesm2022/quang-components-checkbox.mjs.map +1 -1
- package/fesm2022/quang-components-date.mjs +260 -133
- package/fesm2022/quang-components-date.mjs.map +1 -1
- package/fesm2022/quang-components-input.mjs +2 -2
- package/fesm2022/quang-components-input.mjs.map +1 -1
- package/fesm2022/quang-components-radio-group.mjs +59 -0
- package/fesm2022/quang-components-radio-group.mjs.map +1 -0
- package/fesm2022/quang-components-select.mjs +6 -3
- package/fesm2022/quang-components-select.mjs.map +1 -1
- package/fesm2022/quang-components-shared.mjs +35 -14
- package/fesm2022/quang-components-shared.mjs.map +1 -1
- package/package.json +5 -1
|
@@ -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,
|
|
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';
|
|
@@ -29,6 +29,10 @@ import { QuangBaseComponent } from 'quang/components/shared';
|
|
|
29
29
|
class QuangDateComponent extends QuangBaseComponent {
|
|
30
30
|
constructor() {
|
|
31
31
|
super();
|
|
32
|
+
this._ngZone = inject(NgZone);
|
|
33
|
+
this._cdr = inject(ChangeDetectorRef);
|
|
34
|
+
this._appRef = inject(ApplicationRef);
|
|
35
|
+
this._tickScheduled = false;
|
|
32
36
|
/**
|
|
33
37
|
* Format to use to show on the input field.
|
|
34
38
|
* The format is based on the standard {@link https://www.unicode.org/reports/tr35/tr35-dates.html#Date_Field_Symbol_Table}
|
|
@@ -71,7 +75,7 @@ class QuangDateComponent extends QuangBaseComponent {
|
|
|
71
75
|
this._inputForDate = viewChild('inputForDate', ...(ngDevMode ? [{ debugName: "_inputForDate" }] : []));
|
|
72
76
|
this.contentTemplate = viewChild.required('calendarButton');
|
|
73
77
|
this.hasNoContent = computed(() => this.contentTemplate()?.nativeElement.children.length === 0, ...(ngDevMode ? [{ debugName: "hasNoContent" }] : []));
|
|
74
|
-
this._quangTranslationService = signal(inject(QuangTranslationService), ...(ngDevMode ? [{ debugName: "_quangTranslationService" }] : []));
|
|
78
|
+
this._quangTranslationService = signal(inject(QuangTranslationService, { optional: true }) ?? undefined, ...(ngDevMode ? [{ debugName: "_quangTranslationService" }] : []));
|
|
75
79
|
this._quangTranslationActiveLang = computed(() => this._quangTranslationService()?.activeLang() ?? null, ...(ngDevMode ? [{ debugName: "_quangTranslationActiveLang" }] : []));
|
|
76
80
|
this.multipleDatesSeparator = input(' - ', ...(ngDevMode ? [{ debugName: "multipleDatesSeparator" }] : []));
|
|
77
81
|
this.rangeSelection = input(false, ...(ngDevMode ? [{ debugName: "rangeSelection" }] : []));
|
|
@@ -85,6 +89,9 @@ class QuangDateComponent extends QuangBaseComponent {
|
|
|
85
89
|
return navigator.language;
|
|
86
90
|
}, ...(ngDevMode ? [{ debugName: "_activeLanguage" }] : []));
|
|
87
91
|
this._airDatepickerInstance = signal(undefined, ...(ngDevMode ? [{ debugName: "_airDatepickerInstance" }] : []));
|
|
92
|
+
// AirDatepicker doesn't reliably support toggling `inline` at runtime via `update()`.
|
|
93
|
+
// Track the mode used to create the current instance and recreate when it changes.
|
|
94
|
+
this._airDatepickerInlineMode = signal(null, ...(ngDevMode ? [{ debugName: "_airDatepickerInlineMode" }] : []));
|
|
88
95
|
this.searchTextDebounce = input(500, ...(ngDevMode ? [{ debugName: "searchTextDebounce" }] : []));
|
|
89
96
|
this.targetPosition = signal('bottom left', ...(ngDevMode ? [{ debugName: "targetPosition" }] : []));
|
|
90
97
|
this._generateAirDatepickerEffect = effect(() => {
|
|
@@ -97,6 +104,7 @@ class QuangDateComponent extends QuangBaseComponent {
|
|
|
97
104
|
this.showTimepicker = computed(() => !this.rangeSelection() && (this.timepicker() || this.showOnlyTimepicker()), ...(ngDevMode ? [{ debugName: "showTimepicker" }] : []));
|
|
98
105
|
this.isMouseInsideCalendar = signal(false, ...(ngDevMode ? [{ debugName: "isMouseInsideCalendar" }] : []));
|
|
99
106
|
this.isMouseOutsideCalendar = computed(() => !this.isMouseInsideCalendar(), ...(ngDevMode ? [{ debugName: "isMouseOutsideCalendar" }] : []));
|
|
107
|
+
this._shouldRefocusInputOnHide = signal(false, ...(ngDevMode ? [{ debugName: "_shouldRefocusInputOnHide" }] : []));
|
|
100
108
|
fromEvent(document, 'scroll', { capture: true })
|
|
101
109
|
.pipe(takeUntilDestroyed(), debounceTime(250))
|
|
102
110
|
.subscribe(() => {
|
|
@@ -106,110 +114,146 @@ class QuangDateComponent extends QuangBaseComponent {
|
|
|
106
114
|
});
|
|
107
115
|
}
|
|
108
116
|
setupCalendar() {
|
|
109
|
-
if (this._inputForDate()?.nativeElement)
|
|
110
|
-
|
|
111
|
-
|
|
112
|
-
|
|
113
|
-
|
|
114
|
-
|
|
115
|
-
|
|
116
|
-
|
|
117
|
+
if (!this._inputForDate()?.nativeElement)
|
|
118
|
+
return;
|
|
119
|
+
const desiredInlineMode = this.showInline();
|
|
120
|
+
const existingInstance = this._airDatepickerInstance();
|
|
121
|
+
const existingInlineMode = this._airDatepickerInlineMode();
|
|
122
|
+
if (existingInstance && existingInlineMode !== null && existingInlineMode !== desiredInlineMode) {
|
|
123
|
+
const maybeDestroy = existingInstance;
|
|
124
|
+
maybeDestroy.destroy?.();
|
|
125
|
+
this._airDatepickerInstance.set(undefined);
|
|
126
|
+
}
|
|
127
|
+
let currentValue = this._value();
|
|
128
|
+
let targetDate;
|
|
129
|
+
if (currentValue && typeof currentValue === 'string') {
|
|
130
|
+
if (!this.showTimepicker()) {
|
|
131
|
+
currentValue = currentValue.split('T')[0];
|
|
117
132
|
}
|
|
118
|
-
|
|
119
|
-
|
|
120
|
-
|
|
121
|
-
|
|
122
|
-
|
|
123
|
-
|
|
124
|
-
|
|
125
|
-
|
|
126
|
-
|
|
127
|
-
if (currentValue.dateTo) {
|
|
128
|
-
let targetDateTo = currentValue.dateTo;
|
|
129
|
-
if (!this.showTimepicker()) {
|
|
130
|
-
targetDateTo = currentValue.dateTo.split('T')[0];
|
|
131
|
-
}
|
|
132
|
-
targetDate.push(targetDateTo);
|
|
133
|
-
}
|
|
133
|
+
targetDate = [currentValue];
|
|
134
|
+
}
|
|
135
|
+
else if (currentValue && typeof currentValue === 'object') {
|
|
136
|
+
targetDate = [];
|
|
137
|
+
if (currentValue.dateFrom) {
|
|
138
|
+
const targetDateFrom = this.showTimepicker()
|
|
139
|
+
? currentValue.dateFrom
|
|
140
|
+
: currentValue.dateFrom.split('T')[0];
|
|
141
|
+
targetDate.push(targetDateFrom);
|
|
134
142
|
}
|
|
135
|
-
|
|
136
|
-
|
|
137
|
-
|
|
138
|
-
|
|
139
|
-
|
|
140
|
-
|
|
141
|
-
|
|
142
|
-
|
|
143
|
-
|
|
144
|
-
|
|
145
|
-
|
|
146
|
-
|
|
147
|
-
|
|
148
|
-
|
|
149
|
-
|
|
150
|
-
|
|
151
|
-
|
|
152
|
-
|
|
153
|
-
|
|
154
|
-
|
|
155
|
-
|
|
156
|
-
|
|
157
|
-
|
|
158
|
-
|
|
159
|
-
|
|
160
|
-
|
|
161
|
-
|
|
162
|
-
|
|
143
|
+
if (currentValue.dateTo) {
|
|
144
|
+
const targetDateTo = this.showTimepicker() ? currentValue.dateTo : currentValue.dateTo.split('T')[0];
|
|
145
|
+
targetDate.push(targetDateTo);
|
|
146
|
+
}
|
|
147
|
+
}
|
|
148
|
+
this.setCalendarPosition();
|
|
149
|
+
const userDatepickerOptions = this.datepickerOptions() ?? {};
|
|
150
|
+
const userOnSelect = userDatepickerOptions.onSelect;
|
|
151
|
+
const userOnHide = userDatepickerOptions.onHide;
|
|
152
|
+
const userOnShow = userDatepickerOptions.onShow;
|
|
153
|
+
const airDatepickerOpts = {
|
|
154
|
+
...userDatepickerOptions,
|
|
155
|
+
autoClose: !this.showInline(),
|
|
156
|
+
showEvent: 'click',
|
|
157
|
+
classes: this.calendarClasses(),
|
|
158
|
+
dateFormat: this.dateFormat(),
|
|
159
|
+
inline: this.showInline(),
|
|
160
|
+
isMobile: false,
|
|
161
|
+
multipleDatesSeparator: this.multipleDatesSeparator(),
|
|
162
|
+
range: this.rangeSelection(),
|
|
163
|
+
timepicker: this.showTimepicker(),
|
|
164
|
+
onlyTimepicker: this.showOnlyTimepicker(),
|
|
165
|
+
timeFormat: this.timeFormat(),
|
|
166
|
+
minHours: this.minHour(),
|
|
167
|
+
maxHours: this.maxHour(),
|
|
168
|
+
minMinutes: this.minMinute(),
|
|
169
|
+
maxMinutes: this.maxMinute(),
|
|
170
|
+
minDate: this.minDate(),
|
|
171
|
+
maxDate: this.maxDate(),
|
|
172
|
+
toggleSelected: false,
|
|
173
|
+
multipleDates: false,
|
|
174
|
+
selectedDates: targetDate,
|
|
175
|
+
position: this.targetPosition(),
|
|
176
|
+
locale: this.getLocale(),
|
|
177
|
+
onSelect: (args) => {
|
|
178
|
+
const { date } = args;
|
|
179
|
+
// AirDatepicker callbacks may fire outside Angular's zone in some app setups.
|
|
180
|
+
// Ensure CVA propagation happens inside the zone so the connected FormControl updates reliably.
|
|
181
|
+
this._ngZone.run(() => {
|
|
182
|
+
this._shouldRefocusInputOnHide.set(true);
|
|
183
|
+
if (Array.isArray(date)) {
|
|
184
|
+
// Range selection: AirDatepicker emits partial selections too (only start date).
|
|
185
|
+
// Committing `_value` for partial selections can trigger `setupCalendar()` re-sync and
|
|
186
|
+
// break the second click. Only commit once the range is complete.
|
|
187
|
+
const [from, to] = date;
|
|
188
|
+
if (!from || !to) {
|
|
189
|
+
return;
|
|
163
190
|
}
|
|
191
|
+
const value = {
|
|
192
|
+
dateFrom: (this.showTimepicker() ? from : this.dateToUtc(from)).toISOString(),
|
|
193
|
+
dateTo: (this.showTimepicker() ? to : this.dateToUtc(to)).toISOString(),
|
|
194
|
+
};
|
|
195
|
+
this.onChangedHandler(value);
|
|
196
|
+
}
|
|
197
|
+
else if (date) {
|
|
198
|
+
const selectTargetDate = this.showTimepicker() ? date : this.dateToUtc(date);
|
|
164
199
|
this.onChangedHandler(selectTargetDate.toISOString());
|
|
165
200
|
}
|
|
166
201
|
if (this.showInline()) {
|
|
167
|
-
|
|
168
|
-
|
|
169
|
-
|
|
170
|
-
onHide: (isAnimationComplete) => {
|
|
171
|
-
if (isAnimationComplete) {
|
|
172
|
-
this.onHideCalendar();
|
|
173
|
-
}
|
|
174
|
-
},
|
|
175
|
-
...(this.datepickerOptions() ?? {}),
|
|
176
|
-
onShow: (isAnimationComplete) => {
|
|
177
|
-
const datepicker = this._airDatepickerInstance()?.$datepicker;
|
|
178
|
-
if (datepicker) {
|
|
179
|
-
datepicker.onmouseenter = () => {
|
|
180
|
-
this.isMouseInsideCalendar.set(true);
|
|
181
|
-
};
|
|
182
|
-
datepicker.onmouseleave = () => {
|
|
183
|
-
this.isMouseInsideCalendar.set(false);
|
|
184
|
-
};
|
|
185
|
-
}
|
|
186
|
-
if (isAnimationComplete || !this.showTimepicker()) {
|
|
187
|
-
return;
|
|
202
|
+
// Inline mode should update the connected control immediately.
|
|
203
|
+
// Do not rely on `onHideCalendar()` because inline never hides and the input may be visually hidden.
|
|
204
|
+
this.propagateValueToControl();
|
|
188
205
|
}
|
|
189
|
-
|
|
190
|
-
|
|
191
|
-
}
|
|
192
|
-
|
|
193
|
-
if (
|
|
194
|
-
this.
|
|
195
|
-
}
|
|
196
|
-
else {
|
|
197
|
-
this._airDatepickerInstance()?.update(airDatepickerOpts, { silent: true });
|
|
206
|
+
});
|
|
207
|
+
userOnSelect?.(args);
|
|
208
|
+
},
|
|
209
|
+
onHide: (isAnimationComplete) => {
|
|
210
|
+
if (isAnimationComplete) {
|
|
211
|
+
this.onHideCalendar();
|
|
198
212
|
}
|
|
199
|
-
|
|
200
|
-
|
|
201
|
-
|
|
213
|
+
userOnHide?.(isAnimationComplete);
|
|
214
|
+
},
|
|
215
|
+
onShow: (isAnimationComplete) => {
|
|
216
|
+
const datepicker = this._airDatepickerInstance()?.$datepicker;
|
|
217
|
+
if (datepicker) {
|
|
218
|
+
datepicker.onmouseenter = () => {
|
|
219
|
+
this.isMouseInsideCalendar.set(true);
|
|
220
|
+
};
|
|
221
|
+
datepicker.onmouseleave = () => {
|
|
222
|
+
this.isMouseInsideCalendar.set(false);
|
|
223
|
+
};
|
|
202
224
|
}
|
|
203
|
-
|
|
204
|
-
|
|
225
|
+
if (isAnimationComplete || !this.showTimepicker()) {
|
|
226
|
+
return;
|
|
205
227
|
}
|
|
228
|
+
this.setupTimepicker();
|
|
229
|
+
userOnShow?.(isAnimationComplete);
|
|
230
|
+
},
|
|
231
|
+
};
|
|
232
|
+
if (this._airDatepickerInstance()) {
|
|
233
|
+
if (this._airDatepickerInstance()?.visible) {
|
|
234
|
+
this._airDatepickerInstance()?.update(airDatepickerOpts);
|
|
206
235
|
}
|
|
207
236
|
else {
|
|
208
|
-
this._airDatepickerInstance
|
|
237
|
+
this._airDatepickerInstance()?.update(airDatepickerOpts, { silent: true });
|
|
209
238
|
}
|
|
210
|
-
if (
|
|
211
|
-
this.
|
|
239
|
+
if (targetDate) {
|
|
240
|
+
this._airDatepickerInstance()?.selectDate(targetDate, { updateTime: true, silent: true });
|
|
212
241
|
}
|
|
242
|
+
else {
|
|
243
|
+
this._airDatepickerInstance()?.setFocusDate(false);
|
|
244
|
+
this._airDatepickerInstance()?.clear({ silent: true });
|
|
245
|
+
}
|
|
246
|
+
}
|
|
247
|
+
else {
|
|
248
|
+
this._airDatepickerInstance.set(new AirDatepicker(this._inputForDate()?.nativeElement, airDatepickerOpts));
|
|
249
|
+
}
|
|
250
|
+
this._airDatepickerInlineMode.set(desiredInlineMode);
|
|
251
|
+
if (desiredInlineMode) {
|
|
252
|
+
// Ensure inline calendar is visible after re-creation/update.
|
|
253
|
+
this._airDatepickerInstance()?.show?.();
|
|
254
|
+
}
|
|
255
|
+
if (this.showInline()) {
|
|
256
|
+
this.setupTimepicker();
|
|
213
257
|
}
|
|
214
258
|
}
|
|
215
259
|
onChangeText($event) {
|
|
@@ -218,14 +262,23 @@ class QuangDateComponent extends QuangBaseComponent {
|
|
|
218
262
|
// TODO: check format for DateRange
|
|
219
263
|
if (value.length === this.valueFormat().length && isMatch(value, this.valueFormat())) {
|
|
220
264
|
this.onChangedHandler(this.setupInputStringToDate(value).toISOString());
|
|
265
|
+
if (this.showInline()) {
|
|
266
|
+
this.propagateValueToControl();
|
|
267
|
+
}
|
|
221
268
|
}
|
|
222
269
|
}
|
|
223
270
|
else {
|
|
224
271
|
this.onChangedHandler(value);
|
|
272
|
+
if (this.showInline()) {
|
|
273
|
+
this.propagateValueToControl();
|
|
274
|
+
}
|
|
225
275
|
}
|
|
226
276
|
}
|
|
227
277
|
onBlurHandler() {
|
|
228
278
|
super.onBlurHandler();
|
|
279
|
+
if (this.showInline()) {
|
|
280
|
+
return;
|
|
281
|
+
}
|
|
229
282
|
if (this.isMouseOutsideCalendar() && this._airDatepickerInstance()?.visible) {
|
|
230
283
|
this._airDatepickerInstance()?.hide();
|
|
231
284
|
}
|
|
@@ -235,9 +288,9 @@ class QuangDateComponent extends QuangBaseComponent {
|
|
|
235
288
|
if (value.length !== targetValueFormat.length) {
|
|
236
289
|
targetValueFormat = targetValueFormat.replace('yyyy', 'yy');
|
|
237
290
|
}
|
|
238
|
-
|
|
291
|
+
const targetDate = parse(value, targetValueFormat, new Date());
|
|
239
292
|
if (!this.showTimepicker()) {
|
|
240
|
-
|
|
293
|
+
return this.dateToUtc(targetDate);
|
|
241
294
|
}
|
|
242
295
|
return targetDate;
|
|
243
296
|
}
|
|
@@ -276,6 +329,42 @@ class QuangDateComponent extends QuangBaseComponent {
|
|
|
276
329
|
}
|
|
277
330
|
this._value.set(targetDate);
|
|
278
331
|
}
|
|
332
|
+
propagateValueToControl() {
|
|
333
|
+
if (this.formControl()?.getRawValue() !== this._value()) {
|
|
334
|
+
super.onChangedHandler(this._value());
|
|
335
|
+
}
|
|
336
|
+
else if (this.onTouched) {
|
|
337
|
+
this.onTouched();
|
|
338
|
+
}
|
|
339
|
+
this.requestRender();
|
|
340
|
+
}
|
|
341
|
+
requestRender() {
|
|
342
|
+
// Inline datepicker interactions can happen outside Angular-managed events.
|
|
343
|
+
// Marking the view dirty is not always enough in zoneless/event-coalesced setups,
|
|
344
|
+
// so we coalesce a manual tick.
|
|
345
|
+
this._cdr.markForCheck();
|
|
346
|
+
if (this._tickScheduled) {
|
|
347
|
+
return;
|
|
348
|
+
}
|
|
349
|
+
this._tickScheduled = true;
|
|
350
|
+
queueMicrotask(() => {
|
|
351
|
+
this._tickScheduled = false;
|
|
352
|
+
this._appRef.tick();
|
|
353
|
+
});
|
|
354
|
+
}
|
|
355
|
+
syncValueFromDatepickerSelection() {
|
|
356
|
+
if (!this.showInline()) {
|
|
357
|
+
return;
|
|
358
|
+
}
|
|
359
|
+
const datepickerInstance = this._airDatepickerInstance();
|
|
360
|
+
const selectedDate = datepickerInstance?.selectedDates?.[0];
|
|
361
|
+
if (!(selectedDate instanceof Date)) {
|
|
362
|
+
return;
|
|
363
|
+
}
|
|
364
|
+
const targetDate = this.showTimepicker() ? selectedDate : this.dateToUtc(selectedDate);
|
|
365
|
+
this.onChangedHandler(targetDate.toISOString());
|
|
366
|
+
this.propagateValueToControl();
|
|
367
|
+
}
|
|
279
368
|
onHideCalendar() {
|
|
280
369
|
const valueInput = this._inputForDate()?.nativeElement.value;
|
|
281
370
|
let value = valueInput;
|
|
@@ -284,18 +373,14 @@ class QuangDateComponent extends QuangBaseComponent {
|
|
|
284
373
|
const [dateFrom, dateTo] = valueInput.split(this.multipleDatesSeparator());
|
|
285
374
|
value.dateFrom = dateFrom ?? '';
|
|
286
375
|
value.dateTo = dateTo ?? '';
|
|
287
|
-
|
|
288
|
-
value.dateFrom
|
|
289
|
-
|
|
290
|
-
|
|
291
|
-
|
|
292
|
-
|
|
293
|
-
|
|
294
|
-
|
|
295
|
-
}
|
|
296
|
-
else {
|
|
297
|
-
value.dateTo = this.setupInputStringToDate(value.dateTo).toISOString();
|
|
298
|
-
}
|
|
376
|
+
value.dateFrom =
|
|
377
|
+
!value.dateFrom || !this.checkDateMatch(value.dateFrom)
|
|
378
|
+
? null
|
|
379
|
+
: this.setupInputStringToDate(value.dateFrom).toISOString();
|
|
380
|
+
value.dateTo =
|
|
381
|
+
!value.dateTo || !this.checkDateMatch(value.dateTo)
|
|
382
|
+
? null
|
|
383
|
+
: this.setupInputStringToDate(value.dateTo).toISOString();
|
|
299
384
|
this.onChangedHandler(value);
|
|
300
385
|
}
|
|
301
386
|
else if (this.checkDateMatch(value)) {
|
|
@@ -304,21 +389,20 @@ class QuangDateComponent extends QuangBaseComponent {
|
|
|
304
389
|
else {
|
|
305
390
|
this.onChangedHandler(null);
|
|
306
391
|
}
|
|
307
|
-
|
|
308
|
-
|
|
309
|
-
|
|
310
|
-
else if (this.onTouched) {
|
|
311
|
-
this.onTouched();
|
|
392
|
+
this.propagateValueToControl();
|
|
393
|
+
if (this.showInline()) {
|
|
394
|
+
return;
|
|
312
395
|
}
|
|
313
|
-
// Only focus the input
|
|
314
|
-
// (e.g., user selected a date via keyboard or mouse click on the calendar).
|
|
396
|
+
// Only focus the input when the user actually interacted with the calendar.
|
|
315
397
|
// Avoids infinite focus loop when tabbing between multiple datepickers.
|
|
316
398
|
const activeElement = document.activeElement;
|
|
317
399
|
const calendarElement = this._airDatepickerInstance()?.$datepicker;
|
|
318
400
|
const inputElement = this._inputForDate()?.nativeElement;
|
|
319
401
|
const isCalendarFocused = calendarElement?.contains(activeElement);
|
|
320
|
-
|
|
321
|
-
|
|
402
|
+
const shouldRefocus = this._shouldRefocusInputOnHide() || isCalendarFocused || this.isMouseInsideCalendar();
|
|
403
|
+
this._shouldRefocusInputOnHide.set(false);
|
|
404
|
+
if (shouldRefocus) {
|
|
405
|
+
setTimeout(() => inputElement?.focus(), 0);
|
|
322
406
|
}
|
|
323
407
|
this.onBlurHandler();
|
|
324
408
|
}
|
|
@@ -327,6 +411,9 @@ class QuangDateComponent extends QuangBaseComponent {
|
|
|
327
411
|
return format(val, this.valueFormat());
|
|
328
412
|
}
|
|
329
413
|
if (val && typeof val === 'object') {
|
|
414
|
+
if (!val.dateFrom && !val.dateTo) {
|
|
415
|
+
return '';
|
|
416
|
+
}
|
|
330
417
|
let dateFromFormat = '';
|
|
331
418
|
let dateToFormat = '';
|
|
332
419
|
if (val.dateFrom) {
|
|
@@ -340,8 +427,29 @@ class QuangDateComponent extends QuangBaseComponent {
|
|
|
340
427
|
return '';
|
|
341
428
|
}
|
|
342
429
|
openDatePicker() {
|
|
343
|
-
|
|
344
|
-
|
|
430
|
+
const inputEl = this._inputForDate()?.nativeElement;
|
|
431
|
+
if (!inputEl || this._isDisabled()) {
|
|
432
|
+
return;
|
|
433
|
+
}
|
|
434
|
+
inputEl.focus();
|
|
435
|
+
if (!this._airDatepickerInstance()) {
|
|
436
|
+
this.setupCalendar();
|
|
437
|
+
}
|
|
438
|
+
this._airDatepickerInstance()?.show();
|
|
439
|
+
}
|
|
440
|
+
onInputKeydown(event) {
|
|
441
|
+
if (this._isDisabled()) {
|
|
442
|
+
return;
|
|
443
|
+
}
|
|
444
|
+
const datepickerInstance = this._airDatepickerInstance();
|
|
445
|
+
if (event.key === 'Escape' && datepickerInstance?.visible) {
|
|
446
|
+
event.preventDefault();
|
|
447
|
+
datepickerInstance.hide();
|
|
448
|
+
return;
|
|
449
|
+
}
|
|
450
|
+
if (event.key === 'Enter' || event.key === 'ArrowDown') {
|
|
451
|
+
event.preventDefault();
|
|
452
|
+
this.openDatePicker();
|
|
345
453
|
}
|
|
346
454
|
}
|
|
347
455
|
interceptInputInteraction($event) {
|
|
@@ -354,15 +462,25 @@ class QuangDateComponent extends QuangBaseComponent {
|
|
|
354
462
|
getLocale() {
|
|
355
463
|
switch (this._activeLanguage()?.toLowerCase()) {
|
|
356
464
|
case 'en':
|
|
357
|
-
return
|
|
465
|
+
return this.unwrapLocaleModule(en);
|
|
358
466
|
case 'it':
|
|
359
|
-
return
|
|
467
|
+
return this.unwrapLocaleModule(it);
|
|
360
468
|
case 'fr':
|
|
361
|
-
return
|
|
469
|
+
return this.unwrapLocaleModule(fr);
|
|
362
470
|
default:
|
|
363
|
-
return
|
|
471
|
+
return this.unwrapLocaleModule(en);
|
|
364
472
|
}
|
|
365
473
|
}
|
|
474
|
+
unwrapLocaleModule(localeModule) {
|
|
475
|
+
if (typeof localeModule === 'object' && localeModule !== null && 'default' in localeModule) {
|
|
476
|
+
const moduleWithDefault = localeModule;
|
|
477
|
+
if (moduleWithDefault.default) {
|
|
478
|
+
return moduleWithDefault.default;
|
|
479
|
+
}
|
|
480
|
+
return localeModule;
|
|
481
|
+
}
|
|
482
|
+
return localeModule;
|
|
483
|
+
}
|
|
366
484
|
onCancel() {
|
|
367
485
|
this._inputForDate()?.nativeElement.blur();
|
|
368
486
|
}
|
|
@@ -370,10 +488,6 @@ class QuangDateComponent extends QuangBaseComponent {
|
|
|
370
488
|
// convert to UTC time removing the timezone
|
|
371
489
|
return new Date(date.getTime() - date.getTimezoneOffset() * 60000);
|
|
372
490
|
}
|
|
373
|
-
dateToLocal(date) {
|
|
374
|
-
// convert to local time adding the timezone
|
|
375
|
-
return new Date(date.getTime() + date.getTimezoneOffset() * 60000);
|
|
376
|
-
}
|
|
377
491
|
setCalendarPosition() {
|
|
378
492
|
const windowInnerHeight = window.innerHeight;
|
|
379
493
|
const inputBoundingClientRect = this._inputForDate()?.nativeElement.getBoundingClientRect();
|
|
@@ -386,8 +500,23 @@ class QuangDateComponent extends QuangBaseComponent {
|
|
|
386
500
|
}
|
|
387
501
|
}
|
|
388
502
|
setupTimepicker() {
|
|
389
|
-
const
|
|
390
|
-
if (
|
|
503
|
+
const datepickerRoot = this._airDatepickerInstance()?.$datepicker;
|
|
504
|
+
if (!datepickerRoot) {
|
|
505
|
+
return;
|
|
506
|
+
}
|
|
507
|
+
// AirDatepicker may re-render time inputs; use delegated listeners so we don't lose handlers.
|
|
508
|
+
if (!datepickerRoot.dataset['quangTimepickerListeners']) {
|
|
509
|
+
datepickerRoot.dataset['quangTimepickerListeners'] = 'true';
|
|
510
|
+
datepickerRoot.addEventListener('input', () => {
|
|
511
|
+
if (!this.showInline()) {
|
|
512
|
+
return;
|
|
513
|
+
}
|
|
514
|
+
// Let AirDatepicker update its internal selection first.
|
|
515
|
+
setTimeout(() => this._ngZone.run(() => this.syncValueFromDatepickerSelection()), 0);
|
|
516
|
+
}, { capture: true });
|
|
517
|
+
}
|
|
518
|
+
const timepickers = datepickerRoot.getElementsByClassName('air-datepicker-time');
|
|
519
|
+
for (const timepicker of Array.from(timepickers)) {
|
|
391
520
|
const inputs = timepicker.getElementsByTagName('input');
|
|
392
521
|
for (const input of Array.from(inputs)) {
|
|
393
522
|
input.setAttribute('type', 'number');
|
|
@@ -397,7 +526,7 @@ class QuangDateComponent extends QuangBaseComponent {
|
|
|
397
526
|
evt.stopImmediatePropagation();
|
|
398
527
|
};
|
|
399
528
|
input.onblur = () => {
|
|
400
|
-
if (this.isMouseOutsideCalendar()) {
|
|
529
|
+
if (!this.showInline() && this.isMouseOutsideCalendar()) {
|
|
401
530
|
this._airDatepickerInstance()?.hide();
|
|
402
531
|
}
|
|
403
532
|
};
|
|
@@ -408,14 +537,12 @@ class QuangDateComponent extends QuangBaseComponent {
|
|
|
408
537
|
return isMatch(date, this.valueFormat()) || isMatch(date, this.valueFormat().replace('yyyy', 'yy'));
|
|
409
538
|
}
|
|
410
539
|
static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "20.3.15", ngImport: i0, type: QuangDateComponent, deps: [], target: i0.ɵɵFactoryTarget.Component }); }
|
|
411
|
-
static { this.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "20.3.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 d-flex gap-2\"\n >\n <div>\n <span>{{ componentLabel() | transloco }}</span>\n <span [hidden]=\"!_isRequired()\">*</span>\n </div>\n @if (helpMessage() && helpMessageTooltip()) {\n <div [quangTooltip]=\"helpMessage() | transloco\">\n <ng-content select=\"[help-icon]\" />\n </div>\n }\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.
|
|
540
|
+
static { this.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "20.3.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 d-flex gap-2\"\n >\n <div>\n <span>{{ componentLabel() | transloco }}</span>\n <span [hidden]=\"!_isRequired()\">*</span>\n </div>\n @if (helpMessage() && helpMessageTooltip()) {\n <div [quangTooltip]=\"helpMessage() | transloco\">\n <ng-content select=\"[help-icon]\" />\n </div>\n }\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() && !helpMessageTooltip()) {\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: "directive", type: NgClass, selector: "[ngClass]", inputs: ["class", "ngClass"] }, { kind: "directive", type: QuangTooltipDirective, selector: "[quangTooltip]", inputs: ["quangTooltip", "showMethod"] }, { kind: "pipe", type: TranslocoPipe, name: "transloco" }], changeDetection: i0.ChangeDetectionStrategy.OnPush }); }
|
|
412
541
|
}
|
|
413
542
|
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.3.15", ngImport: i0, type: QuangDateComponent, decorators: [{
|
|
414
543
|
type: Component,
|
|
415
|
-
args: [{ selector: 'quang-date', providers: [{ provide: NG_VALUE_ACCESSOR, useExisting: forwardRef(() => QuangDateComponent), multi: true }], imports: [TranslocoPipe, NgClass, QuangTooltipDirective], changeDetection: ChangeDetectionStrategy.OnPush, template: "<div class=\"mb-3\">\n @if (componentLabel()) {\n <label\n [htmlFor]=\"componentId()\"\n class=\"form-label d-flex gap-2\"\n >\n <div>\n <span>{{ componentLabel() | transloco }}</span>\n <span [hidden]=\"!_isRequired()\">*</span>\n </div>\n @if (helpMessage() && helpMessageTooltip()) {\n <div [quangTooltip]=\"helpMessage() | transloco\">\n <ng-content select=\"[help-icon]\" />\n </div>\n }\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.
|
|
416
|
-
}], ctorParameters: () => [], propDecorators: { dateFormat: [{ type: i0.Input, args: [{ isSignal: true, alias: "dateFormat", required: false }] }], timeFormat: [{ type: i0.Input, args: [{ isSignal: true, alias: "timeFormat", required: false }] }], activeLanguageOverride: [{ type: i0.Input, args: [{ isSignal: true, alias: "activeLanguageOverride", required: false }] }], timepicker: [{ type: i0.Input, args: [{ isSignal: true, alias: "timepicker", required: false }] }], invalidDateMessage: [{ type: i0.Input, args: [{ isSignal: true, alias: "invalidDateMessage", required: false }] }], showOnlyTimepicker: [{ type: i0.Input, args: [{ isSignal: true, alias: "showOnlyTimepicker", required: false }] }], minHour: [{ type: i0.Input, args: [{ isSignal: true, alias: "minHour", required: false }] }], maxHour: [{ type: i0.Input, args: [{ isSignal: true, alias: "maxHour", required: false }] }], minMinute: [{ type: i0.Input, args: [{ isSignal: true, alias: "minMinute", required: false }] }], maxMinute: [{ type: i0.Input, args: [{ isSignal: true, alias: "maxMinute", required: false }] }], minDate: [{ type: i0.Input, args: [{ isSignal: true, alias: "minDate", required: false }] }], maxDate: [{ type: i0.Input, args: [{ isSignal: true, alias: "maxDate", required: false }] }], showInline: [{ type: i0.Input, args: [{ isSignal: true, alias: "showInline", required: false }] }], calendarClasses: [{ type: i0.Input, args: [{ isSignal: true, alias: "calendarClasses", required: false }] }], buttonClass: [{ type: i0.Input, args: [{ isSignal: true, alias: "buttonClass", required: false }] }], datepickerOptions: [{ type: i0.Input, args: [{ isSignal: true, alias: "datepickerOptions", required: false }] }], _inputForDate: [{ type: i0.ViewChild, args: ['inputForDate', { isSignal: true }] }], contentTemplate: [{ type: i0.ViewChild, args: ['calendarButton', { isSignal: true }] }],
|
|
417
|
-
type: Optional
|
|
418
|
-
}], multipleDatesSeparator: [{ type: i0.Input, args: [{ isSignal: true, alias: "multipleDatesSeparator", required: false }] }], rangeSelection: [{ type: i0.Input, args: [{ isSignal: true, alias: "rangeSelection", required: false }] }], searchTextDebounce: [{ type: i0.Input, args: [{ isSignal: true, alias: "searchTextDebounce", required: false }] }] } });
|
|
544
|
+
args: [{ selector: 'quang-date', providers: [{ provide: NG_VALUE_ACCESSOR, useExisting: forwardRef(() => QuangDateComponent), multi: true }], imports: [TranslocoPipe, NgClass, QuangTooltipDirective], changeDetection: ChangeDetectionStrategy.OnPush, template: "<div class=\"mb-3\">\n @if (componentLabel()) {\n <label\n [htmlFor]=\"componentId()\"\n class=\"form-label d-flex gap-2\"\n >\n <div>\n <span>{{ componentLabel() | transloco }}</span>\n <span [hidden]=\"!_isRequired()\">*</span>\n </div>\n @if (helpMessage() && helpMessageTooltip()) {\n <div [quangTooltip]=\"helpMessage() | transloco\">\n <ng-content select=\"[help-icon]\" />\n </div>\n }\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() && !helpMessageTooltip()) {\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"] }]
|
|
545
|
+
}], ctorParameters: () => [], propDecorators: { dateFormat: [{ type: i0.Input, args: [{ isSignal: true, alias: "dateFormat", required: false }] }], timeFormat: [{ type: i0.Input, args: [{ isSignal: true, alias: "timeFormat", required: false }] }], activeLanguageOverride: [{ type: i0.Input, args: [{ isSignal: true, alias: "activeLanguageOverride", required: false }] }], timepicker: [{ type: i0.Input, args: [{ isSignal: true, alias: "timepicker", required: false }] }], invalidDateMessage: [{ type: i0.Input, args: [{ isSignal: true, alias: "invalidDateMessage", required: false }] }], showOnlyTimepicker: [{ type: i0.Input, args: [{ isSignal: true, alias: "showOnlyTimepicker", required: false }] }], minHour: [{ type: i0.Input, args: [{ isSignal: true, alias: "minHour", required: false }] }], maxHour: [{ type: i0.Input, args: [{ isSignal: true, alias: "maxHour", required: false }] }], minMinute: [{ type: i0.Input, args: [{ isSignal: true, alias: "minMinute", required: false }] }], maxMinute: [{ type: i0.Input, args: [{ isSignal: true, alias: "maxMinute", required: false }] }], minDate: [{ type: i0.Input, args: [{ isSignal: true, alias: "minDate", required: false }] }], maxDate: [{ type: i0.Input, args: [{ isSignal: true, alias: "maxDate", required: false }] }], showInline: [{ type: i0.Input, args: [{ isSignal: true, alias: "showInline", required: false }] }], calendarClasses: [{ type: i0.Input, args: [{ isSignal: true, alias: "calendarClasses", required: false }] }], buttonClass: [{ type: i0.Input, args: [{ isSignal: true, alias: "buttonClass", required: false }] }], datepickerOptions: [{ type: i0.Input, args: [{ isSignal: true, alias: "datepickerOptions", required: false }] }], _inputForDate: [{ type: i0.ViewChild, args: ['inputForDate', { isSignal: true }] }], contentTemplate: [{ type: i0.ViewChild, args: ['calendarButton', { isSignal: true }] }], multipleDatesSeparator: [{ type: i0.Input, args: [{ isSignal: true, alias: "multipleDatesSeparator", required: false }] }], rangeSelection: [{ type: i0.Input, args: [{ isSignal: true, alias: "rangeSelection", required: false }] }], searchTextDebounce: [{ type: i0.Input, args: [{ isSignal: true, alias: "searchTextDebounce", required: false }] }] } });
|
|
419
546
|
|
|
420
547
|
/**
|
|
421
548
|
* Generated bundle index. Do not edit.
|