@shival99/z-ui 2.0.27 → 2.0.29

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -1,6 +1,6 @@
1
1
  import { NgTemplateOutlet, DecimalPipe } from '@angular/common';
2
2
  import * as i0 from '@angular/core';
3
- import { Pipe, input, output, viewChild, computed, signal, inject, Injector, DestroyRef, effect, forwardRef, ViewEncapsulation, ChangeDetectionStrategy, Component } from '@angular/core';
3
+ import { Pipe, input, output, viewChild, computed, signal, inject, Injector, DestroyRef, linkedSignal, effect, forwardRef, ViewEncapsulation, ChangeDetectionStrategy, Component } from '@angular/core';
4
4
  import { takeUntilDestroyed } from '@angular/core/rxjs-interop';
5
5
  import * as i1 from '@angular/forms';
6
6
  import { NgControl, NgModel, FormsModule, NG_VALUE_ACCESSOR } from '@angular/forms';
@@ -1040,6 +1040,8 @@ class ZCalendarComponent {
1040
1040
  zEvent = output();
1041
1041
  triggerRef = viewChild('triggerEl', ...(ngDevMode ? [{ debugName: "triggerRef" }] : []));
1042
1042
  inputRef = viewChild('inputEl', ...(ngDevMode ? [{ debugName: "inputRef" }] : []));
1043
+ startInputRef = viewChild('startInputEl', ...(ngDevMode ? [{ debugName: "startInputRef" }] : []));
1044
+ endInputRef = viewChild('endInputEl', ...(ngDevMode ? [{ debugName: "endInputRef" }] : []));
1043
1045
  pickerId = zUuid('z-calendar');
1044
1046
  weekdayNames = computed(() => getWeekdayNames(this.zLocale()), ...(ngDevMode ? [{ debugName: "weekdayNames" }] : []));
1045
1047
  monthNames = computed(() => getMonthNames(this.zLocale()), ...(ngDevMode ? [{ debugName: "monthNames" }] : []));
@@ -1116,8 +1118,25 @@ class ZCalendarComponent {
1116
1118
  period = signal('AM', ...(ngDevMode ? [{ debugName: "period" }] : []));
1117
1119
  inputDisplayValue = signal('', ...(ngDevMode ? [{ debugName: "inputDisplayValue" }] : []));
1118
1120
  isInputFocused = signal(false, ...(ngDevMode ? [{ debugName: "isInputFocused" }] : []));
1119
- activePresetKey = signal(null, ...(ngDevMode ? [{ debugName: "activePresetKey" }] : []));
1120
- shortDisplayPresetKey = signal(null, ...(ngDevMode ? [{ debugName: "shortDisplayPresetKey" }] : []));
1121
+ activePresetKey = linkedSignal(() => {
1122
+ const start = this._rangeStart();
1123
+ const end = this._rangeEnd();
1124
+ if (start && end) {
1125
+ return this._detectMatchingPreset(start, end);
1126
+ }
1127
+ return null;
1128
+ }, ...(ngDevMode ? [{ debugName: "activePresetKey" }] : []));
1129
+ shortDisplayPresetKey = linkedSignal(() => {
1130
+ const start = this._rangeStart();
1131
+ const end = this._rangeEnd();
1132
+ if (start && end) {
1133
+ const matching = this._detectMatchingPreset(start, end);
1134
+ if (matching && matching !== 'custom' && this.zShortTime()) {
1135
+ return matching;
1136
+ }
1137
+ }
1138
+ return null;
1139
+ }, ...(ngDevMode ? [{ debugName: "shortDisplayPresetKey" }] : []));
1121
1140
  quickSelectOptions = computed(() => this.quickSelectPresets.map(preset => ({
1122
1141
  label: preset.label,
1123
1142
  value: preset.key,
@@ -1563,19 +1582,51 @@ class ZCalendarComponent {
1563
1582
  if (this.isRangeMode()) {
1564
1583
  if (typeof value === 'object' && 'start' in value && 'end' in value) {
1565
1584
  const range = value;
1566
- this._rangeStart.set(range.start);
1567
- this._rangeEnd.set(range.end);
1568
- if (range.start && range.end) {
1569
- this._currentMonth.set(range.start);
1570
- this._endMonth.set(isSameMonth(range.start, range.end) ? addMonths(range.end, 1) : range.end);
1585
+ let start = null;
1586
+ let end = null;
1587
+ const valStart = range['start'];
1588
+ const valEnd = range['end'];
1589
+ // Tự động phân tích giá trị start nếu chuỗi ISO hoặc định dạng thông thường
1590
+ if (valStart instanceof Date) {
1591
+ start = valStart;
1592
+ }
1593
+ if (typeof valStart === 'string') {
1594
+ const isIsoLike = /^\d{4}-\d{2}-\d{2}/.test(valStart);
1595
+ start =
1596
+ valueType === 'iso' || isIsoLike
1597
+ ? fromISOString(valStart)
1598
+ : parseDate(valStart, this.zFormat(), this.zLocale());
1599
+ if (isIsoLike && (!start || isNaN(start.getTime()))) {
1600
+ start = parseDate(valStart, this.zFormat(), this.zLocale());
1601
+ }
1602
+ }
1603
+ // Tự động phân tích giá trị end nếu là chuỗi ISO hoặc định dạng thông thường
1604
+ if (valEnd instanceof Date) {
1605
+ end = valEnd;
1606
+ }
1607
+ if (typeof valEnd === 'string') {
1608
+ const isIsoLike = /^\d{4}-\d{2}-\d{2}/.test(valEnd);
1609
+ end =
1610
+ valueType === 'iso' || isIsoLike
1611
+ ? fromISOString(valEnd)
1612
+ : parseDate(valEnd, this.zFormat(), this.zLocale());
1613
+ if (isIsoLike && (!end || isNaN(end.getTime()))) {
1614
+ end = parseDate(valEnd, this.zFormat(), this.zLocale());
1615
+ }
1616
+ }
1617
+ this._rangeStart.set(start);
1618
+ this._rangeEnd.set(end);
1619
+ if (start && end) {
1620
+ this._currentMonth.set(start);
1621
+ this._endMonth.set(isSameMonth(start, end) ? addMonths(end, 1) : end);
1571
1622
  if (!this.shortDisplayPresetKey()) {
1572
- const presetKey = this._detectMatchingPreset(range.start, range.end);
1623
+ const presetKey = this._detectMatchingPreset(start, end);
1573
1624
  this.activePresetKey.set(presetKey);
1574
1625
  this.shortDisplayPresetKey.set(this.zShortTime() && presetKey !== 'custom' ? presetKey : null);
1575
1626
  }
1576
1627
  if (this.zShowTime()) {
1577
- this._syncTimeSignals(range.start);
1578
- this._syncEndTimeSignals(range.end);
1628
+ this._syncTimeSignals(start);
1629
+ this._syncEndTimeSignals(end);
1579
1630
  }
1580
1631
  }
1581
1632
  else {
@@ -1589,8 +1640,13 @@ class ZCalendarComponent {
1589
1640
  if (value instanceof Date) {
1590
1641
  date = value;
1591
1642
  }
1643
+ // Tự động phân tích chuỗi ISO của single mode (hữu ích khi nhận giá trị thô từ API)
1592
1644
  if (!date && typeof value === 'string') {
1593
- date = valueType === 'iso' ? fromISOString(value) : parseDate(value, this.zFormat(), this.zLocale());
1645
+ const isIsoLike = /^\d{4}-\d{2}-\d{2}/.test(value);
1646
+ date = valueType === 'iso' || isIsoLike ? fromISOString(value) : parseDate(value, this.zFormat(), this.zLocale());
1647
+ if (isIsoLike && (!date || isNaN(date.getTime()))) {
1648
+ date = parseDate(value, this.zFormat(), this.zLocale());
1649
+ }
1594
1650
  }
1595
1651
  if (!date) {
1596
1652
  return;
@@ -1648,17 +1704,22 @@ class ZCalendarComponent {
1648
1704
  this._rangeStart.set(null);
1649
1705
  this._rangeEnd.set(null);
1650
1706
  this.activePresetKey.set(null);
1707
+ this.shortDisplayPresetKey.set(null);
1651
1708
  this.hour.set(0);
1652
1709
  this.minute.set(0);
1653
1710
  this.second.set(0);
1654
1711
  this.uiState.update(s => ({ ...s, touched: false, dirty: false }));
1655
1712
  this.inputDisplayValue.set('');
1713
+ if (this.isRangeMode()) {
1714
+ this._updateRangeInputDisplay();
1715
+ }
1656
1716
  const emitValue = this._getEmitValue();
1657
1717
  this._onChange(emitValue);
1658
1718
  if (this._ngControl?.control) {
1659
1719
  this._ngControl.control.markAsPristine();
1660
1720
  this._ngControl.control.markAsUntouched();
1661
1721
  }
1722
+ this._syncDOMInputs();
1662
1723
  }
1663
1724
  /** @deprecated Use `valid()` for boolean form-submit checks. */
1664
1725
  validate() {
@@ -1804,11 +1865,7 @@ class ZCalendarComponent {
1804
1865
  if (this.isRangeMode()) {
1805
1866
  this._updateRangeInputDisplay();
1806
1867
  }
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
- }
1868
+ this._syncDOMInputs();
1812
1869
  this.triggerRef()?.nativeElement.blur();
1813
1870
  }
1814
1871
  _restoreFromBackup() {
@@ -1980,23 +2037,30 @@ class ZCalendarComponent {
1980
2037
  const format = this._getParseFormat();
1981
2038
  const date = parseDate(value, format, this.zLocale());
1982
2039
  if (!date) {
1983
- input.value = this.displayValueStart();
2040
+ this._cancelAndRestore();
1984
2041
  input.blur();
1985
2042
  return;
1986
2043
  }
1987
2044
  const endDate = this._rangeEnd();
1988
2045
  if (endDate && date >= endDate) {
1989
- input.value = this.displayValueStart();
2046
+ this._cancelAndRestore();
1990
2047
  input.blur();
1991
2048
  return;
1992
2049
  }
1993
- this._skipBlurHandler.set(true);
1994
2050
  this._rangeStart.set(date);
1995
2051
  this._currentMonth.set(date);
1996
2052
  this._syncTimeSignals(date);
1997
2053
  this.uiState.update(s => ({ ...s, dirty: true }));
1998
2054
  this._inputDisplayStart.set(this.displayValueStart());
1999
- this._confirmTypedValue(input);
2055
+ if (endDate) {
2056
+ this._skipBlurHandler.set(true);
2057
+ this._confirmTypedValue(input);
2058
+ return;
2059
+ }
2060
+ const endEl = this.endInputRef()?.nativeElement;
2061
+ if (endEl) {
2062
+ endEl.focus();
2063
+ }
2000
2064
  }
2001
2065
  onEndInputEnter(event) {
2002
2066
  event.preventDefault();
@@ -2012,23 +2076,30 @@ class ZCalendarComponent {
2012
2076
  const format = this._getParseFormat();
2013
2077
  const date = parseDate(value, format, this.zLocale());
2014
2078
  if (!date) {
2015
- input.value = this.displayValueEnd();
2079
+ this._cancelAndRestore();
2016
2080
  input.blur();
2017
2081
  return;
2018
2082
  }
2019
2083
  const startDate = this._rangeStart();
2020
2084
  if (startDate && date <= startDate) {
2021
- input.value = this.displayValueEnd();
2085
+ this._cancelAndRestore();
2022
2086
  input.blur();
2023
2087
  return;
2024
2088
  }
2025
- this._skipBlurHandler.set(true);
2026
2089
  this._rangeEnd.set(date);
2027
2090
  this._endMonth.set(date);
2028
2091
  this._syncEndTimeSignals(date);
2029
2092
  this.uiState.update(s => ({ ...s, dirty: true }));
2030
2093
  this._inputDisplayEnd.set(this.displayValueEnd());
2031
- this._confirmTypedValue(input);
2094
+ if (startDate) {
2095
+ this._skipBlurHandler.set(true);
2096
+ this._confirmTypedValue(input);
2097
+ return;
2098
+ }
2099
+ const startEl = this.startInputRef()?.nativeElement;
2100
+ if (startEl) {
2101
+ startEl.focus();
2102
+ }
2032
2103
  }
2033
2104
  onInputFocus(_event) {
2034
2105
  this.isInputFocused.set(true);
@@ -2043,6 +2114,16 @@ class ZCalendarComponent {
2043
2114
  return;
2044
2115
  }
2045
2116
  if (this.isRangeMode()) {
2117
+ const target = event.relatedTarget;
2118
+ const isFocusInside = target && (this.triggerRef()?.nativeElement.contains(target) || target.closest('.z-calendar-calendar'));
2119
+ if (isFocusInside) {
2120
+ return;
2121
+ }
2122
+ if (this._hasTypedDraft()) {
2123
+ this._restoreFromBackup();
2124
+ this._hasTypedDraft.set(false);
2125
+ }
2126
+ this._syncDOMInputs();
2046
2127
  return;
2047
2128
  }
2048
2129
  const needsConfirmation = this.showOkButton() || this.showCancelButton();
@@ -2122,10 +2203,7 @@ class ZCalendarComponent {
2122
2203
  return;
2123
2204
  }
2124
2205
  }
2125
- this._restoreFromBackup();
2126
- this._updateInputDisplay();
2127
- this.close();
2128
- input.value = this.displayValue();
2206
+ this._cancelAndRestore();
2129
2207
  input.blur();
2130
2208
  return;
2131
2209
  }
@@ -2140,10 +2218,7 @@ class ZCalendarComponent {
2140
2218
  this._confirmTypedValue(input);
2141
2219
  return;
2142
2220
  }
2143
- this._restoreFromBackup();
2144
- this._updateInputDisplay();
2145
- this.close();
2146
- input.value = this.displayValue();
2221
+ this._cancelAndRestore();
2147
2222
  input.blur();
2148
2223
  }
2149
2224
  onCalendarKeydown(event) {
@@ -2397,6 +2472,7 @@ class ZCalendarComponent {
2397
2472
  this._inputDisplayStart.set('');
2398
2473
  this._inputDisplayEnd.set('');
2399
2474
  }
2475
+ this._syncDOMInputs();
2400
2476
  this.close();
2401
2477
  }
2402
2478
  onCancelClick() {
@@ -2973,14 +3049,15 @@ class ZCalendarComponent {
2973
3049
  this.period.set(date.getHours() >= 12 ? 'PM' : 'AM');
2974
3050
  }
2975
3051
  _getParseFormat() {
2976
- if (!this.zShowTime() && !this.isTimeMode()) {
2977
- return this.zFormat();
2978
- }
2979
- const timeFormat = this._buildTimeFormat();
2980
3052
  if (this.isTimeMode()) {
2981
- return timeFormat;
3053
+ return this._buildTimeFormat();
2982
3054
  }
2983
- return `${this.zFormat()} ${timeFormat}`;
3055
+ const format = this.zFormat();
3056
+ const formatHasTime = hasTimeTokens(format);
3057
+ if (this.zShowTime() && !formatHasTime) {
3058
+ return `${format} ${this._buildTimeFormat()}`;
3059
+ }
3060
+ return format;
2984
3061
  }
2985
3062
  _buildTimeFormat(period) {
2986
3063
  return buildTimeFormat(this.zShowHour(), this.zShowMinute(), this.zShowSecond(), this.zTimeFormat(), period);
@@ -3004,6 +3081,23 @@ class ZCalendarComponent {
3004
3081
  }
3005
3082
  this._selectedDate.set(null);
3006
3083
  }
3084
+ _syncDOMInputs() {
3085
+ if (this.isRangeMode()) {
3086
+ const startEl = this.startInputRef()?.nativeElement;
3087
+ if (startEl) {
3088
+ startEl.value = this.inputDisplayStart();
3089
+ }
3090
+ const endEl = this.endInputRef()?.nativeElement;
3091
+ if (endEl) {
3092
+ endEl.value = this.inputDisplayEnd();
3093
+ }
3094
+ return;
3095
+ }
3096
+ const inputEl = this.inputRef()?.nativeElement;
3097
+ if (inputEl) {
3098
+ inputEl.value = this.inputDisplayValue();
3099
+ }
3100
+ }
3007
3101
  onInputEscape(event) {
3008
3102
  event.preventDefault();
3009
3103
  event.stopPropagation();
@@ -3032,6 +3126,7 @@ class ZCalendarComponent {
3032
3126
  this._restoreFromBackup();
3033
3127
  this._updateAllInputDisplays();
3034
3128
  this.close();
3129
+ this._syncDOMInputs();
3035
3130
  }
3036
3131
  _updateAllInputDisplays() {
3037
3132
  if (this.isRangeMode()) {
@@ -3260,7 +3355,7 @@ class ZCalendarComponent {
3260
3355
  multi: true,
3261
3356
  },
3262
3357
  TranslatePipe,
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 });
3358
+ ], viewQueries: [{ propertyName: "triggerRef", first: true, predicate: ["triggerEl"], descendants: true, isSignal: true }, { propertyName: "inputRef", first: true, predicate: ["inputEl"], descendants: true, isSignal: true }, { propertyName: "startInputRef", first: true, predicate: ["startInputEl"], descendants: true, isSignal: true }, { propertyName: "endInputRef", first: true, predicate: ["endInputEl"], 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 #startInputEl\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 #endInputEl\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 });
3264
3359
  }
3265
3360
  i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.0.9", ngImport: i0, type: ZCalendarComponent, decorators: [{
3266
3361
  type: Component,
@@ -3296,8 +3391,8 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.0.9", ngImpor
3296
3391
  TranslatePipe,
3297
3392
  ], changeDetection: ChangeDetectionStrategy.OnPush, encapsulation: ViewEncapsulation.None, host: {
3298
3393
  class: 'block min-w-0',
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"] }]
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 }] }] } });
3394
+ }, 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 #startInputEl\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 #endInputEl\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"] }]
3395
+ }], 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 }] }], startInputRef: [{ type: i0.ViewChild, args: ['startInputEl', { isSignal: true }] }], endInputRef: [{ type: i0.ViewChild, args: ['endInputEl', { isSignal: true }] }] } });
3301
3396
 
3302
3397
  /**
3303
3398
  * Generated bundle index. Do not edit.