@shival99/z-ui 1.3.9 → 1.3.10

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 { DecimalPipe } from '@angular/common';
2
2
  import * as i0 from '@angular/core';
3
- import { Pipe, input, output, viewChild, computed, signal, inject, Injector, DestroyRef, ChangeDetectorRef, effect, forwardRef, ViewEncapsulation, ChangeDetectionStrategy, Component } from '@angular/core';
3
+ import { Pipe, input, output, viewChild, computed, signal, inject, Injector, DestroyRef, effect, forwardRef, ViewEncapsulation, ChangeDetectionStrategy, Component } from '@angular/core';
4
4
  import { takeUntilDestroyed } from '@angular/core/rxjs-interop';
5
5
  import { NgControl, NG_VALUE_ACCESSOR } from '@angular/forms';
6
6
  import { TranslatePipe } from '@ngx-translate/core';
@@ -395,9 +395,36 @@ const getDayState = (day) => {
395
395
  }
396
396
  return 'default';
397
397
  };
398
- const getMonthState = (monthIndex, currentMonthIndex) => monthIndex === currentMonthIndex ? 'selected' : 'default';
399
- const getQuarterState = (quarterIndex, currentQuarterIndex) => quarterIndex === currentQuarterIndex ? 'selected' : 'default';
400
- const getYearState = (year, currentYear) => year === currentYear ? 'selected' : 'default';
398
+ const getMonthState = (monthIndex, selectedMonthIndex, todayMonthIndex) => {
399
+ if (monthIndex === selectedMonthIndex) {
400
+ return 'selected';
401
+ }
402
+ // Only show current month when no value is selected
403
+ if (selectedMonthIndex === -1 && monthIndex === todayMonthIndex) {
404
+ return 'current';
405
+ }
406
+ return 'default';
407
+ };
408
+ const getQuarterState = (quarterIndex, selectedQuarterIndex, todayQuarterIndex) => {
409
+ if (quarterIndex === selectedQuarterIndex) {
410
+ return 'selected';
411
+ }
412
+ // Only show current quarter when no value is selected
413
+ if (selectedQuarterIndex === -1 && quarterIndex === todayQuarterIndex) {
414
+ return 'current';
415
+ }
416
+ return 'default';
417
+ };
418
+ const getYearState = (year, selectedYear, todayYear) => {
419
+ if (year === selectedYear) {
420
+ return 'selected';
421
+ }
422
+ // Only show current year when no value is selected
423
+ if (selectedYear === -1 && year === todayYear) {
424
+ return 'current';
425
+ }
426
+ return 'default';
427
+ };
401
428
 
402
429
  const zCalendarVariants = cva([
403
430
  'group flex w-fit items-center rounded-[6px] border border-input bg-white shadow-xs cursor-pointer',
@@ -456,7 +483,7 @@ const zCalendarMonthVariants = cva([
456
483
  variants: {
457
484
  state: {
458
485
  default: 'hover:bg-primary/10 text-foreground',
459
- current: 'bg-primary/15 text-primary',
486
+ current: 'bg-primary text-primary-foreground',
460
487
  selected: 'bg-primary text-primary-foreground',
461
488
  disabled: 'text-muted-foreground/50 cursor-not-allowed line-through',
462
489
  },
@@ -473,7 +500,7 @@ const zCalendarYearVariants = cva([
473
500
  variants: {
474
501
  state: {
475
502
  default: 'hover:bg-primary/10 text-foreground',
476
- current: 'bg-primary/15 text-primary',
503
+ current: 'bg-primary text-primary-foreground',
477
504
  selected: 'bg-primary text-primary-foreground',
478
505
  disabled: 'text-muted-foreground/50 cursor-not-allowed line-through',
479
506
  },
@@ -490,6 +517,7 @@ const zCalendarQuarterVariants = cva([
490
517
  variants: {
491
518
  state: {
492
519
  default: 'hover:bg-primary/10 text-foreground',
520
+ current: 'bg-primary text-primary-foreground',
493
521
  selected: 'bg-primary text-primary-foreground',
494
522
  },
495
523
  },
@@ -547,9 +575,121 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.0.6", ngImpor
547
575
  }]
548
576
  }] });
549
577
 
578
+ class ZIsEndHourDisabledPipe {
579
+ transform(hour, context) {
580
+ if (!context.isSameDay) {
581
+ return false;
582
+ }
583
+ let actualHour = hour;
584
+ let actualStartHour = context.startHour;
585
+ if (context.timeFormat === '12h') {
586
+ if (context.endPeriod === 'PM' && hour !== 12) {
587
+ actualHour = hour + 12;
588
+ }
589
+ if (context.endPeriod === 'AM' && hour === 12) {
590
+ actualHour = 0;
591
+ }
592
+ if (context.startPeriod === 'PM' && context.startHour !== 12) {
593
+ actualStartHour = context.startHour + 12;
594
+ }
595
+ if (context.startPeriod === 'AM' && context.startHour === 12) {
596
+ actualStartHour = 0;
597
+ }
598
+ }
599
+ return actualHour < actualStartHour;
600
+ }
601
+ static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "21.0.6", ngImport: i0, type: ZIsEndHourDisabledPipe, deps: [], target: i0.ɵɵFactoryTarget.Pipe });
602
+ static ɵpipe = i0.ɵɵngDeclarePipe({ minVersion: "14.0.0", version: "21.0.6", ngImport: i0, type: ZIsEndHourDisabledPipe, isStandalone: true, name: "zIsEndHourDisabled" });
603
+ }
604
+ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.0.6", ngImport: i0, type: ZIsEndHourDisabledPipe, decorators: [{
605
+ type: Pipe,
606
+ args: [{
607
+ name: 'zIsEndHourDisabled',
608
+ standalone: true,
609
+ pure: true,
610
+ }]
611
+ }] });
612
+ class ZIsEndMinuteDisabledPipe {
613
+ transform(minute, context) {
614
+ if (!context.isSameDay) {
615
+ return false;
616
+ }
617
+ let actualStartHour = context.startHour;
618
+ let actualEndHour = context.endHour;
619
+ if (context.timeFormat === '12h') {
620
+ if (context.startPeriod === 'PM' && context.startHour !== 12) {
621
+ actualStartHour = context.startHour + 12;
622
+ }
623
+ if (context.startPeriod === 'AM' && context.startHour === 12) {
624
+ actualStartHour = 0;
625
+ }
626
+ if (context.endPeriod === 'PM' && context.endHour !== 12) {
627
+ actualEndHour = context.endHour + 12;
628
+ }
629
+ if (context.endPeriod === 'AM' && context.endHour === 12) {
630
+ actualEndHour = 0;
631
+ }
632
+ }
633
+ if (actualEndHour !== actualStartHour) {
634
+ return false;
635
+ }
636
+ return minute < context.startMinute;
637
+ }
638
+ static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "21.0.6", ngImport: i0, type: ZIsEndMinuteDisabledPipe, deps: [], target: i0.ɵɵFactoryTarget.Pipe });
639
+ static ɵpipe = i0.ɵɵngDeclarePipe({ minVersion: "14.0.0", version: "21.0.6", ngImport: i0, type: ZIsEndMinuteDisabledPipe, isStandalone: true, name: "zIsEndMinuteDisabled" });
640
+ }
641
+ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.0.6", ngImport: i0, type: ZIsEndMinuteDisabledPipe, decorators: [{
642
+ type: Pipe,
643
+ args: [{
644
+ name: 'zIsEndMinuteDisabled',
645
+ standalone: true,
646
+ pure: true,
647
+ }]
648
+ }] });
649
+ class ZIsEndSecondDisabledPipe {
650
+ transform(second, context) {
651
+ if (!context.isSameDay) {
652
+ return false;
653
+ }
654
+ let actualStartHour = context.startHour;
655
+ let actualEndHour = context.endHour;
656
+ if (context.timeFormat === '12h') {
657
+ if (context.startPeriod === 'PM' && context.startHour !== 12) {
658
+ actualStartHour = context.startHour + 12;
659
+ }
660
+ if (context.startPeriod === 'AM' && context.startHour === 12) {
661
+ actualStartHour = 0;
662
+ }
663
+ if (context.endPeriod === 'PM' && context.endHour !== 12) {
664
+ actualEndHour = context.endHour + 12;
665
+ }
666
+ if (context.endPeriod === 'AM' && context.endHour === 12) {
667
+ actualEndHour = 0;
668
+ }
669
+ }
670
+ if (actualEndHour !== actualStartHour) {
671
+ return false;
672
+ }
673
+ if (context.endMinute !== context.startMinute) {
674
+ return false;
675
+ }
676
+ return second <= context.startSecond;
677
+ }
678
+ static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "21.0.6", ngImport: i0, type: ZIsEndSecondDisabledPipe, deps: [], target: i0.ɵɵFactoryTarget.Pipe });
679
+ static ɵpipe = i0.ɵɵngDeclarePipe({ minVersion: "14.0.0", version: "21.0.6", ngImport: i0, type: ZIsEndSecondDisabledPipe, isStandalone: true, name: "zIsEndSecondDisabled" });
680
+ }
681
+ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.0.6", ngImport: i0, type: ZIsEndSecondDisabledPipe, decorators: [{
682
+ type: Pipe,
683
+ args: [{
684
+ name: 'zIsEndSecondDisabled',
685
+ standalone: true,
686
+ pure: true,
687
+ }]
688
+ }] });
689
+
550
690
  class ZMonthClassesPipe {
551
- transform(monthIndex, currentMonthIndex) {
552
- const state = getMonthState(monthIndex, currentMonthIndex);
691
+ transform(monthIndex, selectedMonthIndex, todayMonthIndex) {
692
+ const state = getMonthState(monthIndex, selectedMonthIndex, todayMonthIndex);
553
693
  return zCalendarMonthVariants({ state });
554
694
  }
555
695
  static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "21.0.6", ngImport: i0, type: ZMonthClassesPipe, deps: [], target: i0.ɵɵFactoryTarget.Pipe });
@@ -564,9 +704,130 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.0.6", ngImpor
564
704
  }]
565
705
  }] });
566
706
 
707
+ class ZIsStartMonthDisabledPipe {
708
+ transform(monthIndex, context) {
709
+ if (context.disabledDateFn) {
710
+ const monthDate = new Date(context.currentYear, monthIndex, 1);
711
+ if (context.disabledDateFn(monthDate)) {
712
+ return true;
713
+ }
714
+ }
715
+ if (!context.isRangeMode) {
716
+ return false;
717
+ }
718
+ if (context.currentYear > context.endYear) {
719
+ return true;
720
+ }
721
+ if (context.currentYear === context.endYear && monthIndex > context.endMonthIndex) {
722
+ return true;
723
+ }
724
+ return false;
725
+ }
726
+ static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "21.0.6", ngImport: i0, type: ZIsStartMonthDisabledPipe, deps: [], target: i0.ɵɵFactoryTarget.Pipe });
727
+ static ɵpipe = i0.ɵɵngDeclarePipe({ minVersion: "14.0.0", version: "21.0.6", ngImport: i0, type: ZIsStartMonthDisabledPipe, isStandalone: true, name: "zIsStartMonthDisabled" });
728
+ }
729
+ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.0.6", ngImport: i0, type: ZIsStartMonthDisabledPipe, decorators: [{
730
+ type: Pipe,
731
+ args: [{
732
+ name: 'zIsStartMonthDisabled',
733
+ standalone: true,
734
+ pure: true,
735
+ }]
736
+ }] });
737
+ class ZIsEndMonthDisabledPipe {
738
+ transform(monthIndex, context) {
739
+ if (context.disabledDateFn) {
740
+ const monthDate = new Date(context.endYear, monthIndex, 1);
741
+ if (context.disabledDateFn(monthDate)) {
742
+ return true;
743
+ }
744
+ }
745
+ if (!context.isRangeMode) {
746
+ return false;
747
+ }
748
+ if (context.endYear < context.startYear) {
749
+ return true;
750
+ }
751
+ if (context.endYear === context.startYear && monthIndex < context.startMonthIndex) {
752
+ return true;
753
+ }
754
+ return false;
755
+ }
756
+ static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "21.0.6", ngImport: i0, type: ZIsEndMonthDisabledPipe, deps: [], target: i0.ɵɵFactoryTarget.Pipe });
757
+ static ɵpipe = i0.ɵɵngDeclarePipe({ minVersion: "14.0.0", version: "21.0.6", ngImport: i0, type: ZIsEndMonthDisabledPipe, isStandalone: true, name: "zIsEndMonthDisabled" });
758
+ }
759
+ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.0.6", ngImport: i0, type: ZIsEndMonthDisabledPipe, decorators: [{
760
+ type: Pipe,
761
+ args: [{
762
+ name: 'zIsEndMonthDisabled',
763
+ standalone: true,
764
+ pure: true,
765
+ }]
766
+ }] });
767
+ class ZIsStartYearDisabledPipe {
768
+ transform(year, context) {
769
+ if (context.disabledDateFn) {
770
+ const yearDate = new Date(year, 0, 1);
771
+ if (context.disabledDateFn(yearDate)) {
772
+ return true;
773
+ }
774
+ }
775
+ if (!context.isRangeMode) {
776
+ return false;
777
+ }
778
+ if (year > context.endYear) {
779
+ return true;
780
+ }
781
+ if (year === context.endYear && context.startMonthIndex >= context.endMonthIndex) {
782
+ return true;
783
+ }
784
+ return false;
785
+ }
786
+ static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "21.0.6", ngImport: i0, type: ZIsStartYearDisabledPipe, deps: [], target: i0.ɵɵFactoryTarget.Pipe });
787
+ static ɵpipe = i0.ɵɵngDeclarePipe({ minVersion: "14.0.0", version: "21.0.6", ngImport: i0, type: ZIsStartYearDisabledPipe, isStandalone: true, name: "zIsStartYearDisabled" });
788
+ }
789
+ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.0.6", ngImport: i0, type: ZIsStartYearDisabledPipe, decorators: [{
790
+ type: Pipe,
791
+ args: [{
792
+ name: 'zIsStartYearDisabled',
793
+ standalone: true,
794
+ pure: true,
795
+ }]
796
+ }] });
797
+ class ZIsEndYearDisabledPipe {
798
+ transform(year, context) {
799
+ if (context.disabledDateFn) {
800
+ const yearDate = new Date(year, 0, 1);
801
+ if (context.disabledDateFn(yearDate)) {
802
+ return true;
803
+ }
804
+ }
805
+ if (!context.isRangeMode) {
806
+ return false;
807
+ }
808
+ if (year < context.startYear) {
809
+ return true;
810
+ }
811
+ if (year === context.startYear && context.endMonthIndex <= context.startMonthIndex) {
812
+ return true;
813
+ }
814
+ return false;
815
+ }
816
+ static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "21.0.6", ngImport: i0, type: ZIsEndYearDisabledPipe, deps: [], target: i0.ɵɵFactoryTarget.Pipe });
817
+ static ɵpipe = i0.ɵɵngDeclarePipe({ minVersion: "14.0.0", version: "21.0.6", ngImport: i0, type: ZIsEndYearDisabledPipe, isStandalone: true, name: "zIsEndYearDisabled" });
818
+ }
819
+ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.0.6", ngImport: i0, type: ZIsEndYearDisabledPipe, decorators: [{
820
+ type: Pipe,
821
+ args: [{
822
+ name: 'zIsEndYearDisabled',
823
+ standalone: true,
824
+ pure: true,
825
+ }]
826
+ }] });
827
+
567
828
  class ZQuarterClassesPipe {
568
- transform(quarterIndex, currentQuarterIndex) {
569
- const state = getQuarterState(quarterIndex, currentQuarterIndex);
829
+ transform(quarterIndex, selectedQuarterIndex, todayQuarterIndex) {
830
+ const state = getQuarterState(quarterIndex, selectedQuarterIndex, todayQuarterIndex);
570
831
  return zCalendarQuarterVariants({ state });
571
832
  }
572
833
  static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "21.0.6", ngImport: i0, type: ZQuarterClassesPipe, deps: [], target: i0.ɵɵFactoryTarget.Pipe });
@@ -581,9 +842,25 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.0.6", ngImpor
581
842
  }]
582
843
  }] });
583
844
 
845
+ class ZIsTimeSelectedPipe {
846
+ transform(value, selectedValue) {
847
+ return value === selectedValue;
848
+ }
849
+ static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "21.0.6", ngImport: i0, type: ZIsTimeSelectedPipe, deps: [], target: i0.ɵɵFactoryTarget.Pipe });
850
+ static ɵpipe = i0.ɵɵngDeclarePipe({ minVersion: "14.0.0", version: "21.0.6", ngImport: i0, type: ZIsTimeSelectedPipe, isStandalone: true, name: "zIsTimeSelected" });
851
+ }
852
+ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.0.6", ngImport: i0, type: ZIsTimeSelectedPipe, decorators: [{
853
+ type: Pipe,
854
+ args: [{
855
+ name: 'zIsTimeSelected',
856
+ standalone: true,
857
+ pure: true,
858
+ }]
859
+ }] });
860
+
584
861
  class ZYearClassesPipe {
585
- transform(year, currentYear) {
586
- const state = getYearState(year, currentYear);
862
+ transform(year, selectedYear, todayYear) {
863
+ const state = getYearState(year, selectedYear, todayYear);
587
864
  return zCalendarYearVariants({ state });
588
865
  }
589
866
  static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "21.0.6", ngImport: i0, type: ZYearClassesPipe, deps: [], target: i0.ɵɵFactoryTarget.Pipe });
