@shival99/z-ui 2.0.24 → 2.0.26
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/fesm2022/shival99-z-ui-components-z-calendar.mjs +217 -75
- package/fesm2022/shival99-z-ui-components-z-calendar.mjs.map +1 -1
- package/fesm2022/shival99-z-ui-components-z-gallery.mjs +33 -26
- package/fesm2022/shival99-z-ui-components-z-gallery.mjs.map +1 -1
- package/package.json +1 -1
- package/types/shival99-z-ui-components-z-calendar.d.ts +8 -5
- package/types/shival99-z-ui-components-z-gallery.d.ts +1 -0
- package/types/shival99-z-ui-components-z-table.d.ts +1 -1
|
@@ -243,28 +243,61 @@ const formatDate = (date, format, locale = 'vi-VN') => {
|
|
|
243
243
|
}
|
|
244
244
|
return result;
|
|
245
245
|
};
|
|
246
|
-
const parseDate = (dateString, format) => {
|
|
246
|
+
const parseDate = (dateString, format, locale = 'vi-VN') => {
|
|
247
247
|
if (!dateString) {
|
|
248
248
|
return null;
|
|
249
249
|
}
|
|
250
|
-
const
|
|
251
|
-
|
|
252
|
-
|
|
253
|
-
|
|
254
|
-
|
|
255
|
-
.
|
|
256
|
-
.replace(/
|
|
257
|
-
|
|
258
|
-
|
|
259
|
-
|
|
260
|
-
|
|
261
|
-
|
|
262
|
-
|
|
263
|
-
|
|
264
|
-
return
|
|
250
|
+
const getFullMonthNamesPattern = (loc) => {
|
|
251
|
+
const names = [];
|
|
252
|
+
for (let i = 0; i < 12; i++) {
|
|
253
|
+
names.push(getFullMonthName(i, loc));
|
|
254
|
+
}
|
|
255
|
+
const sortedNames = [...names].sort((a, b) => b.length - a.length);
|
|
256
|
+
return `(${sortedNames.map(name => name.replace(/[-/\\^$*+?.()|[\]{}]/g, '\\$&')).join('|')})`;
|
|
257
|
+
};
|
|
258
|
+
const getShortMonthNamesPattern = (loc) => {
|
|
259
|
+
const names = [];
|
|
260
|
+
for (let i = 0; i < 12; i++) {
|
|
261
|
+
names.push(getShortMonthName(i, loc));
|
|
262
|
+
}
|
|
263
|
+
const sortedNames = [...names].sort((a, b) => b.length - a.length);
|
|
264
|
+
return `(${sortedNames.map(name => name.replace(/[-/\\^$*+?.()|[\]{}]/g, '\\$&')).join('|')})`;
|
|
265
|
+
};
|
|
266
|
+
const tokens = {
|
|
267
|
+
YYYY: '_T_0_',
|
|
268
|
+
MMMM: '_T_1_',
|
|
269
|
+
MMM: '_T_2_',
|
|
270
|
+
MM: '_T_3_',
|
|
271
|
+
DD: '_T_4_',
|
|
272
|
+
HH: '_T_5_',
|
|
273
|
+
hh: '_T_6_',
|
|
274
|
+
mm: '_T_7_',
|
|
275
|
+
ss: '_T_8_',
|
|
276
|
+
};
|
|
277
|
+
let tempFormat = format;
|
|
278
|
+
const sortedTokens = Object.keys(tokens).sort((a, b) => b.length - a.length);
|
|
279
|
+
for (const token of sortedTokens) {
|
|
280
|
+
tempFormat = tempFormat.split(token).join(tokens[token]);
|
|
281
|
+
}
|
|
282
|
+
let escapedPattern = tempFormat.replace(/[-/\\^$*+?.()|[\]{},]/g, '\\$&');
|
|
283
|
+
escapedPattern = escapedPattern.replace(/\s+/g, '\\s*');
|
|
284
|
+
const patterns = {
|
|
285
|
+
_T_0_: '(\\d{4})',
|
|
286
|
+
_T_1_: getFullMonthNamesPattern(locale),
|
|
287
|
+
_T_2_: getShortMonthNamesPattern(locale),
|
|
288
|
+
_T_3_: '(\\d{1,2})',
|
|
289
|
+
_T_4_: '(\\d{1,2})',
|
|
290
|
+
_T_5_: '(\\d{1,2})',
|
|
291
|
+
_T_6_: '(\\d{1,2})',
|
|
292
|
+
_T_7_: '(\\d{1,2})',
|
|
293
|
+
_T_8_: '(\\d{1,2})',
|
|
294
|
+
};
|
|
295
|
+
for (const [placeholder, regexStr] of Object.entries(patterns)) {
|
|
296
|
+
escapedPattern = escapedPattern.split(placeholder).join(regexStr);
|
|
265
297
|
}
|
|
266
|
-
const
|
|
267
|
-
|
|
298
|
+
const datePattern = new RegExp(`^${escapedPattern}(\\s*(AM|PM))?$`, 'i');
|
|
299
|
+
const match = dateString.trim().match(datePattern);
|
|
300
|
+
if (!match) {
|
|
268
301
|
return null;
|
|
269
302
|
}
|
|
270
303
|
const currentYear = new Date().getFullYear();
|
|
@@ -277,12 +310,64 @@ const parseDate = (dateString, format) => {
|
|
|
277
310
|
mm: 0,
|
|
278
311
|
ss: 0,
|
|
279
312
|
};
|
|
280
|
-
const
|
|
281
|
-
|
|
282
|
-
|
|
283
|
-
|
|
284
|
-
|
|
285
|
-
|
|
313
|
+
const placeholderOrder = tempFormat.match(/_T_\d+_/g) || [];
|
|
314
|
+
for (let i = 0; i < placeholderOrder.length; i++) {
|
|
315
|
+
const placeholder = placeholderOrder[i];
|
|
316
|
+
const groupVal = match[i + 1];
|
|
317
|
+
if (!groupVal) {
|
|
318
|
+
continue;
|
|
319
|
+
}
|
|
320
|
+
if (placeholder === '_T_0_') {
|
|
321
|
+
values['YYYY'] = parseInt(groupVal, 10);
|
|
322
|
+
}
|
|
323
|
+
else if (placeholder === '_T_3_') {
|
|
324
|
+
values['MM'] = parseInt(groupVal, 10);
|
|
325
|
+
}
|
|
326
|
+
else if (placeholder === '_T_4_') {
|
|
327
|
+
values['DD'] = parseInt(groupVal, 10);
|
|
328
|
+
}
|
|
329
|
+
else if (placeholder === '_T_5_') {
|
|
330
|
+
values['HH'] = parseInt(groupVal, 10);
|
|
331
|
+
}
|
|
332
|
+
else if (placeholder === '_T_6_') {
|
|
333
|
+
values['hh'] = parseInt(groupVal, 10);
|
|
334
|
+
}
|
|
335
|
+
else if (placeholder === '_T_7_') {
|
|
336
|
+
values['mm'] = parseInt(groupVal, 10);
|
|
337
|
+
}
|
|
338
|
+
else if (placeholder === '_T_8_') {
|
|
339
|
+
values['ss'] = parseInt(groupVal, 10);
|
|
340
|
+
}
|
|
341
|
+
else if (placeholder === '_T_1_') {
|
|
342
|
+
let foundMonth = -1;
|
|
343
|
+
for (let m = 0; m < 12; m++) {
|
|
344
|
+
if (getFullMonthName(m, locale).toLowerCase() === groupVal.toLowerCase()) {
|
|
345
|
+
foundMonth = m;
|
|
346
|
+
break;
|
|
347
|
+
}
|
|
348
|
+
}
|
|
349
|
+
if (foundMonth !== -1) {
|
|
350
|
+
values['MM'] = foundMonth + 1;
|
|
351
|
+
}
|
|
352
|
+
else {
|
|
353
|
+
return null;
|
|
354
|
+
}
|
|
355
|
+
}
|
|
356
|
+
else if (placeholder === '_T_2_') {
|
|
357
|
+
let foundMonth = -1;
|
|
358
|
+
for (let m = 0; m < 12; m++) {
|
|
359
|
+
if (getShortMonthName(m, locale).toLowerCase() === groupVal.toLowerCase()) {
|
|
360
|
+
foundMonth = m;
|
|
361
|
+
break;
|
|
362
|
+
}
|
|
363
|
+
}
|
|
364
|
+
if (foundMonth !== -1) {
|
|
365
|
+
values['MM'] = foundMonth + 1;
|
|
366
|
+
}
|
|
367
|
+
else {
|
|
368
|
+
return null;
|
|
369
|
+
}
|
|
370
|
+
}
|
|
286
371
|
}
|
|
287
372
|
const isPM = /PM/i.test(dateString);
|
|
288
373
|
const isAM = /AM/i.test(dateString);
|
|
@@ -565,7 +650,7 @@ const zCalendarDayVariants = cva([
|
|
|
565
650
|
rangeStart: 'bg-primary text-primary-foreground rounded-r-none',
|
|
566
651
|
rangeEnd: 'bg-primary text-primary-foreground rounded-l-none',
|
|
567
652
|
rangeSingle: 'bg-primary text-primary-foreground',
|
|
568
|
-
disabled: 'text-muted-foreground/50 cursor-not-allowed',
|
|
653
|
+
disabled: 'text-muted-foreground/50 cursor-not-allowed line-through',
|
|
569
654
|
otherMonth: 'text-muted-foreground/40 hover:bg-primary/5',
|
|
570
655
|
hovered: 'bg-primary/15 text-foreground',
|
|
571
656
|
},
|
|
@@ -1011,6 +1096,7 @@ class ZCalendarComponent {
|
|
|
1011
1096
|
_backupActivePresetKey = signal(null, ...(ngDevMode ? [{ debugName: "_backupActivePresetKey" }] : []));
|
|
1012
1097
|
_backupShortDisplayPresetKey = signal(null, ...(ngDevMode ? [{ debugName: "_backupShortDisplayPresetKey" }] : []));
|
|
1013
1098
|
_appliedViaOk = signal(false, ...(ngDevMode ? [{ debugName: "_appliedViaOk" }] : []));
|
|
1099
|
+
_hasTypedDraft = signal(false, ...(ngDevMode ? [{ debugName: "_hasTypedDraft" }] : []));
|
|
1014
1100
|
_skipBlurHandler = signal(false, ...(ngDevMode ? [{ debugName: "_skipBlurHandler" }] : []));
|
|
1015
1101
|
_injector = inject(Injector);
|
|
1016
1102
|
_destroyRef = inject(DestroyRef);
|
|
@@ -1504,7 +1590,7 @@ class ZCalendarComponent {
|
|
|
1504
1590
|
date = value;
|
|
1505
1591
|
}
|
|
1506
1592
|
if (!date && typeof value === 'string') {
|
|
1507
|
-
date = valueType === 'iso' ? fromISOString(value) : parseDate(value, this.zFormat());
|
|
1593
|
+
date = valueType === 'iso' ? fromISOString(value) : parseDate(value, this.zFormat(), this.zLocale());
|
|
1508
1594
|
}
|
|
1509
1595
|
if (!date) {
|
|
1510
1596
|
return;
|
|
@@ -1699,8 +1785,9 @@ class ZCalendarComponent {
|
|
|
1699
1785
|
this.zEvent.emit(zCreateEvent('blur', blurEvent));
|
|
1700
1786
|
}
|
|
1701
1787
|
const needsConfirmation = this.showOkButton() || this.showCancelButton();
|
|
1702
|
-
if (needsConfirmation && !this._appliedViaOk()) {
|
|
1788
|
+
if ((needsConfirmation && !this._appliedViaOk()) || this._hasTypedDraft()) {
|
|
1703
1789
|
this._restoreFromBackup();
|
|
1790
|
+
this._hasTypedDraft.set(false);
|
|
1704
1791
|
}
|
|
1705
1792
|
if (this.isRangeMode()) {
|
|
1706
1793
|
const hasIncompleteRange = this._rangeStart() && !this._rangeEnd();
|
|
@@ -1717,6 +1804,11 @@ class ZCalendarComponent {
|
|
|
1717
1804
|
if (this.isRangeMode()) {
|
|
1718
1805
|
this._updateRangeInputDisplay();
|
|
1719
1806
|
}
|
|
1807
|
+
// Force sync DOM input khi signal value không đổi (user gõ nhưng backup giống giá trị cũ)
|
|
1808
|
+
const inputEl = this.inputRef()?.nativeElement;
|
|
1809
|
+
if (inputEl) {
|
|
1810
|
+
inputEl.value = this.inputDisplayValue();
|
|
1811
|
+
}
|
|
1720
1812
|
this.triggerRef()?.nativeElement.blur();
|
|
1721
1813
|
}
|
|
1722
1814
|
_restoreFromBackup() {
|
|
@@ -1767,7 +1859,8 @@ class ZCalendarComponent {
|
|
|
1767
1859
|
}
|
|
1768
1860
|
const input = event.target;
|
|
1769
1861
|
const { value } = input;
|
|
1770
|
-
this.
|
|
1862
|
+
this._preserveInputSelection(input);
|
|
1863
|
+
this._hasTypedDraft.set(true);
|
|
1771
1864
|
const trimmedValue = value.trim();
|
|
1772
1865
|
if (!trimmedValue) {
|
|
1773
1866
|
return;
|
|
@@ -1780,8 +1873,8 @@ class ZCalendarComponent {
|
|
|
1780
1873
|
if (this.isRangeMode()) {
|
|
1781
1874
|
const parts = trimmedValue.split(' - ');
|
|
1782
1875
|
if (parts.length === 2) {
|
|
1783
|
-
const start = parseDate(parts[0].trim(), format);
|
|
1784
|
-
const end = parseDate(parts[1].trim(), format);
|
|
1876
|
+
const start = parseDate(parts[0].trim(), format, this.zLocale());
|
|
1877
|
+
const end = parseDate(parts[1].trim(), format, this.zLocale());
|
|
1785
1878
|
if (start) {
|
|
1786
1879
|
this._rangeStart.set(start);
|
|
1787
1880
|
this._currentMonth.set(start);
|
|
@@ -1793,7 +1886,7 @@ class ZCalendarComponent {
|
|
|
1793
1886
|
}
|
|
1794
1887
|
return;
|
|
1795
1888
|
}
|
|
1796
|
-
const date = parseDate(trimmedValue, format);
|
|
1889
|
+
const date = parseDate(trimmedValue, format, this.zLocale());
|
|
1797
1890
|
if (date) {
|
|
1798
1891
|
this._selectedDate.set(date);
|
|
1799
1892
|
this._currentMonth.set(date);
|
|
@@ -1803,13 +1896,24 @@ class ZCalendarComponent {
|
|
|
1803
1896
|
_getExpectedFormatLength(format) {
|
|
1804
1897
|
return format.replace(/\[.*?\]/g, ' ').length;
|
|
1805
1898
|
}
|
|
1899
|
+
_preserveInputSelection(input) {
|
|
1900
|
+
const start = input.selectionStart;
|
|
1901
|
+
const end = input.selectionEnd;
|
|
1902
|
+
queueMicrotask(() => {
|
|
1903
|
+
if (document.activeElement !== input || start === null || end === null) {
|
|
1904
|
+
return;
|
|
1905
|
+
}
|
|
1906
|
+
input.setSelectionRange(start, end);
|
|
1907
|
+
});
|
|
1908
|
+
}
|
|
1806
1909
|
onStartInputChange(event) {
|
|
1807
1910
|
if (!this.zAllowEdit()) {
|
|
1808
1911
|
return;
|
|
1809
1912
|
}
|
|
1810
1913
|
const input = event.target;
|
|
1811
1914
|
const { value } = input;
|
|
1812
|
-
this.
|
|
1915
|
+
this._preserveInputSelection(input);
|
|
1916
|
+
this._hasTypedDraft.set(true);
|
|
1813
1917
|
const trimmedValue = value.trim();
|
|
1814
1918
|
if (!trimmedValue) {
|
|
1815
1919
|
return;
|
|
@@ -1819,7 +1923,7 @@ class ZCalendarComponent {
|
|
|
1819
1923
|
if (trimmedValue.length < expectedLength) {
|
|
1820
1924
|
return;
|
|
1821
1925
|
}
|
|
1822
|
-
const date = parseDate(trimmedValue, format);
|
|
1926
|
+
const date = parseDate(trimmedValue, format, this.zLocale());
|
|
1823
1927
|
if (!date) {
|
|
1824
1928
|
return;
|
|
1825
1929
|
}
|
|
@@ -1838,7 +1942,8 @@ class ZCalendarComponent {
|
|
|
1838
1942
|
}
|
|
1839
1943
|
const input = event.target;
|
|
1840
1944
|
const { value } = input;
|
|
1841
|
-
this.
|
|
1945
|
+
this._preserveInputSelection(input);
|
|
1946
|
+
this._hasTypedDraft.set(true);
|
|
1842
1947
|
const trimmedValue = value.trim();
|
|
1843
1948
|
if (!trimmedValue) {
|
|
1844
1949
|
return;
|
|
@@ -1848,7 +1953,7 @@ class ZCalendarComponent {
|
|
|
1848
1953
|
if (trimmedValue.length < expectedLength) {
|
|
1849
1954
|
return;
|
|
1850
1955
|
}
|
|
1851
|
-
const date = parseDate(trimmedValue, format);
|
|
1956
|
+
const date = parseDate(trimmedValue, format, this.zLocale());
|
|
1852
1957
|
if (!date) {
|
|
1853
1958
|
return;
|
|
1854
1959
|
}
|
|
@@ -1863,6 +1968,7 @@ class ZCalendarComponent {
|
|
|
1863
1968
|
}
|
|
1864
1969
|
onStartInputEnter(event) {
|
|
1865
1970
|
event.preventDefault();
|
|
1971
|
+
event.stopPropagation();
|
|
1866
1972
|
if (!this.zAllowEdit()) {
|
|
1867
1973
|
this._updateRangeInputDisplay();
|
|
1868
1974
|
const input = event.target;
|
|
@@ -1872,7 +1978,7 @@ class ZCalendarComponent {
|
|
|
1872
1978
|
const input = event.target;
|
|
1873
1979
|
const value = input.value.trim();
|
|
1874
1980
|
const format = this._getParseFormat();
|
|
1875
|
-
const date = parseDate(value, format);
|
|
1981
|
+
const date = parseDate(value, format, this.zLocale());
|
|
1876
1982
|
if (!date) {
|
|
1877
1983
|
input.value = this.displayValueStart();
|
|
1878
1984
|
input.blur();
|
|
@@ -1890,17 +1996,11 @@ class ZCalendarComponent {
|
|
|
1890
1996
|
this._syncTimeSignals(date);
|
|
1891
1997
|
this.uiState.update(s => ({ ...s, dirty: true }));
|
|
1892
1998
|
this._inputDisplayStart.set(this.displayValueStart());
|
|
1893
|
-
|
|
1894
|
-
if (this.showOkButton() && this.canApply()) {
|
|
1895
|
-
this.onOkClick();
|
|
1896
|
-
return;
|
|
1897
|
-
}
|
|
1898
|
-
if (!this.showOkButton()) {
|
|
1899
|
-
this._applyValue();
|
|
1900
|
-
}
|
|
1999
|
+
this._confirmTypedValue(input);
|
|
1901
2000
|
}
|
|
1902
2001
|
onEndInputEnter(event) {
|
|
1903
2002
|
event.preventDefault();
|
|
2003
|
+
event.stopPropagation();
|
|
1904
2004
|
if (!this.zAllowEdit()) {
|
|
1905
2005
|
this._updateRangeInputDisplay();
|
|
1906
2006
|
const input = event.target;
|
|
@@ -1910,7 +2010,7 @@ class ZCalendarComponent {
|
|
|
1910
2010
|
const input = event.target;
|
|
1911
2011
|
const value = input.value.trim();
|
|
1912
2012
|
const format = this._getParseFormat();
|
|
1913
|
-
const date = parseDate(value, format);
|
|
2013
|
+
const date = parseDate(value, format, this.zLocale());
|
|
1914
2014
|
if (!date) {
|
|
1915
2015
|
input.value = this.displayValueEnd();
|
|
1916
2016
|
input.blur();
|
|
@@ -1928,18 +2028,13 @@ class ZCalendarComponent {
|
|
|
1928
2028
|
this._syncEndTimeSignals(date);
|
|
1929
2029
|
this.uiState.update(s => ({ ...s, dirty: true }));
|
|
1930
2030
|
this._inputDisplayEnd.set(this.displayValueEnd());
|
|
1931
|
-
|
|
1932
|
-
if (this.showOkButton() && this.canApply()) {
|
|
1933
|
-
this.onOkClick();
|
|
1934
|
-
return;
|
|
1935
|
-
}
|
|
1936
|
-
if (!this.showOkButton()) {
|
|
1937
|
-
this._applyValue();
|
|
1938
|
-
}
|
|
2031
|
+
this._confirmTypedValue(input);
|
|
1939
2032
|
}
|
|
1940
2033
|
onInputFocus(_event) {
|
|
1941
2034
|
this.isInputFocused.set(true);
|
|
1942
|
-
|
|
2035
|
+
if (!this.isOpen()) {
|
|
2036
|
+
this._backupIfNeeded();
|
|
2037
|
+
}
|
|
1943
2038
|
}
|
|
1944
2039
|
onInputBlur(event) {
|
|
1945
2040
|
this.isInputFocused.set(false);
|
|
@@ -1955,6 +2050,12 @@ class ZCalendarComponent {
|
|
|
1955
2050
|
return;
|
|
1956
2051
|
}
|
|
1957
2052
|
const input = event.target;
|
|
2053
|
+
if (this._hasTypedDraft()) {
|
|
2054
|
+
this._restoreFromBackup();
|
|
2055
|
+
this._hasTypedDraft.set(false);
|
|
2056
|
+
input.value = this.displayValue();
|
|
2057
|
+
return;
|
|
2058
|
+
}
|
|
1958
2059
|
const currentValue = input.value.trim();
|
|
1959
2060
|
const format = this._getParseFormat();
|
|
1960
2061
|
if (!currentValue) {
|
|
@@ -1968,7 +2069,7 @@ class ZCalendarComponent {
|
|
|
1968
2069
|
}
|
|
1969
2070
|
return;
|
|
1970
2071
|
}
|
|
1971
|
-
const parsed = parseDate(currentValue, format);
|
|
2072
|
+
const parsed = parseDate(currentValue, format, this.zLocale());
|
|
1972
2073
|
if (parsed) {
|
|
1973
2074
|
this._selectedDate.set(parsed);
|
|
1974
2075
|
this._currentMonth.set(parsed);
|
|
@@ -1984,6 +2085,7 @@ class ZCalendarComponent {
|
|
|
1984
2085
|
}
|
|
1985
2086
|
onInputEnter(event) {
|
|
1986
2087
|
event.preventDefault();
|
|
2088
|
+
event.stopPropagation();
|
|
1987
2089
|
const input = event.target;
|
|
1988
2090
|
if (!this.zAllowEdit()) {
|
|
1989
2091
|
this.inputDisplayValue.set(this.displayValue());
|
|
@@ -1995,18 +2097,16 @@ class ZCalendarComponent {
|
|
|
1995
2097
|
this._skipBlurHandler.set(true);
|
|
1996
2098
|
this._clearDateValues();
|
|
1997
2099
|
this.uiState.update(s => ({ ...s, dirty: true }));
|
|
1998
|
-
this.
|
|
1999
|
-
this.
|
|
2000
|
-
this.close();
|
|
2001
|
-
input.blur();
|
|
2100
|
+
this.inputDisplayValue.set('');
|
|
2101
|
+
this._confirmTypedValue(input);
|
|
2002
2102
|
return;
|
|
2003
2103
|
}
|
|
2004
2104
|
const format = this._getParseFormat();
|
|
2005
2105
|
if (this.isRangeMode()) {
|
|
2006
2106
|
const parts = value.split(' - ');
|
|
2007
2107
|
if (parts.length === 2) {
|
|
2008
|
-
const start = parseDate(parts[0].trim(), format);
|
|
2009
|
-
const end = parseDate(parts[1].trim(), format);
|
|
2108
|
+
const start = parseDate(parts[0].trim(), format, this.zLocale());
|
|
2109
|
+
const end = parseDate(parts[1].trim(), format, this.zLocale());
|
|
2010
2110
|
if (start && end) {
|
|
2011
2111
|
this._skipBlurHandler.set(true);
|
|
2012
2112
|
const swapped = start > end;
|
|
@@ -2017,35 +2117,33 @@ class ZCalendarComponent {
|
|
|
2017
2117
|
this._currentMonth.set(rangeStart);
|
|
2018
2118
|
this._endMonth.set(rangeEnd);
|
|
2019
2119
|
this.uiState.update(s => ({ ...s, dirty: true }));
|
|
2020
|
-
this.
|
|
2021
|
-
this.
|
|
2022
|
-
this.close();
|
|
2023
|
-
input.blur();
|
|
2120
|
+
this._updateRangeInputDisplay();
|
|
2121
|
+
this._confirmTypedValue(input);
|
|
2024
2122
|
return;
|
|
2025
2123
|
}
|
|
2026
2124
|
}
|
|
2027
2125
|
this._restoreFromBackup();
|
|
2028
2126
|
this._updateInputDisplay();
|
|
2029
2127
|
this.close();
|
|
2128
|
+
input.value = this.displayValue();
|
|
2030
2129
|
input.blur();
|
|
2031
2130
|
return;
|
|
2032
2131
|
}
|
|
2033
|
-
const date = parseDate(value, format);
|
|
2132
|
+
const date = parseDate(value, format, this.zLocale());
|
|
2034
2133
|
if (date) {
|
|
2035
2134
|
this._skipBlurHandler.set(true);
|
|
2036
2135
|
this._selectedDate.set(date);
|
|
2037
2136
|
this._currentMonth.set(date);
|
|
2038
2137
|
this._syncTimeSignals(date);
|
|
2039
2138
|
this.uiState.update(s => ({ ...s, dirty: true }));
|
|
2040
|
-
this.
|
|
2041
|
-
this.
|
|
2042
|
-
this.close();
|
|
2043
|
-
input.blur();
|
|
2139
|
+
this.inputDisplayValue.set(this.displayValue());
|
|
2140
|
+
this._confirmTypedValue(input);
|
|
2044
2141
|
return;
|
|
2045
2142
|
}
|
|
2046
2143
|
this._restoreFromBackup();
|
|
2047
2144
|
this._updateInputDisplay();
|
|
2048
2145
|
this.close();
|
|
2146
|
+
input.value = this.displayValue();
|
|
2049
2147
|
input.blur();
|
|
2050
2148
|
}
|
|
2051
2149
|
onCalendarKeydown(event) {
|
|
@@ -2305,6 +2403,25 @@ class ZCalendarComponent {
|
|
|
2305
2403
|
this.close();
|
|
2306
2404
|
}
|
|
2307
2405
|
onOkClick() {
|
|
2406
|
+
if (this._hasTypedDraft() && !this.isRangeMode()) {
|
|
2407
|
+
const input = this.inputRef()?.nativeElement;
|
|
2408
|
+
const date = parseDate(input?.value.trim() ?? '', this._getParseFormat(), this.zLocale());
|
|
2409
|
+
if (!date) {
|
|
2410
|
+
this._cancelAndRestore();
|
|
2411
|
+
if (input) {
|
|
2412
|
+
input.value = this.displayValue();
|
|
2413
|
+
input.blur();
|
|
2414
|
+
}
|
|
2415
|
+
return;
|
|
2416
|
+
}
|
|
2417
|
+
this._selectedDate.set(date);
|
|
2418
|
+
this._currentMonth.set(date);
|
|
2419
|
+
this._syncTimeSignals(date);
|
|
2420
|
+
this.inputDisplayValue.set(this.displayValue());
|
|
2421
|
+
if (input) {
|
|
2422
|
+
input.value = this.displayValue();
|
|
2423
|
+
}
|
|
2424
|
+
}
|
|
2308
2425
|
if (!this.canApply()) {
|
|
2309
2426
|
return;
|
|
2310
2427
|
}
|
|
@@ -2748,6 +2865,7 @@ class ZCalendarComponent {
|
|
|
2748
2865
|
return false;
|
|
2749
2866
|
}
|
|
2750
2867
|
_applyValue() {
|
|
2868
|
+
this._hasTypedDraft.set(false);
|
|
2751
2869
|
const emitValue = this._getEmitValue();
|
|
2752
2870
|
this._onChange(emitValue);
|
|
2753
2871
|
this.zChange.emit(emitValue);
|
|
@@ -2757,6 +2875,12 @@ class ZCalendarComponent {
|
|
|
2757
2875
|
this._updateRangeInputDisplay();
|
|
2758
2876
|
}
|
|
2759
2877
|
}
|
|
2878
|
+
_confirmTypedValue(input) {
|
|
2879
|
+
this._appliedViaOk.set(true);
|
|
2880
|
+
this._applyValue();
|
|
2881
|
+
this.close();
|
|
2882
|
+
input.blur();
|
|
2883
|
+
}
|
|
2760
2884
|
_getEmitValue() {
|
|
2761
2885
|
const valueType = this.zValueType();
|
|
2762
2886
|
const format = this.zShowTime() ? `${this.zFormat()} HH:mm:ss` : this.zFormat();
|
|
@@ -2862,6 +2986,9 @@ class ZCalendarComponent {
|
|
|
2862
2986
|
return buildTimeFormat(this.zShowHour(), this.zShowMinute(), this.zShowSecond(), this.zTimeFormat(), period);
|
|
2863
2987
|
}
|
|
2864
2988
|
_updateInputDisplay() {
|
|
2989
|
+
if (this._hasTypedDraft()) {
|
|
2990
|
+
return;
|
|
2991
|
+
}
|
|
2865
2992
|
this.inputDisplayValue.set(this.displayValue());
|
|
2866
2993
|
if (this.isRangeMode()) {
|
|
2867
2994
|
this._updateRangeInputDisplay();
|
|
@@ -2877,14 +3004,29 @@ class ZCalendarComponent {
|
|
|
2877
3004
|
}
|
|
2878
3005
|
this._selectedDate.set(null);
|
|
2879
3006
|
}
|
|
2880
|
-
onInputEscape() {
|
|
3007
|
+
onInputEscape(event) {
|
|
3008
|
+
event.preventDefault();
|
|
3009
|
+
event.stopPropagation();
|
|
3010
|
+
const input = event.target;
|
|
2881
3011
|
this._cancelAndRestore();
|
|
3012
|
+
input.value = this.displayValue();
|
|
3013
|
+
input.blur();
|
|
2882
3014
|
}
|
|
2883
|
-
onStartInputEscape() {
|
|
3015
|
+
onStartInputEscape(event) {
|
|
3016
|
+
event.preventDefault();
|
|
3017
|
+
event.stopPropagation();
|
|
3018
|
+
const input = event.target;
|
|
2884
3019
|
this._cancelAndRestore();
|
|
3020
|
+
input.value = this.displayValueStart();
|
|
3021
|
+
input.blur();
|
|
2885
3022
|
}
|
|
2886
|
-
onEndInputEscape() {
|
|
3023
|
+
onEndInputEscape(event) {
|
|
3024
|
+
event.preventDefault();
|
|
3025
|
+
event.stopPropagation();
|
|
3026
|
+
const input = event.target;
|
|
2887
3027
|
this._cancelAndRestore();
|
|
3028
|
+
input.value = this.displayValueEnd();
|
|
3029
|
+
input.blur();
|
|
2888
3030
|
}
|
|
2889
3031
|
_cancelAndRestore() {
|
|
2890
3032
|
this._restoreFromBackup();
|
|
@@ -3118,7 +3260,7 @@ class ZCalendarComponent {
|
|
|
3118
3260
|
multi: true,
|
|
3119
3261
|
},
|
|
3120
3262
|
TranslatePipe,
|
|
3121
|
-
], viewQueries: [{ propertyName: "triggerRef", first: true, predicate: ["triggerEl"], descendants: true, isSignal: true }, { propertyName: "inputRef", first: true, predicate: ["inputEl"], descendants: true, isSignal: true }], exportAs: ["zCalendar"], ngImport: i0, template: "<div class=\"z-calendar-wrapper flex w-full flex-col gap-2\">\n @if (zLabel()) {\n <label [for]=\"pickerId\" class=\"text-xs leading-none font-medium\" [class]=\"zLabelClass()\">\n {{ zLabel() }}\n @if (zRequired()) {\n <span class=\"text-destructive! ml-0.5\">*</span>\n }\n </label>\n }\n\n <div class=\"relative\">\n <div\n #triggerEl\n z-popover\n [zPopoverContent]=\"calendarTpl\"\n zPosition=\"bottom-left\"\n zPopoverWidth=\"auto\"\n [zOffset]=\"6\"\n [zDisabled]=\"isDisabled() || zReadonly()\"\n [zManualClose]=\"showCancelButton()\"\n [zScrollClose]=\"zScrollClose()\"\n zTrigger=\"click\"\n zClass=\"border-0 shadow-none p-0\"\n (zHideStart)=\"onPopoverHide()\"\n (zShow)=\"onPopoverShow()\"\n (zControl)=\"onPopoverControl($event)\"\n [id]=\"pickerId\"\n [class]=\"triggerClasses()\"\n z-tooltip\n [zContent]=\"displayValue()\"\n zTooltipTrigger=\"hover\"\n zTooltipPosition=\"top\"\n [zTooltipDisabled]=\"isInputFocused() || isOpen() || !hasValue()\"\n (keydown)=\"onTriggerKeydown($event)\">\n <z-icon\n [zType]=\"isRangeMode() ? 'lucideCalendarRange' : 'lucideCalendar'\"\n zSize=\"16\"\n class=\"text-muted-foreground shrink-0 cursor-pointer\"\n (click)=\"$event.stopPropagation(); toggle()\" />\n\n @if (isRangeMode()) {\n <input\n type=\"text\"\n data-range-type=\"start\"\n class=\"placeholder:text-muted-foreground w-0 min-w-0 flex-1 truncate bg-transparent text-sm outline-none disabled:opacity-100\"\n [class.cursor-pointer]=\"!zAllowEdit()\"\n [class.pointer-events-none]=\"!zAllowEdit()\"\n [class.text-center]=\"!rangeShortDisplayValue()\"\n [class.text-left]=\"rangeShortDisplayValue()\"\n [placeholder]=\"'i18n_z_ui_calendar_start_date' | translate\"\n [value]=\"inputDisplayStart()\"\n [disabled]=\"isDisabled()\"\n [readonly]=\"zReadonly() || !zAllowEdit()\"\n (click)=\"zAllowEdit() && isOpen() && $event.stopPropagation()\"\n (focus)=\"onInputFocus($event)\"\n (input)=\"onStartInputChange($event)\"\n (blur)=\"onInputBlur($event)\"\n (keydown.enter)=\"onStartInputEnter($event)\"\n (keydown.escape)=\"onStartInputEscape()\" />\n @if (!rangeShortDisplayValue()) {\n <span class=\"text-muted-foreground text-sm\">-</span>\n <input\n type=\"text\"\n data-range-type=\"end\"\n class=\"placeholder:text-muted-foreground w-0 min-w-0 flex-1 truncate bg-transparent text-center text-sm outline-none disabled:opacity-100\"\n [class.cursor-pointer]=\"!zAllowEdit()\"\n [class.pointer-events-none]=\"!zAllowEdit()\"\n [placeholder]=\"'i18n_z_ui_calendar_end_date' | translate\"\n [value]=\"inputDisplayEnd()\"\n [disabled]=\"isDisabled()\"\n [readonly]=\"zReadonly() || !zAllowEdit()\"\n (click)=\"zAllowEdit() && isOpen() && $event.stopPropagation()\"\n (focus)=\"onInputFocus($event)\"\n (input)=\"onEndInputChange($event)\"\n (blur)=\"onInputBlur($event)\"\n (keydown.enter)=\"onEndInputEnter($event)\"\n (keydown.escape)=\"onEndInputEscape()\" />\n }\n } @else {\n <input\n #inputEl\n type=\"text\"\n class=\"placeholder:text-muted-foreground w-0 min-w-0 flex-1 truncate bg-transparent text-sm outline-none disabled:opacity-100\"\n [class.cursor-pointer]=\"!zAllowEdit()\"\n [class.pointer-events-none]=\"!zAllowEdit()\"\n [placeholder]=\"effectivePlaceholder()\"\n [value]=\"inputDisplayValue()\"\n [disabled]=\"isDisabled()\"\n [readonly]=\"zReadonly() || !zAllowEdit()\"\n (click)=\"zAllowEdit() && isOpen() && $event.stopPropagation()\"\n (focus)=\"onInputFocus($event)\"\n (input)=\"onInputChange($event)\"\n (blur)=\"onInputBlur($event)\"\n (keydown.enter)=\"onInputEnter($event)\"\n (keydown.escape)=\"onInputEscape()\" />\n }\n\n @if (zAllowClear() && !isDisabled() && !zReadonly()) {\n <button\n type=\"button\"\n tabindex=\"-1\"\n class=\"text-muted-foreground hover:text-foreground flex size-5 shrink-0 cursor-pointer items-center justify-center rounded-sm transition-all\"\n [class.opacity-0]=\"!hasValue()\"\n [class.pointer-events-none]=\"!hasValue()\"\n (click)=\"onClear($event)\">\n <z-icon zType=\"lucideX\" zSize=\"18\" />\n </button>\n }\n </div>\n </div>\n\n @if (hasError()) {\n <p class=\"text-destructive animate-in fade-in slide-in-from-top-1 m-0 text-xs duration-200\">\n {{ errorMessage() }}\n </p>\n }\n</div>\n\n<ng-template #calendarTpl>\n <div\n class=\"z-calendar-calendar bg-popover border-border flex max-h-[50dvh] max-w-[calc(100vw-1.5rem)] flex-col overflow-hidden rounded-sm border shadow-lg min-[480px]:max-h-[55dvh] sm:max-h-none sm:max-w-none sm:flex-row sm:overflow-visible\"\n (keydown)=\"onCalendarKeydown($event)\">\n @if (zQuickSelect() && zMode() === 'range') {\n <div class=\"border-border hidden shrink-0 flex-col gap-0 space-y-1 overflow-y-auto border-r p-2 sm:flex\">\n @for (preset of quickSelectPresets; track preset.key) {\n @let presetDisabled = preset | zIsPresetDisabled: zDisabledDate();\n <button\n type=\"button\"\n class=\"cursor-pointer rounded-sm px-3 py-1.5 text-left text-sm whitespace-nowrap transition-colors\"\n [class.hover:bg-muted]=\"activePresetKey() !== preset.key && !presetDisabled\"\n [class.bg-primary]=\"activePresetKey() === preset.key\"\n [class.text-primary-foreground]=\"activePresetKey() === preset.key\"\n [class.font-medium]=\"activePresetKey() === preset.key\"\n [class.opacity-40]=\"presetDisabled\"\n [class.cursor-not-allowed]=\"presetDisabled\"\n [disabled]=\"presetDisabled\"\n (click)=\"onQuickSelect(preset)\">\n {{ preset.label | translate }}\n </button>\n }\n </div>\n }\n <div\n class=\"flex min-h-0 flex-1 flex-col items-center overflow-hidden pb-0 sm:overflow-visible sm:py-2\"\n [class.sm:pt-0!]=\"isTimeMode()\"\n [class]=\"\n !isRangeMode()\n ? 'w-[17.75rem] max-w-[calc(100vw-1.5rem)]'\n : 'w-[17.75rem] max-w-[calc(100vw-1.5rem)] sm:w-auto sm:max-w-none'\n \">\n @if (zQuickSelect() && zMode() === 'range') {\n <div class=\"border-border w-full border-b px-2 pt-2 pb-2 sm:hidden\">\n <z-select\n class=\"w-full\"\n zSize=\"sm\"\n zPosition=\"bottom-left\"\n [zShowSearch]=\"false\"\n [zAllowClear]=\"false\"\n [zOptions]=\"quickSelectOptions()\"\n [ngModel]=\"activePresetKey()\"\n [ngModelOptions]=\"{ standalone: true }\"\n (ngModelChange)=\"onQuickSelectKeyChange($event)\" />\n </div>\n }\n <div class=\"min-h-0 w-full flex-1 overflow-x-hidden overflow-y-auto pt-2 sm:overflow-visible sm:pt-0\">\n @if (!isTimeMode()) {\n <div\n class=\"z-calendars-wrapper flex w-full flex-col items-center gap-0 sm:flex-row sm:items-stretch sm:justify-center\">\n <!-- First Calendar -->\n <div class=\"z-calendar-section flex w-[17.5rem] shrink-0 flex-col\">\n @if (!isTimeMode()) {\n <!-- Header -->\n <div class=\"border-border flex w-full items-center justify-between gap-0.5 px-2\">\n <!-- Double left arrow (always visible) -->\n <button\n type=\"button\"\n z-button\n zType=\"ghost\"\n zSize=\"sm\"\n class=\"size-7 shrink-0 p-0!\"\n [zWave]=\"false\"\n (click)=\"navigatePreviousFast()\">\n <z-icon zType=\"lucideChevronsLeft\" zSize=\"18\" />\n </button>\n\n <!-- Single left arrow (hidden in month/year view) -->\n @if (currentView() === 'day') {\n <button\n type=\"button\"\n z-button\n zType=\"ghost\"\n zSize=\"sm\"\n class=\"size-7 shrink-0 p-0!\"\n [zWave]=\"false\"\n (click)=\"navigatePrevious()\">\n <z-icon zType=\"lucideChevronLeft\" zSize=\"18\" />\n </button>\n }\n\n <!-- Header content -->\n <div class=\"flex flex-1 shrink-0 items-center justify-center gap-0\">\n @if (currentView() === 'day') {\n <!-- Day view: Month + Year -->\n @if (!isYearMode() && !isQuarterMode()) {\n <button\n type=\"button\"\n z-button\n zType=\"ghost\"\n zSize=\"sm\"\n class=\"h-7 px-1.5 text-sm!\"\n [zWave]=\"false\"\n (click)=\"setView('month')\">\n {{ currentMonthName() }}\n </button>\n }\n <button\n type=\"button\"\n z-button\n zType=\"ghost\"\n zSize=\"sm\"\n class=\"h-7 px-1.5 text-sm!\"\n [zWave]=\"false\"\n [zDisabled]=\"isYearMode()\"\n (click)=\"setView('year')\">\n {{ currentYear() }}\n </button>\n } @else if (currentView() === 'month') {\n <!-- Month view: Only Year -->\n <button\n type=\"button\"\n z-button\n zType=\"ghost\"\n zSize=\"sm\"\n class=\"h-7 px-1.5 text-sm!\"\n [zWave]=\"false\"\n (click)=\"setView('year')\">\n {{ currentYear() }}\n </button>\n } @else if (currentView() === 'year') {\n <!-- Year view: Year Range -->\n <span class=\"text-sm font-medium\">\n {{ yearRange()[0] }} - {{ yearRange()[yearRange().length - 1] }}\n </span>\n } @else if (currentView() === 'quarter') {\n <!-- Quarter view: Only Year -->\n <button\n type=\"button\"\n z-button\n zType=\"ghost\"\n zSize=\"sm\"\n class=\"h-7 px-1.5 text-sm!\"\n [zWave]=\"false\"\n (click)=\"setView('year')\">\n {{ currentYear() }}\n </button>\n }\n </div>\n\n <!-- Single right arrow (hidden in month/year view) -->\n @if (currentView() === 'day') {\n <button\n type=\"button\"\n z-button\n zType=\"ghost\"\n zSize=\"sm\"\n class=\"size-7 shrink-0 p-0!\"\n [zDisabled]=\"!canNavigateStartNext()\"\n [zWave]=\"false\"\n (click)=\"navigateNext()\">\n <z-icon zType=\"lucideChevronRight\" zSize=\"18\" />\n </button>\n }\n\n <!-- Double right arrow (always visible) -->\n <button\n type=\"button\"\n z-button\n zType=\"ghost\"\n zSize=\"sm\"\n class=\"size-7 shrink-0 p-0!\"\n [zDisabled]=\"!canNavigateStartNext()\"\n [zWave]=\"false\"\n (click)=\"navigateNextFast()\">\n <z-icon zType=\"lucideChevronsRight\" zSize=\"18\" />\n </button>\n </div>\n\n <!-- Body -->\n <div\n class=\"flex h-full w-full flex-col items-center justify-center p-2\"\n [class.min-h-[14rem]]=\"!isQuarterMode()\"\n [class.h-[14rem]]=\"\n !isYearMode() &&\n !isMonthMode() &&\n !isQuarterMode() &&\n (currentView() === 'month' || currentView() === 'year')\n \"\n [class.min-h-[6.25rem]]=\"isQuarterMode()\"\n [class.!min-h-auto]=\"isYearMode() || isMonthMode() || isQuarterMode()\"\n [class.!h-auto]=\"isYearMode() || isMonthMode() || isQuarterMode()\">\n @if (currentView() === 'day') {\n <div\n class=\"flex h-full w-full flex-1 flex-col gap-1\"\n [class.animate-calendar-enter]=\"uiState().hasViewChanged\">\n <!-- Weekday headers -->\n <div class=\"flex w-full flex-1 justify-center gap-1\">\n @for (weekday of weekdayNames(); track weekday) {\n <div\n class=\"text-muted-foreground flex h-[1.875rem] w-[2.0313rem] items-center justify-center text-xs font-medium\">\n {{ weekday }}\n </div>\n }\n </div>\n\n <!-- Date rows -->\n @for (week of calendarDays(); track $index) {\n <div class=\"flex w-full flex-1 justify-center gap-1\">\n @for (day of week; track day.date.getTime()) {\n <button\n type=\"button\"\n [class]=\"day | zDayClasses\"\n class=\"h-[1.875rem] !w-[2.0313rem] !text-sm\"\n [disabled]=\"day.isDisabled\"\n (click)=\"onDayClick(day)\"\n (mouseenter)=\"onDayHover(day)\"\n (mouseleave)=\"onDayLeave()\">\n {{ day.day }}\n </button>\n }\n </div>\n }\n </div>\n }\n @if (currentView() === 'month') {\n <div\n class=\"grid h-full w-full grid-cols-3 grid-rows-4 gap-2.5 gap-y-5!\"\n [class.animate-calendar-enter]=\"uiState().hasViewChanged\">\n @for (month of monthNames(); track month; let i = $index) {\n @let monthDisabled = i | zIsStartMonthDisabled: startMonthDisabledContext();\n <div class=\"flex flex-1 items-center justify-center\">\n <button\n type=\"button\"\n [class]=\"i | zMonthClasses: selectedMonthIndex() : todayMonthIndex()\"\n class=\"!h-7 !w-full !text-sm\"\n [disabled]=\"monthDisabled\"\n [class.opacity-30]=\"monthDisabled\"\n [class.cursor-not-allowed]=\"monthDisabled\"\n (click)=\"onMonthSelect(i)\">\n {{ month }}\n </button>\n </div>\n }\n </div>\n }\n\n @if (currentView() === 'year') {\n <div\n class=\"grid h-full w-full grid-cols-3 grid-rows-4 gap-2.5 gap-y-5!\"\n [class.animate-calendar-enter]=\"uiState().hasViewChanged\">\n @for (year of yearRange(); track year) {\n @let yearDisabled = year | zIsStartYearDisabled: startYearDisabledContext();\n <div class=\"flex flex-1 items-center justify-center\">\n <button\n type=\"button\"\n [class]=\"year | zYearClasses: selectedYear() : todayYear()\"\n class=\"!h-7 !w-full !text-sm\"\n [disabled]=\"yearDisabled\"\n [class.opacity-30]=\"yearDisabled\"\n [class.cursor-not-allowed]=\"yearDisabled\"\n (click)=\"onYearClick(year)\">\n {{ year }}\n </button>\n </div>\n }\n </div>\n }\n\n @if (currentView() === 'quarter') {\n <div\n class=\"grid h-full w-full grid-cols-2 grid-rows-2 gap-2 p-1\"\n [class.animate-calendar-enter]=\"uiState().hasViewChanged\">\n @for (quarter of quarterNames; track quarter; let i = $index) {\n <div class=\"flex flex-1 items-center justify-center\">\n <button\n type=\"button\"\n [class]=\"i | zQuarterClasses: selectedQuarterIndex() : todayQuarterIndex()\"\n class=\"!h-8 !w-full !text-sm\"\n (click)=\"onQuarterClick(i)\">\n {{ quarter }}\n </button>\n </div>\n }\n </div>\n }\n </div>\n }\n </div>\n\n <!-- Second Calendar (Range Mode Only) -->\n @if (isRangeMode()) {\n <!-- Divider -->\n <div\n class=\"border-border bg-border mb-2 hidden self-stretch sm:block sm:w-px\"\n [class.mb-2]=\"!zQuickSelect() || (zQuickSelect() && zShowOk())\"></div>\n <div class=\"border-border bg-border block h-px w-full sm:hidden\"></div>\n\n <div class=\"z-calendar-section flex w-[17.5rem] shrink-0 flex-col pt-2 sm:pt-0\">\n <!-- Header -->\n <div class=\"border-border flex w-full items-center justify-between gap-0.5 px-2\">\n <button\n type=\"button\"\n z-button\n zType=\"ghost\"\n zSize=\"sm\"\n class=\"size-7 shrink-0 p-0!\"\n [zDisabled]=\"!canNavigateEndPrev()\"\n [zWave]=\"false\"\n (click)=\"navigateEndPreviousFast()\">\n <z-icon zType=\"lucideChevronsLeft\" zSize=\"18\" />\n </button>\n\n <button\n type=\"button\"\n z-button\n zType=\"ghost\"\n zSize=\"sm\"\n class=\"size-7 shrink-0 p-0!\"\n [zDisabled]=\"!canNavigateEndPrev()\"\n [zWave]=\"false\"\n (click)=\"navigateEndPrevious()\">\n <z-icon zType=\"lucideChevronLeft\" zSize=\"18\" />\n </button>\n\n <div class=\"flex w-[7.5rem] shrink-0 items-center justify-center gap-0\">\n <button\n type=\"button\"\n z-button\n zType=\"ghost\"\n zSize=\"sm\"\n class=\"h-7 px-1.5 text-sm!\"\n [zWave]=\"false\"\n (click)=\"setEndView('month')\">\n {{ endMonthName() }}\n </button>\n\n <button\n type=\"button\"\n z-button\n zType=\"ghost\"\n zSize=\"sm\"\n class=\"h-7 px-1.5 text-sm!\"\n [zWave]=\"false\"\n (click)=\"setEndView('year')\">\n {{ endMonthYear() }}\n </button>\n </div>\n\n <button\n type=\"button\"\n z-button\n zType=\"ghost\"\n zSize=\"sm\"\n class=\"size-7 shrink-0 p-0!\"\n [zWave]=\"false\"\n [zWave]=\"false\"\n (click)=\"navigateEndNext()\">\n <z-icon zType=\"lucideChevronRight\" zSize=\"18\" />\n </button>\n\n <button\n type=\"button\"\n z-button\n zType=\"ghost\"\n zSize=\"sm\"\n class=\"size-7 shrink-0 p-0!\"\n [zWave]=\"false\"\n [zWave]=\"false\"\n (click)=\"navigateEndNextFast()\">\n <z-icon zType=\"lucideChevronsRight\" zSize=\"18\" />\n </button>\n </div>\n\n <!-- Body -->\n <div\n class=\"flex h-full min-h-[14rem] w-full flex-col items-center justify-center p-2\"\n [class.h-[14rem]]=\"endView() === 'month' || endView() === 'year'\">\n @if (endView() === 'day') {\n <div\n class=\"flex h-full w-full flex-1 flex-col gap-1\"\n [class.animate-calendar-enter]=\"uiState().hasEndViewChanged\">\n <!-- Weekday headers -->\n <div class=\"flex w-full flex-1 justify-center gap-1\">\n @for (weekday of weekdayNames(); track weekday) {\n <div\n class=\"text-muted-foreground flex h-[1.875rem] w-[2.0313rem] items-center justify-center text-xs font-medium\">\n {{ weekday }}\n </div>\n }\n </div>\n\n <!-- Date rows -->\n @for (week of calendarDaysEnd(); track $index) {\n <div class=\"flex w-full flex-1 justify-center gap-1\">\n @for (day of week; track day.date.getTime()) {\n <button\n type=\"button\"\n [class]=\"day | zDayClasses\"\n class=\"h-[1.875rem] !w-[2.0313rem] !text-sm\"\n [disabled]=\"day.isDisabled\"\n (click)=\"onDayClick(day)\"\n (mouseenter)=\"onDayHover(day)\"\n (mouseleave)=\"onDayLeave()\">\n {{ day.day }}\n </button>\n }\n </div>\n }\n </div>\n }\n @if (endView() === 'month') {\n <div\n class=\"grid h-full w-full grid-cols-3 grid-rows-4 gap-2.5 gap-y-5!\"\n [class.animate-calendar-enter]=\"uiState().hasEndViewChanged\">\n @for (month of monthNames(); track month; let i = $index) {\n @let endMonthDisabled = i | zIsEndMonthDisabled: endMonthDisabledContext();\n <div class=\"flex flex-1 items-center justify-center\">\n <button\n type=\"button\"\n [class]=\"i | zMonthClasses: endMonth().getMonth() : -1\"\n class=\"!h-7 !w-full !text-sm\"\n [disabled]=\"endMonthDisabled\"\n [class.opacity-30]=\"endMonthDisabled\"\n [class.cursor-not-allowed]=\"endMonthDisabled\"\n (click)=\"onEndMonthClick(i)\">\n {{ month }}\n </button>\n </div>\n }\n </div>\n }\n\n @if (endView() === 'year') {\n <div\n class=\"grid h-full w-full grid-cols-3 grid-rows-4 gap-2.5 gap-y-5!\"\n [class.animate-calendar-enter]=\"uiState().hasEndViewChanged\">\n @for (year of endYearRange(); track year) {\n @let endYearDisabled = year | zIsEndYearDisabled: endYearDisabledContext();\n <div class=\"flex flex-1 items-center justify-center\">\n <button\n type=\"button\"\n [class]=\"year | zYearClasses: endMonth().getFullYear() : -1\"\n class=\"!h-7 !w-full !text-sm\"\n [disabled]=\"endYearDisabled\"\n [class.opacity-30]=\"endYearDisabled\"\n [class.cursor-not-allowed]=\"endYearDisabled\"\n (click)=\"onEndYearClick(year)\">\n {{ year }}\n </button>\n </div>\n }\n </div>\n }\n </div>\n </div>\n }\n </div>\n\n <!-- Compact Time Picker Below Calendar (Single Date) -->\n @if (!isRangeMode() && zShowTime()) {\n <div\n class=\"hover:bg-muted border-border flex w-full cursor-pointer items-center justify-center gap-1.5 border-t px-3 py-1.5 transition-colors\"\n z-popover\n [zPopoverContent]=\"timeDropdownTpl\"\n zPosition=\"bottom\"\n [zPopoverWidth]=\"240\"\n [zOffset]=\"4\"\n zTrigger=\"click\"\n zClass=\"border-border shadow-lg\"\n (zShow)=\"onTimeDropdownShow()\">\n <z-icon zType=\"lucideCalendarClock\" zSize=\"18\" class=\"text-muted-foreground mr-1 shrink-0\" />\n <span class=\"text-sm font-medium tabular-nums select-none\">\n @if (zShowHour()) {\n {{ formattedHour() }}\n }\n @if (zShowHour() && zShowMinute()) {\n <span class=\"text-muted-foreground\">:</span>\n }\n @if (zShowMinute()) {\n {{ formattedMinute() }}\n }\n @if (zShowMinute() && zShowSecond()) {\n <span class=\"text-muted-foreground\">:</span>\n }\n @if (zShowSecond()) {\n {{ formattedSecond() }}\n }\n @if (zTimeFormat() === '12h') {\n <span class=\"text-primary ml-0.5 font-semibold\">\n {{ period() }}\n </span>\n }\n </span>\n <z-icon zType=\"lucideChevronDown\" zSize=\"14\" class=\"text-muted-foreground shrink-0\" />\n </div>\n }\n\n <!-- Compact Time Pickers Below Calendars (Range Mode) -->\n @if (isRangeMode() && zShowTime()) {\n <div class=\"border-border flex w-full flex-col border-t sm:flex-row\">\n <!-- Start Time -->\n <div\n class=\"hover:bg-muted flex flex-1 cursor-pointer items-center justify-center gap-1.5 px-3 py-1.5 transition-colors\"\n z-popover\n [zPopoverContent]=\"timeDropdownTpl\"\n zPosition=\"bottom\"\n [zPopoverWidth]=\"240\"\n [zOffset]=\"4\"\n zTrigger=\"click\"\n zClass=\"border-border shadow-lg\"\n (zShow)=\"onTimeDropdownShow()\">\n <z-icon zType=\"lucideCalendarClock\" zSize=\"18\" class=\"text-muted-foreground mr-1 shrink-0\" />\n <span class=\"text-sm font-medium tabular-nums select-none\">\n @if (zShowHour()) {\n {{ formattedHour() }}\n }\n @if (zShowHour() && zShowMinute()) {\n <span class=\"text-muted-foreground\">:</span>\n }\n @if (zShowMinute()) {\n {{ formattedMinute() }}\n }\n @if (zShowMinute() && zShowSecond()) {\n <span class=\"text-muted-foreground\">:</span>\n }\n @if (zShowSecond()) {\n {{ formattedSecond() }}\n }\n @if (zTimeFormat() === '12h') {\n <span class=\"text-primary ml-0.5 font-semibold\">\n {{ period() }}\n </span>\n }\n </span>\n <z-icon zType=\"lucideChevronDown\" zSize=\"14\" class=\"text-muted-foreground shrink-0\" />\n </div>\n\n <!-- Divider -->\n <div class=\"border-border bg-border h-px self-stretch sm:block sm:h-full sm:w-px\"></div>\n\n <!-- End Time -->\n <div\n class=\"hover:bg-muted flex flex-1 cursor-pointer items-center justify-center gap-1.5 px-3 py-1.5 transition-colors\"\n z-popover\n [zPopoverContent]=\"timeDropdownEndTpl\"\n zPosition=\"bottom\"\n [zPopoverWidth]=\"240\"\n [zOffset]=\"4\"\n zTrigger=\"click\"\n zClass=\"border-border shadow-lg\"\n (zShow)=\"onTimeDropdownEndShow()\">\n <z-icon zType=\"lucideCalendarClock\" zSize=\"18\" class=\"text-muted-foreground mr-1 shrink-0\" />\n <span class=\"text-sm font-medium tabular-nums select-none\">\n @if (zShowHour()) {\n {{ formattedHourEnd() }}\n }\n @if (zShowHour() && zShowMinute()) {\n <span class=\"text-muted-foreground\">:</span>\n }\n @if (zShowMinute()) {\n {{ formattedMinuteEnd() }}\n }\n @if (zShowMinute() && zShowSecond()) {\n <span class=\"text-muted-foreground\">:</span>\n }\n @if (zShowSecond()) {\n {{ formattedSecondEnd() }}\n }\n @if (zTimeFormat() === '12h') {\n <span class=\"text-primary ml-0.5 font-semibold\">\n {{ periodEnd() }}\n </span>\n }\n </span>\n <z-icon zType=\"lucideChevronDown\" zSize=\"14\" class=\"text-muted-foreground shrink-0\" />\n </div>\n </div>\n }\n } @else {\n <!-- Time Only Mode -->\n <div class=\"flex w-full justify-center px-2 pt-2 pb-1\">\n <ng-container [ngTemplateOutlet]=\"timeDropdownTpl\" />\n </div>\n }\n </div>\n\n @if (!(zQuickSelect() && zMode() === 'range' && !showOkButton() && !showCancelButton())) {\n <div\n class=\"bg-popover border-border z-10 flex w-full shrink-0 items-center justify-between gap-2 border-t px-2 py-2 shadow-[0_-2px_8px_-2px_rgb(0_0_0_/_10%)] sm:pt-2 sm:pb-0 sm:shadow-none\">\n @if (!zQuickSelect() || zMode() !== 'range') {\n <button type=\"button\" z-button zType=\"secondary\" zSize=\"sm\" [zWave]=\"false\" (click)=\"onTodayClick()\">\n {{ todayButtonText() }}\n </button>\n } @else {\n <div></div>\n }\n\n @if (showOkButton() || showCancelButton()) {\n <div class=\"flex items-center gap-2\">\n @if (showCancelButton()) {\n <button type=\"button\" z-button zType=\"outline\" zSize=\"sm\" (click)=\"onCancelClick()\">\n {{ zCancelText() ?? ('i18n_z_ui_calendar_cancel' | translate) }}\n </button>\n }\n @if (showOkButton()) {\n <button type=\"button\" z-button zSize=\"sm\" [zDisabled]=\"!canApply()\" (click)=\"onOkClick()\">\n {{ zOkText() ?? ('i18n_z_ui_calendar_ok' | translate) }}\n </button>\n }\n </div>\n }\n </div>\n }\n </div>\n </div>\n</ng-template>\n\n<ng-template #timeDropdownTpl>\n <div class=\"bg-popover flex min-w-56 justify-center overflow-hidden rounded-sm\">\n @if (zShowHour()) {\n <div\n class=\"flex flex-col\"\n [class.border-r]=\"zShowMinute() || zShowSecond() || zTimeFormat() === '12h'\"\n [class.border-border]=\"zShowMinute() || zShowSecond() || zTimeFormat() === '12h'\">\n <div\n class=\"text-muted-foreground border-b-border flex h-7 shrink-0 items-center justify-center border-b text-xs font-medium select-none\">\n {{ 'i18n_z_ui_calendar_hour' | translate }}\n </div>\n <ng-scrollbar\n class=\"z-time-scroll-hour h-[11rem] w-14\"\n [class.rounded-bl-sm]=\"!zShowMinute() && !zShowSecond() && zTimeFormat() !== '12h'\"\n [class.rounded-tl-sm]=\"zShowMinute() || zShowSecond() || zTimeFormat() === '12h'\"\n track=\"vertical\">\n <div class=\"flex flex-col\">\n @for (hr of hourOptions(); track hr) {\n @let hrSelected = hr === displayHour();\n <button\n type=\"button\"\n class=\"flex h-7 shrink-0 cursor-pointer items-center justify-center text-sm transition-colors\"\n [class.hover:bg-muted]=\"!hrSelected\"\n [class.bg-primary]=\"hrSelected\"\n [class.text-primary-foreground]=\"hrSelected\"\n [class.font-medium]=\"hrSelected\"\n (click)=\"selectHour(hr)\">\n {{ hr | number: '2.0-0' }}\n </button>\n }\n </div>\n </ng-scrollbar>\n </div>\n }\n @if (zShowMinute()) {\n <div\n class=\"flex flex-col\"\n [class.border-r]=\"zShowSecond() || zTimeFormat() === '12h'\"\n [class.border-border]=\"zShowSecond() || zTimeFormat() === '12h'\">\n <div\n class=\"text-muted-foreground border-b-border flex h-7 shrink-0 items-center justify-center border-b text-xs font-medium select-none\">\n {{ 'i18n_z_ui_calendar_minute' | translate }}\n </div>\n <ng-scrollbar\n class=\"z-time-scroll-minute h-[11rem] w-14\"\n [class.rounded-bl-sm]=\"!zShowHour() && !zShowSecond() && zTimeFormat() !== '12h'\"\n [class.rounded-tl-sm]=\"!zShowHour() && (zShowSecond() || zTimeFormat() === '12h')\"\n [class.rounded-br-sm]=\"(zShowHour() || !zShowHour()) && !zShowSecond() && zTimeFormat() !== '12h'\"\n track=\"vertical\">\n <div class=\"flex flex-col\">\n @for (min of minuteOptions; track min) {\n @let minSelected = min === minute();\n <button\n type=\"button\"\n class=\"flex h-7 shrink-0 cursor-pointer items-center justify-center text-sm transition-colors\"\n [class.hover:bg-muted]=\"!minSelected\"\n [class.bg-primary]=\"minSelected\"\n [class.text-primary-foreground]=\"minSelected\"\n [class.font-medium]=\"minSelected\"\n (click)=\"selectMinute(min)\">\n {{ min | number: '2.0-0' }}\n </button>\n }\n </div>\n </ng-scrollbar>\n </div>\n }\n @if (zShowSecond()) {\n <div\n class=\"flex flex-col\"\n [class.border-r]=\"zTimeFormat() === '12h'\"\n [class.border-border]=\"zTimeFormat() === '12h'\">\n <div\n class=\"text-muted-foreground border-b-border flex h-7 shrink-0 items-center justify-center border-b text-xs font-medium select-none\">\n {{ 'i18n_z_ui_calendar_second' | translate }}\n </div>\n <ng-scrollbar\n class=\"z-time-scroll-second h-[11rem] w-14\"\n [class.rounded-br-sm]=\"zTimeFormat() !== '12h'\"\n [class.rounded-bl-sm]=\"!zShowHour() && !zShowMinute() && zTimeFormat() !== '12h'\"\n track=\"vertical\">\n <div class=\"flex flex-col\">\n @for (sec of secondOptions; track sec) {\n @let secSelected = sec === second();\n <button\n type=\"button\"\n class=\"flex h-7 shrink-0 cursor-pointer items-center justify-center text-sm transition-colors\"\n [class.hover:bg-muted]=\"!secSelected\"\n [class.bg-primary]=\"secSelected\"\n [class.text-primary-foreground]=\"secSelected\"\n [class.font-medium]=\"secSelected\"\n (click)=\"selectSecond(sec)\">\n {{ sec | number: '2.0-0' }}\n </button>\n }\n </div>\n </ng-scrollbar>\n </div>\n }\n @if (zTimeFormat() === '12h') {\n <div class=\"flex flex-col\">\n <div\n class=\"text-muted-foreground border-b-border flex h-7 shrink-0 items-center justify-center border-b text-xs font-medium select-none\">\n {{ 'i18n_z_ui_calendar_period' | translate }}\n </div>\n <ng-scrollbar class=\"z-time-scroll-period h-[11rem] w-14\" [class.rounded-br-sm]=\"true\" track=\"vertical\">\n <div class=\"flex flex-col\">\n @for (p of ['AM', 'PM']; track p) {\n @let pSelected = p === period();\n <button\n type=\"button\"\n class=\"flex h-7 shrink-0 cursor-pointer items-center justify-center text-sm transition-colors\"\n [class.hover:bg-muted]=\"!pSelected\"\n [class.bg-primary]=\"pSelected\"\n [class.text-primary-foreground]=\"pSelected\"\n [class.font-medium]=\"pSelected\"\n (click)=\"selectPeriod($any(p))\">\n {{ p }}\n </button>\n }\n </div>\n </ng-scrollbar>\n </div>\n }\n </div>\n</ng-template>\n\n<ng-template #timeDropdownEndTpl>\n <div class=\"bg-popover flex min-w-56 justify-center overflow-hidden rounded-sm\">\n @if (zShowHour()) {\n <div\n class=\"flex flex-col\"\n [class.border-r]=\"zShowMinute() || zShowSecond() || zTimeFormat() === '12h'\"\n [class.border-border]=\"zShowMinute() || zShowSecond() || zTimeFormat() === '12h'\">\n <div\n class=\"text-muted-foreground border-b-border flex h-7 shrink-0 items-center justify-center border-b text-xs font-medium select-none\">\n {{ 'i18n_z_ui_calendar_hour' | translate }}\n </div>\n <ng-scrollbar\n class=\"z-time-scroll-hour-end h-[11rem] w-14\"\n [class.rounded-bl-sm]=\"!zShowMinute() && !zShowSecond() && zTimeFormat() !== '12h'\"\n [class.rounded-tl-sm]=\"zShowMinute() || zShowSecond() || zTimeFormat() === '12h'\"\n track=\"vertical\">\n <div class=\"flex flex-col\">\n @for (hr of hourOptions(); track hr) {\n @let hrDisabled = hr | zIsEndHourDisabled: endTimeContext();\n @let hrEndSelected = hr === displayHourEnd();\n <button\n type=\"button\"\n class=\"flex h-7 shrink-0 items-center justify-center text-sm transition-colors\"\n [class.hover:bg-muted]=\"!hrDisabled && !hrEndSelected\"\n [class.cursor-pointer]=\"!hrDisabled\"\n [class.bg-primary]=\"hrEndSelected\"\n [class.text-primary-foreground]=\"hrEndSelected\"\n [class.font-medium]=\"hrEndSelected\"\n [class.opacity-30]=\"hrDisabled\"\n [class.cursor-not-allowed]=\"hrDisabled\"\n [disabled]=\"hrDisabled\"\n (click)=\"selectHourEnd(hr)\">\n {{ hr | number: '2.0-0' }}\n </button>\n }\n </div>\n </ng-scrollbar>\n </div>\n }\n @if (zShowMinute()) {\n <div\n class=\"flex flex-col\"\n [class.border-r]=\"zShowSecond() || zTimeFormat() === '12h'\"\n [class.border-border]=\"zShowSecond() || zTimeFormat() === '12h'\">\n <div\n class=\"text-muted-foreground border-b-border flex h-7 shrink-0 items-center justify-center border-b text-xs font-medium select-none\">\n {{ 'i18n_z_ui_calendar_minute' | translate }}\n </div>\n <ng-scrollbar\n class=\"z-time-scroll-minute-end h-[11rem] w-14\"\n [class.rounded-bl-sm]=\"!zShowHour() && !zShowSecond() && zTimeFormat() !== '12h'\"\n [class.rounded-tl-sm]=\"!zShowHour() && (zShowSecond() || zTimeFormat() === '12h')\"\n [class.rounded-br-sm]=\"(zShowHour() || !zShowHour()) && !zShowSecond() && zTimeFormat() !== '12h'\"\n track=\"vertical\">\n <div class=\"flex flex-col\">\n @for (min of minuteOptions; track min) {\n @let minDisabled = min | zIsEndMinuteDisabled: endTimeContext();\n @let minEndSelected = min === minuteEnd();\n <button\n type=\"button\"\n class=\"flex h-7 shrink-0 items-center justify-center text-sm transition-colors\"\n [class.hover:bg-muted]=\"!minDisabled && !minEndSelected\"\n [class.cursor-pointer]=\"!minDisabled\"\n [class.bg-primary]=\"minEndSelected\"\n [class.text-primary-foreground]=\"minEndSelected\"\n [class.font-medium]=\"minEndSelected\"\n [class.opacity-30]=\"minDisabled\"\n [class.cursor-not-allowed]=\"minDisabled\"\n [disabled]=\"minDisabled\"\n (click)=\"selectMinuteEnd(min)\">\n {{ min | number: '2.0-0' }}\n </button>\n }\n </div>\n </ng-scrollbar>\n </div>\n }\n @if (zShowSecond()) {\n <div\n class=\"flex flex-col\"\n [class.border-r]=\"zTimeFormat() === '12h'\"\n [class.border-border]=\"zTimeFormat() === '12h'\">\n <div\n class=\"text-muted-foreground border-b-border flex h-7 shrink-0 items-center justify-center border-b text-xs font-medium select-none\">\n {{ 'i18n_z_ui_calendar_second' | translate }}\n </div>\n <ng-scrollbar\n class=\"z-time-scroll-second-end h-[11rem] w-14\"\n [class.rounded-br-sm]=\"zTimeFormat() !== '12h'\"\n [class.rounded-bl-sm]=\"!zShowHour() && !zShowMinute() && zTimeFormat() !== '12h'\"\n track=\"vertical\">\n <div class=\"flex flex-col\">\n @for (sec of secondOptions; track sec) {\n @let secDisabled = sec | zIsEndSecondDisabled: endTimeContext();\n @let secEndSelected = sec === secondEnd();\n <button\n type=\"button\"\n class=\"flex h-7 shrink-0 items-center justify-center text-sm transition-colors\"\n [class.hover:bg-muted]=\"!secDisabled && !secEndSelected\"\n [class.cursor-pointer]=\"!secDisabled\"\n [class.bg-primary]=\"secEndSelected\"\n [class.text-primary-foreground]=\"secEndSelected\"\n [class.font-medium]=\"secEndSelected\"\n [class.opacity-30]=\"secDisabled\"\n [class.cursor-not-allowed]=\"secDisabled\"\n [disabled]=\"secDisabled\"\n (click)=\"selectSecondEnd(sec)\">\n {{ sec | number: '2.0-0' }}\n </button>\n }\n </div>\n </ng-scrollbar>\n </div>\n }\n @if (zTimeFormat() === '12h') {\n <div class=\"flex flex-col\">\n <div\n class=\"text-muted-foreground border-b-border flex h-7 shrink-0 items-center justify-center border-b text-xs font-medium select-none\">\n {{ 'i18n_z_ui_calendar_period' | translate }}\n </div>\n <ng-scrollbar class=\"z-time-scroll-period-end h-[11rem] w-14\" [class.rounded-br-sm]=\"true\" track=\"vertical\">\n <div class=\"flex flex-col\">\n @for (p of ['AM', 'PM']; track p) {\n @let pSelected = p === periodEnd();\n <button\n type=\"button\"\n class=\"flex h-7 shrink-0 cursor-pointer items-center justify-center text-sm transition-colors\"\n [class.hover:bg-muted]=\"!pSelected\"\n [class.bg-primary]=\"pSelected\"\n [class.text-primary-foreground]=\"pSelected\"\n [class.font-medium]=\"pSelected\"\n (click)=\"selectPeriodEnd($any(p))\">\n {{ p }}\n </button>\n }\n </div>\n </ng-scrollbar>\n </div>\n }\n </div>\n</ng-template>\n", styles: [".animate-calendar-enter{animation:z-calendar-view-enter .2s ease-out}@keyframes z-calendar-view-enter{0%{opacity:0;transform:scale(.95) translateY(.25rem)}to{opacity:1;transform:scale(1) translateY(0)}}.z-calendar input{text-overflow:ellipsis;overflow:hidden}\n"], dependencies: [{ kind: "ngmodule", type: FormsModule }, { kind: "directive", type: i1.NgControlStatus, selector: "[formControlName],[ngModel],[formControl]" }, { kind: "directive", type: i1.NgModel, selector: "[ngModel]:not([formControlName]):not([formControl])", inputs: ["name", "disabled", "ngModel", "ngModelOptions"], outputs: ["ngModelChange"], exportAs: ["ngModel"] }, { kind: "directive", type: NgTemplateOutlet, selector: "[ngTemplateOutlet]", inputs: ["ngTemplateOutletContext", "ngTemplateOutlet", "ngTemplateOutletInjector"] }, { kind: "component", type: NgScrollbar, selector: "ng-scrollbar:not([externalViewport]), [ngScrollbar]", exportAs: ["ngScrollbar"] }, { kind: "component", type: ZIconComponent, selector: "z-icon, [z-icon]", inputs: ["class", "zType", "zAnimatedType", "zAnimate", "zAnimationTrigger", "zSize", "zStrokeWidth", "zSvg"] }, { kind: "component", type: ZSelectComponent, selector: "z-select", inputs: ["class", "zMode", "zSize", "zLabel", "zLabelClass", "zPlaceholder", "zRequired", "zDisabled", "zReadonly", "zLoading", "zPrefix", "zAllowClear", "zWrap", "zShowSearch", "zPlaceholderSearch", "zDebounce", "zNotFoundText", "zEmptyText", "zEmptyIcon", "zMaxTagCount", "zDropdownMaxHeight", "zOptionHeight", "zVirtualScroll", "zShowAction", "zOptions", "zConfig", "zTranslateLabels", "zKey", "zSearchServer", "zLoadingMore", "zEnableLoadMore", "zScrollDistance", "zMaxVisible", "zScrollClose", "zPosition", "zSelectedTemplate", "zOptionTemplate", "zActionTemplate", "zAsyncValidators", "zAsyncDebounce", "zAsyncValidateOn", "zValidators"], outputs: ["zOnSearch", "zOnLoadMore", "zOnBlur", "zOnFocus", "zControl", "zEvent"], exportAs: ["zSelect"] }, { kind: "directive", type: ZTooltipDirective, selector: "[z-tooltip], [zTooltip]", inputs: ["zContent", "zPosition", "zTooltipPosition", "zTrigger", "zTooltipTrigger", "zTooltipType", "zTooltipSize", "zClass", "zTooltipClass", "zShowDelay", "zTooltipShowDelay", "zHideDelay", "zTooltipHideDelay", "zArrow", "zTooltipArrow", "zDisabled", "zTooltipDisabled", "zOffset", "zTooltipOffset", "zAutoDetect", "zTriggerElement", "zAlwaysShow", "zMaxWidth"], outputs: ["zShow", "zHide"], exportAs: ["zTooltip"] }, { kind: "directive", type: ZPopoverDirective, selector: "[z-popover]", inputs: ["zPopoverContent", "zPosition", "zTrigger", "zPopoverTrigger", "zClass", "zShowDelay", "zHideDelay", "zDisabled", "zOffset", "zPopoverWidth", "zTriggerRef", "zManualClose", "zOutsideClickClose", "zScrollClose", "zShowArrow"], outputs: ["zShow", "zHide", "zHideStart", "zControl", "zPositionChange", "zOutsideClick"], exportAs: ["zPopover"] }, { kind: "component", type: ZButtonComponent, selector: "z-button, button[z-button], a[z-button]", inputs: ["class", "zType", "zSize", "zShape", "zLabel", "zLoading", "zDisabled", "zTypeIcon", "zAnimatedTypeIcon", "zAnimateIcon", "zAnimationTriggerIcon", "zSizeIcon", "zStrokeWidthIcon", "zWave"], exportAs: ["zButton"] }, { kind: "pipe", type: DecimalPipe, name: "number" }, { kind: "pipe", type: ZDayClassesPipe, name: "zDayClasses" }, { kind: "pipe", type: ZMonthClassesPipe, name: "zMonthClasses" }, { kind: "pipe", type: ZQuarterClassesPipe, name: "zQuarterClasses" }, { kind: "pipe", type: ZYearClassesPipe, name: "zYearClasses" }, { kind: "pipe", type: ZIsPresetDisabledPipe, name: "zIsPresetDisabled" }, { kind: "pipe", type: ZIsEndHourDisabledPipe, name: "zIsEndHourDisabled" }, { kind: "pipe", type: ZIsEndMinuteDisabledPipe, name: "zIsEndMinuteDisabled" }, { kind: "pipe", type: ZIsEndSecondDisabledPipe, name: "zIsEndSecondDisabled" }, { kind: "pipe", type: ZIsStartMonthDisabledPipe, name: "zIsStartMonthDisabled" }, { kind: "pipe", type: ZIsEndMonthDisabledPipe, name: "zIsEndMonthDisabled" }, { kind: "pipe", type: ZIsStartYearDisabledPipe, name: "zIsStartYearDisabled" }, { kind: "pipe", type: ZIsEndYearDisabledPipe, name: "zIsEndYearDisabled" }, { kind: "pipe", type: TranslatePipe, name: "translate" }], changeDetection: i0.ChangeDetectionStrategy.OnPush, encapsulation: i0.ViewEncapsulation.None });
|
|
3263
|
+
], viewQueries: [{ propertyName: "triggerRef", first: true, predicate: ["triggerEl"], descendants: true, isSignal: true }, { propertyName: "inputRef", first: true, predicate: ["inputEl"], descendants: true, isSignal: true }], exportAs: ["zCalendar"], ngImport: i0, template: "<div class=\"z-calendar-wrapper flex w-full flex-col gap-2\">\n @if (zLabel()) {\n <label [for]=\"pickerId\" class=\"text-xs leading-none font-medium\" [class]=\"zLabelClass()\">\n {{ zLabel() }}\n @if (zRequired()) {\n <span class=\"text-destructive! ml-0.5\">*</span>\n }\n </label>\n }\n\n <div class=\"relative\">\n <div\n #triggerEl\n z-popover\n [zPopoverContent]=\"calendarTpl\"\n zPosition=\"bottom-left\"\n zPopoverWidth=\"auto\"\n [zOffset]=\"6\"\n [zDisabled]=\"isDisabled() || zReadonly()\"\n [zManualClose]=\"showCancelButton()\"\n [zOutsideClickClose]=\"true\"\n [zScrollClose]=\"zScrollClose()\"\n zTrigger=\"click\"\n zClass=\"border-0 shadow-none p-0\"\n (zHideStart)=\"onPopoverHide()\"\n (zShow)=\"onPopoverShow()\"\n (zControl)=\"onPopoverControl($event)\"\n [id]=\"pickerId\"\n [class]=\"triggerClasses()\"\n z-tooltip\n [zContent]=\"displayValue()\"\n zTooltipTrigger=\"hover\"\n zTooltipPosition=\"top\"\n [zTooltipDisabled]=\"isInputFocused() || isOpen() || !hasValue()\"\n (keydown)=\"onTriggerKeydown($event)\">\n <z-icon\n [zType]=\"isRangeMode() ? 'lucideCalendarRange' : 'lucideCalendar'\"\n zSize=\"16\"\n class=\"text-muted-foreground shrink-0 cursor-pointer\"\n (click)=\"$event.stopPropagation(); toggle()\" />\n\n @if (isRangeMode()) {\n <input\n type=\"text\"\n data-range-type=\"start\"\n class=\"placeholder:text-muted-foreground w-0 min-w-0 flex-1 truncate bg-transparent text-sm outline-none disabled:opacity-100\"\n [class.cursor-pointer]=\"!zAllowEdit()\"\n [class.pointer-events-none]=\"!zAllowEdit()\"\n [class.text-center]=\"!rangeShortDisplayValue()\"\n [class.text-left]=\"rangeShortDisplayValue()\"\n [placeholder]=\"'i18n_z_ui_calendar_start_date' | translate\"\n [value]=\"inputDisplayStart()\"\n [disabled]=\"isDisabled()\"\n [readonly]=\"zReadonly() || !zAllowEdit()\"\n (click)=\"zAllowEdit() && isOpen() && $event.stopPropagation()\"\n (focus)=\"onInputFocus($event)\"\n (input)=\"onStartInputChange($event)\"\n (blur)=\"onInputBlur($event)\"\n (keydown.enter)=\"onStartInputEnter($event)\"\n (keydown.escape)=\"onStartInputEscape($event)\" />\n @if (!rangeShortDisplayValue()) {\n <span class=\"text-muted-foreground text-sm\">-</span>\n <input\n type=\"text\"\n data-range-type=\"end\"\n class=\"placeholder:text-muted-foreground w-0 min-w-0 flex-1 truncate bg-transparent text-center text-sm outline-none disabled:opacity-100\"\n [class.cursor-pointer]=\"!zAllowEdit()\"\n [class.pointer-events-none]=\"!zAllowEdit()\"\n [placeholder]=\"'i18n_z_ui_calendar_end_date' | translate\"\n [value]=\"inputDisplayEnd()\"\n [disabled]=\"isDisabled()\"\n [readonly]=\"zReadonly() || !zAllowEdit()\"\n (click)=\"zAllowEdit() && isOpen() && $event.stopPropagation()\"\n (focus)=\"onInputFocus($event)\"\n (input)=\"onEndInputChange($event)\"\n (blur)=\"onInputBlur($event)\"\n (keydown.enter)=\"onEndInputEnter($event)\"\n (keydown.escape)=\"onEndInputEscape($event)\" />\n }\n } @else {\n <input\n #inputEl\n type=\"text\"\n class=\"placeholder:text-muted-foreground w-0 min-w-0 flex-1 truncate bg-transparent text-sm outline-none disabled:opacity-100\"\n [class.cursor-pointer]=\"!zAllowEdit()\"\n [class.pointer-events-none]=\"!zAllowEdit()\"\n [placeholder]=\"effectivePlaceholder()\"\n [value]=\"inputDisplayValue()\"\n [disabled]=\"isDisabled()\"\n [readonly]=\"zReadonly() || !zAllowEdit()\"\n (click)=\"zAllowEdit() && isOpen() && $event.stopPropagation()\"\n (focus)=\"onInputFocus($event)\"\n (input)=\"onInputChange($event)\"\n (blur)=\"onInputBlur($event)\"\n (keydown.enter)=\"onInputEnter($event)\"\n (keydown.escape)=\"onInputEscape($event)\" />\n }\n\n @if (zAllowClear() && !isDisabled() && !zReadonly()) {\n <button\n type=\"button\"\n tabindex=\"-1\"\n class=\"text-muted-foreground hover:text-foreground flex size-5 shrink-0 cursor-pointer items-center justify-center rounded-sm transition-all\"\n [class.opacity-0]=\"!hasValue()\"\n [class.pointer-events-none]=\"!hasValue()\"\n (click)=\"onClear($event)\">\n <z-icon zType=\"lucideX\" zSize=\"18\" />\n </button>\n }\n </div>\n </div>\n\n @if (hasError()) {\n <p class=\"text-destructive animate-in fade-in slide-in-from-top-1 m-0 text-xs duration-200\">\n {{ errorMessage() }}\n </p>\n }\n</div>\n\n<ng-template #calendarTpl>\n <div\n class=\"z-calendar-calendar bg-popover border-border flex max-h-[50dvh] max-w-[calc(100vw-1.5rem)] flex-col overflow-hidden rounded-sm border shadow-lg min-[480px]:max-h-[55dvh] sm:max-h-none sm:max-w-none sm:flex-row sm:overflow-visible\"\n (keydown)=\"onCalendarKeydown($event)\">\n @if (zQuickSelect() && zMode() === 'range') {\n <div class=\"border-border hidden shrink-0 flex-col gap-0 space-y-1 overflow-y-auto border-r p-2 sm:flex\">\n @for (preset of quickSelectPresets; track preset.key) {\n @let presetDisabled = preset | zIsPresetDisabled: zDisabledDate();\n <button\n type=\"button\"\n class=\"cursor-pointer rounded-sm px-3 py-1.5 text-left text-sm whitespace-nowrap transition-colors\"\n [class.hover:bg-muted]=\"activePresetKey() !== preset.key && !presetDisabled\"\n [class.bg-primary]=\"activePresetKey() === preset.key\"\n [class.text-primary-foreground]=\"activePresetKey() === preset.key\"\n [class.font-medium]=\"activePresetKey() === preset.key\"\n [class.opacity-40]=\"presetDisabled\"\n [class.cursor-not-allowed]=\"presetDisabled\"\n [disabled]=\"presetDisabled\"\n (click)=\"onQuickSelect(preset)\">\n {{ preset.label | translate }}\n </button>\n }\n </div>\n }\n <div\n class=\"flex min-h-0 flex-1 flex-col items-center overflow-hidden pb-0 sm:overflow-visible sm:py-2\"\n [class.sm:pt-0!]=\"isTimeMode()\"\n [class]=\"\n !isRangeMode()\n ? 'w-[17.75rem] max-w-[calc(100vw-1.5rem)]'\n : 'w-[17.75rem] max-w-[calc(100vw-1.5rem)] sm:w-auto sm:max-w-none'\n \">\n @if (zQuickSelect() && zMode() === 'range') {\n <div class=\"border-border w-full border-b px-2 pt-2 pb-2 sm:hidden\">\n <z-select\n class=\"w-full\"\n zSize=\"sm\"\n zPosition=\"bottom-left\"\n [zShowSearch]=\"false\"\n [zAllowClear]=\"false\"\n [zOptions]=\"quickSelectOptions()\"\n [ngModel]=\"activePresetKey()\"\n [ngModelOptions]=\"{ standalone: true }\"\n (ngModelChange)=\"onQuickSelectKeyChange($event)\" />\n </div>\n }\n <div class=\"min-h-0 w-full flex-1 overflow-x-hidden overflow-y-auto pt-2 sm:overflow-visible sm:pt-0\">\n @if (!isTimeMode()) {\n <div\n class=\"z-calendars-wrapper flex w-full flex-col items-center gap-0 sm:flex-row sm:items-stretch sm:justify-center\">\n <!-- First Calendar -->\n <div class=\"z-calendar-section flex w-[17.5rem] shrink-0 flex-col\">\n @if (!isTimeMode()) {\n <!-- Header -->\n <div class=\"border-border flex w-full items-center justify-between gap-0.5 px-2\">\n <!-- Double left arrow (always visible) -->\n <button\n type=\"button\"\n z-button\n zType=\"ghost\"\n zSize=\"sm\"\n class=\"size-7 shrink-0 p-0!\"\n [zWave]=\"false\"\n (click)=\"navigatePreviousFast()\">\n <z-icon zType=\"lucideChevronsLeft\" zSize=\"18\" />\n </button>\n\n <!-- Single left arrow (hidden in month/year view) -->\n @if (currentView() === 'day') {\n <button\n type=\"button\"\n z-button\n zType=\"ghost\"\n zSize=\"sm\"\n class=\"size-7 shrink-0 p-0!\"\n [zWave]=\"false\"\n (click)=\"navigatePrevious()\">\n <z-icon zType=\"lucideChevronLeft\" zSize=\"18\" />\n </button>\n }\n\n <!-- Header content -->\n <div class=\"flex flex-1 shrink-0 items-center justify-center gap-0\">\n @if (currentView() === 'day') {\n <!-- Day view: Month + Year -->\n @if (!isYearMode() && !isQuarterMode()) {\n <button\n type=\"button\"\n z-button\n zType=\"ghost\"\n zSize=\"sm\"\n class=\"h-7 px-1.5 text-sm!\"\n [zWave]=\"false\"\n (click)=\"setView('month')\">\n {{ currentMonthName() }}\n </button>\n }\n <button\n type=\"button\"\n z-button\n zType=\"ghost\"\n zSize=\"sm\"\n class=\"h-7 px-1.5 text-sm!\"\n [zWave]=\"false\"\n [zDisabled]=\"isYearMode()\"\n (click)=\"setView('year')\">\n {{ currentYear() }}\n </button>\n } @else if (currentView() === 'month') {\n <!-- Month view: Only Year -->\n <button\n type=\"button\"\n z-button\n zType=\"ghost\"\n zSize=\"sm\"\n class=\"h-7 px-1.5 text-sm!\"\n [zWave]=\"false\"\n (click)=\"setView('year')\">\n {{ currentYear() }}\n </button>\n } @else if (currentView() === 'year') {\n <!-- Year view: Year Range -->\n <span class=\"text-sm font-medium\">\n {{ yearRange()[0] }} - {{ yearRange()[yearRange().length - 1] }}\n </span>\n } @else if (currentView() === 'quarter') {\n <!-- Quarter view: Only Year -->\n <button\n type=\"button\"\n z-button\n zType=\"ghost\"\n zSize=\"sm\"\n class=\"h-7 px-1.5 text-sm!\"\n [zWave]=\"false\"\n (click)=\"setView('year')\">\n {{ currentYear() }}\n </button>\n }\n </div>\n\n <!-- Single right arrow (hidden in month/year view) -->\n @if (currentView() === 'day') {\n <button\n type=\"button\"\n z-button\n zType=\"ghost\"\n zSize=\"sm\"\n class=\"size-7 shrink-0 p-0!\"\n [zDisabled]=\"!canNavigateStartNext()\"\n [zWave]=\"false\"\n (click)=\"navigateNext()\">\n <z-icon zType=\"lucideChevronRight\" zSize=\"18\" />\n </button>\n }\n\n <!-- Double right arrow (always visible) -->\n <button\n type=\"button\"\n z-button\n zType=\"ghost\"\n zSize=\"sm\"\n class=\"size-7 shrink-0 p-0!\"\n [zDisabled]=\"!canNavigateStartNext()\"\n [zWave]=\"false\"\n (click)=\"navigateNextFast()\">\n <z-icon zType=\"lucideChevronsRight\" zSize=\"18\" />\n </button>\n </div>\n\n <!-- Body -->\n <div\n class=\"flex h-full w-full flex-col items-center justify-center p-2\"\n [class.min-h-[14rem]]=\"!isQuarterMode()\"\n [class.h-[14rem]]=\"\n !isYearMode() &&\n !isMonthMode() &&\n !isQuarterMode() &&\n (currentView() === 'month' || currentView() === 'year')\n \"\n [class.min-h-[6.25rem]]=\"isQuarterMode()\"\n [class.!min-h-auto]=\"isYearMode() || isMonthMode() || isQuarterMode()\"\n [class.!h-auto]=\"isYearMode() || isMonthMode() || isQuarterMode()\">\n @if (currentView() === 'day') {\n <div\n class=\"flex h-full w-full flex-1 flex-col gap-1\"\n [class.animate-calendar-enter]=\"uiState().hasViewChanged\">\n <!-- Weekday headers -->\n <div class=\"flex w-full flex-1 justify-center gap-1\">\n @for (weekday of weekdayNames(); track weekday) {\n <div\n class=\"text-muted-foreground flex h-[1.875rem] w-[2.0313rem] items-center justify-center text-xs font-medium\">\n {{ weekday }}\n </div>\n }\n </div>\n\n <!-- Date rows -->\n @for (week of calendarDays(); track $index) {\n <div class=\"flex w-full flex-1 justify-center gap-1\">\n @for (day of week; track day.date.getTime()) {\n <button\n type=\"button\"\n [class]=\"day | zDayClasses\"\n class=\"h-[1.875rem] !w-[2.0313rem] !text-sm\"\n [disabled]=\"day.isDisabled\"\n (click)=\"onDayClick(day)\"\n (mouseenter)=\"onDayHover(day)\"\n (mouseleave)=\"onDayLeave()\">\n {{ day.day }}\n </button>\n }\n </div>\n }\n </div>\n }\n @if (currentView() === 'month') {\n <div\n class=\"grid h-full w-full grid-cols-3 grid-rows-4 gap-2.5 gap-y-5!\"\n [class.animate-calendar-enter]=\"uiState().hasViewChanged\">\n @for (month of monthNames(); track month; let i = $index) {\n @let monthDisabled = i | zIsStartMonthDisabled: startMonthDisabledContext();\n <div class=\"flex flex-1 items-center justify-center\">\n <button\n type=\"button\"\n [class]=\"i | zMonthClasses: selectedMonthIndex() : todayMonthIndex()\"\n class=\"!h-7 !w-full !text-sm\"\n [disabled]=\"monthDisabled\"\n [class.opacity-30]=\"monthDisabled\"\n [class.cursor-not-allowed]=\"monthDisabled\"\n (click)=\"onMonthSelect(i)\">\n {{ month }}\n </button>\n </div>\n }\n </div>\n }\n\n @if (currentView() === 'year') {\n <div\n class=\"grid h-full w-full grid-cols-3 grid-rows-4 gap-2.5 gap-y-5!\"\n [class.animate-calendar-enter]=\"uiState().hasViewChanged\">\n @for (year of yearRange(); track year) {\n @let yearDisabled = year | zIsStartYearDisabled: startYearDisabledContext();\n <div class=\"flex flex-1 items-center justify-center\">\n <button\n type=\"button\"\n [class]=\"year | zYearClasses: selectedYear() : todayYear()\"\n class=\"!h-7 !w-full !text-sm\"\n [disabled]=\"yearDisabled\"\n [class.opacity-30]=\"yearDisabled\"\n [class.cursor-not-allowed]=\"yearDisabled\"\n (click)=\"onYearClick(year)\">\n {{ year }}\n </button>\n </div>\n }\n </div>\n }\n\n @if (currentView() === 'quarter') {\n <div\n class=\"grid h-full w-full grid-cols-2 grid-rows-2 gap-2 p-1\"\n [class.animate-calendar-enter]=\"uiState().hasViewChanged\">\n @for (quarter of quarterNames; track quarter; let i = $index) {\n <div class=\"flex flex-1 items-center justify-center\">\n <button\n type=\"button\"\n [class]=\"i | zQuarterClasses: selectedQuarterIndex() : todayQuarterIndex()\"\n class=\"!h-8 !w-full !text-sm\"\n (click)=\"onQuarterClick(i)\">\n {{ quarter }}\n </button>\n </div>\n }\n </div>\n }\n </div>\n }\n </div>\n\n <!-- Second Calendar (Range Mode Only) -->\n @if (isRangeMode()) {\n <!-- Divider -->\n <div\n class=\"border-border bg-border mb-2 hidden self-stretch sm:block sm:w-px\"\n [class.mb-2]=\"!zQuickSelect() || (zQuickSelect() && zShowOk())\"></div>\n <div class=\"border-border bg-border block h-px w-full sm:hidden\"></div>\n\n <div class=\"z-calendar-section flex w-[17.5rem] shrink-0 flex-col pt-2 sm:pt-0\">\n <!-- Header -->\n <div class=\"border-border flex w-full items-center justify-between gap-0.5 px-2\">\n <button\n type=\"button\"\n z-button\n zType=\"ghost\"\n zSize=\"sm\"\n class=\"size-7 shrink-0 p-0!\"\n [zDisabled]=\"!canNavigateEndPrev()\"\n [zWave]=\"false\"\n (click)=\"navigateEndPreviousFast()\">\n <z-icon zType=\"lucideChevronsLeft\" zSize=\"18\" />\n </button>\n\n <button\n type=\"button\"\n z-button\n zType=\"ghost\"\n zSize=\"sm\"\n class=\"size-7 shrink-0 p-0!\"\n [zDisabled]=\"!canNavigateEndPrev()\"\n [zWave]=\"false\"\n (click)=\"navigateEndPrevious()\">\n <z-icon zType=\"lucideChevronLeft\" zSize=\"18\" />\n </button>\n\n <div class=\"flex w-[7.5rem] shrink-0 items-center justify-center gap-0\">\n <button\n type=\"button\"\n z-button\n zType=\"ghost\"\n zSize=\"sm\"\n class=\"h-7 px-1.5 text-sm!\"\n [zWave]=\"false\"\n (click)=\"setEndView('month')\">\n {{ endMonthName() }}\n </button>\n\n <button\n type=\"button\"\n z-button\n zType=\"ghost\"\n zSize=\"sm\"\n class=\"h-7 px-1.5 text-sm!\"\n [zWave]=\"false\"\n (click)=\"setEndView('year')\">\n {{ endMonthYear() }}\n </button>\n </div>\n\n <button\n type=\"button\"\n z-button\n zType=\"ghost\"\n zSize=\"sm\"\n class=\"size-7 shrink-0 p-0!\"\n [zWave]=\"false\"\n [zWave]=\"false\"\n (click)=\"navigateEndNext()\">\n <z-icon zType=\"lucideChevronRight\" zSize=\"18\" />\n </button>\n\n <button\n type=\"button\"\n z-button\n zType=\"ghost\"\n zSize=\"sm\"\n class=\"size-7 shrink-0 p-0!\"\n [zWave]=\"false\"\n [zWave]=\"false\"\n (click)=\"navigateEndNextFast()\">\n <z-icon zType=\"lucideChevronsRight\" zSize=\"18\" />\n </button>\n </div>\n\n <!-- Body -->\n <div\n class=\"flex h-full min-h-[14rem] w-full flex-col items-center justify-center p-2\"\n [class.h-[14rem]]=\"endView() === 'month' || endView() === 'year'\">\n @if (endView() === 'day') {\n <div\n class=\"flex h-full w-full flex-1 flex-col gap-1\"\n [class.animate-calendar-enter]=\"uiState().hasEndViewChanged\">\n <!-- Weekday headers -->\n <div class=\"flex w-full flex-1 justify-center gap-1\">\n @for (weekday of weekdayNames(); track weekday) {\n <div\n class=\"text-muted-foreground flex h-[1.875rem] w-[2.0313rem] items-center justify-center text-xs font-medium\">\n {{ weekday }}\n </div>\n }\n </div>\n\n <!-- Date rows -->\n @for (week of calendarDaysEnd(); track $index) {\n <div class=\"flex w-full flex-1 justify-center gap-1\">\n @for (day of week; track day.date.getTime()) {\n <button\n type=\"button\"\n [class]=\"day | zDayClasses\"\n class=\"h-[1.875rem] !w-[2.0313rem] !text-sm\"\n [disabled]=\"day.isDisabled\"\n (click)=\"onDayClick(day)\"\n (mouseenter)=\"onDayHover(day)\"\n (mouseleave)=\"onDayLeave()\">\n {{ day.day }}\n </button>\n }\n </div>\n }\n </div>\n }\n @if (endView() === 'month') {\n <div\n class=\"grid h-full w-full grid-cols-3 grid-rows-4 gap-2.5 gap-y-5!\"\n [class.animate-calendar-enter]=\"uiState().hasEndViewChanged\">\n @for (month of monthNames(); track month; let i = $index) {\n @let endMonthDisabled = i | zIsEndMonthDisabled: endMonthDisabledContext();\n <div class=\"flex flex-1 items-center justify-center\">\n <button\n type=\"button\"\n [class]=\"i | zMonthClasses: endMonth().getMonth() : -1\"\n class=\"!h-7 !w-full !text-sm\"\n [disabled]=\"endMonthDisabled\"\n [class.opacity-30]=\"endMonthDisabled\"\n [class.cursor-not-allowed]=\"endMonthDisabled\"\n (click)=\"onEndMonthClick(i)\">\n {{ month }}\n </button>\n </div>\n }\n </div>\n }\n\n @if (endView() === 'year') {\n <div\n class=\"grid h-full w-full grid-cols-3 grid-rows-4 gap-2.5 gap-y-5!\"\n [class.animate-calendar-enter]=\"uiState().hasEndViewChanged\">\n @for (year of endYearRange(); track year) {\n @let endYearDisabled = year | zIsEndYearDisabled: endYearDisabledContext();\n <div class=\"flex flex-1 items-center justify-center\">\n <button\n type=\"button\"\n [class]=\"year | zYearClasses: endMonth().getFullYear() : -1\"\n class=\"!h-7 !w-full !text-sm\"\n [disabled]=\"endYearDisabled\"\n [class.opacity-30]=\"endYearDisabled\"\n [class.cursor-not-allowed]=\"endYearDisabled\"\n (click)=\"onEndYearClick(year)\">\n {{ year }}\n </button>\n </div>\n }\n </div>\n }\n </div>\n </div>\n }\n </div>\n\n <!-- Compact Time Picker Below Calendar (Single Date) -->\n @if (!isRangeMode() && zShowTime()) {\n <div\n class=\"hover:bg-muted border-border flex w-full cursor-pointer items-center justify-center gap-1.5 border-t px-3 py-1.5 transition-colors\"\n z-popover\n [zPopoverContent]=\"timeDropdownTpl\"\n zPosition=\"bottom\"\n [zPopoverWidth]=\"240\"\n [zOffset]=\"4\"\n zTrigger=\"click\"\n zClass=\"border-border shadow-lg\"\n (zShow)=\"onTimeDropdownShow()\">\n <z-icon zType=\"lucideCalendarClock\" zSize=\"18\" class=\"text-muted-foreground mr-1 shrink-0\" />\n <span class=\"text-sm font-medium tabular-nums select-none\">\n @if (zShowHour()) {\n {{ formattedHour() }}\n }\n @if (zShowHour() && zShowMinute()) {\n <span class=\"text-muted-foreground\">:</span>\n }\n @if (zShowMinute()) {\n {{ formattedMinute() }}\n }\n @if (zShowMinute() && zShowSecond()) {\n <span class=\"text-muted-foreground\">:</span>\n }\n @if (zShowSecond()) {\n {{ formattedSecond() }}\n }\n @if (zTimeFormat() === '12h') {\n <span class=\"text-primary ml-0.5 font-semibold\">\n {{ period() }}\n </span>\n }\n </span>\n <z-icon zType=\"lucideChevronDown\" zSize=\"14\" class=\"text-muted-foreground shrink-0\" />\n </div>\n }\n\n <!-- Compact Time Pickers Below Calendars (Range Mode) -->\n @if (isRangeMode() && zShowTime()) {\n <div class=\"border-border flex w-full flex-col border-t sm:flex-row\">\n <!-- Start Time -->\n <div\n class=\"hover:bg-muted flex flex-1 cursor-pointer items-center justify-center gap-1.5 px-3 py-1.5 transition-colors\"\n z-popover\n [zPopoverContent]=\"timeDropdownTpl\"\n zPosition=\"bottom\"\n [zPopoverWidth]=\"240\"\n [zOffset]=\"4\"\n zTrigger=\"click\"\n zClass=\"border-border shadow-lg\"\n (zShow)=\"onTimeDropdownShow()\">\n <z-icon zType=\"lucideCalendarClock\" zSize=\"18\" class=\"text-muted-foreground mr-1 shrink-0\" />\n <span class=\"text-sm font-medium tabular-nums select-none\">\n @if (zShowHour()) {\n {{ formattedHour() }}\n }\n @if (zShowHour() && zShowMinute()) {\n <span class=\"text-muted-foreground\">:</span>\n }\n @if (zShowMinute()) {\n {{ formattedMinute() }}\n }\n @if (zShowMinute() && zShowSecond()) {\n <span class=\"text-muted-foreground\">:</span>\n }\n @if (zShowSecond()) {\n {{ formattedSecond() }}\n }\n @if (zTimeFormat() === '12h') {\n <span class=\"text-primary ml-0.5 font-semibold\">\n {{ period() }}\n </span>\n }\n </span>\n <z-icon zType=\"lucideChevronDown\" zSize=\"14\" class=\"text-muted-foreground shrink-0\" />\n </div>\n\n <!-- Divider -->\n <div class=\"border-border bg-border h-px self-stretch sm:block sm:h-full sm:w-px\"></div>\n\n <!-- End Time -->\n <div\n class=\"hover:bg-muted flex flex-1 cursor-pointer items-center justify-center gap-1.5 px-3 py-1.5 transition-colors\"\n z-popover\n [zPopoverContent]=\"timeDropdownEndTpl\"\n zPosition=\"bottom\"\n [zPopoverWidth]=\"240\"\n [zOffset]=\"4\"\n zTrigger=\"click\"\n zClass=\"border-border shadow-lg\"\n (zShow)=\"onTimeDropdownEndShow()\">\n <z-icon zType=\"lucideCalendarClock\" zSize=\"18\" class=\"text-muted-foreground mr-1 shrink-0\" />\n <span class=\"text-sm font-medium tabular-nums select-none\">\n @if (zShowHour()) {\n {{ formattedHourEnd() }}\n }\n @if (zShowHour() && zShowMinute()) {\n <span class=\"text-muted-foreground\">:</span>\n }\n @if (zShowMinute()) {\n {{ formattedMinuteEnd() }}\n }\n @if (zShowMinute() && zShowSecond()) {\n <span class=\"text-muted-foreground\">:</span>\n }\n @if (zShowSecond()) {\n {{ formattedSecondEnd() }}\n }\n @if (zTimeFormat() === '12h') {\n <span class=\"text-primary ml-0.5 font-semibold\">\n {{ periodEnd() }}\n </span>\n }\n </span>\n <z-icon zType=\"lucideChevronDown\" zSize=\"14\" class=\"text-muted-foreground shrink-0\" />\n </div>\n </div>\n }\n } @else {\n <!-- Time Only Mode -->\n <div class=\"flex w-full justify-center px-2 pt-2 pb-1\">\n <ng-container [ngTemplateOutlet]=\"timeDropdownTpl\" />\n </div>\n }\n </div>\n\n @if (!(zQuickSelect() && zMode() === 'range' && !showOkButton() && !showCancelButton())) {\n <div\n class=\"bg-popover border-border z-10 flex w-full shrink-0 items-center justify-between gap-2 border-t px-2 py-2 shadow-[0_-2px_8px_-2px_rgb(0_0_0_/_10%)] sm:pt-2 sm:pb-0 sm:shadow-none\">\n @if (!zQuickSelect() || zMode() !== 'range') {\n <button type=\"button\" z-button zType=\"secondary\" zSize=\"sm\" [zWave]=\"false\" (click)=\"onTodayClick()\">\n {{ todayButtonText() }}\n </button>\n } @else {\n <div></div>\n }\n\n @if (showOkButton() || showCancelButton()) {\n <div class=\"flex items-center gap-2\">\n @if (showCancelButton()) {\n <button type=\"button\" z-button zType=\"outline\" zSize=\"sm\" (click)=\"onCancelClick()\">\n {{ zCancelText() ?? ('i18n_z_ui_calendar_cancel' | translate) }}\n </button>\n }\n @if (showOkButton()) {\n <button type=\"button\" z-button zSize=\"sm\" [zDisabled]=\"!canApply()\" (click)=\"onOkClick()\">\n {{ zOkText() ?? ('i18n_z_ui_calendar_ok' | translate) }}\n </button>\n }\n </div>\n }\n </div>\n }\n </div>\n </div>\n</ng-template>\n\n<ng-template #timeDropdownTpl>\n <div class=\"bg-popover flex min-w-56 justify-center overflow-hidden rounded-sm\">\n @if (zShowHour()) {\n <div\n class=\"flex flex-col\"\n [class.border-r]=\"zShowMinute() || zShowSecond() || zTimeFormat() === '12h'\"\n [class.border-border]=\"zShowMinute() || zShowSecond() || zTimeFormat() === '12h'\">\n <div\n class=\"text-muted-foreground border-b-border flex h-7 shrink-0 items-center justify-center border-b text-xs font-medium select-none\">\n {{ 'i18n_z_ui_calendar_hour' | translate }}\n </div>\n <ng-scrollbar\n class=\"z-time-scroll-hour h-[11rem] w-14\"\n [class.rounded-bl-sm]=\"!zShowMinute() && !zShowSecond() && zTimeFormat() !== '12h'\"\n [class.rounded-tl-sm]=\"zShowMinute() || zShowSecond() || zTimeFormat() === '12h'\"\n track=\"vertical\">\n <div class=\"flex flex-col\">\n @for (hr of hourOptions(); track hr) {\n @let hrSelected = hr === displayHour();\n <button\n type=\"button\"\n class=\"flex h-7 shrink-0 cursor-pointer items-center justify-center text-sm transition-colors\"\n [class.hover:bg-muted]=\"!hrSelected\"\n [class.bg-primary]=\"hrSelected\"\n [class.text-primary-foreground]=\"hrSelected\"\n [class.font-medium]=\"hrSelected\"\n (click)=\"selectHour(hr)\">\n {{ hr | number: '2.0-0' }}\n </button>\n }\n </div>\n </ng-scrollbar>\n </div>\n }\n @if (zShowMinute()) {\n <div\n class=\"flex flex-col\"\n [class.border-r]=\"zShowSecond() || zTimeFormat() === '12h'\"\n [class.border-border]=\"zShowSecond() || zTimeFormat() === '12h'\">\n <div\n class=\"text-muted-foreground border-b-border flex h-7 shrink-0 items-center justify-center border-b text-xs font-medium select-none\">\n {{ 'i18n_z_ui_calendar_minute' | translate }}\n </div>\n <ng-scrollbar\n class=\"z-time-scroll-minute h-[11rem] w-14\"\n [class.rounded-bl-sm]=\"!zShowHour() && !zShowSecond() && zTimeFormat() !== '12h'\"\n [class.rounded-tl-sm]=\"!zShowHour() && (zShowSecond() || zTimeFormat() === '12h')\"\n [class.rounded-br-sm]=\"(zShowHour() || !zShowHour()) && !zShowSecond() && zTimeFormat() !== '12h'\"\n track=\"vertical\">\n <div class=\"flex flex-col\">\n @for (min of minuteOptions; track min) {\n @let minSelected = min === minute();\n <button\n type=\"button\"\n class=\"flex h-7 shrink-0 cursor-pointer items-center justify-center text-sm transition-colors\"\n [class.hover:bg-muted]=\"!minSelected\"\n [class.bg-primary]=\"minSelected\"\n [class.text-primary-foreground]=\"minSelected\"\n [class.font-medium]=\"minSelected\"\n (click)=\"selectMinute(min)\">\n {{ min | number: '2.0-0' }}\n </button>\n }\n </div>\n </ng-scrollbar>\n </div>\n }\n @if (zShowSecond()) {\n <div\n class=\"flex flex-col\"\n [class.border-r]=\"zTimeFormat() === '12h'\"\n [class.border-border]=\"zTimeFormat() === '12h'\">\n <div\n class=\"text-muted-foreground border-b-border flex h-7 shrink-0 items-center justify-center border-b text-xs font-medium select-none\">\n {{ 'i18n_z_ui_calendar_second' | translate }}\n </div>\n <ng-scrollbar\n class=\"z-time-scroll-second h-[11rem] w-14\"\n [class.rounded-br-sm]=\"zTimeFormat() !== '12h'\"\n [class.rounded-bl-sm]=\"!zShowHour() && !zShowMinute() && zTimeFormat() !== '12h'\"\n track=\"vertical\">\n <div class=\"flex flex-col\">\n @for (sec of secondOptions; track sec) {\n @let secSelected = sec === second();\n <button\n type=\"button\"\n class=\"flex h-7 shrink-0 cursor-pointer items-center justify-center text-sm transition-colors\"\n [class.hover:bg-muted]=\"!secSelected\"\n [class.bg-primary]=\"secSelected\"\n [class.text-primary-foreground]=\"secSelected\"\n [class.font-medium]=\"secSelected\"\n (click)=\"selectSecond(sec)\">\n {{ sec | number: '2.0-0' }}\n </button>\n }\n </div>\n </ng-scrollbar>\n </div>\n }\n @if (zTimeFormat() === '12h') {\n <div class=\"flex flex-col\">\n <div\n class=\"text-muted-foreground border-b-border flex h-7 shrink-0 items-center justify-center border-b text-xs font-medium select-none\">\n {{ 'i18n_z_ui_calendar_period' | translate }}\n </div>\n <ng-scrollbar class=\"z-time-scroll-period h-[11rem] w-14\" [class.rounded-br-sm]=\"true\" track=\"vertical\">\n <div class=\"flex flex-col\">\n @for (p of ['AM', 'PM']; track p) {\n @let pSelected = p === period();\n <button\n type=\"button\"\n class=\"flex h-7 shrink-0 cursor-pointer items-center justify-center text-sm transition-colors\"\n [class.hover:bg-muted]=\"!pSelected\"\n [class.bg-primary]=\"pSelected\"\n [class.text-primary-foreground]=\"pSelected\"\n [class.font-medium]=\"pSelected\"\n (click)=\"selectPeriod($any(p))\">\n {{ p }}\n </button>\n }\n </div>\n </ng-scrollbar>\n </div>\n }\n </div>\n</ng-template>\n\n<ng-template #timeDropdownEndTpl>\n <div class=\"bg-popover flex min-w-56 justify-center overflow-hidden rounded-sm\">\n @if (zShowHour()) {\n <div\n class=\"flex flex-col\"\n [class.border-r]=\"zShowMinute() || zShowSecond() || zTimeFormat() === '12h'\"\n [class.border-border]=\"zShowMinute() || zShowSecond() || zTimeFormat() === '12h'\">\n <div\n class=\"text-muted-foreground border-b-border flex h-7 shrink-0 items-center justify-center border-b text-xs font-medium select-none\">\n {{ 'i18n_z_ui_calendar_hour' | translate }}\n </div>\n <ng-scrollbar\n class=\"z-time-scroll-hour-end h-[11rem] w-14\"\n [class.rounded-bl-sm]=\"!zShowMinute() && !zShowSecond() && zTimeFormat() !== '12h'\"\n [class.rounded-tl-sm]=\"zShowMinute() || zShowSecond() || zTimeFormat() === '12h'\"\n track=\"vertical\">\n <div class=\"flex flex-col\">\n @for (hr of hourOptions(); track hr) {\n @let hrDisabled = hr | zIsEndHourDisabled: endTimeContext();\n @let hrEndSelected = hr === displayHourEnd();\n <button\n type=\"button\"\n class=\"flex h-7 shrink-0 items-center justify-center text-sm transition-colors\"\n [class.hover:bg-muted]=\"!hrDisabled && !hrEndSelected\"\n [class.cursor-pointer]=\"!hrDisabled\"\n [class.bg-primary]=\"hrEndSelected\"\n [class.text-primary-foreground]=\"hrEndSelected\"\n [class.font-medium]=\"hrEndSelected\"\n [class.opacity-30]=\"hrDisabled\"\n [class.cursor-not-allowed]=\"hrDisabled\"\n [disabled]=\"hrDisabled\"\n (click)=\"selectHourEnd(hr)\">\n {{ hr | number: '2.0-0' }}\n </button>\n }\n </div>\n </ng-scrollbar>\n </div>\n }\n @if (zShowMinute()) {\n <div\n class=\"flex flex-col\"\n [class.border-r]=\"zShowSecond() || zTimeFormat() === '12h'\"\n [class.border-border]=\"zShowSecond() || zTimeFormat() === '12h'\">\n <div\n class=\"text-muted-foreground border-b-border flex h-7 shrink-0 items-center justify-center border-b text-xs font-medium select-none\">\n {{ 'i18n_z_ui_calendar_minute' | translate }}\n </div>\n <ng-scrollbar\n class=\"z-time-scroll-minute-end h-[11rem] w-14\"\n [class.rounded-bl-sm]=\"!zShowHour() && !zShowSecond() && zTimeFormat() !== '12h'\"\n [class.rounded-tl-sm]=\"!zShowHour() && (zShowSecond() || zTimeFormat() === '12h')\"\n [class.rounded-br-sm]=\"(zShowHour() || !zShowHour()) && !zShowSecond() && zTimeFormat() !== '12h'\"\n track=\"vertical\">\n <div class=\"flex flex-col\">\n @for (min of minuteOptions; track min) {\n @let minDisabled = min | zIsEndMinuteDisabled: endTimeContext();\n @let minEndSelected = min === minuteEnd();\n <button\n type=\"button\"\n class=\"flex h-7 shrink-0 items-center justify-center text-sm transition-colors\"\n [class.hover:bg-muted]=\"!minDisabled && !minEndSelected\"\n [class.cursor-pointer]=\"!minDisabled\"\n [class.bg-primary]=\"minEndSelected\"\n [class.text-primary-foreground]=\"minEndSelected\"\n [class.font-medium]=\"minEndSelected\"\n [class.opacity-30]=\"minDisabled\"\n [class.cursor-not-allowed]=\"minDisabled\"\n [disabled]=\"minDisabled\"\n (click)=\"selectMinuteEnd(min)\">\n {{ min | number: '2.0-0' }}\n </button>\n }\n </div>\n </ng-scrollbar>\n </div>\n }\n @if (zShowSecond()) {\n <div\n class=\"flex flex-col\"\n [class.border-r]=\"zTimeFormat() === '12h'\"\n [class.border-border]=\"zTimeFormat() === '12h'\">\n <div\n class=\"text-muted-foreground border-b-border flex h-7 shrink-0 items-center justify-center border-b text-xs font-medium select-none\">\n {{ 'i18n_z_ui_calendar_second' | translate }}\n </div>\n <ng-scrollbar\n class=\"z-time-scroll-second-end h-[11rem] w-14\"\n [class.rounded-br-sm]=\"zTimeFormat() !== '12h'\"\n [class.rounded-bl-sm]=\"!zShowHour() && !zShowMinute() && zTimeFormat() !== '12h'\"\n track=\"vertical\">\n <div class=\"flex flex-col\">\n @for (sec of secondOptions; track sec) {\n @let secDisabled = sec | zIsEndSecondDisabled: endTimeContext();\n @let secEndSelected = sec === secondEnd();\n <button\n type=\"button\"\n class=\"flex h-7 shrink-0 items-center justify-center text-sm transition-colors\"\n [class.hover:bg-muted]=\"!secDisabled && !secEndSelected\"\n [class.cursor-pointer]=\"!secDisabled\"\n [class.bg-primary]=\"secEndSelected\"\n [class.text-primary-foreground]=\"secEndSelected\"\n [class.font-medium]=\"secEndSelected\"\n [class.opacity-30]=\"secDisabled\"\n [class.cursor-not-allowed]=\"secDisabled\"\n [disabled]=\"secDisabled\"\n (click)=\"selectSecondEnd(sec)\">\n {{ sec | number: '2.0-0' }}\n </button>\n }\n </div>\n </ng-scrollbar>\n </div>\n }\n @if (zTimeFormat() === '12h') {\n <div class=\"flex flex-col\">\n <div\n class=\"text-muted-foreground border-b-border flex h-7 shrink-0 items-center justify-center border-b text-xs font-medium select-none\">\n {{ 'i18n_z_ui_calendar_period' | translate }}\n </div>\n <ng-scrollbar class=\"z-time-scroll-period-end h-[11rem] w-14\" [class.rounded-br-sm]=\"true\" track=\"vertical\">\n <div class=\"flex flex-col\">\n @for (p of ['AM', 'PM']; track p) {\n @let pSelected = p === periodEnd();\n <button\n type=\"button\"\n class=\"flex h-7 shrink-0 cursor-pointer items-center justify-center text-sm transition-colors\"\n [class.hover:bg-muted]=\"!pSelected\"\n [class.bg-primary]=\"pSelected\"\n [class.text-primary-foreground]=\"pSelected\"\n [class.font-medium]=\"pSelected\"\n (click)=\"selectPeriodEnd($any(p))\">\n {{ p }}\n </button>\n }\n </div>\n </ng-scrollbar>\n </div>\n }\n </div>\n</ng-template>\n", styles: [".animate-calendar-enter{animation:z-calendar-view-enter .2s ease-out}@keyframes z-calendar-view-enter{0%{opacity:0;transform:scale(.95) translateY(.25rem)}to{opacity:1;transform:scale(1) translateY(0)}}.z-calendar input{text-overflow:ellipsis;overflow:hidden}\n"], dependencies: [{ kind: "ngmodule", type: FormsModule }, { kind: "directive", type: i1.NgControlStatus, selector: "[formControlName],[ngModel],[formControl]" }, { kind: "directive", type: i1.NgModel, selector: "[ngModel]:not([formControlName]):not([formControl])", inputs: ["name", "disabled", "ngModel", "ngModelOptions"], outputs: ["ngModelChange"], exportAs: ["ngModel"] }, { kind: "directive", type: NgTemplateOutlet, selector: "[ngTemplateOutlet]", inputs: ["ngTemplateOutletContext", "ngTemplateOutlet", "ngTemplateOutletInjector"] }, { kind: "component", type: NgScrollbar, selector: "ng-scrollbar:not([externalViewport]), [ngScrollbar]", exportAs: ["ngScrollbar"] }, { kind: "component", type: ZIconComponent, selector: "z-icon, [z-icon]", inputs: ["class", "zType", "zAnimatedType", "zAnimate", "zAnimationTrigger", "zSize", "zStrokeWidth", "zSvg"] }, { kind: "component", type: ZSelectComponent, selector: "z-select", inputs: ["class", "zMode", "zSize", "zLabel", "zLabelClass", "zPlaceholder", "zRequired", "zDisabled", "zReadonly", "zLoading", "zPrefix", "zAllowClear", "zWrap", "zShowSearch", "zPlaceholderSearch", "zDebounce", "zNotFoundText", "zEmptyText", "zEmptyIcon", "zMaxTagCount", "zDropdownMaxHeight", "zOptionHeight", "zVirtualScroll", "zShowAction", "zOptions", "zConfig", "zTranslateLabels", "zKey", "zSearchServer", "zLoadingMore", "zEnableLoadMore", "zScrollDistance", "zMaxVisible", "zScrollClose", "zPosition", "zSelectedTemplate", "zOptionTemplate", "zActionTemplate", "zAsyncValidators", "zAsyncDebounce", "zAsyncValidateOn", "zValidators"], outputs: ["zOnSearch", "zOnLoadMore", "zOnBlur", "zOnFocus", "zControl", "zEvent"], exportAs: ["zSelect"] }, { kind: "directive", type: ZTooltipDirective, selector: "[z-tooltip], [zTooltip]", inputs: ["zContent", "zPosition", "zTooltipPosition", "zTrigger", "zTooltipTrigger", "zTooltipType", "zTooltipSize", "zClass", "zTooltipClass", "zShowDelay", "zTooltipShowDelay", "zHideDelay", "zTooltipHideDelay", "zArrow", "zTooltipArrow", "zDisabled", "zTooltipDisabled", "zOffset", "zTooltipOffset", "zAutoDetect", "zTriggerElement", "zAlwaysShow", "zMaxWidth"], outputs: ["zShow", "zHide"], exportAs: ["zTooltip"] }, { kind: "directive", type: ZPopoverDirective, selector: "[z-popover]", inputs: ["zPopoverContent", "zPosition", "zTrigger", "zPopoverTrigger", "zClass", "zShowDelay", "zHideDelay", "zDisabled", "zOffset", "zPopoverWidth", "zTriggerRef", "zManualClose", "zOutsideClickClose", "zScrollClose", "zShowArrow"], outputs: ["zShow", "zHide", "zHideStart", "zControl", "zPositionChange", "zOutsideClick"], exportAs: ["zPopover"] }, { kind: "component", type: ZButtonComponent, selector: "z-button, button[z-button], a[z-button]", inputs: ["class", "zType", "zSize", "zShape", "zLabel", "zLoading", "zDisabled", "zTypeIcon", "zAnimatedTypeIcon", "zAnimateIcon", "zAnimationTriggerIcon", "zSizeIcon", "zStrokeWidthIcon", "zWave"], exportAs: ["zButton"] }, { kind: "pipe", type: DecimalPipe, name: "number" }, { kind: "pipe", type: ZDayClassesPipe, name: "zDayClasses" }, { kind: "pipe", type: ZMonthClassesPipe, name: "zMonthClasses" }, { kind: "pipe", type: ZQuarterClassesPipe, name: "zQuarterClasses" }, { kind: "pipe", type: ZYearClassesPipe, name: "zYearClasses" }, { kind: "pipe", type: ZIsPresetDisabledPipe, name: "zIsPresetDisabled" }, { kind: "pipe", type: ZIsEndHourDisabledPipe, name: "zIsEndHourDisabled" }, { kind: "pipe", type: ZIsEndMinuteDisabledPipe, name: "zIsEndMinuteDisabled" }, { kind: "pipe", type: ZIsEndSecondDisabledPipe, name: "zIsEndSecondDisabled" }, { kind: "pipe", type: ZIsStartMonthDisabledPipe, name: "zIsStartMonthDisabled" }, { kind: "pipe", type: ZIsEndMonthDisabledPipe, name: "zIsEndMonthDisabled" }, { kind: "pipe", type: ZIsStartYearDisabledPipe, name: "zIsStartYearDisabled" }, { kind: "pipe", type: ZIsEndYearDisabledPipe, name: "zIsEndYearDisabled" }, { kind: "pipe", type: TranslatePipe, name: "translate" }], changeDetection: i0.ChangeDetectionStrategy.OnPush, encapsulation: i0.ViewEncapsulation.None });
|
|
3122
3264
|
}
|
|
3123
3265
|
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.0.9", ngImport: i0, type: ZCalendarComponent, decorators: [{
|
|
3124
3266
|
type: Component,
|
|
@@ -3154,7 +3296,7 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.0.9", ngImpor
|
|
|
3154
3296
|
TranslatePipe,
|
|
3155
3297
|
], changeDetection: ChangeDetectionStrategy.OnPush, encapsulation: ViewEncapsulation.None, host: {
|
|
3156
3298
|
class: 'block min-w-0',
|
|
3157
|
-
}, exportAs: 'zCalendar', template: "<div class=\"z-calendar-wrapper flex w-full flex-col gap-2\">\n @if (zLabel()) {\n <label [for]=\"pickerId\" class=\"text-xs leading-none font-medium\" [class]=\"zLabelClass()\">\n {{ zLabel() }}\n @if (zRequired()) {\n <span class=\"text-destructive! ml-0.5\">*</span>\n }\n </label>\n }\n\n <div class=\"relative\">\n <div\n #triggerEl\n z-popover\n [zPopoverContent]=\"calendarTpl\"\n zPosition=\"bottom-left\"\n zPopoverWidth=\"auto\"\n [zOffset]=\"6\"\n [zDisabled]=\"isDisabled() || zReadonly()\"\n [zManualClose]=\"showCancelButton()\"\n [zScrollClose]=\"zScrollClose()\"\n zTrigger=\"click\"\n zClass=\"border-0 shadow-none p-0\"\n (zHideStart)=\"onPopoverHide()\"\n (zShow)=\"onPopoverShow()\"\n (zControl)=\"onPopoverControl($event)\"\n [id]=\"pickerId\"\n [class]=\"triggerClasses()\"\n z-tooltip\n [zContent]=\"displayValue()\"\n zTooltipTrigger=\"hover\"\n zTooltipPosition=\"top\"\n [zTooltipDisabled]=\"isInputFocused() || isOpen() || !hasValue()\"\n (keydown)=\"onTriggerKeydown($event)\">\n <z-icon\n [zType]=\"isRangeMode() ? 'lucideCalendarRange' : 'lucideCalendar'\"\n zSize=\"16\"\n class=\"text-muted-foreground shrink-0 cursor-pointer\"\n (click)=\"$event.stopPropagation(); toggle()\" />\n\n @if (isRangeMode()) {\n <input\n type=\"text\"\n data-range-type=\"start\"\n class=\"placeholder:text-muted-foreground w-0 min-w-0 flex-1 truncate bg-transparent text-sm outline-none disabled:opacity-100\"\n [class.cursor-pointer]=\"!zAllowEdit()\"\n [class.pointer-events-none]=\"!zAllowEdit()\"\n [class.text-center]=\"!rangeShortDisplayValue()\"\n [class.text-left]=\"rangeShortDisplayValue()\"\n [placeholder]=\"'i18n_z_ui_calendar_start_date' | translate\"\n [value]=\"inputDisplayStart()\"\n [disabled]=\"isDisabled()\"\n [readonly]=\"zReadonly() || !zAllowEdit()\"\n (click)=\"zAllowEdit() && isOpen() && $event.stopPropagation()\"\n (focus)=\"onInputFocus($event)\"\n (input)=\"onStartInputChange($event)\"\n (blur)=\"onInputBlur($event)\"\n (keydown.enter)=\"onStartInputEnter($event)\"\n (keydown.escape)=\"onStartInputEscape()\" />\n @if (!rangeShortDisplayValue()) {\n <span class=\"text-muted-foreground text-sm\">-</span>\n <input\n type=\"text\"\n data-range-type=\"end\"\n class=\"placeholder:text-muted-foreground w-0 min-w-0 flex-1 truncate bg-transparent text-center text-sm outline-none disabled:opacity-100\"\n [class.cursor-pointer]=\"!zAllowEdit()\"\n [class.pointer-events-none]=\"!zAllowEdit()\"\n [placeholder]=\"'i18n_z_ui_calendar_end_date' | translate\"\n [value]=\"inputDisplayEnd()\"\n [disabled]=\"isDisabled()\"\n [readonly]=\"zReadonly() || !zAllowEdit()\"\n (click)=\"zAllowEdit() && isOpen() && $event.stopPropagation()\"\n (focus)=\"onInputFocus($event)\"\n (input)=\"onEndInputChange($event)\"\n (blur)=\"onInputBlur($event)\"\n (keydown.enter)=\"onEndInputEnter($event)\"\n (keydown.escape)=\"onEndInputEscape()\" />\n }\n } @else {\n <input\n #inputEl\n type=\"text\"\n class=\"placeholder:text-muted-foreground w-0 min-w-0 flex-1 truncate bg-transparent text-sm outline-none disabled:opacity-100\"\n [class.cursor-pointer]=\"!zAllowEdit()\"\n [class.pointer-events-none]=\"!zAllowEdit()\"\n [placeholder]=\"effectivePlaceholder()\"\n [value]=\"inputDisplayValue()\"\n [disabled]=\"isDisabled()\"\n [readonly]=\"zReadonly() || !zAllowEdit()\"\n (click)=\"zAllowEdit() && isOpen() && $event.stopPropagation()\"\n (focus)=\"onInputFocus($event)\"\n (input)=\"onInputChange($event)\"\n (blur)=\"onInputBlur($event)\"\n (keydown.enter)=\"onInputEnter($event)\"\n (keydown.escape)=\"onInputEscape()\" />\n }\n\n @if (zAllowClear() && !isDisabled() && !zReadonly()) {\n <button\n type=\"button\"\n tabindex=\"-1\"\n class=\"text-muted-foreground hover:text-foreground flex size-5 shrink-0 cursor-pointer items-center justify-center rounded-sm transition-all\"\n [class.opacity-0]=\"!hasValue()\"\n [class.pointer-events-none]=\"!hasValue()\"\n (click)=\"onClear($event)\">\n <z-icon zType=\"lucideX\" zSize=\"18\" />\n </button>\n }\n </div>\n </div>\n\n @if (hasError()) {\n <p class=\"text-destructive animate-in fade-in slide-in-from-top-1 m-0 text-xs duration-200\">\n {{ errorMessage() }}\n </p>\n }\n</div>\n\n<ng-template #calendarTpl>\n <div\n class=\"z-calendar-calendar bg-popover border-border flex max-h-[50dvh] max-w-[calc(100vw-1.5rem)] flex-col overflow-hidden rounded-sm border shadow-lg min-[480px]:max-h-[55dvh] sm:max-h-none sm:max-w-none sm:flex-row sm:overflow-visible\"\n (keydown)=\"onCalendarKeydown($event)\">\n @if (zQuickSelect() && zMode() === 'range') {\n <div class=\"border-border hidden shrink-0 flex-col gap-0 space-y-1 overflow-y-auto border-r p-2 sm:flex\">\n @for (preset of quickSelectPresets; track preset.key) {\n @let presetDisabled = preset | zIsPresetDisabled: zDisabledDate();\n <button\n type=\"button\"\n class=\"cursor-pointer rounded-sm px-3 py-1.5 text-left text-sm whitespace-nowrap transition-colors\"\n [class.hover:bg-muted]=\"activePresetKey() !== preset.key && !presetDisabled\"\n [class.bg-primary]=\"activePresetKey() === preset.key\"\n [class.text-primary-foreground]=\"activePresetKey() === preset.key\"\n [class.font-medium]=\"activePresetKey() === preset.key\"\n [class.opacity-40]=\"presetDisabled\"\n [class.cursor-not-allowed]=\"presetDisabled\"\n [disabled]=\"presetDisabled\"\n (click)=\"onQuickSelect(preset)\">\n {{ preset.label | translate }}\n </button>\n }\n </div>\n }\n <div\n class=\"flex min-h-0 flex-1 flex-col items-center overflow-hidden pb-0 sm:overflow-visible sm:py-2\"\n [class.sm:pt-0!]=\"isTimeMode()\"\n [class]=\"\n !isRangeMode()\n ? 'w-[17.75rem] max-w-[calc(100vw-1.5rem)]'\n : 'w-[17.75rem] max-w-[calc(100vw-1.5rem)] sm:w-auto sm:max-w-none'\n \">\n @if (zQuickSelect() && zMode() === 'range') {\n <div class=\"border-border w-full border-b px-2 pt-2 pb-2 sm:hidden\">\n <z-select\n class=\"w-full\"\n zSize=\"sm\"\n zPosition=\"bottom-left\"\n [zShowSearch]=\"false\"\n [zAllowClear]=\"false\"\n [zOptions]=\"quickSelectOptions()\"\n [ngModel]=\"activePresetKey()\"\n [ngModelOptions]=\"{ standalone: true }\"\n (ngModelChange)=\"onQuickSelectKeyChange($event)\" />\n </div>\n }\n <div class=\"min-h-0 w-full flex-1 overflow-x-hidden overflow-y-auto pt-2 sm:overflow-visible sm:pt-0\">\n @if (!isTimeMode()) {\n <div\n class=\"z-calendars-wrapper flex w-full flex-col items-center gap-0 sm:flex-row sm:items-stretch sm:justify-center\">\n <!-- First Calendar -->\n <div class=\"z-calendar-section flex w-[17.5rem] shrink-0 flex-col\">\n @if (!isTimeMode()) {\n <!-- Header -->\n <div class=\"border-border flex w-full items-center justify-between gap-0.5 px-2\">\n <!-- Double left arrow (always visible) -->\n <button\n type=\"button\"\n z-button\n zType=\"ghost\"\n zSize=\"sm\"\n class=\"size-7 shrink-0 p-0!\"\n [zWave]=\"false\"\n (click)=\"navigatePreviousFast()\">\n <z-icon zType=\"lucideChevronsLeft\" zSize=\"18\" />\n </button>\n\n <!-- Single left arrow (hidden in month/year view) -->\n @if (currentView() === 'day') {\n <button\n type=\"button\"\n z-button\n zType=\"ghost\"\n zSize=\"sm\"\n class=\"size-7 shrink-0 p-0!\"\n [zWave]=\"false\"\n (click)=\"navigatePrevious()\">\n <z-icon zType=\"lucideChevronLeft\" zSize=\"18\" />\n </button>\n }\n\n <!-- Header content -->\n <div class=\"flex flex-1 shrink-0 items-center justify-center gap-0\">\n @if (currentView() === 'day') {\n <!-- Day view: Month + Year -->\n @if (!isYearMode() && !isQuarterMode()) {\n <button\n type=\"button\"\n z-button\n zType=\"ghost\"\n zSize=\"sm\"\n class=\"h-7 px-1.5 text-sm!\"\n [zWave]=\"false\"\n (click)=\"setView('month')\">\n {{ currentMonthName() }}\n </button>\n }\n <button\n type=\"button\"\n z-button\n zType=\"ghost\"\n zSize=\"sm\"\n class=\"h-7 px-1.5 text-sm!\"\n [zWave]=\"false\"\n [zDisabled]=\"isYearMode()\"\n (click)=\"setView('year')\">\n {{ currentYear() }}\n </button>\n } @else if (currentView() === 'month') {\n <!-- Month view: Only Year -->\n <button\n type=\"button\"\n z-button\n zType=\"ghost\"\n zSize=\"sm\"\n class=\"h-7 px-1.5 text-sm!\"\n [zWave]=\"false\"\n (click)=\"setView('year')\">\n {{ currentYear() }}\n </button>\n } @else if (currentView() === 'year') {\n <!-- Year view: Year Range -->\n <span class=\"text-sm font-medium\">\n {{ yearRange()[0] }} - {{ yearRange()[yearRange().length - 1] }}\n </span>\n } @else if (currentView() === 'quarter') {\n <!-- Quarter view: Only Year -->\n <button\n type=\"button\"\n z-button\n zType=\"ghost\"\n zSize=\"sm\"\n class=\"h-7 px-1.5 text-sm!\"\n [zWave]=\"false\"\n (click)=\"setView('year')\">\n {{ currentYear() }}\n </button>\n }\n </div>\n\n <!-- Single right arrow (hidden in month/year view) -->\n @if (currentView() === 'day') {\n <button\n type=\"button\"\n z-button\n zType=\"ghost\"\n zSize=\"sm\"\n class=\"size-7 shrink-0 p-0!\"\n [zDisabled]=\"!canNavigateStartNext()\"\n [zWave]=\"false\"\n (click)=\"navigateNext()\">\n <z-icon zType=\"lucideChevronRight\" zSize=\"18\" />\n </button>\n }\n\n <!-- Double right arrow (always visible) -->\n <button\n type=\"button\"\n z-button\n zType=\"ghost\"\n zSize=\"sm\"\n class=\"size-7 shrink-0 p-0!\"\n [zDisabled]=\"!canNavigateStartNext()\"\n [zWave]=\"false\"\n (click)=\"navigateNextFast()\">\n <z-icon zType=\"lucideChevronsRight\" zSize=\"18\" />\n </button>\n </div>\n\n <!-- Body -->\n <div\n class=\"flex h-full w-full flex-col items-center justify-center p-2\"\n [class.min-h-[14rem]]=\"!isQuarterMode()\"\n [class.h-[14rem]]=\"\n !isYearMode() &&\n !isMonthMode() &&\n !isQuarterMode() &&\n (currentView() === 'month' || currentView() === 'year')\n \"\n [class.min-h-[6.25rem]]=\"isQuarterMode()\"\n [class.!min-h-auto]=\"isYearMode() || isMonthMode() || isQuarterMode()\"\n [class.!h-auto]=\"isYearMode() || isMonthMode() || isQuarterMode()\">\n @if (currentView() === 'day') {\n <div\n class=\"flex h-full w-full flex-1 flex-col gap-1\"\n [class.animate-calendar-enter]=\"uiState().hasViewChanged\">\n <!-- Weekday headers -->\n <div class=\"flex w-full flex-1 justify-center gap-1\">\n @for (weekday of weekdayNames(); track weekday) {\n <div\n class=\"text-muted-foreground flex h-[1.875rem] w-[2.0313rem] items-center justify-center text-xs font-medium\">\n {{ weekday }}\n </div>\n }\n </div>\n\n <!-- Date rows -->\n @for (week of calendarDays(); track $index) {\n <div class=\"flex w-full flex-1 justify-center gap-1\">\n @for (day of week; track day.date.getTime()) {\n <button\n type=\"button\"\n [class]=\"day | zDayClasses\"\n class=\"h-[1.875rem] !w-[2.0313rem] !text-sm\"\n [disabled]=\"day.isDisabled\"\n (click)=\"onDayClick(day)\"\n (mouseenter)=\"onDayHover(day)\"\n (mouseleave)=\"onDayLeave()\">\n {{ day.day }}\n </button>\n }\n </div>\n }\n </div>\n }\n @if (currentView() === 'month') {\n <div\n class=\"grid h-full w-full grid-cols-3 grid-rows-4 gap-2.5 gap-y-5!\"\n [class.animate-calendar-enter]=\"uiState().hasViewChanged\">\n @for (month of monthNames(); track month; let i = $index) {\n @let monthDisabled = i | zIsStartMonthDisabled: startMonthDisabledContext();\n <div class=\"flex flex-1 items-center justify-center\">\n <button\n type=\"button\"\n [class]=\"i | zMonthClasses: selectedMonthIndex() : todayMonthIndex()\"\n class=\"!h-7 !w-full !text-sm\"\n [disabled]=\"monthDisabled\"\n [class.opacity-30]=\"monthDisabled\"\n [class.cursor-not-allowed]=\"monthDisabled\"\n (click)=\"onMonthSelect(i)\">\n {{ month }}\n </button>\n </div>\n }\n </div>\n }\n\n @if (currentView() === 'year') {\n <div\n class=\"grid h-full w-full grid-cols-3 grid-rows-4 gap-2.5 gap-y-5!\"\n [class.animate-calendar-enter]=\"uiState().hasViewChanged\">\n @for (year of yearRange(); track year) {\n @let yearDisabled = year | zIsStartYearDisabled: startYearDisabledContext();\n <div class=\"flex flex-1 items-center justify-center\">\n <button\n type=\"button\"\n [class]=\"year | zYearClasses: selectedYear() : todayYear()\"\n class=\"!h-7 !w-full !text-sm\"\n [disabled]=\"yearDisabled\"\n [class.opacity-30]=\"yearDisabled\"\n [class.cursor-not-allowed]=\"yearDisabled\"\n (click)=\"onYearClick(year)\">\n {{ year }}\n </button>\n </div>\n }\n </div>\n }\n\n @if (currentView() === 'quarter') {\n <div\n class=\"grid h-full w-full grid-cols-2 grid-rows-2 gap-2 p-1\"\n [class.animate-calendar-enter]=\"uiState().hasViewChanged\">\n @for (quarter of quarterNames; track quarter; let i = $index) {\n <div class=\"flex flex-1 items-center justify-center\">\n <button\n type=\"button\"\n [class]=\"i | zQuarterClasses: selectedQuarterIndex() : todayQuarterIndex()\"\n class=\"!h-8 !w-full !text-sm\"\n (click)=\"onQuarterClick(i)\">\n {{ quarter }}\n </button>\n </div>\n }\n </div>\n }\n </div>\n }\n </div>\n\n <!-- Second Calendar (Range Mode Only) -->\n @if (isRangeMode()) {\n <!-- Divider -->\n <div\n class=\"border-border bg-border mb-2 hidden self-stretch sm:block sm:w-px\"\n [class.mb-2]=\"!zQuickSelect() || (zQuickSelect() && zShowOk())\"></div>\n <div class=\"border-border bg-border block h-px w-full sm:hidden\"></div>\n\n <div class=\"z-calendar-section flex w-[17.5rem] shrink-0 flex-col pt-2 sm:pt-0\">\n <!-- Header -->\n <div class=\"border-border flex w-full items-center justify-between gap-0.5 px-2\">\n <button\n type=\"button\"\n z-button\n zType=\"ghost\"\n zSize=\"sm\"\n class=\"size-7 shrink-0 p-0!\"\n [zDisabled]=\"!canNavigateEndPrev()\"\n [zWave]=\"false\"\n (click)=\"navigateEndPreviousFast()\">\n <z-icon zType=\"lucideChevronsLeft\" zSize=\"18\" />\n </button>\n\n <button\n type=\"button\"\n z-button\n zType=\"ghost\"\n zSize=\"sm\"\n class=\"size-7 shrink-0 p-0!\"\n [zDisabled]=\"!canNavigateEndPrev()\"\n [zWave]=\"false\"\n (click)=\"navigateEndPrevious()\">\n <z-icon zType=\"lucideChevronLeft\" zSize=\"18\" />\n </button>\n\n <div class=\"flex w-[7.5rem] shrink-0 items-center justify-center gap-0\">\n <button\n type=\"button\"\n z-button\n zType=\"ghost\"\n zSize=\"sm\"\n class=\"h-7 px-1.5 text-sm!\"\n [zWave]=\"false\"\n (click)=\"setEndView('month')\">\n {{ endMonthName() }}\n </button>\n\n <button\n type=\"button\"\n z-button\n zType=\"ghost\"\n zSize=\"sm\"\n class=\"h-7 px-1.5 text-sm!\"\n [zWave]=\"false\"\n (click)=\"setEndView('year')\">\n {{ endMonthYear() }}\n </button>\n </div>\n\n <button\n type=\"button\"\n z-button\n zType=\"ghost\"\n zSize=\"sm\"\n class=\"size-7 shrink-0 p-0!\"\n [zWave]=\"false\"\n [zWave]=\"false\"\n (click)=\"navigateEndNext()\">\n <z-icon zType=\"lucideChevronRight\" zSize=\"18\" />\n </button>\n\n <button\n type=\"button\"\n z-button\n zType=\"ghost\"\n zSize=\"sm\"\n class=\"size-7 shrink-0 p-0!\"\n [zWave]=\"false\"\n [zWave]=\"false\"\n (click)=\"navigateEndNextFast()\">\n <z-icon zType=\"lucideChevronsRight\" zSize=\"18\" />\n </button>\n </div>\n\n <!-- Body -->\n <div\n class=\"flex h-full min-h-[14rem] w-full flex-col items-center justify-center p-2\"\n [class.h-[14rem]]=\"endView() === 'month' || endView() === 'year'\">\n @if (endView() === 'day') {\n <div\n class=\"flex h-full w-full flex-1 flex-col gap-1\"\n [class.animate-calendar-enter]=\"uiState().hasEndViewChanged\">\n <!-- Weekday headers -->\n <div class=\"flex w-full flex-1 justify-center gap-1\">\n @for (weekday of weekdayNames(); track weekday) {\n <div\n class=\"text-muted-foreground flex h-[1.875rem] w-[2.0313rem] items-center justify-center text-xs font-medium\">\n {{ weekday }}\n </div>\n }\n </div>\n\n <!-- Date rows -->\n @for (week of calendarDaysEnd(); track $index) {\n <div class=\"flex w-full flex-1 justify-center gap-1\">\n @for (day of week; track day.date.getTime()) {\n <button\n type=\"button\"\n [class]=\"day | zDayClasses\"\n class=\"h-[1.875rem] !w-[2.0313rem] !text-sm\"\n [disabled]=\"day.isDisabled\"\n (click)=\"onDayClick(day)\"\n (mouseenter)=\"onDayHover(day)\"\n (mouseleave)=\"onDayLeave()\">\n {{ day.day }}\n </button>\n }\n </div>\n }\n </div>\n }\n @if (endView() === 'month') {\n <div\n class=\"grid h-full w-full grid-cols-3 grid-rows-4 gap-2.5 gap-y-5!\"\n [class.animate-calendar-enter]=\"uiState().hasEndViewChanged\">\n @for (month of monthNames(); track month; let i = $index) {\n @let endMonthDisabled = i | zIsEndMonthDisabled: endMonthDisabledContext();\n <div class=\"flex flex-1 items-center justify-center\">\n <button\n type=\"button\"\n [class]=\"i | zMonthClasses: endMonth().getMonth() : -1\"\n class=\"!h-7 !w-full !text-sm\"\n [disabled]=\"endMonthDisabled\"\n [class.opacity-30]=\"endMonthDisabled\"\n [class.cursor-not-allowed]=\"endMonthDisabled\"\n (click)=\"onEndMonthClick(i)\">\n {{ month }}\n </button>\n </div>\n }\n </div>\n }\n\n @if (endView() === 'year') {\n <div\n class=\"grid h-full w-full grid-cols-3 grid-rows-4 gap-2.5 gap-y-5!\"\n [class.animate-calendar-enter]=\"uiState().hasEndViewChanged\">\n @for (year of endYearRange(); track year) {\n @let endYearDisabled = year | zIsEndYearDisabled: endYearDisabledContext();\n <div class=\"flex flex-1 items-center justify-center\">\n <button\n type=\"button\"\n [class]=\"year | zYearClasses: endMonth().getFullYear() : -1\"\n class=\"!h-7 !w-full !text-sm\"\n [disabled]=\"endYearDisabled\"\n [class.opacity-30]=\"endYearDisabled\"\n [class.cursor-not-allowed]=\"endYearDisabled\"\n (click)=\"onEndYearClick(year)\">\n {{ year }}\n </button>\n </div>\n }\n </div>\n }\n </div>\n </div>\n }\n </div>\n\n <!-- Compact Time Picker Below Calendar (Single Date) -->\n @if (!isRangeMode() && zShowTime()) {\n <div\n class=\"hover:bg-muted border-border flex w-full cursor-pointer items-center justify-center gap-1.5 border-t px-3 py-1.5 transition-colors\"\n z-popover\n [zPopoverContent]=\"timeDropdownTpl\"\n zPosition=\"bottom\"\n [zPopoverWidth]=\"240\"\n [zOffset]=\"4\"\n zTrigger=\"click\"\n zClass=\"border-border shadow-lg\"\n (zShow)=\"onTimeDropdownShow()\">\n <z-icon zType=\"lucideCalendarClock\" zSize=\"18\" class=\"text-muted-foreground mr-1 shrink-0\" />\n <span class=\"text-sm font-medium tabular-nums select-none\">\n @if (zShowHour()) {\n {{ formattedHour() }}\n }\n @if (zShowHour() && zShowMinute()) {\n <span class=\"text-muted-foreground\">:</span>\n }\n @if (zShowMinute()) {\n {{ formattedMinute() }}\n }\n @if (zShowMinute() && zShowSecond()) {\n <span class=\"text-muted-foreground\">:</span>\n }\n @if (zShowSecond()) {\n {{ formattedSecond() }}\n }\n @if (zTimeFormat() === '12h') {\n <span class=\"text-primary ml-0.5 font-semibold\">\n {{ period() }}\n </span>\n }\n </span>\n <z-icon zType=\"lucideChevronDown\" zSize=\"14\" class=\"text-muted-foreground shrink-0\" />\n </div>\n }\n\n <!-- Compact Time Pickers Below Calendars (Range Mode) -->\n @if (isRangeMode() && zShowTime()) {\n <div class=\"border-border flex w-full flex-col border-t sm:flex-row\">\n <!-- Start Time -->\n <div\n class=\"hover:bg-muted flex flex-1 cursor-pointer items-center justify-center gap-1.5 px-3 py-1.5 transition-colors\"\n z-popover\n [zPopoverContent]=\"timeDropdownTpl\"\n zPosition=\"bottom\"\n [zPopoverWidth]=\"240\"\n [zOffset]=\"4\"\n zTrigger=\"click\"\n zClass=\"border-border shadow-lg\"\n (zShow)=\"onTimeDropdownShow()\">\n <z-icon zType=\"lucideCalendarClock\" zSize=\"18\" class=\"text-muted-foreground mr-1 shrink-0\" />\n <span class=\"text-sm font-medium tabular-nums select-none\">\n @if (zShowHour()) {\n {{ formattedHour() }}\n }\n @if (zShowHour() && zShowMinute()) {\n <span class=\"text-muted-foreground\">:</span>\n }\n @if (zShowMinute()) {\n {{ formattedMinute() }}\n }\n @if (zShowMinute() && zShowSecond()) {\n <span class=\"text-muted-foreground\">:</span>\n }\n @if (zShowSecond()) {\n {{ formattedSecond() }}\n }\n @if (zTimeFormat() === '12h') {\n <span class=\"text-primary ml-0.5 font-semibold\">\n {{ period() }}\n </span>\n }\n </span>\n <z-icon zType=\"lucideChevronDown\" zSize=\"14\" class=\"text-muted-foreground shrink-0\" />\n </div>\n\n <!-- Divider -->\n <div class=\"border-border bg-border h-px self-stretch sm:block sm:h-full sm:w-px\"></div>\n\n <!-- End Time -->\n <div\n class=\"hover:bg-muted flex flex-1 cursor-pointer items-center justify-center gap-1.5 px-3 py-1.5 transition-colors\"\n z-popover\n [zPopoverContent]=\"timeDropdownEndTpl\"\n zPosition=\"bottom\"\n [zPopoverWidth]=\"240\"\n [zOffset]=\"4\"\n zTrigger=\"click\"\n zClass=\"border-border shadow-lg\"\n (zShow)=\"onTimeDropdownEndShow()\">\n <z-icon zType=\"lucideCalendarClock\" zSize=\"18\" class=\"text-muted-foreground mr-1 shrink-0\" />\n <span class=\"text-sm font-medium tabular-nums select-none\">\n @if (zShowHour()) {\n {{ formattedHourEnd() }}\n }\n @if (zShowHour() && zShowMinute()) {\n <span class=\"text-muted-foreground\">:</span>\n }\n @if (zShowMinute()) {\n {{ formattedMinuteEnd() }}\n }\n @if (zShowMinute() && zShowSecond()) {\n <span class=\"text-muted-foreground\">:</span>\n }\n @if (zShowSecond()) {\n {{ formattedSecondEnd() }}\n }\n @if (zTimeFormat() === '12h') {\n <span class=\"text-primary ml-0.5 font-semibold\">\n {{ periodEnd() }}\n </span>\n }\n </span>\n <z-icon zType=\"lucideChevronDown\" zSize=\"14\" class=\"text-muted-foreground shrink-0\" />\n </div>\n </div>\n }\n } @else {\n <!-- Time Only Mode -->\n <div class=\"flex w-full justify-center px-2 pt-2 pb-1\">\n <ng-container [ngTemplateOutlet]=\"timeDropdownTpl\" />\n </div>\n }\n </div>\n\n @if (!(zQuickSelect() && zMode() === 'range' && !showOkButton() && !showCancelButton())) {\n <div\n class=\"bg-popover border-border z-10 flex w-full shrink-0 items-center justify-between gap-2 border-t px-2 py-2 shadow-[0_-2px_8px_-2px_rgb(0_0_0_/_10%)] sm:pt-2 sm:pb-0 sm:shadow-none\">\n @if (!zQuickSelect() || zMode() !== 'range') {\n <button type=\"button\" z-button zType=\"secondary\" zSize=\"sm\" [zWave]=\"false\" (click)=\"onTodayClick()\">\n {{ todayButtonText() }}\n </button>\n } @else {\n <div></div>\n }\n\n @if (showOkButton() || showCancelButton()) {\n <div class=\"flex items-center gap-2\">\n @if (showCancelButton()) {\n <button type=\"button\" z-button zType=\"outline\" zSize=\"sm\" (click)=\"onCancelClick()\">\n {{ zCancelText() ?? ('i18n_z_ui_calendar_cancel' | translate) }}\n </button>\n }\n @if (showOkButton()) {\n <button type=\"button\" z-button zSize=\"sm\" [zDisabled]=\"!canApply()\" (click)=\"onOkClick()\">\n {{ zOkText() ?? ('i18n_z_ui_calendar_ok' | translate) }}\n </button>\n }\n </div>\n }\n </div>\n }\n </div>\n </div>\n</ng-template>\n\n<ng-template #timeDropdownTpl>\n <div class=\"bg-popover flex min-w-56 justify-center overflow-hidden rounded-sm\">\n @if (zShowHour()) {\n <div\n class=\"flex flex-col\"\n [class.border-r]=\"zShowMinute() || zShowSecond() || zTimeFormat() === '12h'\"\n [class.border-border]=\"zShowMinute() || zShowSecond() || zTimeFormat() === '12h'\">\n <div\n class=\"text-muted-foreground border-b-border flex h-7 shrink-0 items-center justify-center border-b text-xs font-medium select-none\">\n {{ 'i18n_z_ui_calendar_hour' | translate }}\n </div>\n <ng-scrollbar\n class=\"z-time-scroll-hour h-[11rem] w-14\"\n [class.rounded-bl-sm]=\"!zShowMinute() && !zShowSecond() && zTimeFormat() !== '12h'\"\n [class.rounded-tl-sm]=\"zShowMinute() || zShowSecond() || zTimeFormat() === '12h'\"\n track=\"vertical\">\n <div class=\"flex flex-col\">\n @for (hr of hourOptions(); track hr) {\n @let hrSelected = hr === displayHour();\n <button\n type=\"button\"\n class=\"flex h-7 shrink-0 cursor-pointer items-center justify-center text-sm transition-colors\"\n [class.hover:bg-muted]=\"!hrSelected\"\n [class.bg-primary]=\"hrSelected\"\n [class.text-primary-foreground]=\"hrSelected\"\n [class.font-medium]=\"hrSelected\"\n (click)=\"selectHour(hr)\">\n {{ hr | number: '2.0-0' }}\n </button>\n }\n </div>\n </ng-scrollbar>\n </div>\n }\n @if (zShowMinute()) {\n <div\n class=\"flex flex-col\"\n [class.border-r]=\"zShowSecond() || zTimeFormat() === '12h'\"\n [class.border-border]=\"zShowSecond() || zTimeFormat() === '12h'\">\n <div\n class=\"text-muted-foreground border-b-border flex h-7 shrink-0 items-center justify-center border-b text-xs font-medium select-none\">\n {{ 'i18n_z_ui_calendar_minute' | translate }}\n </div>\n <ng-scrollbar\n class=\"z-time-scroll-minute h-[11rem] w-14\"\n [class.rounded-bl-sm]=\"!zShowHour() && !zShowSecond() && zTimeFormat() !== '12h'\"\n [class.rounded-tl-sm]=\"!zShowHour() && (zShowSecond() || zTimeFormat() === '12h')\"\n [class.rounded-br-sm]=\"(zShowHour() || !zShowHour()) && !zShowSecond() && zTimeFormat() !== '12h'\"\n track=\"vertical\">\n <div class=\"flex flex-col\">\n @for (min of minuteOptions; track min) {\n @let minSelected = min === minute();\n <button\n type=\"button\"\n class=\"flex h-7 shrink-0 cursor-pointer items-center justify-center text-sm transition-colors\"\n [class.hover:bg-muted]=\"!minSelected\"\n [class.bg-primary]=\"minSelected\"\n [class.text-primary-foreground]=\"minSelected\"\n [class.font-medium]=\"minSelected\"\n (click)=\"selectMinute(min)\">\n {{ min | number: '2.0-0' }}\n </button>\n }\n </div>\n </ng-scrollbar>\n </div>\n }\n @if (zShowSecond()) {\n <div\n class=\"flex flex-col\"\n [class.border-r]=\"zTimeFormat() === '12h'\"\n [class.border-border]=\"zTimeFormat() === '12h'\">\n <div\n class=\"text-muted-foreground border-b-border flex h-7 shrink-0 items-center justify-center border-b text-xs font-medium select-none\">\n {{ 'i18n_z_ui_calendar_second' | translate }}\n </div>\n <ng-scrollbar\n class=\"z-time-scroll-second h-[11rem] w-14\"\n [class.rounded-br-sm]=\"zTimeFormat() !== '12h'\"\n [class.rounded-bl-sm]=\"!zShowHour() && !zShowMinute() && zTimeFormat() !== '12h'\"\n track=\"vertical\">\n <div class=\"flex flex-col\">\n @for (sec of secondOptions; track sec) {\n @let secSelected = sec === second();\n <button\n type=\"button\"\n class=\"flex h-7 shrink-0 cursor-pointer items-center justify-center text-sm transition-colors\"\n [class.hover:bg-muted]=\"!secSelected\"\n [class.bg-primary]=\"secSelected\"\n [class.text-primary-foreground]=\"secSelected\"\n [class.font-medium]=\"secSelected\"\n (click)=\"selectSecond(sec)\">\n {{ sec | number: '2.0-0' }}\n </button>\n }\n </div>\n </ng-scrollbar>\n </div>\n }\n @if (zTimeFormat() === '12h') {\n <div class=\"flex flex-col\">\n <div\n class=\"text-muted-foreground border-b-border flex h-7 shrink-0 items-center justify-center border-b text-xs font-medium select-none\">\n {{ 'i18n_z_ui_calendar_period' | translate }}\n </div>\n <ng-scrollbar class=\"z-time-scroll-period h-[11rem] w-14\" [class.rounded-br-sm]=\"true\" track=\"vertical\">\n <div class=\"flex flex-col\">\n @for (p of ['AM', 'PM']; track p) {\n @let pSelected = p === period();\n <button\n type=\"button\"\n class=\"flex h-7 shrink-0 cursor-pointer items-center justify-center text-sm transition-colors\"\n [class.hover:bg-muted]=\"!pSelected\"\n [class.bg-primary]=\"pSelected\"\n [class.text-primary-foreground]=\"pSelected\"\n [class.font-medium]=\"pSelected\"\n (click)=\"selectPeriod($any(p))\">\n {{ p }}\n </button>\n }\n </div>\n </ng-scrollbar>\n </div>\n }\n </div>\n</ng-template>\n\n<ng-template #timeDropdownEndTpl>\n <div class=\"bg-popover flex min-w-56 justify-center overflow-hidden rounded-sm\">\n @if (zShowHour()) {\n <div\n class=\"flex flex-col\"\n [class.border-r]=\"zShowMinute() || zShowSecond() || zTimeFormat() === '12h'\"\n [class.border-border]=\"zShowMinute() || zShowSecond() || zTimeFormat() === '12h'\">\n <div\n class=\"text-muted-foreground border-b-border flex h-7 shrink-0 items-center justify-center border-b text-xs font-medium select-none\">\n {{ 'i18n_z_ui_calendar_hour' | translate }}\n </div>\n <ng-scrollbar\n class=\"z-time-scroll-hour-end h-[11rem] w-14\"\n [class.rounded-bl-sm]=\"!zShowMinute() && !zShowSecond() && zTimeFormat() !== '12h'\"\n [class.rounded-tl-sm]=\"zShowMinute() || zShowSecond() || zTimeFormat() === '12h'\"\n track=\"vertical\">\n <div class=\"flex flex-col\">\n @for (hr of hourOptions(); track hr) {\n @let hrDisabled = hr | zIsEndHourDisabled: endTimeContext();\n @let hrEndSelected = hr === displayHourEnd();\n <button\n type=\"button\"\n class=\"flex h-7 shrink-0 items-center justify-center text-sm transition-colors\"\n [class.hover:bg-muted]=\"!hrDisabled && !hrEndSelected\"\n [class.cursor-pointer]=\"!hrDisabled\"\n [class.bg-primary]=\"hrEndSelected\"\n [class.text-primary-foreground]=\"hrEndSelected\"\n [class.font-medium]=\"hrEndSelected\"\n [class.opacity-30]=\"hrDisabled\"\n [class.cursor-not-allowed]=\"hrDisabled\"\n [disabled]=\"hrDisabled\"\n (click)=\"selectHourEnd(hr)\">\n {{ hr | number: '2.0-0' }}\n </button>\n }\n </div>\n </ng-scrollbar>\n </div>\n }\n @if (zShowMinute()) {\n <div\n class=\"flex flex-col\"\n [class.border-r]=\"zShowSecond() || zTimeFormat() === '12h'\"\n [class.border-border]=\"zShowSecond() || zTimeFormat() === '12h'\">\n <div\n class=\"text-muted-foreground border-b-border flex h-7 shrink-0 items-center justify-center border-b text-xs font-medium select-none\">\n {{ 'i18n_z_ui_calendar_minute' | translate }}\n </div>\n <ng-scrollbar\n class=\"z-time-scroll-minute-end h-[11rem] w-14\"\n [class.rounded-bl-sm]=\"!zShowHour() && !zShowSecond() && zTimeFormat() !== '12h'\"\n [class.rounded-tl-sm]=\"!zShowHour() && (zShowSecond() || zTimeFormat() === '12h')\"\n [class.rounded-br-sm]=\"(zShowHour() || !zShowHour()) && !zShowSecond() && zTimeFormat() !== '12h'\"\n track=\"vertical\">\n <div class=\"flex flex-col\">\n @for (min of minuteOptions; track min) {\n @let minDisabled = min | zIsEndMinuteDisabled: endTimeContext();\n @let minEndSelected = min === minuteEnd();\n <button\n type=\"button\"\n class=\"flex h-7 shrink-0 items-center justify-center text-sm transition-colors\"\n [class.hover:bg-muted]=\"!minDisabled && !minEndSelected\"\n [class.cursor-pointer]=\"!minDisabled\"\n [class.bg-primary]=\"minEndSelected\"\n [class.text-primary-foreground]=\"minEndSelected\"\n [class.font-medium]=\"minEndSelected\"\n [class.opacity-30]=\"minDisabled\"\n [class.cursor-not-allowed]=\"minDisabled\"\n [disabled]=\"minDisabled\"\n (click)=\"selectMinuteEnd(min)\">\n {{ min | number: '2.0-0' }}\n </button>\n }\n </div>\n </ng-scrollbar>\n </div>\n }\n @if (zShowSecond()) {\n <div\n class=\"flex flex-col\"\n [class.border-r]=\"zTimeFormat() === '12h'\"\n [class.border-border]=\"zTimeFormat() === '12h'\">\n <div\n class=\"text-muted-foreground border-b-border flex h-7 shrink-0 items-center justify-center border-b text-xs font-medium select-none\">\n {{ 'i18n_z_ui_calendar_second' | translate }}\n </div>\n <ng-scrollbar\n class=\"z-time-scroll-second-end h-[11rem] w-14\"\n [class.rounded-br-sm]=\"zTimeFormat() !== '12h'\"\n [class.rounded-bl-sm]=\"!zShowHour() && !zShowMinute() && zTimeFormat() !== '12h'\"\n track=\"vertical\">\n <div class=\"flex flex-col\">\n @for (sec of secondOptions; track sec) {\n @let secDisabled = sec | zIsEndSecondDisabled: endTimeContext();\n @let secEndSelected = sec === secondEnd();\n <button\n type=\"button\"\n class=\"flex h-7 shrink-0 items-center justify-center text-sm transition-colors\"\n [class.hover:bg-muted]=\"!secDisabled && !secEndSelected\"\n [class.cursor-pointer]=\"!secDisabled\"\n [class.bg-primary]=\"secEndSelected\"\n [class.text-primary-foreground]=\"secEndSelected\"\n [class.font-medium]=\"secEndSelected\"\n [class.opacity-30]=\"secDisabled\"\n [class.cursor-not-allowed]=\"secDisabled\"\n [disabled]=\"secDisabled\"\n (click)=\"selectSecondEnd(sec)\">\n {{ sec | number: '2.0-0' }}\n </button>\n }\n </div>\n </ng-scrollbar>\n </div>\n }\n @if (zTimeFormat() === '12h') {\n <div class=\"flex flex-col\">\n <div\n class=\"text-muted-foreground border-b-border flex h-7 shrink-0 items-center justify-center border-b text-xs font-medium select-none\">\n {{ 'i18n_z_ui_calendar_period' | translate }}\n </div>\n <ng-scrollbar class=\"z-time-scroll-period-end h-[11rem] w-14\" [class.rounded-br-sm]=\"true\" track=\"vertical\">\n <div class=\"flex flex-col\">\n @for (p of ['AM', 'PM']; track p) {\n @let pSelected = p === periodEnd();\n <button\n type=\"button\"\n class=\"flex h-7 shrink-0 cursor-pointer items-center justify-center text-sm transition-colors\"\n [class.hover:bg-muted]=\"!pSelected\"\n [class.bg-primary]=\"pSelected\"\n [class.text-primary-foreground]=\"pSelected\"\n [class.font-medium]=\"pSelected\"\n (click)=\"selectPeriodEnd($any(p))\">\n {{ p }}\n </button>\n }\n </div>\n </ng-scrollbar>\n </div>\n }\n </div>\n</ng-template>\n", styles: [".animate-calendar-enter{animation:z-calendar-view-enter .2s ease-out}@keyframes z-calendar-view-enter{0%{opacity:0;transform:scale(.95) translateY(.25rem)}to{opacity:1;transform:scale(1) translateY(0)}}.z-calendar input{text-overflow:ellipsis;overflow:hidden}\n"] }]
|
|
3299
|
+
}, exportAs: 'zCalendar', template: "<div class=\"z-calendar-wrapper flex w-full flex-col gap-2\">\n @if (zLabel()) {\n <label [for]=\"pickerId\" class=\"text-xs leading-none font-medium\" [class]=\"zLabelClass()\">\n {{ zLabel() }}\n @if (zRequired()) {\n <span class=\"text-destructive! ml-0.5\">*</span>\n }\n </label>\n }\n\n <div class=\"relative\">\n <div\n #triggerEl\n z-popover\n [zPopoverContent]=\"calendarTpl\"\n zPosition=\"bottom-left\"\n zPopoverWidth=\"auto\"\n [zOffset]=\"6\"\n [zDisabled]=\"isDisabled() || zReadonly()\"\n [zManualClose]=\"showCancelButton()\"\n [zOutsideClickClose]=\"true\"\n [zScrollClose]=\"zScrollClose()\"\n zTrigger=\"click\"\n zClass=\"border-0 shadow-none p-0\"\n (zHideStart)=\"onPopoverHide()\"\n (zShow)=\"onPopoverShow()\"\n (zControl)=\"onPopoverControl($event)\"\n [id]=\"pickerId\"\n [class]=\"triggerClasses()\"\n z-tooltip\n [zContent]=\"displayValue()\"\n zTooltipTrigger=\"hover\"\n zTooltipPosition=\"top\"\n [zTooltipDisabled]=\"isInputFocused() || isOpen() || !hasValue()\"\n (keydown)=\"onTriggerKeydown($event)\">\n <z-icon\n [zType]=\"isRangeMode() ? 'lucideCalendarRange' : 'lucideCalendar'\"\n zSize=\"16\"\n class=\"text-muted-foreground shrink-0 cursor-pointer\"\n (click)=\"$event.stopPropagation(); toggle()\" />\n\n @if (isRangeMode()) {\n <input\n type=\"text\"\n data-range-type=\"start\"\n class=\"placeholder:text-muted-foreground w-0 min-w-0 flex-1 truncate bg-transparent text-sm outline-none disabled:opacity-100\"\n [class.cursor-pointer]=\"!zAllowEdit()\"\n [class.pointer-events-none]=\"!zAllowEdit()\"\n [class.text-center]=\"!rangeShortDisplayValue()\"\n [class.text-left]=\"rangeShortDisplayValue()\"\n [placeholder]=\"'i18n_z_ui_calendar_start_date' | translate\"\n [value]=\"inputDisplayStart()\"\n [disabled]=\"isDisabled()\"\n [readonly]=\"zReadonly() || !zAllowEdit()\"\n (click)=\"zAllowEdit() && isOpen() && $event.stopPropagation()\"\n (focus)=\"onInputFocus($event)\"\n (input)=\"onStartInputChange($event)\"\n (blur)=\"onInputBlur($event)\"\n (keydown.enter)=\"onStartInputEnter($event)\"\n (keydown.escape)=\"onStartInputEscape($event)\" />\n @if (!rangeShortDisplayValue()) {\n <span class=\"text-muted-foreground text-sm\">-</span>\n <input\n type=\"text\"\n data-range-type=\"end\"\n class=\"placeholder:text-muted-foreground w-0 min-w-0 flex-1 truncate bg-transparent text-center text-sm outline-none disabled:opacity-100\"\n [class.cursor-pointer]=\"!zAllowEdit()\"\n [class.pointer-events-none]=\"!zAllowEdit()\"\n [placeholder]=\"'i18n_z_ui_calendar_end_date' | translate\"\n [value]=\"inputDisplayEnd()\"\n [disabled]=\"isDisabled()\"\n [readonly]=\"zReadonly() || !zAllowEdit()\"\n (click)=\"zAllowEdit() && isOpen() && $event.stopPropagation()\"\n (focus)=\"onInputFocus($event)\"\n (input)=\"onEndInputChange($event)\"\n (blur)=\"onInputBlur($event)\"\n (keydown.enter)=\"onEndInputEnter($event)\"\n (keydown.escape)=\"onEndInputEscape($event)\" />\n }\n } @else {\n <input\n #inputEl\n type=\"text\"\n class=\"placeholder:text-muted-foreground w-0 min-w-0 flex-1 truncate bg-transparent text-sm outline-none disabled:opacity-100\"\n [class.cursor-pointer]=\"!zAllowEdit()\"\n [class.pointer-events-none]=\"!zAllowEdit()\"\n [placeholder]=\"effectivePlaceholder()\"\n [value]=\"inputDisplayValue()\"\n [disabled]=\"isDisabled()\"\n [readonly]=\"zReadonly() || !zAllowEdit()\"\n (click)=\"zAllowEdit() && isOpen() && $event.stopPropagation()\"\n (focus)=\"onInputFocus($event)\"\n (input)=\"onInputChange($event)\"\n (blur)=\"onInputBlur($event)\"\n (keydown.enter)=\"onInputEnter($event)\"\n (keydown.escape)=\"onInputEscape($event)\" />\n }\n\n @if (zAllowClear() && !isDisabled() && !zReadonly()) {\n <button\n type=\"button\"\n tabindex=\"-1\"\n class=\"text-muted-foreground hover:text-foreground flex size-5 shrink-0 cursor-pointer items-center justify-center rounded-sm transition-all\"\n [class.opacity-0]=\"!hasValue()\"\n [class.pointer-events-none]=\"!hasValue()\"\n (click)=\"onClear($event)\">\n <z-icon zType=\"lucideX\" zSize=\"18\" />\n </button>\n }\n </div>\n </div>\n\n @if (hasError()) {\n <p class=\"text-destructive animate-in fade-in slide-in-from-top-1 m-0 text-xs duration-200\">\n {{ errorMessage() }}\n </p>\n }\n</div>\n\n<ng-template #calendarTpl>\n <div\n class=\"z-calendar-calendar bg-popover border-border flex max-h-[50dvh] max-w-[calc(100vw-1.5rem)] flex-col overflow-hidden rounded-sm border shadow-lg min-[480px]:max-h-[55dvh] sm:max-h-none sm:max-w-none sm:flex-row sm:overflow-visible\"\n (keydown)=\"onCalendarKeydown($event)\">\n @if (zQuickSelect() && zMode() === 'range') {\n <div class=\"border-border hidden shrink-0 flex-col gap-0 space-y-1 overflow-y-auto border-r p-2 sm:flex\">\n @for (preset of quickSelectPresets; track preset.key) {\n @let presetDisabled = preset | zIsPresetDisabled: zDisabledDate();\n <button\n type=\"button\"\n class=\"cursor-pointer rounded-sm px-3 py-1.5 text-left text-sm whitespace-nowrap transition-colors\"\n [class.hover:bg-muted]=\"activePresetKey() !== preset.key && !presetDisabled\"\n [class.bg-primary]=\"activePresetKey() === preset.key\"\n [class.text-primary-foreground]=\"activePresetKey() === preset.key\"\n [class.font-medium]=\"activePresetKey() === preset.key\"\n [class.opacity-40]=\"presetDisabled\"\n [class.cursor-not-allowed]=\"presetDisabled\"\n [disabled]=\"presetDisabled\"\n (click)=\"onQuickSelect(preset)\">\n {{ preset.label | translate }}\n </button>\n }\n </div>\n }\n <div\n class=\"flex min-h-0 flex-1 flex-col items-center overflow-hidden pb-0 sm:overflow-visible sm:py-2\"\n [class.sm:pt-0!]=\"isTimeMode()\"\n [class]=\"\n !isRangeMode()\n ? 'w-[17.75rem] max-w-[calc(100vw-1.5rem)]'\n : 'w-[17.75rem] max-w-[calc(100vw-1.5rem)] sm:w-auto sm:max-w-none'\n \">\n @if (zQuickSelect() && zMode() === 'range') {\n <div class=\"border-border w-full border-b px-2 pt-2 pb-2 sm:hidden\">\n <z-select\n class=\"w-full\"\n zSize=\"sm\"\n zPosition=\"bottom-left\"\n [zShowSearch]=\"false\"\n [zAllowClear]=\"false\"\n [zOptions]=\"quickSelectOptions()\"\n [ngModel]=\"activePresetKey()\"\n [ngModelOptions]=\"{ standalone: true }\"\n (ngModelChange)=\"onQuickSelectKeyChange($event)\" />\n </div>\n }\n <div class=\"min-h-0 w-full flex-1 overflow-x-hidden overflow-y-auto pt-2 sm:overflow-visible sm:pt-0\">\n @if (!isTimeMode()) {\n <div\n class=\"z-calendars-wrapper flex w-full flex-col items-center gap-0 sm:flex-row sm:items-stretch sm:justify-center\">\n <!-- First Calendar -->\n <div class=\"z-calendar-section flex w-[17.5rem] shrink-0 flex-col\">\n @if (!isTimeMode()) {\n <!-- Header -->\n <div class=\"border-border flex w-full items-center justify-between gap-0.5 px-2\">\n <!-- Double left arrow (always visible) -->\n <button\n type=\"button\"\n z-button\n zType=\"ghost\"\n zSize=\"sm\"\n class=\"size-7 shrink-0 p-0!\"\n [zWave]=\"false\"\n (click)=\"navigatePreviousFast()\">\n <z-icon zType=\"lucideChevronsLeft\" zSize=\"18\" />\n </button>\n\n <!-- Single left arrow (hidden in month/year view) -->\n @if (currentView() === 'day') {\n <button\n type=\"button\"\n z-button\n zType=\"ghost\"\n zSize=\"sm\"\n class=\"size-7 shrink-0 p-0!\"\n [zWave]=\"false\"\n (click)=\"navigatePrevious()\">\n <z-icon zType=\"lucideChevronLeft\" zSize=\"18\" />\n </button>\n }\n\n <!-- Header content -->\n <div class=\"flex flex-1 shrink-0 items-center justify-center gap-0\">\n @if (currentView() === 'day') {\n <!-- Day view: Month + Year -->\n @if (!isYearMode() && !isQuarterMode()) {\n <button\n type=\"button\"\n z-button\n zType=\"ghost\"\n zSize=\"sm\"\n class=\"h-7 px-1.5 text-sm!\"\n [zWave]=\"false\"\n (click)=\"setView('month')\">\n {{ currentMonthName() }}\n </button>\n }\n <button\n type=\"button\"\n z-button\n zType=\"ghost\"\n zSize=\"sm\"\n class=\"h-7 px-1.5 text-sm!\"\n [zWave]=\"false\"\n [zDisabled]=\"isYearMode()\"\n (click)=\"setView('year')\">\n {{ currentYear() }}\n </button>\n } @else if (currentView() === 'month') {\n <!-- Month view: Only Year -->\n <button\n type=\"button\"\n z-button\n zType=\"ghost\"\n zSize=\"sm\"\n class=\"h-7 px-1.5 text-sm!\"\n [zWave]=\"false\"\n (click)=\"setView('year')\">\n {{ currentYear() }}\n </button>\n } @else if (currentView() === 'year') {\n <!-- Year view: Year Range -->\n <span class=\"text-sm font-medium\">\n {{ yearRange()[0] }} - {{ yearRange()[yearRange().length - 1] }}\n </span>\n } @else if (currentView() === 'quarter') {\n <!-- Quarter view: Only Year -->\n <button\n type=\"button\"\n z-button\n zType=\"ghost\"\n zSize=\"sm\"\n class=\"h-7 px-1.5 text-sm!\"\n [zWave]=\"false\"\n (click)=\"setView('year')\">\n {{ currentYear() }}\n </button>\n }\n </div>\n\n <!-- Single right arrow (hidden in month/year view) -->\n @if (currentView() === 'day') {\n <button\n type=\"button\"\n z-button\n zType=\"ghost\"\n zSize=\"sm\"\n class=\"size-7 shrink-0 p-0!\"\n [zDisabled]=\"!canNavigateStartNext()\"\n [zWave]=\"false\"\n (click)=\"navigateNext()\">\n <z-icon zType=\"lucideChevronRight\" zSize=\"18\" />\n </button>\n }\n\n <!-- Double right arrow (always visible) -->\n <button\n type=\"button\"\n z-button\n zType=\"ghost\"\n zSize=\"sm\"\n class=\"size-7 shrink-0 p-0!\"\n [zDisabled]=\"!canNavigateStartNext()\"\n [zWave]=\"false\"\n (click)=\"navigateNextFast()\">\n <z-icon zType=\"lucideChevronsRight\" zSize=\"18\" />\n </button>\n </div>\n\n <!-- Body -->\n <div\n class=\"flex h-full w-full flex-col items-center justify-center p-2\"\n [class.min-h-[14rem]]=\"!isQuarterMode()\"\n [class.h-[14rem]]=\"\n !isYearMode() &&\n !isMonthMode() &&\n !isQuarterMode() &&\n (currentView() === 'month' || currentView() === 'year')\n \"\n [class.min-h-[6.25rem]]=\"isQuarterMode()\"\n [class.!min-h-auto]=\"isYearMode() || isMonthMode() || isQuarterMode()\"\n [class.!h-auto]=\"isYearMode() || isMonthMode() || isQuarterMode()\">\n @if (currentView() === 'day') {\n <div\n class=\"flex h-full w-full flex-1 flex-col gap-1\"\n [class.animate-calendar-enter]=\"uiState().hasViewChanged\">\n <!-- Weekday headers -->\n <div class=\"flex w-full flex-1 justify-center gap-1\">\n @for (weekday of weekdayNames(); track weekday) {\n <div\n class=\"text-muted-foreground flex h-[1.875rem] w-[2.0313rem] items-center justify-center text-xs font-medium\">\n {{ weekday }}\n </div>\n }\n </div>\n\n <!-- Date rows -->\n @for (week of calendarDays(); track $index) {\n <div class=\"flex w-full flex-1 justify-center gap-1\">\n @for (day of week; track day.date.getTime()) {\n <button\n type=\"button\"\n [class]=\"day | zDayClasses\"\n class=\"h-[1.875rem] !w-[2.0313rem] !text-sm\"\n [disabled]=\"day.isDisabled\"\n (click)=\"onDayClick(day)\"\n (mouseenter)=\"onDayHover(day)\"\n (mouseleave)=\"onDayLeave()\">\n {{ day.day }}\n </button>\n }\n </div>\n }\n </div>\n }\n @if (currentView() === 'month') {\n <div\n class=\"grid h-full w-full grid-cols-3 grid-rows-4 gap-2.5 gap-y-5!\"\n [class.animate-calendar-enter]=\"uiState().hasViewChanged\">\n @for (month of monthNames(); track month; let i = $index) {\n @let monthDisabled = i | zIsStartMonthDisabled: startMonthDisabledContext();\n <div class=\"flex flex-1 items-center justify-center\">\n <button\n type=\"button\"\n [class]=\"i | zMonthClasses: selectedMonthIndex() : todayMonthIndex()\"\n class=\"!h-7 !w-full !text-sm\"\n [disabled]=\"monthDisabled\"\n [class.opacity-30]=\"monthDisabled\"\n [class.cursor-not-allowed]=\"monthDisabled\"\n (click)=\"onMonthSelect(i)\">\n {{ month }}\n </button>\n </div>\n }\n </div>\n }\n\n @if (currentView() === 'year') {\n <div\n class=\"grid h-full w-full grid-cols-3 grid-rows-4 gap-2.5 gap-y-5!\"\n [class.animate-calendar-enter]=\"uiState().hasViewChanged\">\n @for (year of yearRange(); track year) {\n @let yearDisabled = year | zIsStartYearDisabled: startYearDisabledContext();\n <div class=\"flex flex-1 items-center justify-center\">\n <button\n type=\"button\"\n [class]=\"year | zYearClasses: selectedYear() : todayYear()\"\n class=\"!h-7 !w-full !text-sm\"\n [disabled]=\"yearDisabled\"\n [class.opacity-30]=\"yearDisabled\"\n [class.cursor-not-allowed]=\"yearDisabled\"\n (click)=\"onYearClick(year)\">\n {{ year }}\n </button>\n </div>\n }\n </div>\n }\n\n @if (currentView() === 'quarter') {\n <div\n class=\"grid h-full w-full grid-cols-2 grid-rows-2 gap-2 p-1\"\n [class.animate-calendar-enter]=\"uiState().hasViewChanged\">\n @for (quarter of quarterNames; track quarter; let i = $index) {\n <div class=\"flex flex-1 items-center justify-center\">\n <button\n type=\"button\"\n [class]=\"i | zQuarterClasses: selectedQuarterIndex() : todayQuarterIndex()\"\n class=\"!h-8 !w-full !text-sm\"\n (click)=\"onQuarterClick(i)\">\n {{ quarter }}\n </button>\n </div>\n }\n </div>\n }\n </div>\n }\n </div>\n\n <!-- Second Calendar (Range Mode Only) -->\n @if (isRangeMode()) {\n <!-- Divider -->\n <div\n class=\"border-border bg-border mb-2 hidden self-stretch sm:block sm:w-px\"\n [class.mb-2]=\"!zQuickSelect() || (zQuickSelect() && zShowOk())\"></div>\n <div class=\"border-border bg-border block h-px w-full sm:hidden\"></div>\n\n <div class=\"z-calendar-section flex w-[17.5rem] shrink-0 flex-col pt-2 sm:pt-0\">\n <!-- Header -->\n <div class=\"border-border flex w-full items-center justify-between gap-0.5 px-2\">\n <button\n type=\"button\"\n z-button\n zType=\"ghost\"\n zSize=\"sm\"\n class=\"size-7 shrink-0 p-0!\"\n [zDisabled]=\"!canNavigateEndPrev()\"\n [zWave]=\"false\"\n (click)=\"navigateEndPreviousFast()\">\n <z-icon zType=\"lucideChevronsLeft\" zSize=\"18\" />\n </button>\n\n <button\n type=\"button\"\n z-button\n zType=\"ghost\"\n zSize=\"sm\"\n class=\"size-7 shrink-0 p-0!\"\n [zDisabled]=\"!canNavigateEndPrev()\"\n [zWave]=\"false\"\n (click)=\"navigateEndPrevious()\">\n <z-icon zType=\"lucideChevronLeft\" zSize=\"18\" />\n </button>\n\n <div class=\"flex w-[7.5rem] shrink-0 items-center justify-center gap-0\">\n <button\n type=\"button\"\n z-button\n zType=\"ghost\"\n zSize=\"sm\"\n class=\"h-7 px-1.5 text-sm!\"\n [zWave]=\"false\"\n (click)=\"setEndView('month')\">\n {{ endMonthName() }}\n </button>\n\n <button\n type=\"button\"\n z-button\n zType=\"ghost\"\n zSize=\"sm\"\n class=\"h-7 px-1.5 text-sm!\"\n [zWave]=\"false\"\n (click)=\"setEndView('year')\">\n {{ endMonthYear() }}\n </button>\n </div>\n\n <button\n type=\"button\"\n z-button\n zType=\"ghost\"\n zSize=\"sm\"\n class=\"size-7 shrink-0 p-0!\"\n [zWave]=\"false\"\n [zWave]=\"false\"\n (click)=\"navigateEndNext()\">\n <z-icon zType=\"lucideChevronRight\" zSize=\"18\" />\n </button>\n\n <button\n type=\"button\"\n z-button\n zType=\"ghost\"\n zSize=\"sm\"\n class=\"size-7 shrink-0 p-0!\"\n [zWave]=\"false\"\n [zWave]=\"false\"\n (click)=\"navigateEndNextFast()\">\n <z-icon zType=\"lucideChevronsRight\" zSize=\"18\" />\n </button>\n </div>\n\n <!-- Body -->\n <div\n class=\"flex h-full min-h-[14rem] w-full flex-col items-center justify-center p-2\"\n [class.h-[14rem]]=\"endView() === 'month' || endView() === 'year'\">\n @if (endView() === 'day') {\n <div\n class=\"flex h-full w-full flex-1 flex-col gap-1\"\n [class.animate-calendar-enter]=\"uiState().hasEndViewChanged\">\n <!-- Weekday headers -->\n <div class=\"flex w-full flex-1 justify-center gap-1\">\n @for (weekday of weekdayNames(); track weekday) {\n <div\n class=\"text-muted-foreground flex h-[1.875rem] w-[2.0313rem] items-center justify-center text-xs font-medium\">\n {{ weekday }}\n </div>\n }\n </div>\n\n <!-- Date rows -->\n @for (week of calendarDaysEnd(); track $index) {\n <div class=\"flex w-full flex-1 justify-center gap-1\">\n @for (day of week; track day.date.getTime()) {\n <button\n type=\"button\"\n [class]=\"day | zDayClasses\"\n class=\"h-[1.875rem] !w-[2.0313rem] !text-sm\"\n [disabled]=\"day.isDisabled\"\n (click)=\"onDayClick(day)\"\n (mouseenter)=\"onDayHover(day)\"\n (mouseleave)=\"onDayLeave()\">\n {{ day.day }}\n </button>\n }\n </div>\n }\n </div>\n }\n @if (endView() === 'month') {\n <div\n class=\"grid h-full w-full grid-cols-3 grid-rows-4 gap-2.5 gap-y-5!\"\n [class.animate-calendar-enter]=\"uiState().hasEndViewChanged\">\n @for (month of monthNames(); track month; let i = $index) {\n @let endMonthDisabled = i | zIsEndMonthDisabled: endMonthDisabledContext();\n <div class=\"flex flex-1 items-center justify-center\">\n <button\n type=\"button\"\n [class]=\"i | zMonthClasses: endMonth().getMonth() : -1\"\n class=\"!h-7 !w-full !text-sm\"\n [disabled]=\"endMonthDisabled\"\n [class.opacity-30]=\"endMonthDisabled\"\n [class.cursor-not-allowed]=\"endMonthDisabled\"\n (click)=\"onEndMonthClick(i)\">\n {{ month }}\n </button>\n </div>\n }\n </div>\n }\n\n @if (endView() === 'year') {\n <div\n class=\"grid h-full w-full grid-cols-3 grid-rows-4 gap-2.5 gap-y-5!\"\n [class.animate-calendar-enter]=\"uiState().hasEndViewChanged\">\n @for (year of endYearRange(); track year) {\n @let endYearDisabled = year | zIsEndYearDisabled: endYearDisabledContext();\n <div class=\"flex flex-1 items-center justify-center\">\n <button\n type=\"button\"\n [class]=\"year | zYearClasses: endMonth().getFullYear() : -1\"\n class=\"!h-7 !w-full !text-sm\"\n [disabled]=\"endYearDisabled\"\n [class.opacity-30]=\"endYearDisabled\"\n [class.cursor-not-allowed]=\"endYearDisabled\"\n (click)=\"onEndYearClick(year)\">\n {{ year }}\n </button>\n </div>\n }\n </div>\n }\n </div>\n </div>\n }\n </div>\n\n <!-- Compact Time Picker Below Calendar (Single Date) -->\n @if (!isRangeMode() && zShowTime()) {\n <div\n class=\"hover:bg-muted border-border flex w-full cursor-pointer items-center justify-center gap-1.5 border-t px-3 py-1.5 transition-colors\"\n z-popover\n [zPopoverContent]=\"timeDropdownTpl\"\n zPosition=\"bottom\"\n [zPopoverWidth]=\"240\"\n [zOffset]=\"4\"\n zTrigger=\"click\"\n zClass=\"border-border shadow-lg\"\n (zShow)=\"onTimeDropdownShow()\">\n <z-icon zType=\"lucideCalendarClock\" zSize=\"18\" class=\"text-muted-foreground mr-1 shrink-0\" />\n <span class=\"text-sm font-medium tabular-nums select-none\">\n @if (zShowHour()) {\n {{ formattedHour() }}\n }\n @if (zShowHour() && zShowMinute()) {\n <span class=\"text-muted-foreground\">:</span>\n }\n @if (zShowMinute()) {\n {{ formattedMinute() }}\n }\n @if (zShowMinute() && zShowSecond()) {\n <span class=\"text-muted-foreground\">:</span>\n }\n @if (zShowSecond()) {\n {{ formattedSecond() }}\n }\n @if (zTimeFormat() === '12h') {\n <span class=\"text-primary ml-0.5 font-semibold\">\n {{ period() }}\n </span>\n }\n </span>\n <z-icon zType=\"lucideChevronDown\" zSize=\"14\" class=\"text-muted-foreground shrink-0\" />\n </div>\n }\n\n <!-- Compact Time Pickers Below Calendars (Range Mode) -->\n @if (isRangeMode() && zShowTime()) {\n <div class=\"border-border flex w-full flex-col border-t sm:flex-row\">\n <!-- Start Time -->\n <div\n class=\"hover:bg-muted flex flex-1 cursor-pointer items-center justify-center gap-1.5 px-3 py-1.5 transition-colors\"\n z-popover\n [zPopoverContent]=\"timeDropdownTpl\"\n zPosition=\"bottom\"\n [zPopoverWidth]=\"240\"\n [zOffset]=\"4\"\n zTrigger=\"click\"\n zClass=\"border-border shadow-lg\"\n (zShow)=\"onTimeDropdownShow()\">\n <z-icon zType=\"lucideCalendarClock\" zSize=\"18\" class=\"text-muted-foreground mr-1 shrink-0\" />\n <span class=\"text-sm font-medium tabular-nums select-none\">\n @if (zShowHour()) {\n {{ formattedHour() }}\n }\n @if (zShowHour() && zShowMinute()) {\n <span class=\"text-muted-foreground\">:</span>\n }\n @if (zShowMinute()) {\n {{ formattedMinute() }}\n }\n @if (zShowMinute() && zShowSecond()) {\n <span class=\"text-muted-foreground\">:</span>\n }\n @if (zShowSecond()) {\n {{ formattedSecond() }}\n }\n @if (zTimeFormat() === '12h') {\n <span class=\"text-primary ml-0.5 font-semibold\">\n {{ period() }}\n </span>\n }\n </span>\n <z-icon zType=\"lucideChevronDown\" zSize=\"14\" class=\"text-muted-foreground shrink-0\" />\n </div>\n\n <!-- Divider -->\n <div class=\"border-border bg-border h-px self-stretch sm:block sm:h-full sm:w-px\"></div>\n\n <!-- End Time -->\n <div\n class=\"hover:bg-muted flex flex-1 cursor-pointer items-center justify-center gap-1.5 px-3 py-1.5 transition-colors\"\n z-popover\n [zPopoverContent]=\"timeDropdownEndTpl\"\n zPosition=\"bottom\"\n [zPopoverWidth]=\"240\"\n [zOffset]=\"4\"\n zTrigger=\"click\"\n zClass=\"border-border shadow-lg\"\n (zShow)=\"onTimeDropdownEndShow()\">\n <z-icon zType=\"lucideCalendarClock\" zSize=\"18\" class=\"text-muted-foreground mr-1 shrink-0\" />\n <span class=\"text-sm font-medium tabular-nums select-none\">\n @if (zShowHour()) {\n {{ formattedHourEnd() }}\n }\n @if (zShowHour() && zShowMinute()) {\n <span class=\"text-muted-foreground\">:</span>\n }\n @if (zShowMinute()) {\n {{ formattedMinuteEnd() }}\n }\n @if (zShowMinute() && zShowSecond()) {\n <span class=\"text-muted-foreground\">:</span>\n }\n @if (zShowSecond()) {\n {{ formattedSecondEnd() }}\n }\n @if (zTimeFormat() === '12h') {\n <span class=\"text-primary ml-0.5 font-semibold\">\n {{ periodEnd() }}\n </span>\n }\n </span>\n <z-icon zType=\"lucideChevronDown\" zSize=\"14\" class=\"text-muted-foreground shrink-0\" />\n </div>\n </div>\n }\n } @else {\n <!-- Time Only Mode -->\n <div class=\"flex w-full justify-center px-2 pt-2 pb-1\">\n <ng-container [ngTemplateOutlet]=\"timeDropdownTpl\" />\n </div>\n }\n </div>\n\n @if (!(zQuickSelect() && zMode() === 'range' && !showOkButton() && !showCancelButton())) {\n <div\n class=\"bg-popover border-border z-10 flex w-full shrink-0 items-center justify-between gap-2 border-t px-2 py-2 shadow-[0_-2px_8px_-2px_rgb(0_0_0_/_10%)] sm:pt-2 sm:pb-0 sm:shadow-none\">\n @if (!zQuickSelect() || zMode() !== 'range') {\n <button type=\"button\" z-button zType=\"secondary\" zSize=\"sm\" [zWave]=\"false\" (click)=\"onTodayClick()\">\n {{ todayButtonText() }}\n </button>\n } @else {\n <div></div>\n }\n\n @if (showOkButton() || showCancelButton()) {\n <div class=\"flex items-center gap-2\">\n @if (showCancelButton()) {\n <button type=\"button\" z-button zType=\"outline\" zSize=\"sm\" (click)=\"onCancelClick()\">\n {{ zCancelText() ?? ('i18n_z_ui_calendar_cancel' | translate) }}\n </button>\n }\n @if (showOkButton()) {\n <button type=\"button\" z-button zSize=\"sm\" [zDisabled]=\"!canApply()\" (click)=\"onOkClick()\">\n {{ zOkText() ?? ('i18n_z_ui_calendar_ok' | translate) }}\n </button>\n }\n </div>\n }\n </div>\n }\n </div>\n </div>\n</ng-template>\n\n<ng-template #timeDropdownTpl>\n <div class=\"bg-popover flex min-w-56 justify-center overflow-hidden rounded-sm\">\n @if (zShowHour()) {\n <div\n class=\"flex flex-col\"\n [class.border-r]=\"zShowMinute() || zShowSecond() || zTimeFormat() === '12h'\"\n [class.border-border]=\"zShowMinute() || zShowSecond() || zTimeFormat() === '12h'\">\n <div\n class=\"text-muted-foreground border-b-border flex h-7 shrink-0 items-center justify-center border-b text-xs font-medium select-none\">\n {{ 'i18n_z_ui_calendar_hour' | translate }}\n </div>\n <ng-scrollbar\n class=\"z-time-scroll-hour h-[11rem] w-14\"\n [class.rounded-bl-sm]=\"!zShowMinute() && !zShowSecond() && zTimeFormat() !== '12h'\"\n [class.rounded-tl-sm]=\"zShowMinute() || zShowSecond() || zTimeFormat() === '12h'\"\n track=\"vertical\">\n <div class=\"flex flex-col\">\n @for (hr of hourOptions(); track hr) {\n @let hrSelected = hr === displayHour();\n <button\n type=\"button\"\n class=\"flex h-7 shrink-0 cursor-pointer items-center justify-center text-sm transition-colors\"\n [class.hover:bg-muted]=\"!hrSelected\"\n [class.bg-primary]=\"hrSelected\"\n [class.text-primary-foreground]=\"hrSelected\"\n [class.font-medium]=\"hrSelected\"\n (click)=\"selectHour(hr)\">\n {{ hr | number: '2.0-0' }}\n </button>\n }\n </div>\n </ng-scrollbar>\n </div>\n }\n @if (zShowMinute()) {\n <div\n class=\"flex flex-col\"\n [class.border-r]=\"zShowSecond() || zTimeFormat() === '12h'\"\n [class.border-border]=\"zShowSecond() || zTimeFormat() === '12h'\">\n <div\n class=\"text-muted-foreground border-b-border flex h-7 shrink-0 items-center justify-center border-b text-xs font-medium select-none\">\n {{ 'i18n_z_ui_calendar_minute' | translate }}\n </div>\n <ng-scrollbar\n class=\"z-time-scroll-minute h-[11rem] w-14\"\n [class.rounded-bl-sm]=\"!zShowHour() && !zShowSecond() && zTimeFormat() !== '12h'\"\n [class.rounded-tl-sm]=\"!zShowHour() && (zShowSecond() || zTimeFormat() === '12h')\"\n [class.rounded-br-sm]=\"(zShowHour() || !zShowHour()) && !zShowSecond() && zTimeFormat() !== '12h'\"\n track=\"vertical\">\n <div class=\"flex flex-col\">\n @for (min of minuteOptions; track min) {\n @let minSelected = min === minute();\n <button\n type=\"button\"\n class=\"flex h-7 shrink-0 cursor-pointer items-center justify-center text-sm transition-colors\"\n [class.hover:bg-muted]=\"!minSelected\"\n [class.bg-primary]=\"minSelected\"\n [class.text-primary-foreground]=\"minSelected\"\n [class.font-medium]=\"minSelected\"\n (click)=\"selectMinute(min)\">\n {{ min | number: '2.0-0' }}\n </button>\n }\n </div>\n </ng-scrollbar>\n </div>\n }\n @if (zShowSecond()) {\n <div\n class=\"flex flex-col\"\n [class.border-r]=\"zTimeFormat() === '12h'\"\n [class.border-border]=\"zTimeFormat() === '12h'\">\n <div\n class=\"text-muted-foreground border-b-border flex h-7 shrink-0 items-center justify-center border-b text-xs font-medium select-none\">\n {{ 'i18n_z_ui_calendar_second' | translate }}\n </div>\n <ng-scrollbar\n class=\"z-time-scroll-second h-[11rem] w-14\"\n [class.rounded-br-sm]=\"zTimeFormat() !== '12h'\"\n [class.rounded-bl-sm]=\"!zShowHour() && !zShowMinute() && zTimeFormat() !== '12h'\"\n track=\"vertical\">\n <div class=\"flex flex-col\">\n @for (sec of secondOptions; track sec) {\n @let secSelected = sec === second();\n <button\n type=\"button\"\n class=\"flex h-7 shrink-0 cursor-pointer items-center justify-center text-sm transition-colors\"\n [class.hover:bg-muted]=\"!secSelected\"\n [class.bg-primary]=\"secSelected\"\n [class.text-primary-foreground]=\"secSelected\"\n [class.font-medium]=\"secSelected\"\n (click)=\"selectSecond(sec)\">\n {{ sec | number: '2.0-0' }}\n </button>\n }\n </div>\n </ng-scrollbar>\n </div>\n }\n @if (zTimeFormat() === '12h') {\n <div class=\"flex flex-col\">\n <div\n class=\"text-muted-foreground border-b-border flex h-7 shrink-0 items-center justify-center border-b text-xs font-medium select-none\">\n {{ 'i18n_z_ui_calendar_period' | translate }}\n </div>\n <ng-scrollbar class=\"z-time-scroll-period h-[11rem] w-14\" [class.rounded-br-sm]=\"true\" track=\"vertical\">\n <div class=\"flex flex-col\">\n @for (p of ['AM', 'PM']; track p) {\n @let pSelected = p === period();\n <button\n type=\"button\"\n class=\"flex h-7 shrink-0 cursor-pointer items-center justify-center text-sm transition-colors\"\n [class.hover:bg-muted]=\"!pSelected\"\n [class.bg-primary]=\"pSelected\"\n [class.text-primary-foreground]=\"pSelected\"\n [class.font-medium]=\"pSelected\"\n (click)=\"selectPeriod($any(p))\">\n {{ p }}\n </button>\n }\n </div>\n </ng-scrollbar>\n </div>\n }\n </div>\n</ng-template>\n\n<ng-template #timeDropdownEndTpl>\n <div class=\"bg-popover flex min-w-56 justify-center overflow-hidden rounded-sm\">\n @if (zShowHour()) {\n <div\n class=\"flex flex-col\"\n [class.border-r]=\"zShowMinute() || zShowSecond() || zTimeFormat() === '12h'\"\n [class.border-border]=\"zShowMinute() || zShowSecond() || zTimeFormat() === '12h'\">\n <div\n class=\"text-muted-foreground border-b-border flex h-7 shrink-0 items-center justify-center border-b text-xs font-medium select-none\">\n {{ 'i18n_z_ui_calendar_hour' | translate }}\n </div>\n <ng-scrollbar\n class=\"z-time-scroll-hour-end h-[11rem] w-14\"\n [class.rounded-bl-sm]=\"!zShowMinute() && !zShowSecond() && zTimeFormat() !== '12h'\"\n [class.rounded-tl-sm]=\"zShowMinute() || zShowSecond() || zTimeFormat() === '12h'\"\n track=\"vertical\">\n <div class=\"flex flex-col\">\n @for (hr of hourOptions(); track hr) {\n @let hrDisabled = hr | zIsEndHourDisabled: endTimeContext();\n @let hrEndSelected = hr === displayHourEnd();\n <button\n type=\"button\"\n class=\"flex h-7 shrink-0 items-center justify-center text-sm transition-colors\"\n [class.hover:bg-muted]=\"!hrDisabled && !hrEndSelected\"\n [class.cursor-pointer]=\"!hrDisabled\"\n [class.bg-primary]=\"hrEndSelected\"\n [class.text-primary-foreground]=\"hrEndSelected\"\n [class.font-medium]=\"hrEndSelected\"\n [class.opacity-30]=\"hrDisabled\"\n [class.cursor-not-allowed]=\"hrDisabled\"\n [disabled]=\"hrDisabled\"\n (click)=\"selectHourEnd(hr)\">\n {{ hr | number: '2.0-0' }}\n </button>\n }\n </div>\n </ng-scrollbar>\n </div>\n }\n @if (zShowMinute()) {\n <div\n class=\"flex flex-col\"\n [class.border-r]=\"zShowSecond() || zTimeFormat() === '12h'\"\n [class.border-border]=\"zShowSecond() || zTimeFormat() === '12h'\">\n <div\n class=\"text-muted-foreground border-b-border flex h-7 shrink-0 items-center justify-center border-b text-xs font-medium select-none\">\n {{ 'i18n_z_ui_calendar_minute' | translate }}\n </div>\n <ng-scrollbar\n class=\"z-time-scroll-minute-end h-[11rem] w-14\"\n [class.rounded-bl-sm]=\"!zShowHour() && !zShowSecond() && zTimeFormat() !== '12h'\"\n [class.rounded-tl-sm]=\"!zShowHour() && (zShowSecond() || zTimeFormat() === '12h')\"\n [class.rounded-br-sm]=\"(zShowHour() || !zShowHour()) && !zShowSecond() && zTimeFormat() !== '12h'\"\n track=\"vertical\">\n <div class=\"flex flex-col\">\n @for (min of minuteOptions; track min) {\n @let minDisabled = min | zIsEndMinuteDisabled: endTimeContext();\n @let minEndSelected = min === minuteEnd();\n <button\n type=\"button\"\n class=\"flex h-7 shrink-0 items-center justify-center text-sm transition-colors\"\n [class.hover:bg-muted]=\"!minDisabled && !minEndSelected\"\n [class.cursor-pointer]=\"!minDisabled\"\n [class.bg-primary]=\"minEndSelected\"\n [class.text-primary-foreground]=\"minEndSelected\"\n [class.font-medium]=\"minEndSelected\"\n [class.opacity-30]=\"minDisabled\"\n [class.cursor-not-allowed]=\"minDisabled\"\n [disabled]=\"minDisabled\"\n (click)=\"selectMinuteEnd(min)\">\n {{ min | number: '2.0-0' }}\n </button>\n }\n </div>\n </ng-scrollbar>\n </div>\n }\n @if (zShowSecond()) {\n <div\n class=\"flex flex-col\"\n [class.border-r]=\"zTimeFormat() === '12h'\"\n [class.border-border]=\"zTimeFormat() === '12h'\">\n <div\n class=\"text-muted-foreground border-b-border flex h-7 shrink-0 items-center justify-center border-b text-xs font-medium select-none\">\n {{ 'i18n_z_ui_calendar_second' | translate }}\n </div>\n <ng-scrollbar\n class=\"z-time-scroll-second-end h-[11rem] w-14\"\n [class.rounded-br-sm]=\"zTimeFormat() !== '12h'\"\n [class.rounded-bl-sm]=\"!zShowHour() && !zShowMinute() && zTimeFormat() !== '12h'\"\n track=\"vertical\">\n <div class=\"flex flex-col\">\n @for (sec of secondOptions; track sec) {\n @let secDisabled = sec | zIsEndSecondDisabled: endTimeContext();\n @let secEndSelected = sec === secondEnd();\n <button\n type=\"button\"\n class=\"flex h-7 shrink-0 items-center justify-center text-sm transition-colors\"\n [class.hover:bg-muted]=\"!secDisabled && !secEndSelected\"\n [class.cursor-pointer]=\"!secDisabled\"\n [class.bg-primary]=\"secEndSelected\"\n [class.text-primary-foreground]=\"secEndSelected\"\n [class.font-medium]=\"secEndSelected\"\n [class.opacity-30]=\"secDisabled\"\n [class.cursor-not-allowed]=\"secDisabled\"\n [disabled]=\"secDisabled\"\n (click)=\"selectSecondEnd(sec)\">\n {{ sec | number: '2.0-0' }}\n </button>\n }\n </div>\n </ng-scrollbar>\n </div>\n }\n @if (zTimeFormat() === '12h') {\n <div class=\"flex flex-col\">\n <div\n class=\"text-muted-foreground border-b-border flex h-7 shrink-0 items-center justify-center border-b text-xs font-medium select-none\">\n {{ 'i18n_z_ui_calendar_period' | translate }}\n </div>\n <ng-scrollbar class=\"z-time-scroll-period-end h-[11rem] w-14\" [class.rounded-br-sm]=\"true\" track=\"vertical\">\n <div class=\"flex flex-col\">\n @for (p of ['AM', 'PM']; track p) {\n @let pSelected = p === periodEnd();\n <button\n type=\"button\"\n class=\"flex h-7 shrink-0 cursor-pointer items-center justify-center text-sm transition-colors\"\n [class.hover:bg-muted]=\"!pSelected\"\n [class.bg-primary]=\"pSelected\"\n [class.text-primary-foreground]=\"pSelected\"\n [class.font-medium]=\"pSelected\"\n (click)=\"selectPeriodEnd($any(p))\">\n {{ p }}\n </button>\n }\n </div>\n </ng-scrollbar>\n </div>\n }\n </div>\n</ng-template>\n", styles: [".animate-calendar-enter{animation:z-calendar-view-enter .2s ease-out}@keyframes z-calendar-view-enter{0%{opacity:0;transform:scale(.95) translateY(.25rem)}to{opacity:1;transform:scale(1) translateY(0)}}.z-calendar input{text-overflow:ellipsis;overflow:hidden}\n"] }]
|
|
3158
3300
|
}], ctorParameters: () => [], propDecorators: { class: [{ type: i0.Input, args: [{ isSignal: true, alias: "class", required: false }] }], zMode: [{ type: i0.Input, args: [{ isSignal: true, alias: "zMode", required: false }] }], zSize: [{ type: i0.Input, args: [{ isSignal: true, alias: "zSize", required: false }] }], zLabel: [{ type: i0.Input, args: [{ isSignal: true, alias: "zLabel", required: false }] }], zLabelClass: [{ type: i0.Input, args: [{ isSignal: true, alias: "zLabelClass", required: false }] }], zPlaceholder: [{ type: i0.Input, args: [{ isSignal: true, alias: "zPlaceholder", required: false }] }], zRequired: [{ type: i0.Input, args: [{ isSignal: true, alias: "zRequired", required: false }] }], zDisabled: [{ type: i0.Input, args: [{ isSignal: true, alias: "zDisabled", required: false }] }], zReadonly: [{ type: i0.Input, args: [{ isSignal: true, alias: "zReadonly", required: false }] }], zShowTime: [{ type: i0.Input, args: [{ isSignal: true, alias: "zShowTime", required: false }] }], zTimeFormat: [{ type: i0.Input, args: [{ isSignal: true, alias: "zTimeFormat", required: false }] }], zShowHour: [{ type: i0.Input, args: [{ isSignal: true, alias: "zShowHour", required: false }] }], zShowMinute: [{ type: i0.Input, args: [{ isSignal: true, alias: "zShowMinute", required: false }] }], zShowSecond: [{ type: i0.Input, args: [{ isSignal: true, alias: "zShowSecond", required: false }] }], zQuickSelect: [{ type: i0.Input, args: [{ isSignal: true, alias: "zQuickSelect", required: false }] }], zAllowEdit: [{ type: i0.Input, args: [{ isSignal: true, alias: "zAllowEdit", required: false }] }], zShortTime: [{ type: i0.Input, args: [{ isSignal: true, alias: "zShortTime", required: false }] }], zAllowClear: [{ type: i0.Input, args: [{ isSignal: true, alias: "zAllowClear", required: false }] }], zFormat: [{ type: i0.Input, args: [{ isSignal: true, alias: "zFormat", required: false }] }], zMinDate: [{ type: i0.Input, args: [{ isSignal: true, alias: "zMinDate", required: false }] }], zMaxDate: [{ type: i0.Input, args: [{ isSignal: true, alias: "zMaxDate", required: false }] }], zValueType: [{ type: i0.Input, args: [{ isSignal: true, alias: "zValueType", required: false }] }], zValidators: [{ type: i0.Input, args: [{ isSignal: true, alias: "zValidators", required: false }] }], zShowOk: [{ type: i0.Input, args: [{ isSignal: true, alias: "zShowOk", required: false }] }], zOkText: [{ type: i0.Input, args: [{ isSignal: true, alias: "zOkText", required: false }] }], zShowCancel: [{ type: i0.Input, args: [{ isSignal: true, alias: "zShowCancel", required: false }] }], zCancelText: [{ type: i0.Input, args: [{ isSignal: true, alias: "zCancelText", required: false }] }], zDisabledDate: [{ type: i0.Input, args: [{ isSignal: true, alias: "zDisabledDate", required: false }] }], zScrollClose: [{ type: i0.Input, args: [{ isSignal: true, alias: "zScrollClose", required: false }] }], zDefaultTime: [{ type: i0.Input, args: [{ isSignal: true, alias: "zDefaultTime", required: false }] }], zRangeDefaultTime: [{ type: i0.Input, args: [{ isSignal: true, alias: "zRangeDefaultTime", required: false }] }], zControl: [{ type: i0.Output, args: ["zControl"] }], zChange: [{ type: i0.Output, args: ["zChange"] }], zOnBlur: [{ type: i0.Output, args: ["zOnBlur"] }], zOnFocus: [{ type: i0.Output, args: ["zOnFocus"] }], zEvent: [{ type: i0.Output, args: ["zEvent"] }], triggerRef: [{ type: i0.ViewChild, args: ['triggerEl', { isSignal: true }] }], inputRef: [{ type: i0.ViewChild, args: ['inputEl', { isSignal: true }] }] } });
|
|
3159
3301
|
|
|
3160
3302
|
/**
|