@@ -644,17 +921,17 @@ class ZCalendarComponent {
644
921
  minuteOptions = Array.from({ length: 60 }, (_, i) => i);
645
922
  secondOptions = Array.from({ length: 60 }, (_, i) => i);
646
923
  formattedHour = computed(() => {
647
- const h = this._hour();
924
+ const h = this.hour();
648
925
  if (this.zTimeFormat() === '12h') {
649
926
  const h12 = h % 12 || 12;
650
927
  return formatTimeValue(h12);
651
928
  }
652
929
  return formatTimeValue(h);
653
930
  }, ...(ngDevMode ? [{ debugName: "formattedHour" }] : []));
654
- formattedMinute = computed(() => formatTimeValue(this._minute()), ...(ngDevMode ? [{ debugName: "formattedMinute" }] : []));
655
- formattedSecond = computed(() => formatTimeValue(this._second()), ...(ngDevMode ? [{ debugName: "formattedSecond" }] : []));
931
+ formattedMinute = computed(() => formatTimeValue(this.minute()), ...(ngDevMode ? [{ debugName: "formattedMinute" }] : []));
932
+ formattedSecond = computed(() => formatTimeValue(this.second()), ...(ngDevMode ? [{ debugName: "formattedSecond" }] : []));
656
933
  displayHour = computed(() => {
657
- const h = this._hour();
934
+ const h = this.hour();
658
935
  if (this.zTimeFormat() === '12h') {
659
936
  return h % 12 || 12;
660
937
  }
@@ -671,15 +948,8 @@ class ZCalendarComponent {
671
948
  _selectedDate = signal(null, ...(ngDevMode ? [{ debugName: "_selectedDate" }] : []));
672
949
  _rangeStart = signal(null, ...(ngDevMode ? [{ debugName: "_rangeStart" }] : []));
673
950
  _rangeEnd = signal(null, ...(ngDevMode ? [{ debugName: "_rangeEnd" }] : []));
674
- _hoveredDate = signal(null, ...(ngDevMode ? [{ debugName: "_hoveredDate" }] : []));
675
951
  _currentMonth = signal(getToday(), ...(ngDevMode ? [{ debugName: "_currentMonth" }] : []));
676
952
  _endMonth = signal(addMonths(getToday(), 1), ...(ngDevMode ? [{ debugName: "_endMonth" }] : []));
677
- _currentView = signal('day', ...(ngDevMode ? [{ debugName: "_currentView" }] : []));
678
- _endView = signal('day', ...(ngDevMode ? [{ debugName: "_endView" }] : []));
679
- _hour = signal(0, ...(ngDevMode ? [{ debugName: "_hour" }] : []));
680
- _minute = signal(0, ...(ngDevMode ? [{ debugName: "_minute" }] : []));
681
- _second = signal(0, ...(ngDevMode ? [{ debugName: "_second" }] : []));
682
- _period = signal('AM', ...(ngDevMode ? [{ debugName: "_period" }] : []));
683
953
  _hourEnd = signal(0, ...(ngDevMode ? [{ debugName: "_hourEnd" }] : []));
684
954
  _minuteEnd = signal(0, ...(ngDevMode ? [{ debugName: "_minuteEnd" }] : []));
685
955
  _secondEnd = signal(0, ...(ngDevMode ? [{ debugName: "_secondEnd" }] : []));
@@ -689,38 +959,40 @@ class ZCalendarComponent {
689
959
  _dirty = signal(false, ...(ngDevMode ? [{ debugName: "_dirty" }] : []));
690
960
  _formControl = signal(null, ...(ngDevMode ? [{ debugName: "_formControl" }] : []));
691
961
  _formStateVersion = signal(0, ...(ngDevMode ? [{ debugName: "_formStateVersion" }] : []));
692
- _inputDisplayValue = signal('', ...(ngDevMode ? [{ debugName: "_inputDisplayValue" }] : []));
693
962
  _backupSelectedDate = signal(null, ...(ngDevMode ? [{ debugName: "_backupSelectedDate" }] : []));
694
963
  _backupRangeStart = signal(null, ...(ngDevMode ? [{ debugName: "_backupRangeStart" }] : []));
695
964
  _backupRangeEnd = signal(null, ...(ngDevMode ? [{ debugName: "_backupRangeEnd" }] : []));
696
- _activePresetKey = signal(null, ...(ngDevMode ? [{ debugName: "_activePresetKey" }] : []));
697
- _hasViewChanged = signal(false, ...(ngDevMode ? [{ debugName: "_hasViewChanged" }] : []));
698
- _hasEndViewChanged = signal(false, ...(ngDevMode ? [{ debugName: "_hasEndViewChanged" }] : []));
699
965
  _appliedViaOk = signal(false, ...(ngDevMode ? [{ debugName: "_appliedViaOk" }] : []));
700
966
  _skipBlurHandler = signal(false, ...(ngDevMode ? [{ debugName: "_skipBlurHandler" }] : []));
701
967
  _injector = inject(Injector);
702
968
  _destroyRef = inject(DestroyRef);
703
- _cdr = inject(ChangeDetectorRef);
704
969
  _zTranslate = inject(ZTranslateService);
705
970
  _onChange = () => void 0;
706
971
  _onTouched = () => void 0;
707
972
  _ngControl = null;
708
973
  isOpen = computed(() => this._popoverControl()?.isVisible() ?? false, ...(ngDevMode ? [{ debugName: "isOpen" }] : []));
709
- hoveredDate = this._hoveredDate.asReadonly();
710
- currentView = this._currentView.asReadonly();
711
- hour = this._hour.asReadonly();
712
- minute = this._minute.asReadonly();
713
- second = this._second.asReadonly();
714
- period = this._period.asReadonly();
715
- inputDisplayValue = this._inputDisplayValue.asReadonly();
716
- activePresetKey = this._activePresetKey.asReadonly();
717
- hasViewChanged = this._hasViewChanged.asReadonly();
718
- hasEndViewChanged = this._hasEndViewChanged.asReadonly();
974
+ hoveredDate = signal(null, ...(ngDevMode ? [{ debugName: "hoveredDate" }] : []));
975
+ currentView = signal('day', ...(ngDevMode ? [{ debugName: "currentView" }] : []));
976
+ endView = signal('day', ...(ngDevMode ? [{ debugName: "endView" }] : []));
977
+ hour = signal(0, ...(ngDevMode ? [{ debugName: "hour" }] : []));
978
+ minute = signal(0, ...(ngDevMode ? [{ debugName: "minute" }] : []));
979
+ second = signal(0, ...(ngDevMode ? [{ debugName: "second" }] : []));
980
+ period = signal('AM', ...(ngDevMode ? [{ debugName: "period" }] : []));
981
+ inputDisplayValue = signal('', ...(ngDevMode ? [{ debugName: "inputDisplayValue" }] : []));
982
+ activePresetKey = signal(null, ...(ngDevMode ? [{ debugName: "activePresetKey" }] : []));
983
+ hasViewChanged = signal(false, ...(ngDevMode ? [{ debugName: "hasViewChanged" }] : []));
984
+ hasEndViewChanged = signal(false, ...(ngDevMode ? [{ debugName: "hasEndViewChanged" }] : []));
985
+ timeDropdownOpen = signal(false, ...(ngDevMode ? [{ debugName: "timeDropdownOpen" }] : []));
986
+ timeDropdownEndOpen = signal(false, ...(ngDevMode ? [{ debugName: "timeDropdownEndOpen" }] : []));
719
987
  quarterNames = ['Q1', 'Q2', 'Q3', 'Q4'];
720
- currentQuarterIndex = computed(() => {
988
+ todayQuarterIndex = computed(() => {
989
+ const today = new Date();
990
+ return Math.floor(today.getMonth() / 3);
991
+ }, ...(ngDevMode ? [{ debugName: "todayQuarterIndex" }] : []));
992
+ selectedQuarterIndex = computed(() => {
721
993
  const date = this._selectedDate();
722
994
  return date ? Math.floor(date.getMonth() / 3) : -1;
723
- }, ...(ngDevMode ? [{ debugName: "currentQuarterIndex" }] : []));
995
+ }, ...(ngDevMode ? [{ debugName: "selectedQuarterIndex" }] : []));
724
996
  isSameDayRange = computed(() => {
725
997
  if (!this.isRangeMode()) {
726
998
  return false;
@@ -768,6 +1040,55 @@ class ZCalendarComponent {
768
1040
  currentMonth = computed(() => this._currentMonth(), ...(ngDevMode ? [{ debugName: "currentMonth" }] : []));
769
1041
  currentYear = computed(() => this._currentMonth().getFullYear(), ...(ngDevMode ? [{ debugName: "currentYear" }] : []));
770
1042
  currentMonthIndex = computed(() => this._currentMonth().getMonth(), ...(ngDevMode ? [{ debugName: "currentMonthIndex" }] : []));
1043
+ todayMonthIndex = computed(() => new Date().getMonth(), ...(ngDevMode ? [{ debugName: "todayMonthIndex" }] : []));
1044
+ todayYear = computed(() => new Date().getFullYear(), ...(ngDevMode ? [{ debugName: "todayYear" }] : []));
1045
+ selectedMonthIndex = computed(() => {
1046
+ const date = this._selectedDate();
1047
+ return date ? date.getMonth() : -1;
1048
+ }, ...(ngDevMode ? [{ debugName: "selectedMonthIndex" }] : []));
1049
+ selectedYear = computed(() => {
1050
+ const date = this._selectedDate();
1051
+ return date ? date.getFullYear() : -1;
1052
+ }, ...(ngDevMode ? [{ debugName: "selectedYear" }] : []));
1053
+ endTimeContext = computed(() => ({
1054
+ isSameDay: this.isSameDayRange(),
1055
+ startHour: this.hour(),
1056
+ startMinute: this.minute(),
1057
+ startSecond: this.second(),
1058
+ endHour: this._hourEnd(),
1059
+ endMinute: this._minuteEnd(),
1060
+ timeFormat: this.zTimeFormat(),
1061
+ startPeriod: this.period(),
1062
+ endPeriod: this._periodEnd(),
1063
+ }), ...(ngDevMode ? [{ debugName: "endTimeContext" }] : []));
1064
+ startMonthDisabledContext = computed(() => ({
1065
+ currentYear: this._currentMonth().getFullYear(),
1066
+ endYear: this._endMonth().getFullYear(),
1067
+ endMonthIndex: this._endMonth().getMonth(),
1068
+ isRangeMode: this.isRangeMode(),
1069
+ disabledDateFn: this.zDisabledDate(),
1070
+ }), ...(ngDevMode ? [{ debugName: "startMonthDisabledContext" }] : []));
1071
+ endMonthDisabledContext = computed(() => ({
1072
+ startYear: this._currentMonth().getFullYear(),
1073
+ startMonthIndex: this._currentMonth().getMonth(),
1074
+ endYear: this._endMonth().getFullYear(),
1075
+ isRangeMode: this.isRangeMode(),
1076
+ disabledDateFn: this.zDisabledDate(),
1077
+ }), ...(ngDevMode ? [{ debugName: "endMonthDisabledContext" }] : []));
1078
+ startYearDisabledContext = computed(() => ({
1079
+ endYear: this._endMonth().getFullYear(),
1080
+ startMonthIndex: this._currentMonth().getMonth(),
1081
+ endMonthIndex: this._endMonth().getMonth(),
1082
+ isRangeMode: this.isRangeMode(),
1083
+ disabledDateFn: this.zDisabledDate(),
1084
+ }), ...(ngDevMode ? [{ debugName: "startYearDisabledContext" }] : []));
1085
+ endYearDisabledContext = computed(() => ({
1086
+ startYear: this._currentMonth().getFullYear(),
1087
+ startMonthIndex: this._currentMonth().getMonth(),
1088
+ endMonthIndex: this._endMonth().getMonth(),
1089
+ isRangeMode: this.isRangeMode(),
1090
+ disabledDateFn: this.zDisabledDate(),
1091
+ }), ...(ngDevMode ? [{ debugName: "endYearDisabledContext" }] : []));
771
1092
  currentMonthName = computed(() => {
772
1093
  const month = this._currentMonth();
773
1094
  return month.toLocaleDateString(this.zLocale(), { month: 'long' });
@@ -788,7 +1109,7 @@ class ZCalendarComponent {
788
1109
  selectedDate: this._selectedDate(),
789
1110
  rangeStart: this._rangeStart(),
790
1111
  rangeEnd: this._rangeEnd(),
791
- hoveredDate: this._hoveredDate(),
1112
+ hoveredDate: this.hoveredDate(),
792
1113
  minDate: this.zMinDate(),
793
1114
  maxDate: this.zMaxDate(),
794
1115
  disabledDate: this.zDisabledDate(),
@@ -808,7 +1129,7 @@ class ZCalendarComponent {
808
1129
  selectedDate: this._selectedDate(),
809
1130
  rangeStart: this._rangeStart(),
810
1131
  rangeEnd: this._rangeEnd(),
811
- hoveredDate: this._hoveredDate(),
1132
+ hoveredDate: this.hoveredDate(),
812
1133
  minDate: this.zMinDate(),
813
1134
  maxDate: this.zMaxDate(),
814
1135
  disabledDate: this.zDisabledDate(),
@@ -817,111 +1138,20 @@ class ZCalendarComponent {
817
1138
  formattedHourEnd = computed(() => formatTimeValue(this.zTimeFormat() === '12h' ? this._hourEnd() % 12 || 12 : this._hourEnd()), ...(ngDevMode ? [{ debugName: "formattedHourEnd" }] : []));
818
1139
  formattedMinuteEnd = computed(() => formatTimeValue(this._minuteEnd()), ...(ngDevMode ? [{ debugName: "formattedMinuteEnd" }] : []));
819
1140
  formattedSecondEnd = computed(() => formatTimeValue(this._secondEnd()), ...(ngDevMode ? [{ debugName: "formattedSecondEnd" }] : []));
1141
+ minuteEnd = computed(() => this._minuteEnd(), ...(ngDevMode ? [{ debugName: "minuteEnd" }] : []));
1142
+ secondEnd = computed(() => this._secondEnd(), ...(ngDevMode ? [{ debugName: "secondEnd" }] : []));
820
1143
  periodEnd = computed(() => this._periodEnd(), ...(ngDevMode ? [{ debugName: "periodEnd" }] : []));
821
- endView = this._endView.asReadonly();
822
1144
  endYearRange = computed(() => {
823
1145
  const currentYear = this._endMonth().getFullYear();
824
1146
  return getYearRange(currentYear);
825
1147
  }, ...(ngDevMode ? [{ debugName: "endYearRange" }] : []));
826
- isStartMonthDisabled(monthIndex) {
827
- const disabledDateFn = this.zDisabledDate();
828
- if (disabledDateFn) {
829
- const year = this._currentMonth().getFullYear();
830
- const monthDate = new Date(year, monthIndex, 1);
831
- if (disabledDateFn(monthDate)) {
832
- return true;
833
- }
834
- }
835
- if (!this.isRangeMode()) {
836
- return false;
837
- }
838
- const startYear = this._currentMonth().getFullYear();
839
- const endMonth = this._endMonth();
840
- const endYear = endMonth.getFullYear();
841
- const endMonthIndex = endMonth.getMonth();
842
- if (startYear > endYear) {
843
- return true;
844
- }
845
- if (startYear === endYear && monthIndex > endMonthIndex) {
846
- return true;
847
- }
848
- return false;
849
- }
850
- isEndMonthDisabled(monthIndex) {
851
- const disabledDateFn = this.zDisabledDate();
852
- if (disabledDateFn) {
853
- const year = this._endMonth().getFullYear();
854
- const monthDate = new Date(year, monthIndex, 1);
855
- if (disabledDateFn(monthDate)) {
856
- return true;
857
- }
858
- }
859
- if (!this.isRangeMode()) {
860
- return false;
861
- }
862
- const startMonth = this._currentMonth();
863
- const startYear = startMonth.getFullYear();
864
- const startMonthIndex = startMonth.getMonth();
865
- const endYear = this._endMonth().getFullYear();
866
- if (endYear < startYear) {
867
- return true;
868
- }
869
- if (endYear === startYear && monthIndex < startMonthIndex) {
870
- return true;
871
- }
872
- return false;
873
- }
874
- isStartYearDisabled(year) {
875
- const disabledDateFn = this.zDisabledDate();
876
- if (disabledDateFn) {
877
- const yearDate = new Date(year, 0, 1);
878
- if (disabledDateFn(yearDate)) {
879
- return true;
880
- }
881
- }
882
- if (!this.isRangeMode()) {
883
- return false;
884
- }
885
- const endYear = this._endMonth().getFullYear();
886
- const startMonthIndex = this._currentMonth().getMonth();
887
- const endMonthIndex = this._endMonth().getMonth();
888
- if (year > endYear) {
889
- return true;
890
- }
891
- if (year === endYear && startMonthIndex >= endMonthIndex) {
892
- return true;
893
- }
894
- return false;
895
- }
896
- isEndYearDisabled(year) {
897
- const disabledDateFn = this.zDisabledDate();
898
- if (disabledDateFn) {
899
- const yearDate = new Date(year, 0, 1);
900
- if (disabledDateFn(yearDate)) {
901
- return true;
902
- }
903
- }
904
- if (!this.isRangeMode()) {
905
- return false;
906
- }
907
- const startYear = this._currentMonth().getFullYear();
908
- const startMonthIndex = this._currentMonth().getMonth();
909
- const endMonthIndex = this._endMonth().getMonth();
910
- if (year < startYear) {
911
- return true;
912
- }
913
- if (year === startYear && endMonthIndex <= startMonthIndex) {
914
- return true;
915
- }
916
- return false;
917
- }
918
1148
  canNavigateStartNext = computed(() => {
919
1149
  if (!this.isRangeMode()) {
920
1150
  return true;
921
1151
  }
922
1152
  const current = this._currentMonth();
923
1153
  const end = this._endMonth();
924
- const view = this._currentView();
1154
+ const view = this.currentView();
925
1155
  if (view === 'day') {
926
1156
  const startNext = addMonths(current, 1);
927
1157
  return (startNext.getFullYear() < end.getFullYear() ||
@@ -944,7 +1174,7 @@ class ZCalendarComponent {
944
1174
  }
945
1175
  const start = this._currentMonth();
946
1176
  const end = this._endMonth();
947
- const view = this._endView();
1177
+ const view = this.endView();
948
1178
  if (view === 'day') {
949
1179
  const endPrev = addMonths(end, -1);
950
1180
  return (endPrev.getFullYear() > start.getFullYear() ||
@@ -975,7 +1205,7 @@ class ZCalendarComponent {
975
1205
  timeParts.push('ss');
976
1206
  }
977
1207
  const timeFormat = timeParts.join(':');
978
- const periodSuffix = this.zTimeFormat() === '12h' ? ` ${this._period()}` : '';
1208
+ const periodSuffix = this.zTimeFormat() === '12h' ? ` ${this.period()}` : '';
979
1209
  format = this.isTimeMode() ? timeFormat + periodSuffix : `${this.zFormat()} ${timeFormat}${periodSuffix}`;
980
1210
  }
981
1211
  if (this.isRangeMode()) {
@@ -1030,7 +1260,7 @@ class ZCalendarComponent {
1030
1260
  timeParts.push('ss');
1031
1261
  }
1032
1262
  const timeFormat = timeParts.join(':');
1033
- const periodSuffix = this.zTimeFormat() === '12h' ? ` ${this._period()}` : '';
1263
+ const periodSuffix = this.zTimeFormat() === '12h' ? ` ${this.period()}` : '';
1034
1264
  format = this.isTimeMode() ? timeFormat + periodSuffix : `${this.zFormat()} ${timeFormat}${periodSuffix}`;
1035
1265
  }
1036
1266
  return format;
@@ -1132,9 +1362,9 @@ class ZCalendarComponent {
1132
1362
  effect(() => {
1133
1363
  const date = this._selectedDate();
1134
1364
  if (date && this.zShowTime()) {
1135
- this._hour.set(date.getHours());
1136
- this._minute.set(date.getMinutes());
1137
- this._second.set(date.getSeconds());
1365
+ this.hour.set(date.getHours());
1366
+ this.minute.set(date.getMinutes());
1367
+ this.second.set(date.getSeconds());
1138
1368
  }
1139
1369
  });
1140
1370
  }
@@ -1151,14 +1381,13 @@ class ZCalendarComponent {
1151
1381
  .pipe(takeUntilDestroyed(this._destroyRef))
1152
1382
  .subscribe(() => {
1153
1383
  this._formStateVersion.update(v => v + 1);
1154
- this._cdr.markForCheck();
1155
1384
  });
1156
1385
  }
1157
1386
  catch {
1158
1387
  this._ngControl = null;
1159
1388
  }
1160
1389
  });
1161
- setTimeout(() => this._emitControl());
1390
+ this._emitControl();
1162
1391
  }
1163
1392
  writeValue(value) {
1164
1393
  if (value === null || value === undefined) {
@@ -1177,11 +1406,8 @@ class ZCalendarComponent {
1177
1406
  this._currentMonth.set(range.start);
1178
1407
  this._endMonth.set(isSameMonth(range.start, range.end) ? addMonths(range.end, 1) : range.end);
1179
1408
  }
1180
- setTimeout(() => {
1181
- this._inputDisplayStart.set(this.displayValueStart());
1182
- this._inputDisplayEnd.set(this.displayValueEnd());
1183
- this._cdr.markForCheck();
1184
- });
1409
+ this._inputDisplayStart.set(this.displayValueStart());
1410
+ this._inputDisplayEnd.set(this.displayValueEnd());
1185
1411
  }
1186
1412
  return;
1187
1413
  }
@@ -1247,12 +1473,12 @@ class ZCalendarComponent {
1247
1473
  this._selectedDate.set(null);
1248
1474
  this._rangeStart.set(null);
1249
1475
  this._rangeEnd.set(null);
1250
- this._hour.set(0);
1251
- this._minute.set(0);
1252
- this._second.set(0);
1476
+ this.hour.set(0);
1477
+ this.minute.set(0);
1478
+ this.second.set(0);
1253
1479
  this._touched.set(false);
1254
1480
  this._dirty.set(false);
1255
- this._inputDisplayValue.set('');
1481
+ this.inputDisplayValue.set('');
1256
1482
  const emitValue = this._getEmitValue();
1257
1483
  this._onChange(emitValue);
1258
1484
  if (this._ngControl?.control) {
@@ -1285,33 +1511,32 @@ class ZCalendarComponent {
1285
1511
  onPopoverShow() {
1286
1512
  this._backupIfNeeded();
1287
1513
  this._appliedViaOk.set(false);
1288
- this._hasViewChanged.set(false);
1289
- this._hasEndViewChanged.set(false);
1514
+ this.hasViewChanged.set(false);
1515
+ this.hasEndViewChanged.set(false);
1290
1516
  if (this.isMonthMode()) {
1291
- this._currentView.set('month');
1517
+ this.currentView.set('month');
1292
1518
  this._initializeTimeIfNeeded();
1293
1519
  return;
1294
1520
  }
1295
1521
  if (this.isYearMode()) {
1296
- this._currentView.set('year');
1522
+ this.currentView.set('year');
1297
1523
  this._initializeTimeIfNeeded();
1298
1524
  return;
1299
1525
  }
1300
1526
  if (this.isQuarterMode()) {
1301
- this._currentView.set('quarter');
1527
+ this.currentView.set('quarter');
1302
1528
  this._initializeTimeIfNeeded();
1303
1529
  return;
1304
1530
  }
1305
- this._currentView.set('day');
1531
+ this.currentView.set('day');
1306
1532
  this._initializeTimeIfNeeded();
1307
1533
  if (this.isRangeMode()) {
1308
- this._endView.set('day');
1534
+ this.endView.set('day');
1309
1535
  this._inputDisplayStart.set(this.displayValueStart());
1310
1536
  this._inputDisplayEnd.set(this.displayValueEnd());
1311
1537
  }
1312
- this._scrollToTimeOnOpen();
1313
1538
  if (!this.isRangeMode()) {
1314
- this._activePresetKey.set(null);
1539
+ this.activePresetKey.set(null);
1315
1540
  const selected = this._selectedDate();
1316
1541
  if (selected) {
1317
1542
  this._currentMonth.set(selected);
@@ -1325,15 +1550,15 @@ class ZCalendarComponent {
1325
1550
  if (start && end) {
1326
1551
  this._currentMonth.set(start);
1327
1552
  this._endMonth.set(isSameMonth(start, end) ? addMonths(end, 1) : end);
1328
- this._activePresetKey.set(this._detectMatchingPreset(start, end));
1553
+ this.activePresetKey.set(this._detectMatchingPreset(start, end));
1329
1554
  return;
1330
1555
  }
1331
1556
  if (this.zQuickSelect()) {
1332
- this._activePresetKey.set(null);
1557
+ this.activePresetKey.set(null);
1333
1558
  this._resetCalendarsToDefault();
1334
1559
  return;
1335
1560
  }
1336
- this._activePresetKey.set(null);
1561
+ this.activePresetKey.set(null);
1337
1562
  this._resetCalendarsToDefault();
1338
1563
  }
1339
1564
  _initializeTimeIfNeeded() {
@@ -1362,8 +1587,8 @@ class ZCalendarComponent {
1362
1587
  const today = getToday();
1363
1588
  this._currentMonth.set(today);
1364
1589
  this._endMonth.set(addMonths(today, 1));
1365
- this._currentView.set('day');
1366
- this._endView.set('day');
1590
+ this.currentView.set('day');
1591
+ this.endView.set('day');
1367
1592
  }
1368
1593
  _backupIfNeeded() {
1369
1594
  this._backupSelectedDate.set(this._selectedDate());
@@ -1371,7 +1596,7 @@ class ZCalendarComponent {
1371
1596
  this._backupRangeEnd.set(this._rangeEnd());
1372
1597
  }
1373
1598
  onPopoverHide() {
1374
- this._hoveredDate.set(null);
1599
+ this.hoveredDate.set(null);
1375
1600
  const needsConfirmation = this.showOkButton() || this.showCancelButton();
1376
1601
  if (needsConfirmation && !this._appliedViaOk()) {
1377
1602
  this._restoreFromBackup();
@@ -1387,7 +1612,7 @@ class ZCalendarComponent {
1387
1612
  this._touched.set(true);
1388
1613
  }
1389
1614
  this._onTouched();
1390
- this._inputDisplayValue.set(this.displayValue());
1615
+ this.inputDisplayValue.set(this.displayValue());
1391
1616
  if (this.isRangeMode()) {
1392
1617
  this._inputDisplayStart.set(this.displayValueStart());
1393
1618
  this._inputDisplayEnd.set(this.displayValueEnd());
@@ -1416,7 +1641,7 @@ class ZCalendarComponent {
1416
1641
  if (backup) {
1417
1642
  this._syncTimeSignals(backup);
1418
1643
  }
1419
- this._inputDisplayValue.set(this.displayValue());
1644
+ this.inputDisplayValue.set(this.displayValue());
1420
1645
  }
1421
1646
  onPopoverControl(control) {
1422
1647
  this._popoverControl.set(control);
@@ -1438,7 +1663,7 @@ class ZCalendarComponent {
1438
1663
  onInputChange(event) {
1439
1664
  const input = event.target;
1440
1665
  const { value } = input;
1441
- this._inputDisplayValue.set(value);
1666
+ this.inputDisplayValue.set(value);
1442
1667
  const trimmedValue = value.trim();
1443
1668
  if (!trimmedValue) {
1444
1669
  return;
@@ -1469,7 +1694,6 @@ class ZCalendarComponent {
1469
1694
  this._selectedDate.set(date);
1470
1695
  this._currentMonth.set(date);
1471
1696
  this._syncTimeSignals(date);
1472
- this._scrollToCurrentTime();
1473
1697
  }
1474
1698
  }
1475
1699
  _getExpectedFormatLength(format) {
@@ -1500,7 +1724,6 @@ class ZCalendarComponent {
1500
1724
  this._rangeStart.set(date);
1501
1725
  this._currentMonth.set(date);
1502
1726
  this._syncTimeSignals(date);
1503
- this._scrollToCurrentTime();
1504
1727
  }
1505
1728
  onEndInputChange(event) {
1506
1729
  const input = event.target;
@@ -1527,7 +1750,6 @@ class ZCalendarComponent {
1527
1750
  this._rangeEnd.set(date);
1528
1751
  this._endMonth.set(date);
1529
1752
  this._syncEndTimeSignals(date);
1530
- this._scrollToEndTime();
1531
1753
  }
1532
1754
  onStartInputEnter(event) {
1533
1755
  event.preventDefault();
@@ -1606,7 +1828,7 @@ class ZCalendarComponent {
1606
1828
  if (!currentValue) {
1607
1829
  this._selectedDate.set(null);
1608
1830
  this._backupSelectedDate.set(null);
1609
- this._inputDisplayValue.set('');
1831
+ this.inputDisplayValue.set('');
1610
1832
  this._applyValue();
1611
1833
  return;
1612
1834
  }
@@ -1616,13 +1838,13 @@ class ZCalendarComponent {
1616
1838
  this._currentMonth.set(parsed);
1617
1839
  this._syncTimeSignals(parsed);
1618
1840
  this._backupSelectedDate.set(parsed);
1619
- this._inputDisplayValue.set(this.displayValue());
1841
+ this.inputDisplayValue.set(this.displayValue());
1620
1842
  this._applyValue();
1621
1843
  return;
1622
1844
  }
1623
1845
  const backup = this._backupSelectedDate();
1624
1846
  this._selectedDate.set(backup);
1625
- this._inputDisplayValue.set(this.displayValue());
1847
+ this.inputDisplayValue.set(this.displayValue());
1626
1848
  }
1627
1849
  onInputEnter(event) {
1628
1850
  event.preventDefault();
@@ -1692,7 +1914,7 @@ class ZCalendarComponent {
1692
1914
  this._cancelAndRestore();
1693
1915
  return;
1694
1916
  }
1695
- if (this._currentView() !== 'day') {
1917
+ if (this.currentView() !== 'day') {
1696
1918
  return;
1697
1919
  }
1698
1920
  if (key === 'Enter') {
@@ -1722,12 +1944,12 @@ class ZCalendarComponent {
1722
1944
  }
1723
1945
  onDayHover(day) {
1724
1946
  if (this.isRangeMode() && this._rangeStart() && !this._rangeEnd()) {
1725
- this._hoveredDate.set(day.date);
1947
+ this.hoveredDate.set(day.date);
1726
1948
  }
1727
1949
  }
1728
1950
  onDayLeave() {
1729
1951
  if (this.isRangeMode()) {
1730
- this._hoveredDate.set(null);
1952
+ this.hoveredDate.set(null);
1731
1953
  }
1732
1954
  }
1733
1955
  onMonthClick(monthIndex) {
@@ -1742,15 +1964,15 @@ class ZCalendarComponent {
1742
1964
  }
1743
1965
  }
1744
1966
  this._currentMonth.set(newMonth);
1745
- this._hasViewChanged.set(true);
1746
- this._currentView.set('day');
1967
+ this.hasViewChanged.set(true);
1968
+ this.currentView.set('day');
1747
1969
  }
1748
1970
  onYearClick(year) {
1749
1971
  const currentDate = this._currentMonth();
1750
1972
  if (this.isYearMode()) {
1751
1973
  this._selectedDate.set(setYear(new Date(year, 0, 1), year));
1752
1974
  this._dirty.set(true);
1753
- this._inputDisplayValue.set(this.displayValue());
1975
+ this.inputDisplayValue.set(this.displayValue());
1754
1976
  this._applyValue();
1755
1977
  this.close();
1756
1978
  return;
@@ -1763,8 +1985,8 @@ class ZCalendarComponent {
1763
1985
  }
1764
1986
  }
1765
1987
  this._currentMonth.set(setYear(currentDate, newYear));
1766
- this._hasViewChanged.set(true);
1767
- this._currentView.set(this.isQuarterMode() ? 'quarter' : 'month');
1988
+ this.hasViewChanged.set(true);
1989
+ this.currentView.set(this.isQuarterMode() ? 'quarter' : 'month');
1768
1990
  }
1769
1991
  onQuarterClick(quarterIndex) {
1770
1992
  const currentYear = this._currentMonth().getFullYear();
@@ -1772,7 +1994,7 @@ class ZCalendarComponent {
1772
1994
  const date = new Date(currentYear, firstMonthOfQuarter, 1);
1773
1995
  this._selectedDate.set(date);
1774
1996
  this._dirty.set(true);
1775
- this._inputDisplayValue.set(this.displayValue());
1997
+ this.inputDisplayValue.set(this.displayValue());
1776
1998
  this._applyValue();
1777
1999
  this.close();
1778
2000
  }
@@ -1781,7 +2003,7 @@ class ZCalendarComponent {
1781
2003
  const currentYear = this._currentMonth().getFullYear();
1782
2004
  this._selectedDate.set(new Date(currentYear, monthIndex, 1));
1783
2005
  this._dirty.set(true);
1784
- this._inputDisplayValue.set(this.displayValue());
2006
+ this.inputDisplayValue.set(this.displayValue());
1785
2007
  this._applyValue();
1786
2008
  this.close();
1787
2009
  return;
@@ -1789,7 +2011,7 @@ class ZCalendarComponent {
1789
2011
  this.onMonthClick(monthIndex);
1790
2012
  }
1791
2013
  onQuickSelect(preset) {
1792
- this._activePresetKey.set(preset.key);
2014
+ this.activePresetKey.set(preset.key);
1793
2015
  if (preset.key === 'custom') {
1794
2016
  this._rangeStart.set(null);
1795
2017
  this._rangeEnd.set(null);
@@ -1834,16 +2056,15 @@ class ZCalendarComponent {
1834
2056
  const today = getToday();
1835
2057
  this._currentMonth.set(today);
1836
2058
  if (this.zShowTime() || this.isTimeMode()) {
1837
- this._hour.set(now.getHours());
1838
- this._minute.set(now.getMinutes());
1839
- this._second.set(now.getSeconds());
1840
- this._period.set(now.getHours() >= 12 ? 'PM' : 'AM');
1841
- this._scrollToCurrentTime();
2059
+ this.hour.set(now.getHours());
2060
+ this.minute.set(now.getMinutes());
2061
+ this.second.set(now.getSeconds());
2062
+ this.period.set(now.getHours() >= 12 ? 'PM' : 'AM');
1842
2063
  }
1843
2064
  if (this.isMonthMode()) {
1844
2065
  this._selectedDate.set(new Date(now.getFullYear(), now.getMonth(), 1));
1845
2066
  this._dirty.set(true);
1846
- this._inputDisplayValue.set(this.displayValue());
2067
+ this.inputDisplayValue.set(this.displayValue());
1847
2068
  this._applyValue();
1848
2069
  this.close();
1849
2070
  return;
@@ -1851,7 +2072,7 @@ class ZCalendarComponent {
1851
2072
  if (this.isYearMode()) {
1852
2073
  this._selectedDate.set(new Date(now.getFullYear(), 0, 1));
1853
2074
  this._dirty.set(true);
1854
- this._inputDisplayValue.set(this.displayValue());
2075
+ this.inputDisplayValue.set(this.displayValue());
1855
2076
  this._applyValue();
1856
2077
  this.close();
1857
2078
  return;
@@ -1860,7 +2081,7 @@ class ZCalendarComponent {
1860
2081
  const currentQuarter = Math.floor(now.getMonth() / 3);
1861
2082
  this._selectedDate.set(new Date(now.getFullYear(), currentQuarter * 3, 1));
1862
2083
  this._dirty.set(true);
1863
- this._inputDisplayValue.set(this.displayValue());
2084
+ this.inputDisplayValue.set(this.displayValue());
1864
2085
  this._applyValue();
1865
2086
  this.close();
1866
2087
  return;
@@ -1868,7 +2089,7 @@ class ZCalendarComponent {
1868
2089
  if (this.isTimeMode()) {
1869
2090
  this._selectedDate.set(now);
1870
2091
  this._dirty.set(true);
1871
- this._inputDisplayValue.set(this.displayValue());
2092
+ this.inputDisplayValue.set(this.displayValue());
1872
2093
  if (!this.showOkButton()) {
1873
2094
  this._applyValue();
1874
2095
  this.close();
@@ -1895,7 +2116,7 @@ class ZCalendarComponent {
1895
2116
  const selectedDate = this.zShowTime() ? now : today;
1896
2117
  this._selectedDate.set(selectedDate);
1897
2118
  this._dirty.set(true);
1898
- this._inputDisplayValue.set(this.displayValue());
2119
+ this.inputDisplayValue.set(this.displayValue());
1899
2120
  if (!this.showOkButton()) {
1900
2121
  this._applyValue();
1901
2122
  this.close();
@@ -1907,9 +2128,9 @@ class ZCalendarComponent {
1907
2128
  this._selectedDate.set(null);
1908
2129
  this._rangeStart.set(null);
1909
2130
  this._rangeEnd.set(null);
1910
- this._hour.set(0);
1911
- this._minute.set(0);
1912
- this._second.set(0);
2131
+ this.hour.set(0);
2132
+ this.minute.set(0);
2133
+ this.second.set(0);
1913
2134
  this._dirty.set(true);
1914
2135
  this._backupSelectedDate.set(null);
1915
2136
  this._backupRangeStart.set(null);
@@ -1918,7 +2139,7 @@ class ZCalendarComponent {
1918
2139
  const emitValue = this._getEmitValue();
1919
2140
  this._onChange(emitValue);
1920
2141
  this.zChange.emit(emitValue);
1921
- this._inputDisplayValue.set('');
2142
+ this.inputDisplayValue.set('');
1922
2143
  if (this.isRangeMode()) {
1923
2144
  this._inputDisplayStart.set('');
1924
2145
  this._inputDisplayEnd.set('');
@@ -1933,24 +2154,24 @@ class ZCalendarComponent {
1933
2154
  return;
1934
2155
  }
1935
2156
  if (this.isTimeMode()) {
1936
- let hour = this._hour();
2157
+ let hour = this.hour();
1937
2158
  if (this.zTimeFormat() === '12h') {
1938
- if (this._period() === 'PM' && hour < 12) {
2159
+ if (this.period() === 'PM' && hour < 12) {
1939
2160
  hour += 12;
1940
2161
  }
1941
- if (this._period() === 'AM' && hour === 12) {
2162
+ if (this.period() === 'AM' && hour === 12) {
1942
2163
  hour = 0;
1943
2164
  }
1944
2165
  }
1945
2166
  const baseDate = this._selectedDate() ?? new Date();
1946
- this._selectedDate.set(setTime(baseDate, hour, this._minute(), this._second()));
2167
+ this._selectedDate.set(setTime(baseDate, hour, this.minute(), this.second()));
1947
2168
  }
1948
2169
  this._appliedViaOk.set(true);
1949
2170
  this._applyValue();
1950
2171
  this.close();
1951
2172
  }
1952
2173
  navigatePrevious() {
1953
- const view = this._currentView();
2174
+ const view = this.currentView();
1954
2175
  const current = this._currentMonth();
1955
2176
  const yearStep = this.isYearMode() || this.isQuarterMode() ? 9 : 12;
1956
2177
  const navigationMap = {
@@ -1962,7 +2183,7 @@ class ZCalendarComponent {
1962
2183
  this._currentMonth.set(navigationMap[view]);
1963
2184
  }
1964
2185
  navigateNext() {
1965
- const view = this._currentView();
2186
+ const view = this.currentView();
1966
2187
  const current = this._currentMonth();
1967
2188
  const yearStep = this.isYearMode() || this.isQuarterMode() ? 9 : 12;
1968
2189
  const navigationMap = {
@@ -1982,12 +2203,12 @@ class ZCalendarComponent {
1982
2203
  this._currentMonth.set(addYears(current, 1));
1983
2204
  }
1984
2205
  setView(view) {
1985
- this._hasViewChanged.set(true);
1986
- this._currentView.set(view);
2206
+ this.hasViewChanged.set(true);
2207
+ this.currentView.set(view);
1987
2208
  }
1988
2209
  setEndView(view) {
1989
- this._hasEndViewChanged.set(true);
1990
- this._endView.set(view);
2210
+ this.hasEndViewChanged.set(true);
2211
+ this.endView.set(view);
1991
2212
  }
1992
2213
  onEndMonthClick(monthIndex) {
1993
2214
  const currentDate = this._endMonth();
@@ -1999,8 +2220,8 @@ class ZCalendarComponent {
1999
2220
  newMonth = addMonths(startMonth, 1);
2000
2221
  }
2001
2222
  this._endMonth.set(newMonth);
2002
- this._hasEndViewChanged.set(true);
2003
- this._endView.set('day');
2223
+ this.hasEndViewChanged.set(true);
2224
+ this.endView.set('day');
2004
2225
  }
2005
2226
  onEndYearClick(year) {
2006
2227
  const currentDate = this._endMonth();
@@ -2010,8 +2231,8 @@ class ZCalendarComponent {
2010
2231
  newYear = startYear + 1;
2011
2232
  }
2012
2233
  this._endMonth.set(setYear(currentDate, newYear));
2013
- this._hasEndViewChanged.set(true);
2014
- this._endView.set('month');
2234
+ this.hasEndViewChanged.set(true);
2235
+ this.endView.set('month');
2015
2236
  }
2016
2237
  onHourInput(event) {
2017
2238
  const input = event.target;
@@ -2020,7 +2241,7 @@ class ZCalendarComponent {
2020
2241
  return;
2021
2242
  }
2022
2243
  const value = parseTimeValue(digits, 23);
2023
- this._hour.set(value);
2244
+ this.hour.set(value);
2024
2245
  this._updateTimeToDate();
2025
2246
  this._updateInputDisplayAfterTimeChange();
2026
2247
  }
@@ -2031,7 +2252,7 @@ class ZCalendarComponent {
2031
2252
  return;
2032
2253
  }
2033
2254
  const value = parseTimeValue(digits, 59);
2034
- this._minute.set(value);
2255
+ this.minute.set(value);
2035
2256
  this._updateTimeToDate();
2036
2257
  this._updateInputDisplayAfterTimeChange();
2037
2258
  }
@@ -2042,7 +2263,7 @@ class ZCalendarComponent {
2042
2263
  return;
2043
2264
  }
2044
2265
  const value = parseTimeValue(digits, 59);
2045
- this._second.set(value);
2266
+ this.second.set(value);
2046
2267
  this._updateTimeToDate();
2047
2268
  this._updateInputDisplayAfterTimeChange();
2048
2269
  }
@@ -2053,19 +2274,19 @@ class ZCalendarComponent {
2053
2274
  if (digits.length > 0 && digits.length <= 2) {
2054
2275
  if (dataType === 'hour') {
2055
2276
  const value = parseTimeValue(digits, this.zTimeFormat() === '12h' ? 12 : 23);
2056
- this._hour.set(value);
2277
+ this.hour.set(value);
2057
2278
  this._updateTimeToDate();
2058
2279
  this._updateInputDisplayAfterTimeChange();
2059
2280
  }
2060
2281
  if (dataType === 'minute') {
2061
2282
  const value = parseTimeValue(digits, 59);
2062
- this._minute.set(value);
2283
+ this.minute.set(value);
2063
2284
  this._updateTimeToDate();
2064
2285
  this._updateInputDisplayAfterTimeChange();
2065
2286
  }
2066
2287
  if (dataType === 'second') {
2067
2288
  const value = parseTimeValue(digits, 59);
2068
- this._second.set(value);
2289
+ this.second.set(value);
2069
2290
  this._updateTimeToDate();
2070
2291
  this._updateInputDisplayAfterTimeChange();
2071
2292
  }
@@ -2198,11 +2419,11 @@ class ZCalendarComponent {
2198
2419
  _handleSingleSelection(date) {
2199
2420
  let finalDate = date;
2200
2421
  if (this.zShowTime()) {
2201
- finalDate = setTime(date, this._hour(), this._minute(), this._second());
2422
+ finalDate = setTime(date, this.hour(), this.minute(), this.second());
2202
2423
  }
2203
2424
  this._selectedDate.set(finalDate);
2204
2425
  this._dirty.set(true);
2205
- this._inputDisplayValue.set(this.displayValue());
2426
+ this.inputDisplayValue.set(this.displayValue());
2206
2427
  if (!this.zShowTime() && !this.zShowOk()) {
2207
2428
  this._applyValue();
2208
2429
  this.close();
@@ -2214,20 +2435,20 @@ class ZCalendarComponent {
2214
2435
  if (!start || (start && end)) {
2215
2436
  let startDate = date;
2216
2437
  if (this.zShowTime()) {
2217
- let hour = this._hour();
2438
+ let hour = this.hour();
2218
2439
  if (this.zTimeFormat() === '12h') {
2219
- if (this._period() === 'PM' && hour < 12) {
2440
+ if (this.period() === 'PM' && hour < 12) {
2220
2441
  hour += 12;
2221
2442
  }
2222
- if (this._period() === 'AM' && hour === 12) {
2443
+ if (this.period() === 'AM' && hour === 12) {
2223
2444
  hour = 0;
2224
2445
  }
2225
2446
  }
2226
- startDate = setTime(date, hour, this._minute(), this._second());
2447
+ startDate = setTime(date, hour, this.minute(), this.second());
2227
2448
  }
2228
2449
  this._rangeStart.set(startDate);
2229
2450
  this._rangeEnd.set(null);
2230
- this._activePresetKey.set('custom');
2451
+ this.activePresetKey.set('custom');
2231
2452
  this._inputDisplayStart.set(this.displayValueStart());
2232
2453
  this._inputDisplayEnd.set('');
2233
2454
  return;
@@ -2252,7 +2473,7 @@ class ZCalendarComponent {
2252
2473
  this._inputDisplayStart.set(this.displayValueStart());
2253
2474
  this._inputDisplayEnd.set(this.displayValueEnd());
2254
2475
  if (normalized.start && normalized.end) {
2255
- this._activePresetKey.set(this._detectMatchingPreset(normalized.start, normalized.end));
2476
+ this.activePresetKey.set(this._detectMatchingPreset(normalized.start, normalized.end));
2256
2477
  }
2257
2478
  if (!this.showOkButton() && !this.showCancelButton()) {
2258
2479
  this._applyValue();
@@ -2260,29 +2481,29 @@ class ZCalendarComponent {
2260
2481
  }
2261
2482
  }
2262
2483
  _updateTimeToDate() {
2263
- if (!this.zShowTime()) {
2484
+ if (!this.zShowTime() && !this.isTimeMode()) {
2264
2485
  return;
2265
2486
  }
2266
- let hour = this._hour();
2487
+ let hour = this.hour();
2267
2488
  if (this.zTimeFormat() === '12h') {
2268
- if (this._period() === 'PM' && hour < 12) {
2489
+ if (this.period() === 'PM' && hour < 12) {
2269
2490
  hour += 12;
2270
2491
  }
2271
- if (this._period() === 'AM' && hour === 12) {
2492
+ if (this.period() === 'AM' && hour === 12) {
2272
2493
  hour = 0;
2273
2494
  }
2274
2495
  }
2275
2496
  if (this.isRangeMode()) {
2276
2497
  const start = this._rangeStart();
2277
2498
  if (start) {
2278
- this._rangeStart.set(setTime(start, hour, this._minute(), this._second()));
2499
+ this._rangeStart.set(setTime(start, hour, this.minute(), this.second()));
2279
2500
  this._dirty.set(true);
2280
2501
  }
2281
2502
  return;
2282
2503
  }
2283
2504
  const selected = this._selectedDate();
2284
2505
  if (selected) {
2285
- this._selectedDate.set(setTime(selected, hour, this._minute(), this._second()));
2506
+ this._selectedDate.set(setTime(selected, hour, this.minute(), this.second()));
2286
2507
  }
2287
2508
  }
2288
2509
  _detectMatchingPreset(start, end) {
@@ -2304,7 +2525,7 @@ class ZCalendarComponent {
2304
2525
  this._onChange(emitValue);
2305
2526
  this.zChange.emit(emitValue);
2306
2527
  this._dirty.set(true);
2307
- this._inputDisplayValue.set(this.displayValue());
2528
+ this.inputDisplayValue.set(this.displayValue());
2308
2529
  if (this.isRangeMode()) {
2309
2530
  this._inputDisplayStart.set(this.displayValueStart());
2310
2531
  this._inputDisplayEnd.set(this.displayValueEnd());
@@ -2393,10 +2614,10 @@ class ZCalendarComponent {
2393
2614
  }
2394
2615
  }
2395
2616
  _syncTimeSignals(date) {
2396
- this._hour.set(date.getHours());
2397
- this._minute.set(date.getMinutes());
2398
- this._second.set(date.getSeconds());
2399
- this._period.set(date.getHours() >= 12 ? 'PM' : 'AM');
2617
+ this.hour.set(date.getHours());
2618
+ this.minute.set(date.getMinutes());
2619
+ this.second.set(date.getSeconds());
2620
+ this.period.set(date.getHours() >= 12 ? 'PM' : 'AM');
2400
2621
  }
2401
2622
  _getParseFormat() {
2402
2623
  if (!this.zShowTime() && !this.isTimeMode()) {
@@ -2419,7 +2640,7 @@ class ZCalendarComponent {
2419
2640
  return `${this.zFormat()} ${timeFormat}`;
2420
2641
  }
2421
2642
  _updateInputDisplay() {
2422
- this._inputDisplayValue.set(this.displayValue());
2643
+ this.inputDisplayValue.set(this.displayValue());
2423
2644
  }
2424
2645
  _clearDateValues() {
2425
2646
  if (this.isRangeMode()) {
@@ -2449,7 +2670,7 @@ class ZCalendarComponent {
2449
2670
  this._inputDisplayEnd.set(this.displayValueEnd());
2450
2671
  return;
2451
2672
  }
2452
- this._inputDisplayValue.set(this.displayValue());
2673
+ this.inputDisplayValue.set(this.displayValue());
2453
2674
  }
2454
2675
  _emitControl() {
2455
2676
  this.zControl.emit({
@@ -2471,65 +2692,170 @@ class ZCalendarComponent {
2471
2692
  });
2472
2693
  }
2473
2694
  togglePeriod() {
2474
- const currentPeriod = this._period();
2695
+ const currentPeriod = this.period();
2475
2696
  const newPeriod = currentPeriod === 'AM' ? 'PM' : 'AM';
2476
- this._period.set(newPeriod);
2477
- const currentHour = this._hour();
2697
+ this.period.set(newPeriod);
2698
+ const currentHour = this.hour();
2478
2699
  if (newPeriod === 'PM' && currentHour < 12) {
2479
- this._hour.set(currentHour + 12);
2700
+ this.hour.set(currentHour + 12);
2480
2701
  }
2481
2702
  if (newPeriod === 'AM' && currentHour >= 12) {
2482
- this._hour.set(currentHour - 12);
2703
+ this.hour.set(currentHour - 12);
2483
2704
  }
2484
2705
  this._updateTimeToDate();
2485
2706
  this._updateInputDisplayAfterTimeChange();
2486
2707
  }
2708
+ incrementHour() {
2709
+ const maxHour = this.zTimeFormat() === '12h' ? 12 : 23;
2710
+ const minHour = this.zTimeFormat() === '12h' ? 1 : 0;
2711
+ let currentHour = this.displayHour();
2712
+ currentHour = currentHour >= maxHour ? minHour : currentHour + 1;
2713
+ this.selectHour(currentHour);
2714
+ }
2715
+ decrementHour() {
2716
+ const maxHour = this.zTimeFormat() === '12h' ? 12 : 23;
2717
+ const minHour = this.zTimeFormat() === '12h' ? 1 : 0;
2718
+ let currentHour = this.displayHour();
2719
+ currentHour = currentHour <= minHour ? maxHour : currentHour - 1;
2720
+ this.selectHour(currentHour);
2721
+ }
2722
+ incrementMinute() {
2723
+ let currentMinute = this.minute();
2724
+ currentMinute = currentMinute >= 59 ? 0 : currentMinute + 1;
2725
+ this.selectMinute(currentMinute);
2726
+ }
2727
+ decrementMinute() {
2728
+ let currentMinute = this.minute();
2729
+ currentMinute = currentMinute <= 0 ? 59 : currentMinute - 1;
2730
+ this.selectMinute(currentMinute);
2731
+ }
2732
+ incrementSecond() {
2733
+ let currentSecond = this.second();
2734
+ currentSecond = currentSecond >= 59 ? 0 : currentSecond + 1;
2735
+ this.selectSecond(currentSecond);
2736
+ }
2737
+ decrementSecond() {
2738
+ let currentSecond = this.second();
2739
+ currentSecond = currentSecond <= 0 ? 59 : currentSecond - 1;
2740
+ this.selectSecond(currentSecond);
2741
+ }
2742
+ incrementHourEnd() {
2743
+ const maxHour = this.zTimeFormat() === '12h' ? 12 : 23;
2744
+ const minHour = this.zTimeFormat() === '12h' ? 1 : 0;
2745
+ let currentHour = this.displayHourEnd();
2746
+ currentHour = currentHour >= maxHour ? minHour : currentHour + 1;
2747
+ this.selectHourEnd(currentHour);
2748
+ }
2749
+ decrementHourEnd() {
2750
+ const maxHour = this.zTimeFormat() === '12h' ? 12 : 23;
2751
+ const minHour = this.zTimeFormat() === '12h' ? 1 : 0;
2752
+ let currentHour = this.displayHourEnd();
2753
+ currentHour = currentHour <= minHour ? maxHour : currentHour - 1;
2754
+ this.selectHourEnd(currentHour);
2755
+ }
2756
+ incrementMinuteEnd() {
2757
+ let currentMinute = this._minuteEnd();
2758
+ currentMinute = currentMinute >= 59 ? 0 : currentMinute + 1;
2759
+ this.selectMinuteEnd(currentMinute);
2760
+ }
2761
+ decrementMinuteEnd() {
2762
+ let currentMinute = this._minuteEnd();
2763
+ currentMinute = currentMinute <= 0 ? 59 : currentMinute - 1;
2764
+ this.selectMinuteEnd(currentMinute);
2765
+ }
2766
+ incrementSecondEnd() {
2767
+ let currentSecond = this._secondEnd();
2768
+ currentSecond = currentSecond >= 59 ? 0 : currentSecond + 1;
2769
+ this.selectSecondEnd(currentSecond);
2770
+ }
2771
+ decrementSecondEnd() {
2772
+ let currentSecond = this._secondEnd();
2773
+ currentSecond = currentSecond <= 0 ? 59 : currentSecond - 1;
2774
+ this.selectSecondEnd(currentSecond);
2775
+ }
2776
+ openTimeDropdown(event) {
2777
+ event.stopPropagation();
2778
+ this.timeDropdownOpen.set(true);
2779
+ }
2780
+ closeTimeDropdown() {
2781
+ this.timeDropdownOpen.set(false);
2782
+ }
2783
+ openTimeDropdownEnd(event) {
2784
+ event.stopPropagation();
2785
+ this.timeDropdownEndOpen.set(true);
2786
+ }
2787
+ closeTimeDropdownEnd() {
2788
+ this.timeDropdownEndOpen.set(false);
2789
+ }
2790
+ onTimeDropdownShow() {
2791
+ this._scrollToTimeDropdown();
2792
+ }
2793
+ onTimeDropdownEndShow() {
2794
+ this._scrollToTimeDropdown(true);
2795
+ }
2796
+ _scrollToTimeDropdown(isEnd = false) {
2797
+ setTimeout(() => {
2798
+ const suffix = isEnd ? '-end' : '';
2799
+ if (this.zShowHour()) {
2800
+ this._scrollToTimeValue(`.z-time-scroll-hour${suffix}`);
2801
+ }
2802
+ if (this.zShowMinute()) {
2803
+ this._scrollToTimeValue(`.z-time-scroll-minute${suffix}`);
2804
+ }
2805
+ if (this.zShowSecond()) {
2806
+ this._scrollToTimeValue(`.z-time-scroll-second${suffix}`);
2807
+ }
2808
+ });
2809
+ }
2487
2810
  _updateInputDisplayAfterTimeChange() {
2488
2811
  if (this.isRangeMode()) {
2489
2812
  this._inputDisplayStart.set(this.displayValueStart());
2490
2813
  return;
2491
2814
  }
2492
- this._inputDisplayValue.set(this.displayValue());
2815
+ this.inputDisplayValue.set(this.displayValue());
2493
2816
  }
2494
2817
  onPeriodChange(event) {
2495
2818
  const select = event.target;
2496
2819
  const newPeriod = select.value;
2497
- const currentHour = this._hour();
2498
- this._period.set(newPeriod);
2820
+ const currentHour = this.hour();
2821
+ this.period.set(newPeriod);
2499
2822
  if (newPeriod === 'PM' && currentHour < 12) {
2500
- this._hour.set(currentHour + 12);
2823
+ this.hour.set(currentHour + 12);
2501
2824
  }
2502
2825
  if (newPeriod === 'AM' && currentHour >= 12) {
2503
- this._hour.set(currentHour - 12);
2826
+ this.hour.set(currentHour - 12);
2504
2827
  }
2505
2828
  this._updateTimeToDate();
2506
2829
  }
2507
2830
  selectHour(hour) {
2508
2831
  let actualHour = hour;
2509
2832
  if (this.zTimeFormat() === '12h') {
2510
- if (this._period() === 'PM' && hour !== 12) {
2833
+ if (this.period() === 'PM' && hour !== 12) {
2511
2834
  actualHour = hour + 12;
2512
2835
  }
2513
- if (this._period() === 'AM' && hour === 12) {
2836
+ if (this.period() === 'AM' && hour === 12) {
2514
2837
  actualHour = 0;
2515
2838
  }
2516
2839
  }
2517
- this._hour.set(actualHour);
2840
+ this.hour.set(actualHour);
2518
2841
  this._updateTimeToDate();
2519
2842
  this._updateInputDisplayAfterTimeChange();
2843
+ this._scrollToTimeValue('.z-time-scroll-hour');
2520
2844
  }
2521
2845
  selectMinute(minute) {
2522
- this._minute.set(minute);
2846
+ this.minute.set(minute);
2523
2847
  this._updateTimeToDate();
2524
2848
  this._updateInputDisplayAfterTimeChange();
2849
+ this._scrollToTimeValue('.z-time-scroll-minute');
2525
2850
  }
2526
2851
  selectSecond(second) {
2527
- this._second.set(second);
2852
+ this.second.set(second);
2528
2853
  this._updateTimeToDate();
2529
2854
  this._updateInputDisplayAfterTimeChange();
2855
+ this._scrollToTimeValue('.z-time-scroll-second');
2530
2856
  }
2531
2857
  selectPeriod(period) {
2532
- if (this._period() === period) {
2858
+ if (this.period() === period) {
2533
2859
  return;
2534
2860
  }
2535
2861
  this.togglePeriod();
@@ -2547,16 +2873,19 @@ class ZCalendarComponent {
2547
2873
  this._hourEnd.set(actualHour);
2548
2874
  this._updateEndTimeToDate();
2549
2875
  this._inputDisplayEnd.set(this.displayValueEnd());
2876
+ this._scrollToTimeValue('.z-time-scroll-hour-end');
2550
2877
  }
2551
2878
  selectMinuteEnd(minute) {
2552
2879
  this._minuteEnd.set(minute);
2553
2880
  this._updateEndTimeToDate();
2554
2881
  this._inputDisplayEnd.set(this.displayValueEnd());
2882
+ this._scrollToTimeValue('.z-time-scroll-minute-end');
2555
2883
  }
2556
2884
  selectSecondEnd(second) {
2557
2885
  this._secondEnd.set(second);
2558
2886
  this._updateEndTimeToDate();
2559
2887
  this._inputDisplayEnd.set(this.displayValueEnd());
2888
+ this._scrollToTimeValue('.z-time-scroll-second-end');
2560
2889
  }
2561
2890
  selectPeriodEnd(period) {
2562
2891
  if (this._periodEnd() === period) {
@@ -2571,268 +2900,15 @@ class ZCalendarComponent {
2571
2900
  const scrollTop = value * itemHeight;
2572
2901
  container.scrollTo({ top: scrollTop, behavior: 'smooth' });
2573
2902
  }
2574
- isHourSelected(hour) {
2575
- return this.displayHour() === hour;
2576
- }
2577
- isMinuteSelected(minute) {
2578
- return this._minute() === minute;
2579
- }
2580
- isSecondSelected(second) {
2581
- return this._second() === second;
2582
- }
2583
- isHourEndSelected(hour) {
2584
- return this.displayHourEnd() === hour;
2585
- }
2586
- isMinuteEndSelected(minute) {
2587
- return this._minuteEnd() === minute;
2588
- }
2589
- isSecondEndSelected(second) {
2590
- return this._secondEnd() === second;
2591
- }
2592
- isEndHourDisabled(hour) {
2593
- if (!this.isSameDayRange()) {
2594
- return false;
2595
- }
2596
- const startHour = this._hour();
2597
- let actualHour = hour;
2598
- let actualStartHour = startHour;
2599
- if (this.zTimeFormat() === '12h') {
2600
- if (this._periodEnd() === 'PM' && hour !== 12) {
2601
- actualHour = hour + 12;
2602
- }
2603
- if (this._periodEnd() === 'AM' && hour === 12) {
2604
- actualHour = 0;
2605
- }
2606
- if (this._period() === 'PM' && startHour !== 12) {
2607
- actualStartHour = startHour + 12;
2608
- }
2609
- if (this._period() === 'AM' && startHour === 12) {
2610
- actualStartHour = 0;
2611
- }
2612
- }
2613
- return actualHour < actualStartHour;
2614
- }
2615
- isEndMinuteDisabled(minute) {
2616
- if (!this.isSameDayRange()) {
2617
- return false;
2618
- }
2619
- const startHour = this._hour();
2620
- const endHour = this._hourEnd();
2621
- let actualStartHour = startHour;
2622
- let actualEndHour = endHour;
2623
- if (this.zTimeFormat() === '12h') {
2624
- if (this._period() === 'PM' && startHour !== 12) {
2625
- actualStartHour = startHour + 12;
2626
- }
2627
- if (this._period() === 'AM' && startHour === 12) {
2628
- actualStartHour = 0;
2629
- }
2630
- if (this._periodEnd() === 'PM' && endHour !== 12) {
2631
- actualEndHour = endHour + 12;
2632
- }
2633
- if (this._periodEnd() === 'AM' && endHour === 12) {
2634
- actualEndHour = 0;
2635
- }
2636
- }
2637
- if (actualEndHour !== actualStartHour) {
2638
- return false;
2639
- }
2640
- return minute < this._minute();
2641
- }
2642
- isEndSecondDisabled(second) {
2643
- if (!this.isSameDayRange()) {
2644
- return false;
2645
- }
2646
- const startHour = this._hour();
2647
- const endHour = this._hourEnd();
2648
- let actualStartHour = startHour;
2649
- let actualEndHour = endHour;
2650
- if (this.zTimeFormat() === '12h') {
2651
- if (this._period() === 'PM' && startHour !== 12) {
2652
- actualStartHour = startHour + 12;
2653
- }
2654
- if (this._period() === 'AM' && startHour === 12) {
2655
- actualStartHour = 0;
2656
- }
2657
- if (this._periodEnd() === 'PM' && endHour !== 12) {
2658
- actualEndHour = endHour + 12;
2659
- }
2660
- if (this._periodEnd() === 'AM' && endHour === 12) {
2661
- actualEndHour = 0;
2662
- }
2663
- }
2664
- if (actualEndHour !== actualStartHour) {
2665
- return false;
2666
- }
2667
- if (this._minuteEnd() !== this._minute()) {
2668
- return false;
2669
- }
2670
- return second <= this._second();
2671
- }
2672
- isEndPeriodDisabled(period) {
2673
- if (!this.isSameDayRange()) {
2674
- return false;
2675
- }
2676
- if (this._period() === 'PM' && period === 'AM') {
2677
- return true;
2678
- }
2679
- return false;
2680
- }
2681
- _scrollToCurrentTime() {
2682
- if (!this.zShowTime() && !this.isTimeMode()) {
2683
- return;
2684
- }
2685
- const itemHeight = 28;
2686
- setTimeout(() => {
2687
- const timeColumns = document.querySelectorAll('.z-time-column');
2688
- if (!timeColumns.length) {
2689
- return;
2690
- }
2691
- const columnsArray = Array.from(timeColumns);
2692
- const startIndex = 0;
2693
- let columnIndex = startIndex;
2694
- if (this.zShowHour()) {
2695
- const hourColumn = columnsArray[columnIndex];
2696
- if (hourColumn) {
2697
- const hourValue = this.zTimeFormat() === '12h' ? this.displayHour() - 1 : this._hour();
2698
- hourColumn.scrollTo({ top: hourValue * itemHeight, behavior: 'smooth' });
2699
- }
2700
- columnIndex++;
2701
- }
2702
- if (this.zShowMinute()) {
2703
- const minuteColumn = columnsArray[columnIndex];
2704
- if (minuteColumn) {
2705
- minuteColumn.scrollTo({ top: this._minute() * itemHeight, behavior: 'smooth' });
2706
- }
2707
- columnIndex++;
2708
- }
2709
- if (this.zShowSecond()) {
2710
- const secondColumn = columnsArray[columnIndex];
2711
- if (secondColumn) {
2712
- secondColumn.scrollTo({ top: this._second() * itemHeight, behavior: 'smooth' });
2713
- }
2714
- }
2715
- }, 50);
2716
- }
2717
- _scrollToEndTime() {
2718
- if (!this.zShowTime() || !this.isRangeMode()) {
2903
+ _scrollToTimeValue(scrollbarSelector) {
2904
+ const scrollbar = document.querySelector(scrollbarSelector);
2905
+ if (!scrollbar) {
2719
2906
  return;
2720
2907
  }
2721
- const itemHeight = 28;
2722
- setTimeout(() => {
2723
- const timeColumns = document.querySelectorAll('.z-time-column');
2724
- if (!timeColumns.length) {
2725
- return;
2726
- }
2727
- const columnsArray = Array.from(timeColumns);
2728
- const columnsPerSection = (this.zShowHour() ? 1 : 0) + (this.zShowMinute() ? 1 : 0) + (this.zShowSecond() ? 1 : 0);
2729
- const endStartIndex = columnsPerSection;
2730
- let columnIndex = endStartIndex;
2731
- if (this.zShowHour()) {
2732
- const hourColumn = columnsArray[columnIndex];
2733
- if (hourColumn) {
2734
- const hourValue = this.zTimeFormat() === '12h' ? this.displayHourEnd() - 1 : this._hourEnd();
2735
- hourColumn.scrollTo({ top: hourValue * itemHeight, behavior: 'smooth' });
2736
- }
2737
- columnIndex++;
2738
- }
2739
- if (this.zShowMinute()) {
2740
- const minuteColumn = columnsArray[columnIndex];
2741
- if (minuteColumn) {
2742
- minuteColumn.scrollTo({ top: this._minuteEnd() * itemHeight, behavior: 'smooth' });
2743
- }
2744
- columnIndex++;
2745
- }
2746
- if (this.zShowSecond()) {
2747
- const secondColumn = columnsArray[columnIndex];
2748
- if (secondColumn) {
2749
- secondColumn.scrollTo({ top: this._secondEnd() * itemHeight, behavior: 'smooth' });
2750
- }
2751
- }
2752
- }, 50);
2753
- }
2754
- _scrollToTimeOnOpen() {
2755
- if (!this.zShowTime() && !this.isTimeMode()) {
2756
- return;
2908
+ const selectedButton = scrollbar.querySelector('button.bg-primary');
2909
+ if (selectedButton) {
2910
+ selectedButton.scrollIntoView({ block: 'center', behavior: 'smooth' });
2757
2911
  }
2758
- const itemHeight = 28;
2759
- setTimeout(() => {
2760
- const timeColumns = document.querySelectorAll('.z-time-column');
2761
- if (!timeColumns.length) {
2762
- return;
2763
- }
2764
- const columnsArray = Array.from(timeColumns);
2765
- if (this.isRangeMode()) {
2766
- const columnsPerSection = (this.zShowHour() ? 1 : 0) + (this.zShowMinute() ? 1 : 0) + (this.zShowSecond() ? 1 : 0);
2767
- let columnIndex = 0;
2768
- if (this.zShowHour()) {
2769
- const hourColumn = columnsArray[columnIndex];
2770
- if (hourColumn) {
2771
- const hourValue = this.zTimeFormat() === '12h' ? this.displayHour() - 1 : this._hour();
2772
- hourColumn.scrollTop = hourValue * itemHeight;
2773
- }
2774
- columnIndex++;
2775
- }
2776
- if (this.zShowMinute()) {
2777
- const minuteColumn = columnsArray[columnIndex];
2778
- if (minuteColumn) {
2779
- minuteColumn.scrollTop = this._minute() * itemHeight;
2780
- }
2781
- columnIndex++;
2782
- }
2783
- if (this.zShowSecond()) {
2784
- const secondColumn = columnsArray[columnIndex];
2785
- if (secondColumn) {
2786
- secondColumn.scrollTop = this._second() * itemHeight;
2787
- }
2788
- }
2789
- columnIndex = columnsPerSection;
2790
- if (this.zShowHour()) {
2791
- const hourColumn = columnsArray[columnIndex];
2792
- if (hourColumn) {
2793
- const hourValue = this.zTimeFormat() === '12h' ? this.displayHourEnd() - 1 : this._hourEnd();
2794
- hourColumn.scrollTop = hourValue * itemHeight;
2795
- }
2796
- columnIndex++;
2797
- }
2798
- if (this.zShowMinute()) {
2799
- const minuteColumn = columnsArray[columnIndex];
2800
- if (minuteColumn) {
2801
- minuteColumn.scrollTop = this._minuteEnd() * itemHeight;
2802
- }
2803
- columnIndex++;
2804
- }
2805
- if (this.zShowSecond()) {
2806
- const secondColumn = columnsArray[columnIndex];
2807
- if (secondColumn) {
2808
- secondColumn.scrollTop = this._secondEnd() * itemHeight;
2809
- }
2810
- }
2811
- return;
2812
- }
2813
- let columnIndex = 0;
2814
- if (this.zShowHour()) {
2815
- const hourColumn = columnsArray[columnIndex];
2816
- if (hourColumn) {
2817
- const hourValue = this.zTimeFormat() === '12h' ? this.displayHour() - 1 : this._hour();
2818
- hourColumn.scrollTop = hourValue * itemHeight;
2819
- }
2820
- columnIndex++;
2821
- }
2822
- if (this.zShowMinute()) {
2823
- const minuteColumn = columnsArray[columnIndex];
2824
- if (minuteColumn) {
2825
- minuteColumn.scrollTop = this._minute() * itemHeight;
2826
- }
2827
- columnIndex++;
2828
- }
2829
- if (this.zShowSecond()) {
2830
- const secondColumn = columnsArray[columnIndex];
2831
- if (secondColumn) {
2832
- secondColumn.scrollTop = this._second() * itemHeight;
2833
- }
2834
- }
2835
- }, 0);
2836
2912
  }
2837
2913
  static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "21.0.6", ngImport: i0, type: ZCalendarComponent, deps: [], target: i0.ɵɵFactoryTarget.Component });
2838
2914
  static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "21.0.6", type: ZCalendarComponent, isStandalone: true, selector: "z-calendar", inputs: { class: { classPropertyName: "class", publicName: "class", isSignal: true, isRequired: false, transformFunction: null }, zMode: { classPropertyName: "zMode", publicName: "zMode", isSignal: true, isRequired: false, transformFunction: null }, zSize: { classPropertyName: "zSize", publicName: "zSize", isSignal: true, isRequired: false, transformFunction: null }, zLabel: { classPropertyName: "zLabel", publicName: "zLabel", isSignal: true, isRequired: false, transformFunction: null }, zLabelClass: { classPropertyName: "zLabelClass", publicName: "zLabelClass", isSignal: true, isRequired: false, transformFunction: null }, zPlaceholder: { classPropertyName: "zPlaceholder", publicName: "zPlaceholder", isSignal: true, isRequired: false, transformFunction: null }, zRequired: { classPropertyName: "zRequired", publicName: "zRequired", isSignal: true, isRequired: false, transformFunction: null }, zDisabled: { classPropertyName: "zDisabled", publicName: "zDisabled", isSignal: true, isRequired: false, transformFunction: null }, zReadonly: { classPropertyName: "zReadonly", publicName: "zReadonly", isSignal: true, isRequired: false, transformFunction: null }, zShowTime: { classPropertyName: "zShowTime", publicName: "zShowTime", isSignal: true, isRequired: false, transformFunction: null }, zTimeFormat: { classPropertyName: "zTimeFormat", publicName: "zTimeFormat", isSignal: true, isRequired: false, transformFunction: null }, zShowHour: { classPropertyName: "zShowHour", publicName: "zShowHour", isSignal: true, isRequired: false, transformFunction: null }, zShowMinute: { classPropertyName: "zShowMinute", publicName: "zShowMinute", isSignal: true, isRequired: false, transformFunction: null }, zShowSecond: { classPropertyName: "zShowSecond", publicName: "zShowSecond", isSignal: true, isRequired: false, transformFunction: null }, zQuickSelect: { classPropertyName: "zQuickSelect", publicName: "zQuickSelect", isSignal: true, isRequired: false, transformFunction: null }, zAllowClear: { classPropertyName: "zAllowClear", publicName: "zAllowClear", isSignal: true, isRequired: false, transformFunction: null }, zFormat: { classPropertyName: "zFormat", publicName: "zFormat", isSignal: true, isRequired: false, transformFunction: null }, zMinDate: { classPropertyName: "zMinDate", publicName: "zMinDate", isSignal: true, isRequired: false, transformFunction: null }, zMaxDate: { classPropertyName: "zMaxDate", publicName: "zMaxDate", isSignal: true, isRequired: false, transformFunction: null }, zValueType: { classPropertyName: "zValueType", publicName: "zValueType", isSignal: true, isRequired: false, transformFunction: null }, zValidators: { classPropertyName: "zValidators", publicName: "zValidators", isSignal: true, isRequired: false, transformFunction: null }, zLocale: { classPropertyName: "zLocale", publicName: "zLocale", isSignal: true, isRequired: false, transformFunction: null }, zShowOk: { classPropertyName: "zShowOk", publicName: "zShowOk", isSignal: true, isRequired: false, transformFunction: null }, zOkText: { classPropertyName: "zOkText", publicName: "zOkText", isSignal: true, isRequired: false, transformFunction: null }, zShowCancel: { classPropertyName: "zShowCancel", publicName: "zShowCancel", isSignal: true, isRequired: false, transformFunction: null }, zCancelText: { classPropertyName: "zCancelText", publicName: "zCancelText", isSignal: true, isRequired: false, transformFunction: null }, zDisabledDate: { classPropertyName: "zDisabledDate", publicName: "zDisabledDate", isSignal: true, isRequired: false, transformFunction: null }, zScrollClose: { classPropertyName: "zScrollClose", publicName: "zScrollClose", isSignal: true, isRequired: false, transformFunction: null } }, outputs: { zControl: "zControl", zChange: "zChange" }, providers: [
@@ -2842,7 +2918,7 @@ class ZCalendarComponent {
2842
2918
  multi: true,
2843
2919
  },
2844
2920
  TranslatePipe,
2845
- ], viewQueries: [{ propertyName: "triggerRef", first: true, predicate: ["triggerEl"], descendants: true, isSignal: true }, { propertyName: "inputRef", first: true, predicate: ["inputEl"], descendants: true, isSignal: true }], exportAs: ["zCalendar"], ngImport: i0, template: "<div class=\"z-calendar-wrapper flex w-full flex-col gap-2\">\n @if (zLabel()) {\n <label [for]=\"pickerId\" class=\"text-xs leading-none font-medium\" [class]=\"zLabelClass()\">\n {{ zLabel() }}\n @if (zRequired()) {\n <span class=\"text-destructive! ml-0.5\">*</span>\n }\n </label>\n }\n\n <div class=\"relative\">\n <div\n #triggerEl\n z-popover\n [zPopoverContent]=\"calendarTpl\"\n zPosition=\"bottom-left\"\n zPopoverWidth=\"auto\"\n [zOffset]=\"6\"\n [zDisabled]=\"isDisabled() || zReadonly()\"\n [zManualClose]=\"showCancelButton()\"\n [zScrollClose]=\"zScrollClose()\"\n zTrigger=\"click\"\n zClass=\"border-0 shadow-none bg-transparent p-0\"\n (zHideStart)=\"onPopoverHide()\"\n (zShow)=\"onPopoverShow()\"\n (zControl)=\"onPopoverControl($event)\"\n [id]=\"pickerId\"\n [class]=\"triggerClasses()\"\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 min-w-0 flex-1 truncate bg-transparent text-center text-sm outline-none\"\n [placeholder]=\"'i18n_z_ui_calendar_start_date' | translate\"\n [value]=\"inputDisplayStart()\"\n [disabled]=\"isDisabled()\"\n [readonly]=\"zReadonly()\"\n (click)=\"isOpen() && $event.stopPropagation()\"\n (focus)=\"onInputFocus($event)\"\n (input)=\"onStartInputChange($event)\"\n (blur)=\"onInputBlur($event)\"\n (keydown.enter)=\"onStartInputEnter($event)\"\n (keydown.escape)=\"onStartInputEscape()\" />\n <span class=\"text-muted-foreground text-sm\">-</span>\n <input\n type=\"text\"\n data-range-type=\"end\"\n class=\"placeholder:text-muted-foreground min-w-0 flex-1 truncate bg-transparent text-center text-sm outline-none\"\n [placeholder]=\"'i18n_z_ui_calendar_end_date' | translate\"\n [value]=\"inputDisplayEnd()\"\n [disabled]=\"isDisabled()\"\n [readonly]=\"zReadonly()\"\n (click)=\"isOpen() && $event.stopPropagation()\"\n (focus)=\"onInputFocus($event)\"\n (input)=\"onEndInputChange($event)\"\n (blur)=\"onInputBlur($event)\"\n (keydown.enter)=\"onEndInputEnter($event)\"\n (keydown.escape)=\"onEndInputEscape()\" />\n } @else {\n <input\n #inputEl\n type=\"text\"\n class=\"placeholder:text-muted-foreground min-w-0 flex-1 truncate bg-transparent text-sm outline-none\"\n [placeholder]=\"zPlaceholder()\"\n [value]=\"inputDisplayValue()\"\n [disabled]=\"isDisabled()\"\n [readonly]=\"zReadonly()\"\n (click)=\"isOpen() && $event.stopPropagation()\"\n (focus)=\"onInputFocus($event)\"\n (input)=\"onInputChange($event)\"\n (blur)=\"onInputBlur($event)\"\n (keydown.enter)=\"onInputEnter($event)\"\n (keydown.escape)=\"onInputEscape()\" />\n }\n\n @if (zAllowClear() && !isDisabled() && !zReadonly()) {\n <button\n type=\"button\"\n tabindex=\"-1\"\n class=\"text-muted-foreground hover:text-foreground flex size-5 shrink-0 cursor-pointer items-center justify-center rounded transition-all\"\n [class.opacity-0]=\"!hasValue()\"\n [class.pointer-events-none]=\"!hasValue()\"\n (click)=\"onClear($event)\">\n <z-icon zType=\"lucideX\" zSize=\"14\" />\n </button>\n }\n </div>\n </div>\n\n @if (showError()) {\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-[90vh] max-w-[95vw] flex-col overflow-auto rounded-[6px] border shadow-lg 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\n class=\"border-border flex shrink-0 flex-row gap-1 overflow-x-auto border-b p-2 sm:flex-col sm:gap-0 sm:space-y-1 sm:overflow-x-visible sm:border-r sm:border-b-0\">\n @for (preset of quickSelectPresets; track preset.key) {\n @let presetDisabled = preset | zIsPresetDisabled: zDisabledDate();\n <button\n type=\"button\"\n class=\"cursor-pointer rounded-[4px] 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 }}\n </button>\n }\n </div>\n }\n <div class=\"flex flex-1 flex-col gap-2 overflow-auto p-3 sm:overflow-visible\">\n @if (!isTimeMode()) {\n <div class=\"z-calendars-wrapper flex flex-col items-start gap-3 sm:flex-row sm:gap-0\">\n <!-- First Calendar -->\n <div class=\"z-calendar-section flex flex-col gap-1\">\n @if (!isTimeMode()) {\n <div class=\"flex w-full items-center justify-between space-x-1\">\n <button\n type=\"button\"\n z-button\n zType=\"ghost\"\n zSize=\"sm\"\n class=\"size-8 p-0!\"\n [zWave]=\"false\"\n [zWave]=\"false\"\n (click)=\"navigatePrevious()\">\n <z-icon zType=\"lucideChevronsLeft\" zSize=\"16\" />\n </button>\n\n <button\n type=\"button\"\n z-button\n zType=\"ghost\"\n zSize=\"sm\"\n class=\"size-8 p-0!\"\n [zWave]=\"false\"\n [zWave]=\"false\"\n (click)=\"navigatePreviousFast()\">\n <z-icon zType=\"lucideChevronLeft\" zSize=\"16\" />\n </button>\n\n <div class=\"flex flex-1 items-center justify-center gap-0.5\">\n @if (!isYearMode() && !isQuarterMode()) {\n <button\n type=\"button\"\n z-button\n zType=\"ghost\"\n zSize=\"sm\"\n class=\"w-20 px-2!\"\n [zWave]=\"false\"\n [zDisabled]=\"false\"\n (click)=\"setView('month')\">\n {{ currentMonthName() }}\n </button>\n }\n\n <button\n type=\"button\"\n z-button\n zType=\"ghost\"\n zSize=\"sm\"\n class=\"px-2!\"\n [zWave]=\"false\"\n [zDisabled]=\"isYearMode()\"\n (click)=\"setView('year')\">\n {{ currentYear() }}\n </button>\n </div>\n\n <button\n type=\"button\"\n z-button\n zType=\"ghost\"\n zSize=\"sm\"\n class=\"size-8 p-0!\"\n [zDisabled]=\"!canNavigateStartNext()\"\n [zWave]=\"false\"\n (click)=\"navigateNextFast()\">\n <z-icon zType=\"lucideChevronRight\" zSize=\"16\" />\n </button>\n\n <button\n type=\"button\"\n z-button\n zType=\"ghost\"\n zSize=\"sm\"\n class=\"size-8 p-0!\"\n [zDisabled]=\"!canNavigateStartNext()\"\n [zWave]=\"false\"\n (click)=\"navigateNext()\">\n <z-icon zType=\"lucideChevronsRight\" zSize=\"16\" />\n </button>\n </div>\n\n <div class=\"z-calendar-views w-full\" [class.z-calendar-views-quarter]=\"isQuarterMode()\">\n @if (currentView() === 'day') {\n <div class=\"flex h-full w-full flex-col gap-1\" [class.z-calendar-animate]=\"hasViewChanged()\">\n <div class=\"grid w-full grid-cols-7\">\n @for (weekday of weekdayNames; track weekday) {\n <div class=\"text-muted-foreground flex h-7 items-center justify-center text-xs font-medium\">\n {{ weekday }}\n </div>\n }\n </div>\n\n @for (week of calendarDays(); track $index) {\n <div class=\"grid w-full grid-cols-7\">\n @for (day of week; track day.date.getTime()) {\n <button\n type=\"button\"\n [class]=\"day | zDayClasses\"\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\n @if (currentView() === 'month') {\n <div class=\"grid h-full w-full grid-cols-3 grid-rows-4\" [class.z-calendar-animate]=\"hasViewChanged()\">\n @for (month of monthNames; track month; let i = $index) {\n @let monthDisabled = isStartMonthDisabled(i);\n <div class=\"flex items-center justify-center\">\n <button\n type=\"button\"\n [class]=\"i | zMonthClasses: currentMonthIndex()\"\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 gap-0.5\"\n [class.grid-rows-4]=\"!isYearMode() && !isQuarterMode()\"\n [class.grid-rows-3]=\"isYearMode() || isQuarterMode()\"\n [class.z-calendar-animate]=\"hasViewChanged()\">\n @for (year of isYearMode() || isQuarterMode() ? yearRangeSmall() : yearRange(); track year) {\n @let yearDisabled = isStartYearDisabled(year);\n <div class=\"flex items-center justify-center\">\n <button\n type=\"button\"\n [class]=\"year | zYearClasses: currentYear()\"\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 class=\"grid w-full grid-cols-2 gap-2\" [class.z-calendar-animate]=\"hasViewChanged()\">\n @for (quarter of quarterNames; track quarter; let i = $index) {\n <div class=\"flex items-center justify-center\">\n <button\n type=\"button\"\n [class]=\"i | zQuarterClasses: currentQuarterIndex()\"\n (click)=\"onQuarterClick(i)\">\n {{ quarter }}\n </button>\n </div>\n }\n </div>\n }\n </div>\n }\n </div>\n\n <!-- Time Picker Side Panel (for single date with showTime) -->\n @if (!isRangeMode() && zShowTime() && currentView() === 'day') {\n <div\n class=\"border-border mt-3 flex w-full flex-col items-center border-t pt-3 sm:mt-0 sm:w-auto sm:border-t-0 sm:border-l sm:pt-0 sm:pl-3\">\n <div class=\"text-muted-foreground mb-2 text-center text-xs font-medium\">\n {{ 'i18n_z_ui_calendar_time' | translate }}\n </div>\n <div class=\"flex flex-col items-center gap-2\">\n <div class=\"flex justify-center gap-1\">\n @if (zShowHour()) {\n <ng-scrollbar\n class=\"z-time-column border-border h-[140px] w-12 rounded border sm:h-[235px]\"\n track=\"vertical\">\n <div class=\"flex flex-col\">\n @for (hour of hourOptions(); track hour) {\n <button\n type=\"button\"\n class=\"hover:bg-muted flex h-7 shrink-0 cursor-pointer items-center justify-center text-sm transition-colors\"\n [class.bg-primary]=\"isHourSelected(hour)\"\n [class.text-primary-foreground]=\"isHourSelected(hour)\"\n [class.font-medium]=\"isHourSelected(hour)\"\n (click)=\"selectHour(hour)\">\n {{ hour | number: '2.0-0' }}\n </button>\n }\n </div>\n </ng-scrollbar>\n }\n @if (zShowMinute()) {\n <ng-scrollbar\n class=\"z-time-column border-border h-[140px] w-12 rounded border sm:h-[235px]\"\n track=\"vertical\">\n <div class=\"flex flex-col\">\n @for (minute of minuteOptions; track minute) {\n <button\n type=\"button\"\n class=\"hover:bg-muted flex h-7 shrink-0 cursor-pointer items-center justify-center text-sm transition-colors\"\n [class.bg-primary]=\"isMinuteSelected(minute)\"\n [class.text-primary-foreground]=\"isMinuteSelected(minute)\"\n [class.font-medium]=\"isMinuteSelected(minute)\"\n (click)=\"selectMinute(minute)\">\n {{ minute | number: '2.0-0' }}\n </button>\n }\n </div>\n </ng-scrollbar>\n }\n @if (zShowSecond()) {\n <ng-scrollbar\n class=\"z-time-column border-border h-[140px] w-12 rounded border sm:h-[235px]\"\n track=\"vertical\">\n <div class=\"flex flex-col\">\n @for (second of secondOptions; track second) {\n <button\n type=\"button\"\n class=\"hover:bg-muted flex h-7 shrink-0 cursor-pointer items-center justify-center text-sm transition-colors\"\n [class.bg-primary]=\"isSecondSelected(second)\"\n [class.text-primary-foreground]=\"isSecondSelected(second)\"\n [class.font-medium]=\"isSecondSelected(second)\"\n (click)=\"selectSecond(second)\">\n {{ second | number: '2.0-0' }}\n </button>\n }\n </div>\n </ng-scrollbar>\n }\n </div>\n @if (zTimeFormat() === '12h') {\n <div class=\"flex w-full gap-1\">\n <button\n type=\"button\"\n class=\"hover:bg-muted flex h-7 flex-1 cursor-pointer items-center justify-center rounded text-sm font-medium transition-colors\"\n [class.bg-primary]=\"period() === 'AM'\"\n [class.text-primary-foreground]=\"period() === 'AM'\"\n (click)=\"selectPeriod('AM')\">\n AM\n </button>\n <button\n type=\"button\"\n class=\"hover:bg-muted flex h-7 flex-1 cursor-pointer items-center justify-center rounded text-sm font-medium transition-colors\"\n [class.bg-primary]=\"period() === 'PM'\"\n [class.text-primary-foreground]=\"period() === 'PM'\"\n (click)=\"selectPeriod('PM')\">\n PM\n </button>\n </div>\n }\n </div>\n </div>\n }\n\n <!-- Second Calendar (Range Mode Only) -->\n @if (isRangeMode()) {\n <!-- Divider -->\n <div class=\"border-border bg-border hidden self-stretch sm:mx-3 sm:block sm:w-px\"></div>\n <div class=\"border-border bg-border block h-px w-full sm:hidden\"></div>\n\n <div class=\"z-calendar-section flex flex-col gap-1\">\n <div class=\"flex w-full items-center justify-between space-x-1\">\n <button\n type=\"button\"\n z-button\n zType=\"ghost\"\n zSize=\"sm\"\n class=\"size-8 p-0!\"\n [zDisabled]=\"!canNavigateEndPrev()\"\n [zWave]=\"false\"\n (click)=\"navigateEndPreviousFast()\">\n <z-icon zType=\"lucideChevronsLeft\" zSize=\"16\" />\n </button>\n\n <button\n type=\"button\"\n z-button\n zType=\"ghost\"\n zSize=\"sm\"\n class=\"size-8 p-0!\"\n [zDisabled]=\"!canNavigateEndPrev()\"\n [zWave]=\"false\"\n (click)=\"navigateEndPrevious()\">\n <z-icon zType=\"lucideChevronLeft\" zSize=\"16\" />\n </button>\n\n <div class=\"flex flex-1 items-center justify-center gap-0.5\">\n <button\n type=\"button\"\n z-button\n zType=\"ghost\"\n zSize=\"sm\"\n class=\"w-20 px-2!\"\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=\"px-2!\"\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-8 p-0!\"\n [zWave]=\"false\"\n [zWave]=\"false\"\n (click)=\"navigateEndNext()\">\n <z-icon zType=\"lucideChevronRight\" zSize=\"16\" />\n </button>\n\n <button\n type=\"button\"\n z-button\n zType=\"ghost\"\n zSize=\"sm\"\n class=\"size-8 p-0!\"\n [zWave]=\"false\"\n [zWave]=\"false\"\n (click)=\"navigateEndNextFast()\">\n <z-icon zType=\"lucideChevronsRight\" zSize=\"16\" />\n </button>\n </div>\n\n <div class=\"z-calendar-views w-full\">\n @if (endView() === 'day') {\n <div class=\"flex h-full w-full flex-col gap-1\" [class.z-calendar-animate]=\"hasEndViewChanged()\">\n <div class=\"grid grid-cols-7 gap-px\">\n @for (weekday of weekdayNames; track weekday) {\n <div class=\"text-muted-foreground flex h-8 w-8 items-center justify-center text-xs font-medium\">\n {{ weekday }}\n </div>\n }\n </div>\n\n @for (week of calendarDaysEnd(); track $index) {\n <div class=\"grid grid-cols-7 gap-px\">\n @for (day of week; track day.date.getTime()) {\n <button\n type=\"button\"\n [class]=\"day | zDayClasses\"\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\n @if (endView() === 'month') {\n <div\n class=\"grid h-full w-full grid-cols-3 grid-rows-4\"\n [class.z-calendar-animate]=\"hasEndViewChanged()\">\n @for (month of monthNames; track month; let i = $index) {\n @let endMonthDisabled = isEndMonthDisabled(i);\n <div class=\"flex items-center justify-center\">\n <button\n type=\"button\"\n [class]=\"i | zMonthClasses: endMonth().getMonth()\"\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-0.5\"\n [class.z-calendar-animate]=\"hasEndViewChanged()\">\n @for (year of endYearRange(); track year) {\n @let endYearDisabled = isEndYearDisabled(year);\n <div class=\"flex items-center justify-center\">\n <button\n type=\"button\"\n [class]=\"year | zYearClasses: endMonth().getFullYear()\"\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\n <!-- Range Mode Time Picker Side Panel -->\n @if (isRangeMode() && zShowTime() && currentView() === 'day' && endView() === 'day') {\n <div\n class=\"border-border mt-3 flex w-full flex-row justify-center gap-3 border-t pt-3 sm:mt-0 sm:w-auto sm:border-t-0 sm:border-l sm:pt-0 sm:pl-3\">\n <!-- Start Time -->\n <div class=\"flex flex-col\">\n <div class=\"text-muted-foreground mb-2 text-center text-xs font-medium\">\n {{ 'i18n_z_ui_calendar_start' | translate }}\n </div>\n <div class=\"flex flex-col gap-2\">\n <div class=\"flex justify-center gap-1\">\n @if (zShowHour()) {\n <ng-scrollbar\n class=\"z-time-column border-border h-[120px] w-10 rounded border sm:h-[235px]\"\n track=\"vertical\">\n <div class=\"flex flex-col\">\n @for (hour of hourOptions(); track hour) {\n <button\n type=\"button\"\n class=\"hover:bg-muted flex h-7 shrink-0 cursor-pointer items-center justify-center text-xs transition-colors\"\n [class.bg-primary]=\"isHourSelected(hour)\"\n [class.text-primary-foreground]=\"isHourSelected(hour)\"\n [class.font-medium]=\"isHourSelected(hour)\"\n (click)=\"selectHour(hour)\">\n {{ hour | number: '2.0-0' }}\n </button>\n }\n </div>\n </ng-scrollbar>\n }\n @if (zShowMinute()) {\n <ng-scrollbar\n class=\"z-time-column border-border h-[120px] w-10 rounded border sm:h-[235px]\"\n track=\"vertical\">\n <div class=\"flex flex-col\">\n @for (minute of minuteOptions; track minute) {\n <button\n type=\"button\"\n class=\"hover:bg-muted flex h-7 shrink-0 cursor-pointer items-center justify-center text-xs transition-colors\"\n [class.bg-primary]=\"isMinuteSelected(minute)\"\n [class.text-primary-foreground]=\"isMinuteSelected(minute)\"\n [class.font-medium]=\"isMinuteSelected(minute)\"\n (click)=\"selectMinute(minute)\">\n {{ minute | number: '2.0-0' }}\n </button>\n }\n </div>\n </ng-scrollbar>\n }\n @if (zShowSecond()) {\n <ng-scrollbar\n class=\"z-time-column border-border h-[120px] w-10 rounded border sm:h-[235px]\"\n track=\"vertical\">\n <div class=\"flex flex-col\">\n @for (second of secondOptions; track second) {\n <button\n type=\"button\"\n class=\"hover:bg-muted flex h-7 shrink-0 cursor-pointer items-center justify-center text-xs transition-colors\"\n [class.bg-primary]=\"isSecondSelected(second)\"\n [class.text-primary-foreground]=\"isSecondSelected(second)\"\n [class.font-medium]=\"isSecondSelected(second)\"\n (click)=\"selectSecond(second)\">\n {{ second | number: '2.0-0' }}\n </button>\n }\n </div>\n </ng-scrollbar>\n }\n </div>\n @if (zTimeFormat() === '12h') {\n <div class=\"flex gap-1\">\n <button\n type=\"button\"\n class=\"hover:bg-muted flex h-6 flex-1 cursor-pointer items-center justify-center rounded text-xs font-medium transition-colors\"\n [class.bg-primary]=\"period() === 'AM'\"\n [class.text-primary-foreground]=\"period() === 'AM'\"\n (click)=\"selectPeriod('AM')\">\n AM\n </button>\n <button\n type=\"button\"\n class=\"hover:bg-muted flex h-6 flex-1 cursor-pointer items-center justify-center rounded text-xs font-medium transition-colors\"\n [class.bg-primary]=\"period() === 'PM'\"\n [class.text-primary-foreground]=\"period() === 'PM'\"\n (click)=\"selectPeriod('PM')\">\n PM\n </button>\n </div>\n }\n </div>\n </div>\n\n <!-- End Time -->\n <div class=\"flex flex-col\">\n <div class=\"text-muted-foreground mb-2 text-center text-xs font-medium\">\n {{ 'i18n_z_ui_calendar_end' | translate }}\n </div>\n <div class=\"flex flex-col gap-2\">\n <div class=\"flex justify-center gap-1\">\n @if (zShowHour()) {\n <ng-scrollbar\n class=\"z-time-column border-border h-[120px] w-10 rounded border sm:h-[235px]\"\n track=\"vertical\">\n <div class=\"flex flex-col\">\n @for (hour of hourOptions(); track hour) {\n @let hourDisabled = isEndHourDisabled(hour);\n <button\n type=\"button\"\n class=\"flex h-7 shrink-0 items-center justify-center text-xs transition-colors\"\n [class.hover:bg-muted]=\"!hourDisabled\"\n [class.cursor-pointer]=\"!hourDisabled\"\n [class.bg-primary]=\"isHourEndSelected(hour)\"\n [class.text-primary-foreground]=\"isHourEndSelected(hour)\"\n [class.font-medium]=\"isHourEndSelected(hour)\"\n [class.opacity-30]=\"hourDisabled\"\n [class.cursor-not-allowed]=\"hourDisabled\"\n [disabled]=\"hourDisabled\"\n (click)=\"selectHourEnd(hour)\">\n {{ hour | number: '2.0-0' }}\n </button>\n }\n </div>\n </ng-scrollbar>\n }\n @if (zShowMinute()) {\n <ng-scrollbar\n class=\"z-time-column border-border h-[120px] w-10 rounded border sm:h-[235px]\"\n track=\"vertical\">\n <div class=\"flex flex-col\">\n @for (minute of minuteOptions; track minute) {\n @let minuteDisabled = isEndMinuteDisabled(minute);\n <button\n type=\"button\"\n class=\"flex h-7 shrink-0 items-center justify-center text-xs transition-colors\"\n [class.hover:bg-muted]=\"!minuteDisabled\"\n [class.cursor-pointer]=\"!minuteDisabled\"\n [class.bg-primary]=\"isMinuteEndSelected(minute)\"\n [class.text-primary-foreground]=\"isMinuteEndSelected(minute)\"\n [class.font-medium]=\"isMinuteEndSelected(minute)\"\n [class.opacity-30]=\"minuteDisabled\"\n [class.cursor-not-allowed]=\"minuteDisabled\"\n [disabled]=\"minuteDisabled\"\n (click)=\"selectMinuteEnd(minute)\">\n {{ minute | number: '2.0-0' }}\n </button>\n }\n </div>\n </ng-scrollbar>\n }\n @if (zShowSecond()) {\n <ng-scrollbar\n class=\"z-time-column border-border h-[120px] w-10 rounded border sm:h-[235px]\"\n track=\"vertical\">\n <div class=\"flex flex-col\">\n @for (second of secondOptions; track second) {\n @let secondDisabled = isEndSecondDisabled(second);\n <button\n type=\"button\"\n class=\"flex h-7 shrink-0 items-center justify-center text-xs transition-colors\"\n [class.hover:bg-muted]=\"!secondDisabled\"\n [class.cursor-pointer]=\"!secondDisabled\"\n [class.bg-primary]=\"isSecondEndSelected(second)\"\n [class.text-primary-foreground]=\"isSecondEndSelected(second)\"\n [class.font-medium]=\"isSecondEndSelected(second)\"\n [class.opacity-30]=\"secondDisabled\"\n [class.cursor-not-allowed]=\"secondDisabled\"\n [disabled]=\"secondDisabled\"\n (click)=\"selectSecondEnd(second)\">\n {{ second | number: '2.0-0' }}\n </button>\n }\n </div>\n </ng-scrollbar>\n }\n </div>\n @if (zTimeFormat() === '12h') {\n <div class=\"flex gap-1\">\n @let amDisabled = isEndPeriodDisabled('AM');\n <button\n type=\"button\"\n class=\"flex h-6 flex-1 items-center justify-center rounded text-xs font-medium transition-colors\"\n [class.hover:bg-muted]=\"!amDisabled\"\n [class.cursor-pointer]=\"!amDisabled\"\n [class.bg-primary]=\"periodEnd() === 'AM'\"\n [class.text-primary-foreground]=\"periodEnd() === 'AM'\"\n [class.opacity-30]=\"amDisabled\"\n [class.cursor-not-allowed]=\"amDisabled\"\n [disabled]=\"amDisabled\"\n (click)=\"selectPeriodEnd('AM')\">\n AM\n </button>\n @let pmDisabled = isEndPeriodDisabled('PM');\n <button\n type=\"button\"\n class=\"flex h-6 flex-1 items-center justify-center rounded text-xs font-medium transition-colors\"\n [class.hover:bg-muted]=\"!pmDisabled\"\n [class.cursor-pointer]=\"!pmDisabled\"\n [class.bg-primary]=\"periodEnd() === 'PM'\"\n [class.text-primary-foreground]=\"periodEnd() === 'PM'\"\n [class.opacity-30]=\"pmDisabled\"\n [class.cursor-not-allowed]=\"pmDisabled\"\n [disabled]=\"pmDisabled\"\n (click)=\"selectPeriodEnd('PM')\">\n PM\n </button>\n </div>\n }\n </div>\n </div>\n </div>\n }\n </div>\n } @else {\n <div class=\"flex flex-col items-center gap-2 py-2\">\n <div class=\"flex justify-center gap-1\">\n @if (zShowHour()) {\n <ng-scrollbar class=\"z-time-column border-border h-[196px] w-14 rounded border\" track=\"vertical\">\n <div class=\"flex flex-col\">\n @for (hour of hourOptions(); track hour) {\n <button\n type=\"button\"\n class=\"hover:bg-muted flex h-7 shrink-0 cursor-pointer items-center justify-center text-sm transition-colors\"\n [class.bg-primary]=\"isHourSelected(hour)\"\n [class.text-primary-foreground]=\"isHourSelected(hour)\"\n [class.font-medium]=\"isHourSelected(hour)\"\n (click)=\"selectHour(hour)\">\n {{ hour | number: '2.0-0' }}\n </button>\n }\n </div>\n </ng-scrollbar>\n }\n @if (zShowMinute()) {\n <ng-scrollbar class=\"z-time-column border-border h-[196px] w-14 rounded border\" track=\"vertical\">\n <div class=\"flex flex-col\">\n @for (minute of minuteOptions; track minute) {\n <button\n type=\"button\"\n class=\"hover:bg-muted flex h-7 shrink-0 cursor-pointer items-center justify-center text-sm transition-colors\"\n [class.bg-primary]=\"isMinuteSelected(minute)\"\n [class.text-primary-foreground]=\"isMinuteSelected(minute)\"\n [class.font-medium]=\"isMinuteSelected(minute)\"\n (click)=\"selectMinute(minute)\">\n {{ minute | number: '2.0-0' }}\n </button>\n }\n </div>\n </ng-scrollbar>\n }\n @if (zShowSecond()) {\n <ng-scrollbar class=\"z-time-column border-border h-[196px] w-14 rounded border\" track=\"vertical\">\n <div class=\"flex flex-col\">\n @for (second of secondOptions; track second) {\n <button\n type=\"button\"\n class=\"hover:bg-muted flex h-7 shrink-0 cursor-pointer items-center justify-center text-sm transition-colors\"\n [class.bg-primary]=\"isSecondSelected(second)\"\n [class.text-primary-foreground]=\"isSecondSelected(second)\"\n [class.font-medium]=\"isSecondSelected(second)\"\n (click)=\"selectSecond(second)\">\n {{ second | number: '2.0-0' }}\n </button>\n }\n </div>\n </ng-scrollbar>\n }\n </div>\n @if (zTimeFormat() === '12h') {\n <div class=\"flex w-full gap-1\">\n <button\n type=\"button\"\n class=\"hover:bg-muted flex h-7 flex-1 cursor-pointer items-center justify-center rounded text-sm font-medium transition-colors\"\n [class.bg-primary]=\"period() === 'AM'\"\n [class.text-primary-foreground]=\"period() === 'AM'\"\n (click)=\"selectPeriod('AM')\">\n AM\n </button>\n <button\n type=\"button\"\n class=\"hover:bg-muted flex h-7 flex-1 cursor-pointer items-center justify-center rounded text-sm font-medium transition-colors\"\n [class.bg-primary]=\"period() === 'PM'\"\n [class.text-primary-foreground]=\"period() === 'PM'\"\n (click)=\"selectPeriod('PM')\">\n PM\n </button>\n </div>\n }\n </div>\n }\n\n @if (!(zQuickSelect() && zMode() === 'range' && !showOkButton() && !showCancelButton())) {\n <div class=\"border-border flex items-center justify-between gap-2 border-t pt-2\">\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", styles: [".z-calendar-calendar .z-calendar-section{width:280px;flex-shrink:0}.z-calendar-calendar .z-calendar-views{height:225px;width:100%;display:flex;align-items:center;justify-content:center;flex-direction:column}.z-calendar-calendar .z-calendar-views.z-calendar-views-quarter{height:auto}.z-calendar-calendar .z-calendar-animate{animation:z-calendar-view-enter .2s ease-out}.z-time-picker{display:flex;flex-direction:column;gap:.5rem;flex-shrink:0}.z-time-picker .z-time-columns{display:flex;gap:.25rem}.z-time-picker .z-time-column{width:42px;height:180px;overflow-y:auto;scroll-snap-type:y mandatory;scroll-behavior:smooth;scrollbar-width:thin}.z-time-picker .z-time-column::-webkit-scrollbar{width:4px}.z-time-picker .z-time-column::-webkit-scrollbar-track{background:transparent}.z-time-picker .z-time-column::-webkit-scrollbar-thumb{background-color:hsl(var(--border));border-radius:2px}.z-time-picker .z-time-item{height:32px;width:100%;display:flex;align-items:center;justify-content:center;font-size:.875rem;scroll-snap-align:center;border-radius:4px;cursor:pointer;transition:background-color .15s ease,color .15s ease}.z-time-picker .z-time-item:hover:not(.z-time-item-selected){background-color:hsl(var(--muted))}.z-time-picker .z-time-item.z-time-item-selected{background-color:hsl(var(--primary));color:hsl(var(--primary-foreground));font-weight:500}.z-time-picker .z-time-item:focus-visible{outline:2px solid hsl(var(--ring));outline-offset:-2px}.z-time-picker .z-time-period-buttons{display:flex;flex-direction:column;gap:.25rem;padding-top:8px}.z-time-picker .z-time-period-buttons button{height:28px;font-size:.75rem;border-radius:4px;transition:background-color .15s ease,color .15s ease}@keyframes z-calendar-view-enter{0%{opacity:0;transform:scale(.95) translateY(4px)}to{opacity:1;transform:scale(1) translateY(0)}}\n"], dependencies: [{ kind: "component", type: NgScrollbar, selector: "ng-scrollbar:not([externalViewport]), [ngScrollbar]", exportAs: ["ngScrollbar"] }, { kind: "component", type: ZIconComponent, selector: "z-icon, [z-icon]", inputs: ["class", "zType", "zSize", "zStrokeWidth", "zSvg"] }, { kind: "directive", type: ZPopoverDirective, selector: "[z-popover]", inputs: ["zPopoverContent", "zPosition", "zTrigger", "zClass", "zShowDelay", "zHideDelay", "zDisabled", "zOffset", "zPopoverWidth", "zManualClose", "zScrollClose", "zShowArrow"], outputs: ["zShow", "zHide", "zHideStart", "zControl"], exportAs: ["zPopover"] }, { kind: "component", type: ZButtonComponent, selector: "z-button, button[z-button], a[z-button]", inputs: ["class", "zType", "zSize", "zShape", "zLabel", "zLoading", "zDisabled", "zTypeIcon", "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: TranslatePipe, name: "translate" }], changeDetection: i0.ChangeDetectionStrategy.OnPush, encapsulation: i0.ViewEncapsulation.None });
2921
+ ], viewQueries: [{ propertyName: "triggerRef", first: true, predicate: ["triggerEl"], descendants: true, isSignal: true }, { propertyName: "inputRef", first: true, predicate: ["inputEl"], descendants: true, isSignal: true }], exportAs: ["zCalendar"], ngImport: i0, template: "<div class=\"z-calendar-wrapper flex w-full flex-col gap-2\">\n @if (zLabel()) {\n <label [for]=\"pickerId\" class=\"text-xs leading-none font-medium\" [class]=\"zLabelClass()\">\n {{ zLabel() }}\n @if (zRequired()) {\n <span class=\"text-destructive! ml-0.5\">*</span>\n }\n </label>\n }\n\n <div class=\"relative\">\n <div\n #triggerEl\n z-popover\n [zPopoverContent]=\"calendarTpl\"\n zPosition=\"bottom-left\"\n zPopoverWidth=\"auto\"\n [zOffset]=\"6\"\n [zDisabled]=\"isDisabled() || zReadonly()\"\n [zManualClose]=\"showCancelButton()\"\n [zScrollClose]=\"zScrollClose()\"\n zTrigger=\"click\"\n zClass=\"border-0 shadow-none bg-transparent p-0\"\n (zHideStart)=\"onPopoverHide()\"\n (zShow)=\"onPopoverShow()\"\n (zControl)=\"onPopoverControl($event)\"\n [id]=\"pickerId\"\n [class]=\"triggerClasses()\"\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 min-w-0 flex-1 truncate bg-transparent text-center text-sm outline-none\"\n [placeholder]=\"'i18n_z_ui_calendar_start_date' | translate\"\n [value]=\"inputDisplayStart()\"\n [disabled]=\"isDisabled()\"\n [readonly]=\"zReadonly()\"\n (click)=\"isOpen() && $event.stopPropagation()\"\n (focus)=\"onInputFocus($event)\"\n (input)=\"onStartInputChange($event)\"\n (blur)=\"onInputBlur($event)\"\n (keydown.enter)=\"onStartInputEnter($event)\"\n (keydown.escape)=\"onStartInputEscape()\" />\n <span class=\"text-muted-foreground text-sm\">-</span>\n <input\n type=\"text\"\n data-range-type=\"end\"\n class=\"placeholder:text-muted-foreground min-w-0 flex-1 truncate bg-transparent text-center text-sm outline-none\"\n [placeholder]=\"'i18n_z_ui_calendar_end_date' | translate\"\n [value]=\"inputDisplayEnd()\"\n [disabled]=\"isDisabled()\"\n [readonly]=\"zReadonly()\"\n (click)=\"isOpen() && $event.stopPropagation()\"\n (focus)=\"onInputFocus($event)\"\n (input)=\"onEndInputChange($event)\"\n (blur)=\"onInputBlur($event)\"\n (keydown.enter)=\"onEndInputEnter($event)\"\n (keydown.escape)=\"onEndInputEscape()\" />\n } @else {\n <input\n #inputEl\n type=\"text\"\n class=\"placeholder:text-muted-foreground min-w-0 flex-1 truncate bg-transparent text-sm outline-none\"\n [placeholder]=\"zPlaceholder()\"\n [value]=\"inputDisplayValue()\"\n [disabled]=\"isDisabled()\"\n [readonly]=\"zReadonly()\"\n (click)=\"isOpen() && $event.stopPropagation()\"\n (focus)=\"onInputFocus($event)\"\n (input)=\"onInputChange($event)\"\n (blur)=\"onInputBlur($event)\"\n (keydown.enter)=\"onInputEnter($event)\"\n (keydown.escape)=\"onInputEscape()\" />\n }\n\n @if (zAllowClear() && !isDisabled() && !zReadonly()) {\n <button\n type=\"button\"\n tabindex=\"-1\"\n class=\"text-muted-foreground hover:text-foreground flex size-5 shrink-0 cursor-pointer items-center justify-center rounded transition-all\"\n [class.opacity-0]=\"!hasValue()\"\n [class.pointer-events-none]=\"!hasValue()\"\n (click)=\"onClear($event)\">\n <z-icon zType=\"lucideX\" zSize=\"14\" />\n </button>\n }\n </div>\n </div>\n\n @if (showError()) {\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-[90vh] max-w-[95vw] flex-col overflow-auto rounded-[6px] border shadow-lg 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\n class=\"border-border flex shrink-0 flex-row gap-1 overflow-x-auto border-b p-2 sm:flex-col sm:gap-0 sm:space-y-1 sm:overflow-x-visible sm:border-r sm:border-b-0\">\n @for (preset of quickSelectPresets; track preset.key) {\n @let presetDisabled = preset | zIsPresetDisabled: zDisabledDate();\n <button\n type=\"button\"\n class=\"cursor-pointer rounded-[4px] 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 }}\n </button>\n }\n </div>\n }\n <div\n class=\"flex flex-1 flex-col items-center overflow-auto p-2 sm:overflow-visible\"\n [class]=\"!isRangeMode() ? 'w-[280px]' : ''\">\n @if (!isTimeMode()) {\n <div\n class=\"z-calendars-wrapper flex w-full flex-col items-center gap-3 sm:flex-row sm:items-stretch sm:justify-center sm:gap-0\">\n <!-- First Calendar -->\n <div class=\"z-calendar-section flex w-[280px] 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 <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)=\"navigatePrevious()\">\n <z-icon zType=\"lucideChevronsLeft\" zSize=\"14\" />\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)=\"navigatePreviousFast()\">\n <z-icon zType=\"lucideChevronLeft\" zSize=\"14\" />\n </button>\n\n <div class=\"flex flex-1 items-center justify-center gap-0\">\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 [zDisabled]=\"false\"\n (click)=\"setView('month')\">\n {{ currentMonthName() }}\n </button>\n }\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 </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 [zDisabled]=\"!canNavigateStartNext()\"\n [zWave]=\"false\"\n (click)=\"navigateNextFast()\">\n <z-icon zType=\"lucideChevronRight\" zSize=\"14\" />\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]=\"!canNavigateStartNext()\"\n [zWave]=\"false\"\n (click)=\"navigateNext()\">\n <z-icon zType=\"lucideChevronsRight\" zSize=\"14\" />\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-[224px]]=\"!isQuarterMode()\"\n [class.h-[224px]]=\"\n !isYearMode() &&\n !isMonthMode() &&\n !isQuarterMode() &&\n (currentView() === 'month' || currentView() === 'year')\n \"\n [class.min-h-[100px]]=\"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]=\"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 w-[33px] 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=\"!w-[33px] !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]=\"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]=\"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]=\"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 class=\"border-border bg-border hidden self-stretch sm:mx-2 sm:block sm:w-px\"></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-[280px] shrink-0 flex-col\">\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 p-0!\"\n [zDisabled]=\"!canNavigateEndPrev()\"\n [zWave]=\"false\"\n (click)=\"navigateEndPreviousFast()\">\n <z-icon zType=\"lucideChevronsLeft\" zSize=\"14\" />\n </button>\n\n <button\n type=\"button\"\n z-button\n zType=\"ghost\"\n zSize=\"sm\"\n class=\"size-7 p-0!\"\n [zDisabled]=\"!canNavigateEndPrev()\"\n [zWave]=\"false\"\n (click)=\"navigateEndPrevious()\">\n <z-icon zType=\"lucideChevronLeft\" zSize=\"14\" />\n </button>\n\n <div class=\"flex flex-1 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 p-0!\"\n [zWave]=\"false\"\n [zWave]=\"false\"\n (click)=\"navigateEndNext()\">\n <z-icon zType=\"lucideChevronRight\" zSize=\"14\" />\n </button>\n\n <button\n type=\"button\"\n z-button\n zType=\"ghost\"\n zSize=\"sm\"\n class=\"size-7 p-0!\"\n [zWave]=\"false\"\n [zWave]=\"false\"\n (click)=\"navigateEndNextFast()\">\n <z-icon zType=\"lucideChevronsRight\" zSize=\"14\" />\n </button>\n </div>\n\n <!-- Body -->\n <div\n class=\"flex h-full min-h-[224px] w-full flex-col items-center justify-center p-2\"\n [class.h-[224px]]=\"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]=\"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 w-[33px] 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=\"!w-[33px] !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]=\"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]=\"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 class=\"border-border w-full border-t text-center\">\n <div\n class=\"hover:bg-muted my-1 inline-flex cursor-pointer items-center rounded-sm px-2 py-1 transition-colors\"\n z-popover\n [zPopoverContent]=\"timeDropdownTpl\"\n zPosition=\"bottom\"\n zPopoverWidth=\"auto\"\n [zOffset]=\"4\"\n zTrigger=\"click\"\n zClass=\"border-border shadow-md\"\n (zShow)=\"onTimeDropdownShow()\">\n <div class=\"flex items-center justify-center gap-1\">\n <!-- Hour -->\n @if (zShowHour()) {\n <div\n class=\"hover:bg-muted/50 flex min-w-7 cursor-pointer flex-col items-center gap-0 rounded px-1 transition-colors\">\n <button\n type=\"button\"\n class=\"text-muted-foreground hover:bg-muted hover:text-foreground active:bg-accent mb-0.5 flex h-4 w-full cursor-pointer items-center justify-center rounded border-none bg-transparent transition-colors\"\n (click)=\"decrementHour(); $event.stopPropagation()\">\n <z-icon zType=\"lucideChevronUp\" zSize=\"14\" />\n </button>\n <span class=\"text-foreground min-w-5 text-center text-sm leading-tight font-medium select-none\">\n {{ formattedHour() }}\n </span>\n <button\n type=\"button\"\n class=\"text-muted-foreground hover:bg-muted hover:text-foreground active:bg-accent mt-0.5 flex h-4 w-full cursor-pointer items-center justify-center rounded border-none bg-transparent transition-colors\"\n (click)=\"incrementHour(); $event.stopPropagation()\">\n <z-icon zType=\"lucideChevronDown\" zSize=\"14\" />\n </button>\n </div>\n }\n @if (zShowHour() && zShowMinute()) {\n <span class=\"text-muted-foreground text-sm font-medium\">:</span>\n }\n <!-- Minute -->\n @if (zShowMinute()) {\n <div\n class=\"hover:bg-muted/50 flex min-w-7 cursor-pointer flex-col items-center gap-0 rounded px-1 transition-colors\">\n <button\n type=\"button\"\n class=\"text-muted-foreground hover:bg-muted hover:text-foreground active:bg-accent mb-0.5 flex h-4 w-full cursor-pointer items-center justify-center rounded border-none bg-transparent transition-colors\"\n (click)=\"decrementMinute(); $event.stopPropagation()\">\n <z-icon zType=\"lucideChevronUp\" zSize=\"14\" />\n </button>\n <span class=\"text-foreground min-w-5 text-center text-sm leading-tight font-medium select-none\">\n {{ formattedMinute() }}\n </span>\n <button\n type=\"button\"\n class=\"text-muted-foreground hover:bg-muted hover:text-foreground active:bg-accent mt-0.5 flex h-4 w-full cursor-pointer items-center justify-center rounded border-none bg-transparent transition-colors\"\n (click)=\"incrementMinute(); $event.stopPropagation()\">\n <z-icon zType=\"lucideChevronDown\" zSize=\"14\" />\n </button>\n </div>\n }\n @if (zShowMinute() && zShowSecond()) {\n <span class=\"text-muted-foreground text-sm font-medium\">:</span>\n }\n <!-- Second -->\n @if (zShowSecond()) {\n <div\n class=\"hover:bg-muted/50 flex min-w-7 cursor-pointer flex-col items-center gap-0 rounded px-1 transition-colors\">\n <button\n type=\"button\"\n class=\"text-muted-foreground hover:bg-muted hover:text-foreground active:bg-accent mb-0.5 flex h-4 w-full cursor-pointer items-center justify-center rounded border-none bg-transparent transition-colors\"\n (click)=\"decrementSecond(); $event.stopPropagation()\">\n <z-icon zType=\"lucideChevronUp\" zSize=\"14\" />\n </button>\n <span class=\"text-foreground min-w-5 text-center text-sm leading-tight font-medium select-none\">\n {{ formattedSecond() }}\n </span>\n <button\n type=\"button\"\n class=\"text-muted-foreground hover:bg-muted hover:text-foreground active:bg-accent mt-0.5 flex h-4 w-full cursor-pointer items-center justify-center rounded border-none bg-transparent transition-colors\"\n (click)=\"incrementSecond(); $event.stopPropagation()\">\n <z-icon zType=\"lucideChevronDown\" zSize=\"14\" />\n </button>\n </div>\n }\n <!-- AM/PM Toggle -->\n @if (zTimeFormat() === '12h') {\n <button\n type=\"button\"\n class=\"bg-primary/10 text-primary hover:bg-primary/20 active:bg-primary/30 ml-1 flex w-8 cursor-pointer items-center justify-center rounded border-none px-2 py-1 text-xs font-semibold transition-colors\"\n (click)=\"togglePeriod(); $event.stopPropagation()\">\n {{ period() }}\n </button>\n }\n </div>\n </div>\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 sm:gap-3\">\n <!-- Start Time -->\n <div class=\"flex w-full flex-col items-center justify-center gap-1\">\n <div\n class=\"hover:bg-muted my-1 inline-flex cursor-pointer items-center rounded-sm px-2 py-1 transition-colors\"\n z-popover\n [zPopoverContent]=\"timeDropdownStartTpl\"\n zPosition=\"bottom\"\n zPopoverWidth=\"auto\"\n [zOffset]=\"4\"\n zTrigger=\"click\"\n zClass=\"border-border shadow-md\"\n (zShow)=\"onTimeDropdownShow()\">\n <div class=\"flex items-center justify-center gap-1\">\n <!-- Hour -->\n @if (zShowHour()) {\n <div\n class=\"hover:bg-muted/50 flex min-w-7 cursor-pointer flex-col items-center gap-0 rounded px-1 transition-colors\">\n <button\n type=\"button\"\n class=\"text-muted-foreground hover:bg-muted hover:text-foreground active:bg-accent mb-0.5 flex h-4 w-full cursor-pointer items-center justify-center rounded border-none bg-transparent transition-colors\"\n (click)=\"decrementHour(); $event.stopPropagation()\">\n <z-icon zType=\"lucideChevronUp\" zSize=\"14\" />\n </button>\n <span class=\"text-foreground min-w-5 text-center text-sm leading-tight font-medium select-none\">\n {{ formattedHour() }}\n </span>\n <button\n type=\"button\"\n class=\"text-muted-foreground hover:bg-muted hover:text-foreground active:bg-accent mt-0.5 flex h-4 w-full cursor-pointer items-center justify-center rounded border-none bg-transparent transition-colors\"\n (click)=\"incrementHour(); $event.stopPropagation()\">\n <z-icon zType=\"lucideChevronDown\" zSize=\"14\" />\n </button>\n </div>\n }\n @if (zShowHour() && zShowMinute()) {\n <span class=\"text-muted-foreground text-sm font-medium\">:</span>\n }\n <!-- Minute -->\n @if (zShowMinute()) {\n <div\n class=\"hover:bg-muted/50 flex min-w-7 cursor-pointer flex-col items-center gap-0 rounded px-1 transition-colors\">\n <button\n type=\"button\"\n class=\"text-muted-foreground hover:bg-muted hover:text-foreground active:bg-accent mb-0.5 flex h-4 w-full cursor-pointer items-center justify-center rounded border-none bg-transparent transition-colors\"\n (click)=\"decrementMinute(); $event.stopPropagation()\">\n <z-icon zType=\"lucideChevronUp\" zSize=\"14\" />\n </button>\n <span class=\"text-foreground min-w-5 text-center text-sm leading-tight font-medium select-none\">\n {{ formattedMinute() }}\n </span>\n <button\n type=\"button\"\n class=\"text-muted-foreground hover:bg-muted hover:text-foreground active:bg-accent mt-0.5 flex h-4 w-full cursor-pointer items-center justify-center rounded border-none bg-transparent transition-colors\"\n (click)=\"incrementMinute(); $event.stopPropagation()\">\n <z-icon zType=\"lucideChevronDown\" zSize=\"14\" />\n </button>\n </div>\n }\n @if (zShowMinute() && zShowSecond()) {\n <span class=\"text-muted-foreground text-sm font-medium\">:</span>\n }\n <!-- Second -->\n @if (zShowSecond()) {\n <div\n class=\"hover:bg-muted/50 flex min-w-7 cursor-pointer flex-col items-center gap-0 rounded px-1 transition-colors\">\n <button\n type=\"button\"\n class=\"text-muted-foreground hover:bg-muted hover:text-foreground active:bg-accent mb-0.5 flex h-4 w-full cursor-pointer items-center justify-center rounded border-none bg-transparent transition-colors\"\n (click)=\"decrementSecond(); $event.stopPropagation()\">\n <z-icon zType=\"lucideChevronUp\" zSize=\"14\" />\n </button>\n <span class=\"text-foreground min-w-5 text-center text-sm leading-tight font-medium select-none\">\n {{ formattedSecond() }}\n </span>\n <button\n type=\"button\"\n class=\"text-muted-foreground hover:bg-muted hover:text-foreground active:bg-accent mt-0.5 flex h-4 w-full cursor-pointer items-center justify-center rounded border-none bg-transparent transition-colors\"\n (click)=\"incrementSecond(); $event.stopPropagation()\">\n <z-icon zType=\"lucideChevronDown\" zSize=\"14\" />\n </button>\n </div>\n }\n <!-- AM/PM Toggle -->\n @if (zTimeFormat() === '12h') {\n <button\n type=\"button\"\n class=\"bg-primary/10 text-primary hover:bg-primary/20 active:bg-primary/30 ml-1 flex w-8 cursor-pointer items-center justify-center rounded border-none px-2 py-1 text-xs font-semibold transition-colors\"\n (click)=\"togglePeriod(); $event.stopPropagation()\">\n {{ period() }}\n </button>\n }\n </div>\n </div>\n </div>\n\n <!-- Divider space -->\n <div class=\"border-border bg-border h-px self-stretch sm:mx-2 sm:block sm:h-full sm:w-px\"></div>\n\n <!-- End Time -->\n <div class=\"flex w-full flex-col items-center justify-center gap-1\">\n <div\n class=\"hover:bg-muted my-1 inline-flex cursor-pointer items-center rounded-sm px-2 py-1 transition-colors\"\n z-popover\n [zPopoverContent]=\"timeDropdownEndTpl\"\n zPosition=\"bottom\"\n zPopoverWidth=\"auto\"\n [zOffset]=\"4\"\n zTrigger=\"click\"\n zClass=\"border-border shadow-md\"\n (zShow)=\"onTimeDropdownEndShow()\">\n <div class=\"flex items-center justify-center gap-1\">\n <!-- Hour -->\n @if (zShowHour()) {\n <div\n class=\"hover:bg-muted/50 flex min-w-7 cursor-pointer flex-col items-center gap-0 rounded px-1 transition-colors\">\n <button\n type=\"button\"\n class=\"text-muted-foreground hover:bg-muted hover:text-foreground active:bg-accent mb-0.5 flex h-4 w-full cursor-pointer items-center justify-center rounded border-none bg-transparent transition-colors\"\n (click)=\"decrementHourEnd(); $event.stopPropagation()\">\n <z-icon zType=\"lucideChevronUp\" zSize=\"14\" />\n </button>\n <span class=\"text-foreground min-w-5 text-center text-sm leading-tight font-medium select-none\">\n {{ formattedHourEnd() }}\n </span>\n <button\n type=\"button\"\n class=\"text-muted-foreground hover:bg-muted hover:text-foreground active:bg-accent mt-0.5 flex h-4 w-full cursor-pointer items-center justify-center rounded border-none bg-transparent transition-colors\"\n (click)=\"incrementHourEnd(); $event.stopPropagation()\">\n <z-icon zType=\"lucideChevronDown\" zSize=\"14\" />\n </button>\n </div>\n }\n @if (zShowHour() && zShowMinute()) {\n <span class=\"text-muted-foreground text-sm font-medium\">:</span>\n }\n <!-- Minute -->\n @if (zShowMinute()) {\n <div\n class=\"hover:bg-muted/50 flex min-w-7 cursor-pointer flex-col items-center gap-0 rounded px-1 transition-colors\">\n <button\n type=\"button\"\n class=\"text-muted-foreground hover:bg-muted hover:text-foreground active:bg-accent mb-0.5 flex h-4 w-full cursor-pointer items-center justify-center rounded border-none bg-transparent transition-colors\"\n (click)=\"decrementMinuteEnd(); $event.stopPropagation()\">\n <z-icon zType=\"lucideChevronUp\" zSize=\"14\" />\n </button>\n <span class=\"text-foreground min-w-5 text-center text-sm leading-tight font-medium select-none\">\n {{ formattedMinuteEnd() }}\n </span>\n <button\n type=\"button\"\n class=\"text-muted-foreground hover:bg-muted hover:text-foreground active:bg-accent mt-0.5 flex h-4 w-full cursor-pointer items-center justify-center rounded border-none bg-transparent transition-colors\"\n (click)=\"incrementMinuteEnd(); $event.stopPropagation()\">\n <z-icon zType=\"lucideChevronDown\" zSize=\"14\" />\n </button>\n </div>\n }\n @if (zShowMinute() && zShowSecond()) {\n <span class=\"text-muted-foreground text-sm font-medium\">:</span>\n }\n <!-- Second -->\n @if (zShowSecond()) {\n <div\n class=\"hover:bg-muted/50 flex min-w-7 cursor-pointer flex-col items-center gap-0 rounded px-1 transition-colors\">\n <button\n type=\"button\"\n class=\"text-muted-foreground hover:bg-muted hover:text-foreground active:bg-accent mb-0.5 flex h-4 w-full cursor-pointer items-center justify-center rounded border-none bg-transparent transition-colors\"\n (click)=\"decrementSecondEnd(); $event.stopPropagation()\">\n <z-icon zType=\"lucideChevronUp\" zSize=\"14\" />\n </button>\n <span class=\"text-foreground min-w-5 text-center text-sm leading-tight font-medium select-none\">\n {{ formattedSecondEnd() }}\n </span>\n <button\n type=\"button\"\n class=\"text-muted-foreground hover:bg-muted hover:text-foreground active:bg-accent mt-0.5 flex h-4 w-full cursor-pointer items-center justify-center rounded border-none bg-transparent transition-colors\"\n (click)=\"incrementSecondEnd(); $event.stopPropagation()\">\n <z-icon zType=\"lucideChevronDown\" zSize=\"14\" />\n </button>\n </div>\n }\n <!-- AM/PM Toggle -->\n @if (zTimeFormat() === '12h') {\n <button\n type=\"button\"\n class=\"bg-primary/10 text-primary hover:bg-primary/20 active:bg-primary/30 ml-1 flex w-8 cursor-pointer items-center justify-center rounded border-none px-2 py-1 text-xs font-semibold transition-colors\"\n (click)=\"togglePeriodEnd(); $event.stopPropagation()\">\n {{ periodEnd() }}\n </button>\n }\n </div>\n </div>\n </div>\n </div>\n }\n } @else {\n <!-- Time Only Mode - Compact Display -->\n <div class=\"flex flex-col items-center gap-3 pb-2\">\n <div\n class=\"hover:bg-muted inline-flex cursor-pointer items-center rounded-md px-3 py-2 transition-colors\"\n z-popover\n [zPopoverContent]=\"timeDropdownTpl\"\n zPosition=\"bottom\"\n zPopoverWidth=\"auto\"\n [zOffset]=\"4\"\n zTrigger=\"click\"\n zClass=\"border-border shadow-md\"\n (zShow)=\"onTimeDropdownShow()\">\n <div class=\"flex items-center justify-center gap-1.5\">\n <!-- Hour -->\n @if (zShowHour()) {\n <div\n class=\"hover:bg-muted/50 flex min-w-9 cursor-pointer flex-col items-center gap-0 rounded px-1.5 transition-colors\">\n <button\n type=\"button\"\n class=\"text-muted-foreground hover:bg-muted hover:text-foreground active:bg-accent mb-1 flex h-5 w-full cursor-pointer items-center justify-center rounded border-none bg-transparent transition-colors\"\n (click)=\"decrementHour(); $event.stopPropagation()\">\n <z-icon zType=\"lucideChevronUp\" zSize=\"16\" />\n </button>\n <span class=\"text-foreground min-w-6 text-center text-base leading-tight font-medium select-none\">\n {{ formattedHour() }}\n </span>\n <button\n type=\"button\"\n class=\"text-muted-foreground hover:bg-muted hover:text-foreground active:bg-accent mt-1 flex h-5 w-full cursor-pointer items-center justify-center rounded border-none bg-transparent transition-colors\"\n (click)=\"incrementHour(); $event.stopPropagation()\">\n <z-icon zType=\"lucideChevronDown\" zSize=\"16\" />\n </button>\n </div>\n }\n @if (zShowHour() && zShowMinute()) {\n <span class=\"text-muted-foreground text-base font-medium\">:</span>\n }\n <!-- Minute -->\n @if (zShowMinute()) {\n <div\n class=\"hover:bg-muted/50 flex min-w-9 cursor-pointer flex-col items-center gap-0 rounded px-1.5 transition-colors\">\n <button\n type=\"button\"\n class=\"text-muted-foreground hover:bg-muted hover:text-foreground active:bg-accent mb-1 flex h-5 w-full cursor-pointer items-center justify-center rounded border-none bg-transparent transition-colors\"\n (click)=\"decrementMinute(); $event.stopPropagation()\">\n <z-icon zType=\"lucideChevronUp\" zSize=\"16\" />\n </button>\n <span class=\"text-foreground min-w-6 text-center text-base leading-tight font-medium select-none\">\n {{ formattedMinute() }}\n </span>\n <button\n type=\"button\"\n class=\"text-muted-foreground hover:bg-muted hover:text-foreground active:bg-accent mt-1 flex h-5 w-full cursor-pointer items-center justify-center rounded border-none bg-transparent transition-colors\"\n (click)=\"incrementMinute(); $event.stopPropagation()\">\n <z-icon zType=\"lucideChevronDown\" zSize=\"16\" />\n </button>\n </div>\n }\n @if (zShowMinute() && zShowSecond()) {\n <span class=\"text-muted-foreground text-base font-medium\">:</span>\n }\n <!-- Second -->\n @if (zShowSecond()) {\n <div\n class=\"hover:bg-muted/50 flex min-w-9 cursor-pointer flex-col items-center gap-0 rounded px-1.5 transition-colors\">\n <button\n type=\"button\"\n class=\"text-muted-foreground hover:bg-muted hover:text-foreground active:bg-accent mb-1 flex h-5 w-full cursor-pointer items-center justify-center rounded border-none bg-transparent transition-colors\"\n (click)=\"decrementSecond(); $event.stopPropagation()\">\n <z-icon zType=\"lucideChevronUp\" zSize=\"16\" />\n </button>\n <span class=\"text-foreground min-w-6 text-center text-base leading-tight font-medium select-none\">\n {{ formattedSecond() }}\n </span>\n <button\n type=\"button\"\n class=\"text-muted-foreground hover:bg-muted hover:text-foreground active:bg-accent mt-1 flex h-5 w-full cursor-pointer items-center justify-center rounded border-none bg-transparent transition-colors\"\n (click)=\"incrementSecond(); $event.stopPropagation()\">\n <z-icon zType=\"lucideChevronDown\" zSize=\"16\" />\n </button>\n </div>\n }\n <!-- AM/PM Toggle -->\n @if (zTimeFormat() === '12h') {\n <button\n type=\"button\"\n class=\"bg-primary/10 text-primary hover:bg-primary/20 active:bg-primary/30 ml-1 flex w-10 cursor-pointer items-center justify-center rounded border-none px-2.5 py-1.5 text-sm font-semibold transition-colors\"\n (click)=\"togglePeriod(); $event.stopPropagation()\">\n {{ period() }}\n </button>\n }\n </div>\n </div>\n </div>\n }\n\n @if (!(zQuickSelect() && zMode() === 'range' && !showOkButton() && !showCancelButton())) {\n <div class=\"border-border flex w-full items-center justify-between gap-2 border-t pt-2\">\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 overflow-hidden rounded-[6px]\">\n @if (zShowHour()) {\n <div\n class=\"flex flex-col\"\n [class.border-r]=\"zShowMinute() || zShowSecond()\"\n [class.border-border]=\"zShowMinute() || zShowSecond()\">\n <ng-scrollbar\n class=\"z-time-scroll-hour h-[200px] w-12\"\n [class.rounded]=\"!zShowMinute() && !zShowSecond()\"\n [class.rounded-l]=\"zShowMinute() || zShowSecond()\"\n track=\"vertical\">\n <div class=\"flex flex-col\">\n @for (hr of hourOptions(); track hr) {\n @let hrSelected = hr | zIsTimeSelected: 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 class=\"flex flex-col\" [class.border-r]=\"zShowSecond()\" [class.border-border]=\"zShowSecond()\">\n <ng-scrollbar\n class=\"z-time-scroll-minute h-[200px] w-12\"\n [class.rounded]=\"!zShowHour() && !zShowSecond()\"\n [class.rounded-l]=\"!zShowHour() && zShowSecond()\"\n [class.rounded-r]=\"zShowHour() && !zShowSecond()\"\n track=\"vertical\">\n <div class=\"flex flex-col\">\n @for (min of minuteOptions; track min) {\n @let minSelected = min | zIsTimeSelected: 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 class=\"flex flex-col\">\n <ng-scrollbar\n class=\"z-time-scroll-second h-[200px] w-12\"\n [class.rounded]=\"!zShowHour() && !zShowMinute()\"\n [class.rounded-r]=\"zShowHour() || zShowMinute()\"\n track=\"vertical\">\n <div class=\"flex flex-col\">\n @for (sec of secondOptions; track sec) {\n @let secSelected = sec | zIsTimeSelected: 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 </div>\n</ng-template>\n\n<ng-template #timeDropdownStartTpl>\n <div class=\"bg-popover flex overflow-hidden rounded-[6px]\">\n @if (zShowHour()) {\n <div\n class=\"flex flex-col\"\n [class.border-r]=\"zShowMinute() || zShowSecond()\"\n [class.border-border]=\"zShowMinute() || zShowSecond()\">\n <ng-scrollbar\n class=\"z-time-scroll-hour h-[200px] w-12\"\n [class.rounded]=\"!zShowMinute() && !zShowSecond()\"\n [class.rounded-l]=\"zShowMinute() || zShowSecond()\"\n track=\"vertical\">\n <div class=\"flex flex-col\">\n @for (hr of hourOptions(); track hr) {\n @let hrSelected = hr | zIsTimeSelected: 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 class=\"flex flex-col\" [class.border-r]=\"zShowSecond()\" [class.border-border]=\"zShowSecond()\">\n <ng-scrollbar\n class=\"z-time-scroll-minute h-[200px] w-12\"\n [class.rounded]=\"!zShowHour() && !zShowSecond()\"\n [class.rounded-l]=\"!zShowHour() && zShowSecond()\"\n [class.rounded-r]=\"zShowHour() && !zShowSecond()\"\n track=\"vertical\">\n <div class=\"flex flex-col\">\n @for (min of minuteOptions; track min) {\n @let minSelected = min | zIsTimeSelected: 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 class=\"flex flex-col\">\n <ng-scrollbar\n class=\"z-time-scroll-second h-[200px] w-12\"\n [class.rounded]=\"!zShowHour() && !zShowMinute()\"\n [class.rounded-r]=\"zShowHour() || zShowMinute()\"\n track=\"vertical\">\n <div class=\"flex flex-col\">\n @for (sec of secondOptions; track sec) {\n @let secSelected = sec | zIsTimeSelected: 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 </div>\n</ng-template>\n\n<ng-template #timeDropdownEndTpl>\n <div class=\"bg-popover flex overflow-hidden rounded-[6px]\">\n @if (zShowHour()) {\n <div\n class=\"flex flex-col\"\n [class.border-r]=\"zShowMinute() || zShowSecond()\"\n [class.border-border]=\"zShowMinute() || zShowSecond()\">\n <ng-scrollbar\n class=\"z-time-scroll-hour-end h-[200px] w-12\"\n [class.rounded]=\"!zShowMinute() && !zShowSecond()\"\n [class.rounded-l]=\"zShowMinute() || zShowSecond()\"\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 | zIsTimeSelected: 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 class=\"flex flex-col\" [class.border-r]=\"zShowSecond()\" [class.border-border]=\"zShowSecond()\">\n <ng-scrollbar\n class=\"z-time-scroll-minute-end h-[200px] w-12\"\n [class.rounded]=\"!zShowHour() && !zShowSecond()\"\n [class.rounded-l]=\"!zShowHour() && zShowSecond()\"\n [class.rounded-r]=\"zShowHour() && !zShowSecond()\"\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 | zIsTimeSelected: 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 class=\"flex flex-col\">\n <ng-scrollbar\n class=\"z-time-scroll-second-end h-[200px] w-12\"\n [class.rounded]=\"!zShowHour() && !zShowMinute()\"\n [class.rounded-r]=\"zShowHour() || zShowMinute()\"\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 | zIsTimeSelected: 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 </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(4px)}to{opacity:1;transform:scale(1) translateY(0)}}\n"], dependencies: [{ kind: "component", type: NgScrollbar, selector: "ng-scrollbar:not([externalViewport]), [ngScrollbar]", exportAs: ["ngScrollbar"] }, { kind: "component", type: ZIconComponent, selector: "z-icon, [z-icon]", inputs: ["class", "zType", "zSize", "zStrokeWidth", "zSvg"] }, { kind: "directive", type: ZPopoverDirective, selector: "[z-popover]", inputs: ["zPopoverContent", "zPosition", "zTrigger", "zClass", "zShowDelay", "zHideDelay", "zDisabled", "zOffset", "zPopoverWidth", "zManualClose", "zScrollClose", "zShowArrow"], outputs: ["zShow", "zHide", "zHideStart", "zControl"], exportAs: ["zPopover"] }, { kind: "component", type: ZButtonComponent, selector: "z-button, button[z-button], a[z-button]", inputs: ["class", "zType", "zSize", "zShape", "zLabel", "zLoading", "zDisabled", "zTypeIcon", "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: ZIsTimeSelectedPipe, name: "zIsTimeSelected" }, { 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 });
2846
2922
  }
2847
2923
  i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.0.6", ngImport: i0, type: ZCalendarComponent, decorators: [{
2848
2924
  type: Component,
@@ -2857,6 +2933,14 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.0.6", ngImpor
2857
2933
  ZQuarterClassesPipe,
2858
2934
  ZYearClassesPipe,
2859
2935
  ZIsPresetDisabledPipe,
2936
+ ZIsTimeSelectedPipe,
2937
+ ZIsEndHourDisabledPipe,
2938
+ ZIsEndMinuteDisabledPipe,
2939
+ ZIsEndSecondDisabledPipe,
2940
+ ZIsStartMonthDisabledPipe,
2941
+ ZIsEndMonthDisabledPipe,
2942
+ ZIsStartYearDisabledPipe,
2943
+ ZIsEndYearDisabledPipe,
2860
2944
  TranslatePipe,
2861
2945
  ], standalone: true, providers: [
2862
2946
  {
@@ -2865,7 +2949,7 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.0.6", ngImpor
2865
2949
  multi: true,
2866
2950
  },
2867
2951
  TranslatePipe,
2868
- ], changeDetection: ChangeDetectionStrategy.OnPush, encapsulation: ViewEncapsulation.None, exportAs: 'zCalendar', template: "<div class=\"z-calendar-wrapper flex w-full flex-col gap-2\">\n @if (zLabel()) {\n <label [for]=\"pickerId\" class=\"text-xs leading-none font-medium\" [class]=\"zLabelClass()\">\n {{ zLabel() }}\n @if (zRequired()) {\n <span class=\"text-destructive! ml-0.5\">*</span>\n }\n </label>\n }\n\n <div class=\"relative\">\n <div\n #triggerEl\n z-popover\n [zPopoverContent]=\"calendarTpl\"\n zPosition=\"bottom-left\"\n zPopoverWidth=\"auto\"\n [zOffset]=\"6\"\n [zDisabled]=\"isDisabled() || zReadonly()\"\n [zManualClose]=\"showCancelButton()\"\n [zScrollClose]=\"zScrollClose()\"\n zTrigger=\"click\"\n zClass=\"border-0 shadow-none bg-transparent p-0\"\n (zHideStart)=\"onPopoverHide()\"\n (zShow)=\"onPopoverShow()\"\n (zControl)=\"onPopoverControl($event)\"\n [id]=\"pickerId\"\n [class]=\"triggerClasses()\"\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 min-w-0 flex-1 truncate bg-transparent text-center text-sm outline-none\"\n [placeholder]=\"'i18n_z_ui_calendar_start_date' | translate\"\n [value]=\"inputDisplayStart()\"\n [disabled]=\"isDisabled()\"\n [readonly]=\"zReadonly()\"\n (click)=\"isOpen() && $event.stopPropagation()\"\n (focus)=\"onInputFocus($event)\"\n (input)=\"onStartInputChange($event)\"\n (blur)=\"onInputBlur($event)\"\n (keydown.enter)=\"onStartInputEnter($event)\"\n (keydown.escape)=\"onStartInputEscape()\" />\n <span class=\"text-muted-foreground text-sm\">-</span>\n <input\n type=\"text\"\n data-range-type=\"end\"\n class=\"placeholder:text-muted-foreground min-w-0 flex-1 truncate bg-transparent text-center text-sm outline-none\"\n [placeholder]=\"'i18n_z_ui_calendar_end_date' | translate\"\n [value]=\"inputDisplayEnd()\"\n [disabled]=\"isDisabled()\"\n [readonly]=\"zReadonly()\"\n (click)=\"isOpen() && $event.stopPropagation()\"\n (focus)=\"onInputFocus($event)\"\n (input)=\"onEndInputChange($event)\"\n (blur)=\"onInputBlur($event)\"\n (keydown.enter)=\"onEndInputEnter($event)\"\n (keydown.escape)=\"onEndInputEscape()\" />\n } @else {\n <input\n #inputEl\n type=\"text\"\n class=\"placeholder:text-muted-foreground min-w-0 flex-1 truncate bg-transparent text-sm outline-none\"\n [placeholder]=\"zPlaceholder()\"\n [value]=\"inputDisplayValue()\"\n [disabled]=\"isDisabled()\"\n [readonly]=\"zReadonly()\"\n (click)=\"isOpen() && $event.stopPropagation()\"\n (focus)=\"onInputFocus($event)\"\n (input)=\"onInputChange($event)\"\n (blur)=\"onInputBlur($event)\"\n (keydown.enter)=\"onInputEnter($event)\"\n (keydown.escape)=\"onInputEscape()\" />\n }\n\n @if (zAllowClear() && !isDisabled() && !zReadonly()) {\n <button\n type=\"button\"\n tabindex=\"-1\"\n class=\"text-muted-foreground hover:text-foreground flex size-5 shrink-0 cursor-pointer items-center justify-center rounded transition-all\"\n [class.opacity-0]=\"!hasValue()\"\n [class.pointer-events-none]=\"!hasValue()\"\n (click)=\"onClear($event)\">\n <z-icon zType=\"lucideX\" zSize=\"14\" />\n </button>\n }\n </div>\n </div>\n\n @if (showError()) {\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-[90vh] max-w-[95vw] flex-col overflow-auto rounded-[6px] border shadow-lg 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\n class=\"border-border flex shrink-0 flex-row gap-1 overflow-x-auto border-b p-2 sm:flex-col sm:gap-0 sm:space-y-1 sm:overflow-x-visible sm:border-r sm:border-b-0\">\n @for (preset of quickSelectPresets; track preset.key) {\n @let presetDisabled = preset | zIsPresetDisabled: zDisabledDate();\n <button\n type=\"button\"\n class=\"cursor-pointer rounded-[4px] 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 }}\n </button>\n }\n </div>\n }\n <div class=\"flex flex-1 flex-col gap-2 overflow-auto p-3 sm:overflow-visible\">\n @if (!isTimeMode()) {\n <div class=\"z-calendars-wrapper flex flex-col items-start gap-3 sm:flex-row sm:gap-0\">\n <!-- First Calendar -->\n <div class=\"z-calendar-section flex flex-col gap-1\">\n @if (!isTimeMode()) {\n <div class=\"flex w-full items-center justify-between space-x-1\">\n <button\n type=\"button\"\n z-button\n zType=\"ghost\"\n zSize=\"sm\"\n class=\"size-8 p-0!\"\n [zWave]=\"false\"\n [zWave]=\"false\"\n (click)=\"navigatePrevious()\">\n <z-icon zType=\"lucideChevronsLeft\" zSize=\"16\" />\n </button>\n\n <button\n type=\"button\"\n z-button\n zType=\"ghost\"\n zSize=\"sm\"\n class=\"size-8 p-0!\"\n [zWave]=\"false\"\n [zWave]=\"false\"\n (click)=\"navigatePreviousFast()\">\n <z-icon zType=\"lucideChevronLeft\" zSize=\"16\" />\n </button>\n\n <div class=\"flex flex-1 items-center justify-center gap-0.5\">\n @if (!isYearMode() && !isQuarterMode()) {\n <button\n type=\"button\"\n z-button\n zType=\"ghost\"\n zSize=\"sm\"\n class=\"w-20 px-2!\"\n [zWave]=\"false\"\n [zDisabled]=\"false\"\n (click)=\"setView('month')\">\n {{ currentMonthName() }}\n </button>\n }\n\n <button\n type=\"button\"\n z-button\n zType=\"ghost\"\n zSize=\"sm\"\n class=\"px-2!\"\n [zWave]=\"false\"\n [zDisabled]=\"isYearMode()\"\n (click)=\"setView('year')\">\n {{ currentYear() }}\n </button>\n </div>\n\n <button\n type=\"button\"\n z-button\n zType=\"ghost\"\n zSize=\"sm\"\n class=\"size-8 p-0!\"\n [zDisabled]=\"!canNavigateStartNext()\"\n [zWave]=\"false\"\n (click)=\"navigateNextFast()\">\n <z-icon zType=\"lucideChevronRight\" zSize=\"16\" />\n </button>\n\n <button\n type=\"button\"\n z-button\n zType=\"ghost\"\n zSize=\"sm\"\n class=\"size-8 p-0!\"\n [zDisabled]=\"!canNavigateStartNext()\"\n [zWave]=\"false\"\n (click)=\"navigateNext()\">\n <z-icon zType=\"lucideChevronsRight\" zSize=\"16\" />\n </button>\n </div>\n\n <div class=\"z-calendar-views w-full\" [class.z-calendar-views-quarter]=\"isQuarterMode()\">\n @if (currentView() === 'day') {\n <div class=\"flex h-full w-full flex-col gap-1\" [class.z-calendar-animate]=\"hasViewChanged()\">\n <div class=\"grid w-full grid-cols-7\">\n @for (weekday of weekdayNames; track weekday) {\n <div class=\"text-muted-foreground flex h-7 items-center justify-center text-xs font-medium\">\n {{ weekday }}\n </div>\n }\n </div>\n\n @for (week of calendarDays(); track $index) {\n <div class=\"grid w-full grid-cols-7\">\n @for (day of week; track day.date.getTime()) {\n <button\n type=\"button\"\n [class]=\"day | zDayClasses\"\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\n @if (currentView() === 'month') {\n <div class=\"grid h-full w-full grid-cols-3 grid-rows-4\" [class.z-calendar-animate]=\"hasViewChanged()\">\n @for (month of monthNames; track month; let i = $index) {\n @let monthDisabled = isStartMonthDisabled(i);\n <div class=\"flex items-center justify-center\">\n <button\n type=\"button\"\n [class]=\"i | zMonthClasses: currentMonthIndex()\"\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 gap-0.5\"\n [class.grid-rows-4]=\"!isYearMode() && !isQuarterMode()\"\n [class.grid-rows-3]=\"isYearMode() || isQuarterMode()\"\n [class.z-calendar-animate]=\"hasViewChanged()\">\n @for (year of isYearMode() || isQuarterMode() ? yearRangeSmall() : yearRange(); track year) {\n @let yearDisabled = isStartYearDisabled(year);\n <div class=\"flex items-center justify-center\">\n <button\n type=\"button\"\n [class]=\"year | zYearClasses: currentYear()\"\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 class=\"grid w-full grid-cols-2 gap-2\" [class.z-calendar-animate]=\"hasViewChanged()\">\n @for (quarter of quarterNames; track quarter; let i = $index) {\n <div class=\"flex items-center justify-center\">\n <button\n type=\"button\"\n [class]=\"i | zQuarterClasses: currentQuarterIndex()\"\n (click)=\"onQuarterClick(i)\">\n {{ quarter }}\n </button>\n </div>\n }\n </div>\n }\n </div>\n }\n </div>\n\n <!-- Time Picker Side Panel (for single date with showTime) -->\n @if (!isRangeMode() && zShowTime() && currentView() === 'day') {\n <div\n class=\"border-border mt-3 flex w-full flex-col items-center border-t pt-3 sm:mt-0 sm:w-auto sm:border-t-0 sm:border-l sm:pt-0 sm:pl-3\">\n <div class=\"text-muted-foreground mb-2 text-center text-xs font-medium\">\n {{ 'i18n_z_ui_calendar_time' | translate }}\n </div>\n <div class=\"flex flex-col items-center gap-2\">\n <div class=\"flex justify-center gap-1\">\n @if (zShowHour()) {\n <ng-scrollbar\n class=\"z-time-column border-border h-[140px] w-12 rounded border sm:h-[235px]\"\n track=\"vertical\">\n <div class=\"flex flex-col\">\n @for (hour of hourOptions(); track hour) {\n <button\n type=\"button\"\n class=\"hover:bg-muted flex h-7 shrink-0 cursor-pointer items-center justify-center text-sm transition-colors\"\n [class.bg-primary]=\"isHourSelected(hour)\"\n [class.text-primary-foreground]=\"isHourSelected(hour)\"\n [class.font-medium]=\"isHourSelected(hour)\"\n (click)=\"selectHour(hour)\">\n {{ hour | number: '2.0-0' }}\n </button>\n }\n </div>\n </ng-scrollbar>\n }\n @if (zShowMinute()) {\n <ng-scrollbar\n class=\"z-time-column border-border h-[140px] w-12 rounded border sm:h-[235px]\"\n track=\"vertical\">\n <div class=\"flex flex-col\">\n @for (minute of minuteOptions; track minute) {\n <button\n type=\"button\"\n class=\"hover:bg-muted flex h-7 shrink-0 cursor-pointer items-center justify-center text-sm transition-colors\"\n [class.bg-primary]=\"isMinuteSelected(minute)\"\n [class.text-primary-foreground]=\"isMinuteSelected(minute)\"\n [class.font-medium]=\"isMinuteSelected(minute)\"\n (click)=\"selectMinute(minute)\">\n {{ minute | number: '2.0-0' }}\n </button>\n }\n </div>\n </ng-scrollbar>\n }\n @if (zShowSecond()) {\n <ng-scrollbar\n class=\"z-time-column border-border h-[140px] w-12 rounded border sm:h-[235px]\"\n track=\"vertical\">\n <div class=\"flex flex-col\">\n @for (second of secondOptions; track second) {\n <button\n type=\"button\"\n class=\"hover:bg-muted flex h-7 shrink-0 cursor-pointer items-center justify-center text-sm transition-colors\"\n [class.bg-primary]=\"isSecondSelected(second)\"\n [class.text-primary-foreground]=\"isSecondSelected(second)\"\n [class.font-medium]=\"isSecondSelected(second)\"\n (click)=\"selectSecond(second)\">\n {{ second | number: '2.0-0' }}\n </button>\n }\n </div>\n </ng-scrollbar>\n }\n </div>\n @if (zTimeFormat() === '12h') {\n <div class=\"flex w-full gap-1\">\n <button\n type=\"button\"\n class=\"hover:bg-muted flex h-7 flex-1 cursor-pointer items-center justify-center rounded text-sm font-medium transition-colors\"\n [class.bg-primary]=\"period() === 'AM'\"\n [class.text-primary-foreground]=\"period() === 'AM'\"\n (click)=\"selectPeriod('AM')\">\n AM\n </button>\n <button\n type=\"button\"\n class=\"hover:bg-muted flex h-7 flex-1 cursor-pointer items-center justify-center rounded text-sm font-medium transition-colors\"\n [class.bg-primary]=\"period() === 'PM'\"\n [class.text-primary-foreground]=\"period() === 'PM'\"\n (click)=\"selectPeriod('PM')\">\n PM\n </button>\n </div>\n }\n </div>\n </div>\n }\n\n <!-- Second Calendar (Range Mode Only) -->\n @if (isRangeMode()) {\n <!-- Divider -->\n <div class=\"border-border bg-border hidden self-stretch sm:mx-3 sm:block sm:w-px\"></div>\n <div class=\"border-border bg-border block h-px w-full sm:hidden\"></div>\n\n <div class=\"z-calendar-section flex flex-col gap-1\">\n <div class=\"flex w-full items-center justify-between space-x-1\">\n <button\n type=\"button\"\n z-button\n zType=\"ghost\"\n zSize=\"sm\"\n class=\"size-8 p-0!\"\n [zDisabled]=\"!canNavigateEndPrev()\"\n [zWave]=\"false\"\n (click)=\"navigateEndPreviousFast()\">\n <z-icon zType=\"lucideChevronsLeft\" zSize=\"16\" />\n </button>\n\n <button\n type=\"button\"\n z-button\n zType=\"ghost\"\n zSize=\"sm\"\n class=\"size-8 p-0!\"\n [zDisabled]=\"!canNavigateEndPrev()\"\n [zWave]=\"false\"\n (click)=\"navigateEndPrevious()\">\n <z-icon zType=\"lucideChevronLeft\" zSize=\"16\" />\n </button>\n\n <div class=\"flex flex-1 items-center justify-center gap-0.5\">\n <button\n type=\"button\"\n z-button\n zType=\"ghost\"\n zSize=\"sm\"\n class=\"w-20 px-2!\"\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=\"px-2!\"\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-8 p-0!\"\n [zWave]=\"false\"\n [zWave]=\"false\"\n (click)=\"navigateEndNext()\">\n <z-icon zType=\"lucideChevronRight\" zSize=\"16\" />\n </button>\n\n <button\n type=\"button\"\n z-button\n zType=\"ghost\"\n zSize=\"sm\"\n class=\"size-8 p-0!\"\n [zWave]=\"false\"\n [zWave]=\"false\"\n (click)=\"navigateEndNextFast()\">\n <z-icon zType=\"lucideChevronsRight\" zSize=\"16\" />\n </button>\n </div>\n\n <div class=\"z-calendar-views w-full\">\n @if (endView() === 'day') {\n <div class=\"flex h-full w-full flex-col gap-1\" [class.z-calendar-animate]=\"hasEndViewChanged()\">\n <div class=\"grid grid-cols-7 gap-px\">\n @for (weekday of weekdayNames; track weekday) {\n <div class=\"text-muted-foreground flex h-8 w-8 items-center justify-center text-xs font-medium\">\n {{ weekday }}\n </div>\n }\n </div>\n\n @for (week of calendarDaysEnd(); track $index) {\n <div class=\"grid grid-cols-7 gap-px\">\n @for (day of week; track day.date.getTime()) {\n <button\n type=\"button\"\n [class]=\"day | zDayClasses\"\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\n @if (endView() === 'month') {\n <div\n class=\"grid h-full w-full grid-cols-3 grid-rows-4\"\n [class.z-calendar-animate]=\"hasEndViewChanged()\">\n @for (month of monthNames; track month; let i = $index) {\n @let endMonthDisabled = isEndMonthDisabled(i);\n <div class=\"flex items-center justify-center\">\n <button\n type=\"button\"\n [class]=\"i | zMonthClasses: endMonth().getMonth()\"\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-0.5\"\n [class.z-calendar-animate]=\"hasEndViewChanged()\">\n @for (year of endYearRange(); track year) {\n @let endYearDisabled = isEndYearDisabled(year);\n <div class=\"flex items-center justify-center\">\n <button\n type=\"button\"\n [class]=\"year | zYearClasses: endMonth().getFullYear()\"\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\n <!-- Range Mode Time Picker Side Panel -->\n @if (isRangeMode() && zShowTime() && currentView() === 'day' && endView() === 'day') {\n <div\n class=\"border-border mt-3 flex w-full flex-row justify-center gap-3 border-t pt-3 sm:mt-0 sm:w-auto sm:border-t-0 sm:border-l sm:pt-0 sm:pl-3\">\n <!-- Start Time -->\n <div class=\"flex flex-col\">\n <div class=\"text-muted-foreground mb-2 text-center text-xs font-medium\">\n {{ 'i18n_z_ui_calendar_start' | translate }}\n </div>\n <div class=\"flex flex-col gap-2\">\n <div class=\"flex justify-center gap-1\">\n @if (zShowHour()) {\n <ng-scrollbar\n class=\"z-time-column border-border h-[120px] w-10 rounded border sm:h-[235px]\"\n track=\"vertical\">\n <div class=\"flex flex-col\">\n @for (hour of hourOptions(); track hour) {\n <button\n type=\"button\"\n class=\"hover:bg-muted flex h-7 shrink-0 cursor-pointer items-center justify-center text-xs transition-colors\"\n [class.bg-primary]=\"isHourSelected(hour)\"\n [class.text-primary-foreground]=\"isHourSelected(hour)\"\n [class.font-medium]=\"isHourSelected(hour)\"\n (click)=\"selectHour(hour)\">\n {{ hour | number: '2.0-0' }}\n </button>\n }\n </div>\n </ng-scrollbar>\n }\n @if (zShowMinute()) {\n <ng-scrollbar\n class=\"z-time-column border-border h-[120px] w-10 rounded border sm:h-[235px]\"\n track=\"vertical\">\n <div class=\"flex flex-col\">\n @for (minute of minuteOptions; track minute) {\n <button\n type=\"button\"\n class=\"hover:bg-muted flex h-7 shrink-0 cursor-pointer items-center justify-center text-xs transition-colors\"\n [class.bg-primary]=\"isMinuteSelected(minute)\"\n [class.text-primary-foreground]=\"isMinuteSelected(minute)\"\n [class.font-medium]=\"isMinuteSelected(minute)\"\n (click)=\"selectMinute(minute)\">\n {{ minute | number: '2.0-0' }}\n </button>\n }\n </div>\n </ng-scrollbar>\n }\n @if (zShowSecond()) {\n <ng-scrollbar\n class=\"z-time-column border-border h-[120px] w-10 rounded border sm:h-[235px]\"\n track=\"vertical\">\n <div class=\"flex flex-col\">\n @for (second of secondOptions; track second) {\n <button\n type=\"button\"\n class=\"hover:bg-muted flex h-7 shrink-0 cursor-pointer items-center justify-center text-xs transition-colors\"\n [class.bg-primary]=\"isSecondSelected(second)\"\n [class.text-primary-foreground]=\"isSecondSelected(second)\"\n [class.font-medium]=\"isSecondSelected(second)\"\n (click)=\"selectSecond(second)\">\n {{ second | number: '2.0-0' }}\n </button>\n }\n </div>\n </ng-scrollbar>\n }\n </div>\n @if (zTimeFormat() === '12h') {\n <div class=\"flex gap-1\">\n <button\n type=\"button\"\n class=\"hover:bg-muted flex h-6 flex-1 cursor-pointer items-center justify-center rounded text-xs font-medium transition-colors\"\n [class.bg-primary]=\"period() === 'AM'\"\n [class.text-primary-foreground]=\"period() === 'AM'\"\n (click)=\"selectPeriod('AM')\">\n AM\n </button>\n <button\n type=\"button\"\n class=\"hover:bg-muted flex h-6 flex-1 cursor-pointer items-center justify-center rounded text-xs font-medium transition-colors\"\n [class.bg-primary]=\"period() === 'PM'\"\n [class.text-primary-foreground]=\"period() === 'PM'\"\n (click)=\"selectPeriod('PM')\">\n PM\n </button>\n </div>\n }\n </div>\n </div>\n\n <!-- End Time -->\n <div class=\"flex flex-col\">\n <div class=\"text-muted-foreground mb-2 text-center text-xs font-medium\">\n {{ 'i18n_z_ui_calendar_end' | translate }}\n </div>\n <div class=\"flex flex-col gap-2\">\n <div class=\"flex justify-center gap-1\">\n @if (zShowHour()) {\n <ng-scrollbar\n class=\"z-time-column border-border h-[120px] w-10 rounded border sm:h-[235px]\"\n track=\"vertical\">\n <div class=\"flex flex-col\">\n @for (hour of hourOptions(); track hour) {\n @let hourDisabled = isEndHourDisabled(hour);\n <button\n type=\"button\"\n class=\"flex h-7 shrink-0 items-center justify-center text-xs transition-colors\"\n [class.hover:bg-muted]=\"!hourDisabled\"\n [class.cursor-pointer]=\"!hourDisabled\"\n [class.bg-primary]=\"isHourEndSelected(hour)\"\n [class.text-primary-foreground]=\"isHourEndSelected(hour)\"\n [class.font-medium]=\"isHourEndSelected(hour)\"\n [class.opacity-30]=\"hourDisabled\"\n [class.cursor-not-allowed]=\"hourDisabled\"\n [disabled]=\"hourDisabled\"\n (click)=\"selectHourEnd(hour)\">\n {{ hour | number: '2.0-0' }}\n </button>\n }\n </div>\n </ng-scrollbar>\n }\n @if (zShowMinute()) {\n <ng-scrollbar\n class=\"z-time-column border-border h-[120px] w-10 rounded border sm:h-[235px]\"\n track=\"vertical\">\n <div class=\"flex flex-col\">\n @for (minute of minuteOptions; track minute) {\n @let minuteDisabled = isEndMinuteDisabled(minute);\n <button\n type=\"button\"\n class=\"flex h-7 shrink-0 items-center justify-center text-xs transition-colors\"\n [class.hover:bg-muted]=\"!minuteDisabled\"\n [class.cursor-pointer]=\"!minuteDisabled\"\n [class.bg-primary]=\"isMinuteEndSelected(minute)\"\n [class.text-primary-foreground]=\"isMinuteEndSelected(minute)\"\n [class.font-medium]=\"isMinuteEndSelected(minute)\"\n [class.opacity-30]=\"minuteDisabled\"\n [class.cursor-not-allowed]=\"minuteDisabled\"\n [disabled]=\"minuteDisabled\"\n (click)=\"selectMinuteEnd(minute)\">\n {{ minute | number: '2.0-0' }}\n </button>\n }\n </div>\n </ng-scrollbar>\n }\n @if (zShowSecond()) {\n <ng-scrollbar\n class=\"z-time-column border-border h-[120px] w-10 rounded border sm:h-[235px]\"\n track=\"vertical\">\n <div class=\"flex flex-col\">\n @for (second of secondOptions; track second) {\n @let secondDisabled = isEndSecondDisabled(second);\n <button\n type=\"button\"\n class=\"flex h-7 shrink-0 items-center justify-center text-xs transition-colors\"\n [class.hover:bg-muted]=\"!secondDisabled\"\n [class.cursor-pointer]=\"!secondDisabled\"\n [class.bg-primary]=\"isSecondEndSelected(second)\"\n [class.text-primary-foreground]=\"isSecondEndSelected(second)\"\n [class.font-medium]=\"isSecondEndSelected(second)\"\n [class.opacity-30]=\"secondDisabled\"\n [class.cursor-not-allowed]=\"secondDisabled\"\n [disabled]=\"secondDisabled\"\n (click)=\"selectSecondEnd(second)\">\n {{ second | number: '2.0-0' }}\n </button>\n }\n </div>\n </ng-scrollbar>\n }\n </div>\n @if (zTimeFormat() === '12h') {\n <div class=\"flex gap-1\">\n @let amDisabled = isEndPeriodDisabled('AM');\n <button\n type=\"button\"\n class=\"flex h-6 flex-1 items-center justify-center rounded text-xs font-medium transition-colors\"\n [class.hover:bg-muted]=\"!amDisabled\"\n [class.cursor-pointer]=\"!amDisabled\"\n [class.bg-primary]=\"periodEnd() === 'AM'\"\n [class.text-primary-foreground]=\"periodEnd() === 'AM'\"\n [class.opacity-30]=\"amDisabled\"\n [class.cursor-not-allowed]=\"amDisabled\"\n [disabled]=\"amDisabled\"\n (click)=\"selectPeriodEnd('AM')\">\n AM\n </button>\n @let pmDisabled = isEndPeriodDisabled('PM');\n <button\n type=\"button\"\n class=\"flex h-6 flex-1 items-center justify-center rounded text-xs font-medium transition-colors\"\n [class.hover:bg-muted]=\"!pmDisabled\"\n [class.cursor-pointer]=\"!pmDisabled\"\n [class.bg-primary]=\"periodEnd() === 'PM'\"\n [class.text-primary-foreground]=\"periodEnd() === 'PM'\"\n [class.opacity-30]=\"pmDisabled\"\n [class.cursor-not-allowed]=\"pmDisabled\"\n [disabled]=\"pmDisabled\"\n (click)=\"selectPeriodEnd('PM')\">\n PM\n </button>\n </div>\n }\n </div>\n </div>\n </div>\n }\n </div>\n } @else {\n <div class=\"flex flex-col items-center gap-2 py-2\">\n <div class=\"flex justify-center gap-1\">\n @if (zShowHour()) {\n <ng-scrollbar class=\"z-time-column border-border h-[196px] w-14 rounded border\" track=\"vertical\">\n <div class=\"flex flex-col\">\n @for (hour of hourOptions(); track hour) {\n <button\n type=\"button\"\n class=\"hover:bg-muted flex h-7 shrink-0 cursor-pointer items-center justify-center text-sm transition-colors\"\n [class.bg-primary]=\"isHourSelected(hour)\"\n [class.text-primary-foreground]=\"isHourSelected(hour)\"\n [class.font-medium]=\"isHourSelected(hour)\"\n (click)=\"selectHour(hour)\">\n {{ hour | number: '2.0-0' }}\n </button>\n }\n </div>\n </ng-scrollbar>\n }\n @if (zShowMinute()) {\n <ng-scrollbar class=\"z-time-column border-border h-[196px] w-14 rounded border\" track=\"vertical\">\n <div class=\"flex flex-col\">\n @for (minute of minuteOptions; track minute) {\n <button\n type=\"button\"\n class=\"hover:bg-muted flex h-7 shrink-0 cursor-pointer items-center justify-center text-sm transition-colors\"\n [class.bg-primary]=\"isMinuteSelected(minute)\"\n [class.text-primary-foreground]=\"isMinuteSelected(minute)\"\n [class.font-medium]=\"isMinuteSelected(minute)\"\n (click)=\"selectMinute(minute)\">\n {{ minute | number: '2.0-0' }}\n </button>\n }\n </div>\n </ng-scrollbar>\n }\n @if (zShowSecond()) {\n <ng-scrollbar class=\"z-time-column border-border h-[196px] w-14 rounded border\" track=\"vertical\">\n <div class=\"flex flex-col\">\n @for (second of secondOptions; track second) {\n <button\n type=\"button\"\n class=\"hover:bg-muted flex h-7 shrink-0 cursor-pointer items-center justify-center text-sm transition-colors\"\n [class.bg-primary]=\"isSecondSelected(second)\"\n [class.text-primary-foreground]=\"isSecondSelected(second)\"\n [class.font-medium]=\"isSecondSelected(second)\"\n (click)=\"selectSecond(second)\">\n {{ second | number: '2.0-0' }}\n </button>\n }\n </div>\n </ng-scrollbar>\n }\n </div>\n @if (zTimeFormat() === '12h') {\n <div class=\"flex w-full gap-1\">\n <button\n type=\"button\"\n class=\"hover:bg-muted flex h-7 flex-1 cursor-pointer items-center justify-center rounded text-sm font-medium transition-colors\"\n [class.bg-primary]=\"period() === 'AM'\"\n [class.text-primary-foreground]=\"period() === 'AM'\"\n (click)=\"selectPeriod('AM')\">\n AM\n </button>\n <button\n type=\"button\"\n class=\"hover:bg-muted flex h-7 flex-1 cursor-pointer items-center justify-center rounded text-sm font-medium transition-colors\"\n [class.bg-primary]=\"period() === 'PM'\"\n [class.text-primary-foreground]=\"period() === 'PM'\"\n (click)=\"selectPeriod('PM')\">\n PM\n </button>\n </div>\n }\n </div>\n }\n\n @if (!(zQuickSelect() && zMode() === 'range' && !showOkButton() && !showCancelButton())) {\n <div class=\"border-border flex items-center justify-between gap-2 border-t pt-2\">\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", styles: [".z-calendar-calendar .z-calendar-section{width:280px;flex-shrink:0}.z-calendar-calendar .z-calendar-views{height:225px;width:100%;display:flex;align-items:center;justify-content:center;flex-direction:column}.z-calendar-calendar .z-calendar-views.z-calendar-views-quarter{height:auto}.z-calendar-calendar .z-calendar-animate{animation:z-calendar-view-enter .2s ease-out}.z-time-picker{display:flex;flex-direction:column;gap:.5rem;flex-shrink:0}.z-time-picker .z-time-columns{display:flex;gap:.25rem}.z-time-picker .z-time-column{width:42px;height:180px;overflow-y:auto;scroll-snap-type:y mandatory;scroll-behavior:smooth;scrollbar-width:thin}.z-time-picker .z-time-column::-webkit-scrollbar{width:4px}.z-time-picker .z-time-column::-webkit-scrollbar-track{background:transparent}.z-time-picker .z-time-column::-webkit-scrollbar-thumb{background-color:hsl(var(--border));border-radius:2px}.z-time-picker .z-time-item{height:32px;width:100%;display:flex;align-items:center;justify-content:center;font-size:.875rem;scroll-snap-align:center;border-radius:4px;cursor:pointer;transition:background-color .15s ease,color .15s ease}.z-time-picker .z-time-item:hover:not(.z-time-item-selected){background-color:hsl(var(--muted))}.z-time-picker .z-time-item.z-time-item-selected{background-color:hsl(var(--primary));color:hsl(var(--primary-foreground));font-weight:500}.z-time-picker .z-time-item:focus-visible{outline:2px solid hsl(var(--ring));outline-offset:-2px}.z-time-picker .z-time-period-buttons{display:flex;flex-direction:column;gap:.25rem;padding-top:8px}.z-time-picker .z-time-period-buttons button{height:28px;font-size:.75rem;border-radius:4px;transition:background-color .15s ease,color .15s ease}@keyframes z-calendar-view-enter{0%{opacity:0;transform:scale(.95) translateY(4px)}to{opacity:1;transform:scale(1) translateY(0)}}\n"] }]
2952
+ ], changeDetection: ChangeDetectionStrategy.OnPush, encapsulation: ViewEncapsulation.None, exportAs: 'zCalendar', template: "<div class=\"z-calendar-wrapper flex w-full flex-col gap-2\">\n @if (zLabel()) {\n <label [for]=\"pickerId\" class=\"text-xs leading-none font-medium\" [class]=\"zLabelClass()\">\n {{ zLabel() }}\n @if (zRequired()) {\n <span class=\"text-destructive! ml-0.5\">*</span>\n }\n </label>\n }\n\n <div class=\"relative\">\n <div\n #triggerEl\n z-popover\n [zPopoverContent]=\"calendarTpl\"\n zPosition=\"bottom-left\"\n zPopoverWidth=\"auto\"\n [zOffset]=\"6\"\n [zDisabled]=\"isDisabled() || zReadonly()\"\n [zManualClose]=\"showCancelButton()\"\n [zScrollClose]=\"zScrollClose()\"\n zTrigger=\"click\"\n zClass=\"border-0 shadow-none bg-transparent p-0\"\n (zHideStart)=\"onPopoverHide()\"\n (zShow)=\"onPopoverShow()\"\n (zControl)=\"onPopoverControl($event)\"\n [id]=\"pickerId\"\n [class]=\"triggerClasses()\"\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 min-w-0 flex-1 truncate bg-transparent text-center text-sm outline-none\"\n [placeholder]=\"'i18n_z_ui_calendar_start_date' | translate\"\n [value]=\"inputDisplayStart()\"\n [disabled]=\"isDisabled()\"\n [readonly]=\"zReadonly()\"\n (click)=\"isOpen() && $event.stopPropagation()\"\n (focus)=\"onInputFocus($event)\"\n (input)=\"onStartInputChange($event)\"\n (blur)=\"onInputBlur($event)\"\n (keydown.enter)=\"onStartInputEnter($event)\"\n (keydown.escape)=\"onStartInputEscape()\" />\n <span class=\"text-muted-foreground text-sm\">-</span>\n <input\n type=\"text\"\n data-range-type=\"end\"\n class=\"placeholder:text-muted-foreground min-w-0 flex-1 truncate bg-transparent text-center text-sm outline-none\"\n [placeholder]=\"'i18n_z_ui_calendar_end_date' | translate\"\n [value]=\"inputDisplayEnd()\"\n [disabled]=\"isDisabled()\"\n [readonly]=\"zReadonly()\"\n (click)=\"isOpen() && $event.stopPropagation()\"\n (focus)=\"onInputFocus($event)\"\n (input)=\"onEndInputChange($event)\"\n (blur)=\"onInputBlur($event)\"\n (keydown.enter)=\"onEndInputEnter($event)\"\n (keydown.escape)=\"onEndInputEscape()\" />\n } @else {\n <input\n #inputEl\n type=\"text\"\n class=\"placeholder:text-muted-foreground min-w-0 flex-1 truncate bg-transparent text-sm outline-none\"\n [placeholder]=\"zPlaceholder()\"\n [value]=\"inputDisplayValue()\"\n [disabled]=\"isDisabled()\"\n [readonly]=\"zReadonly()\"\n (click)=\"isOpen() && $event.stopPropagation()\"\n (focus)=\"onInputFocus($event)\"\n (input)=\"onInputChange($event)\"\n (blur)=\"onInputBlur($event)\"\n (keydown.enter)=\"onInputEnter($event)\"\n (keydown.escape)=\"onInputEscape()\" />\n }\n\n @if (zAllowClear() && !isDisabled() && !zReadonly()) {\n <button\n type=\"button\"\n tabindex=\"-1\"\n class=\"text-muted-foreground hover:text-foreground flex size-5 shrink-0 cursor-pointer items-center justify-center rounded transition-all\"\n [class.opacity-0]=\"!hasValue()\"\n [class.pointer-events-none]=\"!hasValue()\"\n (click)=\"onClear($event)\">\n <z-icon zType=\"lucideX\" zSize=\"14\" />\n </button>\n }\n </div>\n </div>\n\n @if (showError()) {\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-[90vh] max-w-[95vw] flex-col overflow-auto rounded-[6px] border shadow-lg 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\n class=\"border-border flex shrink-0 flex-row gap-1 overflow-x-auto border-b p-2 sm:flex-col sm:gap-0 sm:space-y-1 sm:overflow-x-visible sm:border-r sm:border-b-0\">\n @for (preset of quickSelectPresets; track preset.key) {\n @let presetDisabled = preset | zIsPresetDisabled: zDisabledDate();\n <button\n type=\"button\"\n class=\"cursor-pointer rounded-[4px] 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 }}\n </button>\n }\n </div>\n }\n <div\n class=\"flex flex-1 flex-col items-center overflow-auto p-2 sm:overflow-visible\"\n [class]=\"!isRangeMode() ? 'w-[280px]' : ''\">\n @if (!isTimeMode()) {\n <div\n class=\"z-calendars-wrapper flex w-full flex-col items-center gap-3 sm:flex-row sm:items-stretch sm:justify-center sm:gap-0\">\n <!-- First Calendar -->\n <div class=\"z-calendar-section flex w-[280px] 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 <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)=\"navigatePrevious()\">\n <z-icon zType=\"lucideChevronsLeft\" zSize=\"14\" />\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)=\"navigatePreviousFast()\">\n <z-icon zType=\"lucideChevronLeft\" zSize=\"14\" />\n </button>\n\n <div class=\"flex flex-1 items-center justify-center gap-0\">\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 [zDisabled]=\"false\"\n (click)=\"setView('month')\">\n {{ currentMonthName() }}\n </button>\n }\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 </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 [zDisabled]=\"!canNavigateStartNext()\"\n [zWave]=\"false\"\n (click)=\"navigateNextFast()\">\n <z-icon zType=\"lucideChevronRight\" zSize=\"14\" />\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]=\"!canNavigateStartNext()\"\n [zWave]=\"false\"\n (click)=\"navigateNext()\">\n <z-icon zType=\"lucideChevronsRight\" zSize=\"14\" />\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-[224px]]=\"!isQuarterMode()\"\n [class.h-[224px]]=\"\n !isYearMode() &&\n !isMonthMode() &&\n !isQuarterMode() &&\n (currentView() === 'month' || currentView() === 'year')\n \"\n [class.min-h-[100px]]=\"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]=\"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 w-[33px] 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=\"!w-[33px] !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]=\"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]=\"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]=\"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 class=\"border-border bg-border hidden self-stretch sm:mx-2 sm:block sm:w-px\"></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-[280px] shrink-0 flex-col\">\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 p-0!\"\n [zDisabled]=\"!canNavigateEndPrev()\"\n [zWave]=\"false\"\n (click)=\"navigateEndPreviousFast()\">\n <z-icon zType=\"lucideChevronsLeft\" zSize=\"14\" />\n </button>\n\n <button\n type=\"button\"\n z-button\n zType=\"ghost\"\n zSize=\"sm\"\n class=\"size-7 p-0!\"\n [zDisabled]=\"!canNavigateEndPrev()\"\n [zWave]=\"false\"\n (click)=\"navigateEndPrevious()\">\n <z-icon zType=\"lucideChevronLeft\" zSize=\"14\" />\n </button>\n\n <div class=\"flex flex-1 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 p-0!\"\n [zWave]=\"false\"\n [zWave]=\"false\"\n (click)=\"navigateEndNext()\">\n <z-icon zType=\"lucideChevronRight\" zSize=\"14\" />\n </button>\n\n <button\n type=\"button\"\n z-button\n zType=\"ghost\"\n zSize=\"sm\"\n class=\"size-7 p-0!\"\n [zWave]=\"false\"\n [zWave]=\"false\"\n (click)=\"navigateEndNextFast()\">\n <z-icon zType=\"lucideChevronsRight\" zSize=\"14\" />\n </button>\n </div>\n\n <!-- Body -->\n <div\n class=\"flex h-full min-h-[224px] w-full flex-col items-center justify-center p-2\"\n [class.h-[224px]]=\"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]=\"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 w-[33px] 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=\"!w-[33px] !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]=\"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]=\"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 class=\"border-border w-full border-t text-center\">\n <div\n class=\"hover:bg-muted my-1 inline-flex cursor-pointer items-center rounded-sm px-2 py-1 transition-colors\"\n z-popover\n [zPopoverContent]=\"timeDropdownTpl\"\n zPosition=\"bottom\"\n zPopoverWidth=\"auto\"\n [zOffset]=\"4\"\n zTrigger=\"click\"\n zClass=\"border-border shadow-md\"\n (zShow)=\"onTimeDropdownShow()\">\n <div class=\"flex items-center justify-center gap-1\">\n <!-- Hour -->\n @if (zShowHour()) {\n <div\n class=\"hover:bg-muted/50 flex min-w-7 cursor-pointer flex-col items-center gap-0 rounded px-1 transition-colors\">\n <button\n type=\"button\"\n class=\"text-muted-foreground hover:bg-muted hover:text-foreground active:bg-accent mb-0.5 flex h-4 w-full cursor-pointer items-center justify-center rounded border-none bg-transparent transition-colors\"\n (click)=\"decrementHour(); $event.stopPropagation()\">\n <z-icon zType=\"lucideChevronUp\" zSize=\"14\" />\n </button>\n <span class=\"text-foreground min-w-5 text-center text-sm leading-tight font-medium select-none\">\n {{ formattedHour() }}\n </span>\n <button\n type=\"button\"\n class=\"text-muted-foreground hover:bg-muted hover:text-foreground active:bg-accent mt-0.5 flex h-4 w-full cursor-pointer items-center justify-center rounded border-none bg-transparent transition-colors\"\n (click)=\"incrementHour(); $event.stopPropagation()\">\n <z-icon zType=\"lucideChevronDown\" zSize=\"14\" />\n </button>\n </div>\n }\n @if (zShowHour() && zShowMinute()) {\n <span class=\"text-muted-foreground text-sm font-medium\">:</span>\n }\n <!-- Minute -->\n @if (zShowMinute()) {\n <div\n class=\"hover:bg-muted/50 flex min-w-7 cursor-pointer flex-col items-center gap-0 rounded px-1 transition-colors\">\n <button\n type=\"button\"\n class=\"text-muted-foreground hover:bg-muted hover:text-foreground active:bg-accent mb-0.5 flex h-4 w-full cursor-pointer items-center justify-center rounded border-none bg-transparent transition-colors\"\n (click)=\"decrementMinute(); $event.stopPropagation()\">\n <z-icon zType=\"lucideChevronUp\" zSize=\"14\" />\n </button>\n <span class=\"text-foreground min-w-5 text-center text-sm leading-tight font-medium select-none\">\n {{ formattedMinute() }}\n </span>\n <button\n type=\"button\"\n class=\"text-muted-foreground hover:bg-muted hover:text-foreground active:bg-accent mt-0.5 flex h-4 w-full cursor-pointer items-center justify-center rounded border-none bg-transparent transition-colors\"\n (click)=\"incrementMinute(); $event.stopPropagation()\">\n <z-icon zType=\"lucideChevronDown\" zSize=\"14\" />\n </button>\n </div>\n }\n @if (zShowMinute() && zShowSecond()) {\n <span class=\"text-muted-foreground text-sm font-medium\">:</span>\n }\n <!-- Second -->\n @if (zShowSecond()) {\n <div\n class=\"hover:bg-muted/50 flex min-w-7 cursor-pointer flex-col items-center gap-0 rounded px-1 transition-colors\">\n <button\n type=\"button\"\n class=\"text-muted-foreground hover:bg-muted hover:text-foreground active:bg-accent mb-0.5 flex h-4 w-full cursor-pointer items-center justify-center rounded border-none bg-transparent transition-colors\"\n (click)=\"decrementSecond(); $event.stopPropagation()\">\n <z-icon zType=\"lucideChevronUp\" zSize=\"14\" />\n </button>\n <span class=\"text-foreground min-w-5 text-center text-sm leading-tight font-medium select-none\">\n {{ formattedSecond() }}\n </span>\n <button\n type=\"button\"\n class=\"text-muted-foreground hover:bg-muted hover:text-foreground active:bg-accent mt-0.5 flex h-4 w-full cursor-pointer items-center justify-center rounded border-none bg-transparent transition-colors\"\n (click)=\"incrementSecond(); $event.stopPropagation()\">\n <z-icon zType=\"lucideChevronDown\" zSize=\"14\" />\n </button>\n </div>\n }\n <!-- AM/PM Toggle -->\n @if (zTimeFormat() === '12h') {\n <button\n type=\"button\"\n class=\"bg-primary/10 text-primary hover:bg-primary/20 active:bg-primary/30 ml-1 flex w-8 cursor-pointer items-center justify-center rounded border-none px-2 py-1 text-xs font-semibold transition-colors\"\n (click)=\"togglePeriod(); $event.stopPropagation()\">\n {{ period() }}\n </button>\n }\n </div>\n </div>\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 sm:gap-3\">\n <!-- Start Time -->\n <div class=\"flex w-full flex-col items-center justify-center gap-1\">\n <div\n class=\"hover:bg-muted my-1 inline-flex cursor-pointer items-center rounded-sm px-2 py-1 transition-colors\"\n z-popover\n [zPopoverContent]=\"timeDropdownStartTpl\"\n zPosition=\"bottom\"\n zPopoverWidth=\"auto\"\n [zOffset]=\"4\"\n zTrigger=\"click\"\n zClass=\"border-border shadow-md\"\n (zShow)=\"onTimeDropdownShow()\">\n <div class=\"flex items-center justify-center gap-1\">\n <!-- Hour -->\n @if (zShowHour()) {\n <div\n class=\"hover:bg-muted/50 flex min-w-7 cursor-pointer flex-col items-center gap-0 rounded px-1 transition-colors\">\n <button\n type=\"button\"\n class=\"text-muted-foreground hover:bg-muted hover:text-foreground active:bg-accent mb-0.5 flex h-4 w-full cursor-pointer items-center justify-center rounded border-none bg-transparent transition-colors\"\n (click)=\"decrementHour(); $event.stopPropagation()\">\n <z-icon zType=\"lucideChevronUp\" zSize=\"14\" />\n </button>\n <span class=\"text-foreground min-w-5 text-center text-sm leading-tight font-medium select-none\">\n {{ formattedHour() }}\n </span>\n <button\n type=\"button\"\n class=\"text-muted-foreground hover:bg-muted hover:text-foreground active:bg-accent mt-0.5 flex h-4 w-full cursor-pointer items-center justify-center rounded border-none bg-transparent transition-colors\"\n (click)=\"incrementHour(); $event.stopPropagation()\">\n <z-icon zType=\"lucideChevronDown\" zSize=\"14\" />\n </button>\n </div>\n }\n @if (zShowHour() && zShowMinute()) {\n <span class=\"text-muted-foreground text-sm font-medium\">:</span>\n }\n <!-- Minute -->\n @if (zShowMinute()) {\n <div\n class=\"hover:bg-muted/50 flex min-w-7 cursor-pointer flex-col items-center gap-0 rounded px-1 transition-colors\">\n <button\n type=\"button\"\n class=\"text-muted-foreground hover:bg-muted hover:text-foreground active:bg-accent mb-0.5 flex h-4 w-full cursor-pointer items-center justify-center rounded border-none bg-transparent transition-colors\"\n (click)=\"decrementMinute(); $event.stopPropagation()\">\n <z-icon zType=\"lucideChevronUp\" zSize=\"14\" />\n </button>\n <span class=\"text-foreground min-w-5 text-center text-sm leading-tight font-medium select-none\">\n {{ formattedMinute() }}\n </span>\n <button\n type=\"button\"\n class=\"text-muted-foreground hover:bg-muted hover:text-foreground active:bg-accent mt-0.5 flex h-4 w-full cursor-pointer items-center justify-center rounded border-none bg-transparent transition-colors\"\n (click)=\"incrementMinute(); $event.stopPropagation()\">\n <z-icon zType=\"lucideChevronDown\" zSize=\"14\" />\n </button>\n </div>\n }\n @if (zShowMinute() && zShowSecond()) {\n <span class=\"text-muted-foreground text-sm font-medium\">:</span>\n }\n <!-- Second -->\n @if (zShowSecond()) {\n <div\n class=\"hover:bg-muted/50 flex min-w-7 cursor-pointer flex-col items-center gap-0 rounded px-1 transition-colors\">\n <button\n type=\"button\"\n class=\"text-muted-foreground hover:bg-muted hover:text-foreground active:bg-accent mb-0.5 flex h-4 w-full cursor-pointer items-center justify-center rounded border-none bg-transparent transition-colors\"\n (click)=\"decrementSecond(); $event.stopPropagation()\">\n <z-icon zType=\"lucideChevronUp\" zSize=\"14\" />\n </button>\n <span class=\"text-foreground min-w-5 text-center text-sm leading-tight font-medium select-none\">\n {{ formattedSecond() }}\n </span>\n <button\n type=\"button\"\n class=\"text-muted-foreground hover:bg-muted hover:text-foreground active:bg-accent mt-0.5 flex h-4 w-full cursor-pointer items-center justify-center rounded border-none bg-transparent transition-colors\"\n (click)=\"incrementSecond(); $event.stopPropagation()\">\n <z-icon zType=\"lucideChevronDown\" zSize=\"14\" />\n </button>\n </div>\n }\n <!-- AM/PM Toggle -->\n @if (zTimeFormat() === '12h') {\n <button\n type=\"button\"\n class=\"bg-primary/10 text-primary hover:bg-primary/20 active:bg-primary/30 ml-1 flex w-8 cursor-pointer items-center justify-center rounded border-none px-2 py-1 text-xs font-semibold transition-colors\"\n (click)=\"togglePeriod(); $event.stopPropagation()\">\n {{ period() }}\n </button>\n }\n </div>\n </div>\n </div>\n\n <!-- Divider space -->\n <div class=\"border-border bg-border h-px self-stretch sm:mx-2 sm:block sm:h-full sm:w-px\"></div>\n\n <!-- End Time -->\n <div class=\"flex w-full flex-col items-center justify-center gap-1\">\n <div\n class=\"hover:bg-muted my-1 inline-flex cursor-pointer items-center rounded-sm px-2 py-1 transition-colors\"\n z-popover\n [zPopoverContent]=\"timeDropdownEndTpl\"\n zPosition=\"bottom\"\n zPopoverWidth=\"auto\"\n [zOffset]=\"4\"\n zTrigger=\"click\"\n zClass=\"border-border shadow-md\"\n (zShow)=\"onTimeDropdownEndShow()\">\n <div class=\"flex items-center justify-center gap-1\">\n <!-- Hour -->\n @if (zShowHour()) {\n <div\n class=\"hover:bg-muted/50 flex min-w-7 cursor-pointer flex-col items-center gap-0 rounded px-1 transition-colors\">\n <button\n type=\"button\"\n class=\"text-muted-foreground hover:bg-muted hover:text-foreground active:bg-accent mb-0.5 flex h-4 w-full cursor-pointer items-center justify-center rounded border-none bg-transparent transition-colors\"\n (click)=\"decrementHourEnd(); $event.stopPropagation()\">\n <z-icon zType=\"lucideChevronUp\" zSize=\"14\" />\n </button>\n <span class=\"text-foreground min-w-5 text-center text-sm leading-tight font-medium select-none\">\n {{ formattedHourEnd() }}\n </span>\n <button\n type=\"button\"\n class=\"text-muted-foreground hover:bg-muted hover:text-foreground active:bg-accent mt-0.5 flex h-4 w-full cursor-pointer items-center justify-center rounded border-none bg-transparent transition-colors\"\n (click)=\"incrementHourEnd(); $event.stopPropagation()\">\n <z-icon zType=\"lucideChevronDown\" zSize=\"14\" />\n </button>\n </div>\n }\n @if (zShowHour() && zShowMinute()) {\n <span class=\"text-muted-foreground text-sm font-medium\">:</span>\n }\n <!-- Minute -->\n @if (zShowMinute()) {\n <div\n class=\"hover:bg-muted/50 flex min-w-7 cursor-pointer flex-col items-center gap-0 rounded px-1 transition-colors\">\n <button\n type=\"button\"\n class=\"text-muted-foreground hover:bg-muted hover:text-foreground active:bg-accent mb-0.5 flex h-4 w-full cursor-pointer items-center justify-center rounded border-none bg-transparent transition-colors\"\n (click)=\"decrementMinuteEnd(); $event.stopPropagation()\">\n <z-icon zType=\"lucideChevronUp\" zSize=\"14\" />\n </button>\n <span class=\"text-foreground min-w-5 text-center text-sm leading-tight font-medium select-none\">\n {{ formattedMinuteEnd() }}\n </span>\n <button\n type=\"button\"\n class=\"text-muted-foreground hover:bg-muted hover:text-foreground active:bg-accent mt-0.5 flex h-4 w-full cursor-pointer items-center justify-center rounded border-none bg-transparent transition-colors\"\n (click)=\"incrementMinuteEnd(); $event.stopPropagation()\">\n <z-icon zType=\"lucideChevronDown\" zSize=\"14\" />\n </button>\n </div>\n }\n @if (zShowMinute() && zShowSecond()) {\n <span class=\"text-muted-foreground text-sm font-medium\">:</span>\n }\n <!-- Second -->\n @if (zShowSecond()) {\n <div\n class=\"hover:bg-muted/50 flex min-w-7 cursor-pointer flex-col items-center gap-0 rounded px-1 transition-colors\">\n <button\n type=\"button\"\n class=\"text-muted-foreground hover:bg-muted hover:text-foreground active:bg-accent mb-0.5 flex h-4 w-full cursor-pointer items-center justify-center rounded border-none bg-transparent transition-colors\"\n (click)=\"decrementSecondEnd(); $event.stopPropagation()\">\n <z-icon zType=\"lucideChevronUp\" zSize=\"14\" />\n </button>\n <span class=\"text-foreground min-w-5 text-center text-sm leading-tight font-medium select-none\">\n {{ formattedSecondEnd() }}\n </span>\n <button\n type=\"button\"\n class=\"text-muted-foreground hover:bg-muted hover:text-foreground active:bg-accent mt-0.5 flex h-4 w-full cursor-pointer items-center justify-center rounded border-none bg-transparent transition-colors\"\n (click)=\"incrementSecondEnd(); $event.stopPropagation()\">\n <z-icon zType=\"lucideChevronDown\" zSize=\"14\" />\n </button>\n </div>\n }\n <!-- AM/PM Toggle -->\n @if (zTimeFormat() === '12h') {\n <button\n type=\"button\"\n class=\"bg-primary/10 text-primary hover:bg-primary/20 active:bg-primary/30 ml-1 flex w-8 cursor-pointer items-center justify-center rounded border-none px-2 py-1 text-xs font-semibold transition-colors\"\n (click)=\"togglePeriodEnd(); $event.stopPropagation()\">\n {{ periodEnd() }}\n </button>\n }\n </div>\n </div>\n </div>\n </div>\n }\n } @else {\n <!-- Time Only Mode - Compact Display -->\n <div class=\"flex flex-col items-center gap-3 pb-2\">\n <div\n class=\"hover:bg-muted inline-flex cursor-pointer items-center rounded-md px-3 py-2 transition-colors\"\n z-popover\n [zPopoverContent]=\"timeDropdownTpl\"\n zPosition=\"bottom\"\n zPopoverWidth=\"auto\"\n [zOffset]=\"4\"\n zTrigger=\"click\"\n zClass=\"border-border shadow-md\"\n (zShow)=\"onTimeDropdownShow()\">\n <div class=\"flex items-center justify-center gap-1.5\">\n <!-- Hour -->\n @if (zShowHour()) {\n <div\n class=\"hover:bg-muted/50 flex min-w-9 cursor-pointer flex-col items-center gap-0 rounded px-1.5 transition-colors\">\n <button\n type=\"button\"\n class=\"text-muted-foreground hover:bg-muted hover:text-foreground active:bg-accent mb-1 flex h-5 w-full cursor-pointer items-center justify-center rounded border-none bg-transparent transition-colors\"\n (click)=\"decrementHour(); $event.stopPropagation()\">\n <z-icon zType=\"lucideChevronUp\" zSize=\"16\" />\n </button>\n <span class=\"text-foreground min-w-6 text-center text-base leading-tight font-medium select-none\">\n {{ formattedHour() }}\n </span>\n <button\n type=\"button\"\n class=\"text-muted-foreground hover:bg-muted hover:text-foreground active:bg-accent mt-1 flex h-5 w-full cursor-pointer items-center justify-center rounded border-none bg-transparent transition-colors\"\n (click)=\"incrementHour(); $event.stopPropagation()\">\n <z-icon zType=\"lucideChevronDown\" zSize=\"16\" />\n </button>\n </div>\n }\n @if (zShowHour() && zShowMinute()) {\n <span class=\"text-muted-foreground text-base font-medium\">:</span>\n }\n <!-- Minute -->\n @if (zShowMinute()) {\n <div\n class=\"hover:bg-muted/50 flex min-w-9 cursor-pointer flex-col items-center gap-0 rounded px-1.5 transition-colors\">\n <button\n type=\"button\"\n class=\"text-muted-foreground hover:bg-muted hover:text-foreground active:bg-accent mb-1 flex h-5 w-full cursor-pointer items-center justify-center rounded border-none bg-transparent transition-colors\"\n (click)=\"decrementMinute(); $event.stopPropagation()\">\n <z-icon zType=\"lucideChevronUp\" zSize=\"16\" />\n </button>\n <span class=\"text-foreground min-w-6 text-center text-base leading-tight font-medium select-none\">\n {{ formattedMinute() }}\n </span>\n <button\n type=\"button\"\n class=\"text-muted-foreground hover:bg-muted hover:text-foreground active:bg-accent mt-1 flex h-5 w-full cursor-pointer items-center justify-center rounded border-none bg-transparent transition-colors\"\n (click)=\"incrementMinute(); $event.stopPropagation()\">\n <z-icon zType=\"lucideChevronDown\" zSize=\"16\" />\n </button>\n </div>\n }\n @if (zShowMinute() && zShowSecond()) {\n <span class=\"text-muted-foreground text-base font-medium\">:</span>\n }\n <!-- Second -->\n @if (zShowSecond()) {\n <div\n class=\"hover:bg-muted/50 flex min-w-9 cursor-pointer flex-col items-center gap-0 rounded px-1.5 transition-colors\">\n <button\n type=\"button\"\n class=\"text-muted-foreground hover:bg-muted hover:text-foreground active:bg-accent mb-1 flex h-5 w-full cursor-pointer items-center justify-center rounded border-none bg-transparent transition-colors\"\n (click)=\"decrementSecond(); $event.stopPropagation()\">\n <z-icon zType=\"lucideChevronUp\" zSize=\"16\" />\n </button>\n <span class=\"text-foreground min-w-6 text-center text-base leading-tight font-medium select-none\">\n {{ formattedSecond() }}\n </span>\n <button\n type=\"button\"\n class=\"text-muted-foreground hover:bg-muted hover:text-foreground active:bg-accent mt-1 flex h-5 w-full cursor-pointer items-center justify-center rounded border-none bg-transparent transition-colors\"\n (click)=\"incrementSecond(); $event.stopPropagation()\">\n <z-icon zType=\"lucideChevronDown\" zSize=\"16\" />\n </button>\n </div>\n }\n <!-- AM/PM Toggle -->\n @if (zTimeFormat() === '12h') {\n <button\n type=\"button\"\n class=\"bg-primary/10 text-primary hover:bg-primary/20 active:bg-primary/30 ml-1 flex w-10 cursor-pointer items-center justify-center rounded border-none px-2.5 py-1.5 text-sm font-semibold transition-colors\"\n (click)=\"togglePeriod(); $event.stopPropagation()\">\n {{ period() }}\n </button>\n }\n </div>\n </div>\n </div>\n }\n\n @if (!(zQuickSelect() && zMode() === 'range' && !showOkButton() && !showCancelButton())) {\n <div class=\"border-border flex w-full items-center justify-between gap-2 border-t pt-2\">\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 overflow-hidden rounded-[6px]\">\n @if (zShowHour()) {\n <div\n class=\"flex flex-col\"\n [class.border-r]=\"zShowMinute() || zShowSecond()\"\n [class.border-border]=\"zShowMinute() || zShowSecond()\">\n <ng-scrollbar\n class=\"z-time-scroll-hour h-[200px] w-12\"\n [class.rounded]=\"!zShowMinute() && !zShowSecond()\"\n [class.rounded-l]=\"zShowMinute() || zShowSecond()\"\n track=\"vertical\">\n <div class=\"flex flex-col\">\n @for (hr of hourOptions(); track hr) {\n @let hrSelected = hr | zIsTimeSelected: 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 class=\"flex flex-col\" [class.border-r]=\"zShowSecond()\" [class.border-border]=\"zShowSecond()\">\n <ng-scrollbar\n class=\"z-time-scroll-minute h-[200px] w-12\"\n [class.rounded]=\"!zShowHour() && !zShowSecond()\"\n [class.rounded-l]=\"!zShowHour() && zShowSecond()\"\n [class.rounded-r]=\"zShowHour() && !zShowSecond()\"\n track=\"vertical\">\n <div class=\"flex flex-col\">\n @for (min of minuteOptions; track min) {\n @let minSelected = min | zIsTimeSelected: 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 class=\"flex flex-col\">\n <ng-scrollbar\n class=\"z-time-scroll-second h-[200px] w-12\"\n [class.rounded]=\"!zShowHour() && !zShowMinute()\"\n [class.rounded-r]=\"zShowHour() || zShowMinute()\"\n track=\"vertical\">\n <div class=\"flex flex-col\">\n @for (sec of secondOptions; track sec) {\n @let secSelected = sec | zIsTimeSelected: 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 </div>\n</ng-template>\n\n<ng-template #timeDropdownStartTpl>\n <div class=\"bg-popover flex overflow-hidden rounded-[6px]\">\n @if (zShowHour()) {\n <div\n class=\"flex flex-col\"\n [class.border-r]=\"zShowMinute() || zShowSecond()\"\n [class.border-border]=\"zShowMinute() || zShowSecond()\">\n <ng-scrollbar\n class=\"z-time-scroll-hour h-[200px] w-12\"\n [class.rounded]=\"!zShowMinute() && !zShowSecond()\"\n [class.rounded-l]=\"zShowMinute() || zShowSecond()\"\n track=\"vertical\">\n <div class=\"flex flex-col\">\n @for (hr of hourOptions(); track hr) {\n @let hrSelected = hr | zIsTimeSelected: 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 class=\"flex flex-col\" [class.border-r]=\"zShowSecond()\" [class.border-border]=\"zShowSecond()\">\n <ng-scrollbar\n class=\"z-time-scroll-minute h-[200px] w-12\"\n [class.rounded]=\"!zShowHour() && !zShowSecond()\"\n [class.rounded-l]=\"!zShowHour() && zShowSecond()\"\n [class.rounded-r]=\"zShowHour() && !zShowSecond()\"\n track=\"vertical\">\n <div class=\"flex flex-col\">\n @for (min of minuteOptions; track min) {\n @let minSelected = min | zIsTimeSelected: 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 class=\"flex flex-col\">\n <ng-scrollbar\n class=\"z-time-scroll-second h-[200px] w-12\"\n [class.rounded]=\"!zShowHour() && !zShowMinute()\"\n [class.rounded-r]=\"zShowHour() || zShowMinute()\"\n track=\"vertical\">\n <div class=\"flex flex-col\">\n @for (sec of secondOptions; track sec) {\n @let secSelected = sec | zIsTimeSelected: 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 </div>\n</ng-template>\n\n<ng-template #timeDropdownEndTpl>\n <div class=\"bg-popover flex overflow-hidden rounded-[6px]\">\n @if (zShowHour()) {\n <div\n class=\"flex flex-col\"\n [class.border-r]=\"zShowMinute() || zShowSecond()\"\n [class.border-border]=\"zShowMinute() || zShowSecond()\">\n <ng-scrollbar\n class=\"z-time-scroll-hour-end h-[200px] w-12\"\n [class.rounded]=\"!zShowMinute() && !zShowSecond()\"\n [class.rounded-l]=\"zShowMinute() || zShowSecond()\"\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 | zIsTimeSelected: 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 class=\"flex flex-col\" [class.border-r]=\"zShowSecond()\" [class.border-border]=\"zShowSecond()\">\n <ng-scrollbar\n class=\"z-time-scroll-minute-end h-[200px] w-12\"\n [class.rounded]=\"!zShowHour() && !zShowSecond()\"\n [class.rounded-l]=\"!zShowHour() && zShowSecond()\"\n [class.rounded-r]=\"zShowHour() && !zShowSecond()\"\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 | zIsTimeSelected: 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 class=\"flex flex-col\">\n <ng-scrollbar\n class=\"z-time-scroll-second-end h-[200px] w-12\"\n [class.rounded]=\"!zShowHour() && !zShowMinute()\"\n [class.rounded-r]=\"zShowHour() || zShowMinute()\"\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 | zIsTimeSelected: 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 </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(4px)}to{opacity:1;transform:scale(1) translateY(0)}}\n"] }]
2869
2953
  }], 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 }] }], 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 }] }], zLocale: [{ type: i0.Input, args: [{ isSignal: true, alias: "zLocale", 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 }] }], zControl: [{ type: i0.Output, args: ["zControl"] }], zChange: [{ type: i0.Output, args: ["zChange"] }], triggerRef: [{ type: i0.ViewChild, args: ['triggerEl', { isSignal: true }] }], inputRef: [{ type: i0.ViewChild, args: ['inputEl', { isSignal: true }] }] } });
2870
2954
 
2871
2955
  /**