@shival99/z-ui 1.0.1 → 1.0.2
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/assets/css/animations.css +207 -0
- package/assets/css/base.css +76 -0
- package/assets/css/tailwind.css +53 -0
- package/assets/css/themes/gray.css +73 -0
- package/assets/css/themes/green.css +75 -0
- package/assets/css/themes/hospital.css +79 -0
- package/assets/css/themes/neutral.css +73 -0
- package/assets/css/themes/orange.css +73 -0
- package/assets/css/themes/slate.css +73 -0
- package/assets/css/themes/stone.css +73 -0
- package/assets/css/themes/violet.css +73 -0
- package/assets/css/themes/zinc.css +73 -0
- package/assets/images/avatar.svg +6 -0
- package/assets/images/logo.svg +6 -0
- package/fesm2022/shival99-z-ui-components-z-accordion.mjs +148 -0
- package/fesm2022/shival99-z-ui-components-z-accordion.mjs.map +1 -0
- package/fesm2022/shival99-z-ui-components-z-breadcrumb.mjs +74 -0
- package/fesm2022/shival99-z-ui-components-z-breadcrumb.mjs.map +1 -0
- package/fesm2022/shival99-z-ui-components-z-button.mjs +155 -0
- package/fesm2022/shival99-z-ui-components-z-button.mjs.map +1 -0
- package/fesm2022/shival99-z-ui-components-z-calendar.mjs +2335 -0
- package/fesm2022/shival99-z-ui-components-z-calendar.mjs.map +1 -0
- package/fesm2022/shival99-z-ui-components-z-checkbox.mjs +240 -0
- package/fesm2022/shival99-z-ui-components-z-checkbox.mjs.map +1 -0
- package/fesm2022/shival99-z-ui-components-z-code.mjs +139 -0
- package/fesm2022/shival99-z-ui-components-z-code.mjs.map +1 -0
- package/fesm2022/shival99-z-ui-components-z-drawer.mjs +664 -0
- package/fesm2022/shival99-z-ui-components-z-drawer.mjs.map +1 -0
- package/fesm2022/shival99-z-ui-components-z-dropdown-menu.mjs +55 -0
- package/fesm2022/shival99-z-ui-components-z-dropdown-menu.mjs.map +1 -0
- package/fesm2022/shival99-z-ui-components-z-editor.mjs +411 -0
- package/fesm2022/shival99-z-ui-components-z-editor.mjs.map +1 -0
- package/fesm2022/shival99-z-ui-components-z-filter.mjs +794 -0
- package/fesm2022/shival99-z-ui-components-z-filter.mjs.map +1 -0
- package/fesm2022/shival99-z-ui-components-z-icon.mjs +451 -0
- package/fesm2022/shival99-z-ui-components-z-icon.mjs.map +1 -0
- package/fesm2022/shival99-z-ui-components-z-input.mjs +804 -0
- package/fesm2022/shival99-z-ui-components-z-input.mjs.map +1 -0
- package/fesm2022/shival99-z-ui-components-z-loading.mjs +105 -0
- package/fesm2022/shival99-z-ui-components-z-loading.mjs.map +1 -0
- package/fesm2022/shival99-z-ui-components-z-menu.mjs +351 -0
- package/fesm2022/shival99-z-ui-components-z-menu.mjs.map +1 -0
- package/fesm2022/shival99-z-ui-components-z-modal.mjs +722 -0
- package/fesm2022/shival99-z-ui-components-z-modal.mjs.map +1 -0
- package/fesm2022/shival99-z-ui-components-z-pagination.mjs +131 -0
- package/fesm2022/shival99-z-ui-components-z-pagination.mjs.map +1 -0
- package/fesm2022/shival99-z-ui-components-z-popover.mjs +917 -0
- package/fesm2022/shival99-z-ui-components-z-popover.mjs.map +1 -0
- package/fesm2022/shival99-z-ui-components-z-radio.mjs +154 -0
- package/fesm2022/shival99-z-ui-components-z-radio.mjs.map +1 -0
- package/fesm2022/shival99-z-ui-components-z-select.mjs +998 -0
- package/fesm2022/shival99-z-ui-components-z-select.mjs.map +1 -0
- package/fesm2022/shival99-z-ui-components-z-skeleton.mjs +139 -0
- package/fesm2022/shival99-z-ui-components-z-skeleton.mjs.map +1 -0
- package/fesm2022/shival99-z-ui-components-z-switch.mjs +127 -0
- package/fesm2022/shival99-z-ui-components-z-switch.mjs.map +1 -0
- package/fesm2022/shival99-z-ui-components-z-table.mjs +2628 -0
- package/fesm2022/shival99-z-ui-components-z-table.mjs.map +1 -0
- package/fesm2022/shival99-z-ui-components-z-tabs.mjs +259 -0
- package/fesm2022/shival99-z-ui-components-z-tabs.mjs.map +1 -0
- package/fesm2022/shival99-z-ui-components-z-timeline.mjs +335 -0
- package/fesm2022/shival99-z-ui-components-z-timeline.mjs.map +1 -0
- package/fesm2022/shival99-z-ui-components-z-toast.mjs +93 -0
- package/fesm2022/shival99-z-ui-components-z-toast.mjs.map +1 -0
- package/fesm2022/shival99-z-ui-components-z-tooltip.mjs +660 -0
- package/fesm2022/shival99-z-ui-components-z-tooltip.mjs.map +1 -0
- package/fesm2022/shival99-z-ui-components-z-upload.mjs +504 -0
- package/fesm2022/shival99-z-ui-components-z-upload.mjs.map +1 -0
- package/fesm2022/shival99-z-ui-i18n.mjs +258 -0
- package/fesm2022/shival99-z-ui-i18n.mjs.map +1 -0
- package/fesm2022/shival99-z-ui-pipes.mjs +116 -0
- package/fesm2022/shival99-z-ui-pipes.mjs.map +1 -0
- package/fesm2022/shival99-z-ui-providers.mjs +203 -0
- package/fesm2022/shival99-z-ui-providers.mjs.map +1 -0
- package/fesm2022/shival99-z-ui-services.mjs +919 -0
- package/fesm2022/shival99-z-ui-services.mjs.map +1 -0
- package/fesm2022/shival99-z-ui-utils.mjs +591 -0
- package/fesm2022/shival99-z-ui-utils.mjs.map +1 -0
- package/fesm2022/z-ui.mjs +3 -19924
- package/fesm2022/z-ui.mjs.map +1 -1
- package/package.json +129 -1
- package/types/shival99-z-ui-components-z-accordion.d.ts +55 -0
- package/types/shival99-z-ui-components-z-breadcrumb.d.ts +36 -0
- package/types/shival99-z-ui-components-z-button.d.ts +41 -0
- package/types/shival99-z-ui-components-z-calendar.d.ts +300 -0
- package/types/shival99-z-ui-components-z-checkbox.d.ts +84 -0
- package/types/shival99-z-ui-components-z-code.d.ts +35 -0
- package/types/shival99-z-ui-components-z-drawer.d.ts +232 -0
- package/types/shival99-z-ui-components-z-dropdown-menu.d.ts +50 -0
- package/types/shival99-z-ui-components-z-editor.d.ts +115 -0
- package/types/shival99-z-ui-components-z-filter.d.ts +268 -0
- package/types/shival99-z-ui-components-z-icon.d.ts +291 -0
- package/types/shival99-z-ui-components-z-input.d.ts +188 -0
- package/types/shival99-z-ui-components-z-loading.d.ts +46 -0
- package/types/shival99-z-ui-components-z-menu.d.ts +116 -0
- package/types/shival99-z-ui-components-z-modal.d.ts +270 -0
- package/types/shival99-z-ui-components-z-pagination.d.ts +52 -0
- package/types/shival99-z-ui-components-z-popover.d.ts +134 -0
- package/types/shival99-z-ui-components-z-radio.d.ts +63 -0
- package/types/shival99-z-ui-components-z-select.d.ts +268 -0
- package/types/shival99-z-ui-components-z-skeleton.d.ts +55 -0
- package/types/shival99-z-ui-components-z-switch.d.ts +48 -0
- package/types/shival99-z-ui-components-z-table.d.ts +482 -0
- package/types/shival99-z-ui-components-z-tabs.d.ts +75 -0
- package/types/shival99-z-ui-components-z-timeline.d.ts +98 -0
- package/types/shival99-z-ui-components-z-toast.d.ts +61 -0
- package/types/shival99-z-ui-components-z-tooltip.d.ts +85 -0
- package/types/shival99-z-ui-components-z-upload.d.ts +136 -0
- package/types/shival99-z-ui-i18n.d.ts +50 -0
- package/types/shival99-z-ui-pipes.d.ts +36 -0
- package/types/shival99-z-ui-providers.d.ts +132 -0
- package/types/shival99-z-ui-services.d.ts +364 -0
- package/types/shival99-z-ui-utils.d.ts +145 -0
- package/types/z-ui.d.ts +3 -4977
|
@@ -0,0 +1,2335 @@
|
|
|
1
|
+
import * as i0 from '@angular/core';
|
|
2
|
+
import { Pipe, input, output, viewChild, computed, signal, inject, Injector, DestroyRef, ChangeDetectorRef, effect, forwardRef, ViewEncapsulation, ChangeDetectionStrategy, Component } from '@angular/core';
|
|
3
|
+
import { takeUntilDestroyed } from '@angular/core/rxjs-interop';
|
|
4
|
+
import { NgControl, NG_VALUE_ACCESSOR } from '@angular/forms';
|
|
5
|
+
import { merge } from 'rxjs';
|
|
6
|
+
import { cva } from 'class-variance-authority';
|
|
7
|
+
import { zTransform, zGenerateId, zMergeClasses } from '@shival99/z-ui/utils';
|
|
8
|
+
import { ZButtonComponent } from '@shival99/z-ui/components/z-button';
|
|
9
|
+
import { ZIconComponent } from '@shival99/z-ui/components/z-icon';
|
|
10
|
+
import { ZPopoverDirective } from '@shival99/z-ui/components/z-popover';
|
|
11
|
+
|
|
12
|
+
const createDate = (year, month, day, hour = 0, minute = 0, second = 0) => new Date(year, month, day, hour, minute, second);
|
|
13
|
+
const cloneDate = (date) => new Date(date.getTime());
|
|
14
|
+
const getToday = () => {
|
|
15
|
+
const now = new Date();
|
|
16
|
+
return createDate(now.getFullYear(), now.getMonth(), now.getDate());
|
|
17
|
+
};
|
|
18
|
+
const startOfDay = (date) => createDate(date.getFullYear(), date.getMonth(), date.getDate());
|
|
19
|
+
const startOfMonth = (date) => createDate(date.getFullYear(), date.getMonth(), 1);
|
|
20
|
+
const endOfMonth = (date) => createDate(date.getFullYear(), date.getMonth() + 1, 0);
|
|
21
|
+
const startOfYear = (date) => createDate(date.getFullYear(), 0, 1);
|
|
22
|
+
const addDays = (date, days) => {
|
|
23
|
+
const result = cloneDate(date);
|
|
24
|
+
result.setDate(result.getDate() + days);
|
|
25
|
+
return result;
|
|
26
|
+
};
|
|
27
|
+
const addMonths = (date, months) => {
|
|
28
|
+
const result = cloneDate(date);
|
|
29
|
+
result.setMonth(result.getMonth() + months);
|
|
30
|
+
return result;
|
|
31
|
+
};
|
|
32
|
+
const addYears = (date, years) => {
|
|
33
|
+
const result = cloneDate(date);
|
|
34
|
+
result.setFullYear(result.getFullYear() + years);
|
|
35
|
+
return result;
|
|
36
|
+
};
|
|
37
|
+
const setMonth = (date, month) => {
|
|
38
|
+
const result = cloneDate(date);
|
|
39
|
+
result.setMonth(month);
|
|
40
|
+
return result;
|
|
41
|
+
};
|
|
42
|
+
const setYear = (date, year) => {
|
|
43
|
+
const result = cloneDate(date);
|
|
44
|
+
result.setFullYear(year);
|
|
45
|
+
return result;
|
|
46
|
+
};
|
|
47
|
+
const setTime = (date, hour, minute, second) => {
|
|
48
|
+
const result = cloneDate(date);
|
|
49
|
+
result.setHours(hour, minute, second, 0);
|
|
50
|
+
return result;
|
|
51
|
+
};
|
|
52
|
+
const isSameDay = (date1, date2) => {
|
|
53
|
+
if (!date1 || !date2) {
|
|
54
|
+
return false;
|
|
55
|
+
}
|
|
56
|
+
return (date1.getFullYear() === date2.getFullYear() &&
|
|
57
|
+
date1.getMonth() === date2.getMonth() &&
|
|
58
|
+
date1.getDate() === date2.getDate());
|
|
59
|
+
};
|
|
60
|
+
const isSameMonth = (date1, date2) => date1.getFullYear() === date2.getFullYear() && date1.getMonth() === date2.getMonth();
|
|
61
|
+
const isSameYear = (date1, date2) => date1.getFullYear() === date2.getFullYear();
|
|
62
|
+
const isToday = (date) => isSameDay(date, new Date());
|
|
63
|
+
const isBefore = (date1, date2) => startOfDay(date1).getTime() < startOfDay(date2).getTime();
|
|
64
|
+
const isAfter = (date1, date2) => startOfDay(date1).getTime() > startOfDay(date2).getTime();
|
|
65
|
+
const isBeforeOrEqual = (date1, date2) => startOfDay(date1).getTime() <= startOfDay(date2).getTime();
|
|
66
|
+
const isAfterOrEqual = (date1, date2) => startOfDay(date1).getTime() >= startOfDay(date2).getTime();
|
|
67
|
+
const isBetween = (date, start, end) => {
|
|
68
|
+
const time = startOfDay(date).getTime();
|
|
69
|
+
const startTime = startOfDay(start).getTime();
|
|
70
|
+
const endTime = startOfDay(end).getTime();
|
|
71
|
+
return time > startTime && time < endTime;
|
|
72
|
+
};
|
|
73
|
+
const isDateInRange = (date, minDate, maxDate) => {
|
|
74
|
+
if (minDate && isBefore(date, minDate)) {
|
|
75
|
+
return false;
|
|
76
|
+
}
|
|
77
|
+
if (maxDate && isAfter(date, maxDate)) {
|
|
78
|
+
return false;
|
|
79
|
+
}
|
|
80
|
+
return true;
|
|
81
|
+
};
|
|
82
|
+
const getDaysInMonth = (year, month) => new Date(year, month + 1, 0).getDate();
|
|
83
|
+
const getFirstDayOfMonth = (year, month) => new Date(year, month, 1).getDay();
|
|
84
|
+
const computeRangeProperties = (date, rangeStart, rangeEnd, hoveredDate) => {
|
|
85
|
+
const defaultProps = {
|
|
86
|
+
isRangeStart: false,
|
|
87
|
+
isRangeEnd: false,
|
|
88
|
+
isInRange: false,
|
|
89
|
+
isHovered: false,
|
|
90
|
+
};
|
|
91
|
+
if (rangeStart && rangeEnd) {
|
|
92
|
+
const actualStart = isBefore(rangeStart, rangeEnd) ? rangeStart : rangeEnd;
|
|
93
|
+
const actualEnd = isAfter(rangeEnd, rangeStart) ? rangeEnd : rangeStart;
|
|
94
|
+
return {
|
|
95
|
+
isRangeStart: isSameDay(date, actualStart),
|
|
96
|
+
isRangeEnd: isSameDay(date, actualEnd),
|
|
97
|
+
isInRange: isBetween(date, actualStart, actualEnd),
|
|
98
|
+
isHovered: false,
|
|
99
|
+
};
|
|
100
|
+
}
|
|
101
|
+
if (rangeStart && hoveredDate && !rangeEnd) {
|
|
102
|
+
const isHoveredBefore = isBefore(hoveredDate, rangeStart);
|
|
103
|
+
const effectiveStart = isHoveredBefore ? hoveredDate : rangeStart;
|
|
104
|
+
const effectiveEnd = isHoveredBefore ? rangeStart : hoveredDate;
|
|
105
|
+
return {
|
|
106
|
+
isRangeStart: isSameDay(date, effectiveStart),
|
|
107
|
+
isRangeEnd: isSameDay(date, effectiveEnd),
|
|
108
|
+
isInRange: isBetween(date, effectiveStart, effectiveEnd),
|
|
109
|
+
isHovered: isSameDay(date, hoveredDate),
|
|
110
|
+
};
|
|
111
|
+
}
|
|
112
|
+
if (rangeStart) {
|
|
113
|
+
return { ...defaultProps, isRangeStart: isSameDay(date, rangeStart) };
|
|
114
|
+
}
|
|
115
|
+
return defaultProps;
|
|
116
|
+
};
|
|
117
|
+
const createCalendarDay = (date, isCurrentMonth, today, options) => {
|
|
118
|
+
const { selectedDate, minDate, maxDate, rangeStart, rangeEnd, hoveredDate, disabledDate } = options;
|
|
119
|
+
const isSelected = selectedDate ? isSameDay(date, selectedDate) : false;
|
|
120
|
+
const rangeProps = computeRangeProperties(date, rangeStart, rangeEnd, hoveredDate);
|
|
121
|
+
const isOutOfRange = !isDateInRange(date, minDate ?? null, maxDate ?? null);
|
|
122
|
+
const isDisabledByFn = disabledDate ? disabledDate(date) : false;
|
|
123
|
+
return {
|
|
124
|
+
date,
|
|
125
|
+
day: date.getDate(),
|
|
126
|
+
isCurrentMonth,
|
|
127
|
+
isToday: isSameDay(date, today),
|
|
128
|
+
isDisabled: isOutOfRange || isDisabledByFn,
|
|
129
|
+
isSelected,
|
|
130
|
+
...rangeProps,
|
|
131
|
+
};
|
|
132
|
+
};
|
|
133
|
+
const generateCalendarGrid = (year, month, options = {}) => {
|
|
134
|
+
const daysInMonth = getDaysInMonth(year, month);
|
|
135
|
+
const firstDayOfMonth = getFirstDayOfMonth(year, month);
|
|
136
|
+
const today = getToday();
|
|
137
|
+
const prevMonth = month === 0 ? 11 : month - 1;
|
|
138
|
+
const prevMonthYear = month === 0 ? year - 1 : year;
|
|
139
|
+
const daysInPrevMonth = getDaysInMonth(prevMonthYear, prevMonth);
|
|
140
|
+
const days = [];
|
|
141
|
+
for (let i = firstDayOfMonth - 1; i >= 0; i--) {
|
|
142
|
+
const day = daysInPrevMonth - i;
|
|
143
|
+
const date = createDate(prevMonthYear, prevMonth, day);
|
|
144
|
+
days.push(createCalendarDay(date, false, today, options));
|
|
145
|
+
}
|
|
146
|
+
for (let day = 1; day <= daysInMonth; day++) {
|
|
147
|
+
const date = createDate(year, month, day);
|
|
148
|
+
days.push(createCalendarDay(date, true, today, options));
|
|
149
|
+
}
|
|
150
|
+
const nextMonth = month === 11 ? 0 : month + 1;
|
|
151
|
+
const nextMonthYear = month === 11 ? year + 1 : year;
|
|
152
|
+
const remainingDays = 42 - days.length;
|
|
153
|
+
for (let day = 1; day <= remainingDays; day++) {
|
|
154
|
+
const date = createDate(nextMonthYear, nextMonth, day);
|
|
155
|
+
days.push(createCalendarDay(date, false, today, options));
|
|
156
|
+
}
|
|
157
|
+
const weeks = [];
|
|
158
|
+
for (let i = 0; i < 6; i++) {
|
|
159
|
+
weeks.push(days.slice(i * 7, (i + 1) * 7));
|
|
160
|
+
}
|
|
161
|
+
return weeks;
|
|
162
|
+
};
|
|
163
|
+
const getMonthNames = (locale = 'vi-VN') => {
|
|
164
|
+
if (locale === 'vi-VN') {
|
|
165
|
+
return ['T1', 'T2', 'T3', 'T4', 'T5', 'T6', 'T7', 'T8', 'T9', 'T10', 'T11', 'T12'];
|
|
166
|
+
}
|
|
167
|
+
const months = [];
|
|
168
|
+
for (let i = 0; i < 12; i++) {
|
|
169
|
+
const date = new Date(2024, i, 1);
|
|
170
|
+
months.push(date.toLocaleDateString(locale, { month: 'short' }));
|
|
171
|
+
}
|
|
172
|
+
return months;
|
|
173
|
+
};
|
|
174
|
+
const getWeekdayNames = (locale = 'vi-VN') => {
|
|
175
|
+
const weekdays = [];
|
|
176
|
+
for (let i = 0; i < 7; i++) {
|
|
177
|
+
const actualDate = new Date(2024, 0, 7 + i);
|
|
178
|
+
weekdays.push(actualDate.toLocaleDateString(locale, { weekday: 'narrow' }));
|
|
179
|
+
}
|
|
180
|
+
return weekdays;
|
|
181
|
+
};
|
|
182
|
+
const getYearRange = (centerYear, range = 12) => {
|
|
183
|
+
const startYear = centerYear - Math.floor(range / 2);
|
|
184
|
+
return Array.from({ length: range }, (_, i) => startYear + i);
|
|
185
|
+
};
|
|
186
|
+
const formatDate = (date, format) => {
|
|
187
|
+
if (!date) {
|
|
188
|
+
return '';
|
|
189
|
+
}
|
|
190
|
+
const hours = date.getHours();
|
|
191
|
+
const hours12 = hours % 12 || 12;
|
|
192
|
+
const tokens = {
|
|
193
|
+
YYYY: String(date.getFullYear()),
|
|
194
|
+
MM: String(date.getMonth() + 1).padStart(2, '0'),
|
|
195
|
+
DD: String(date.getDate()).padStart(2, '0'),
|
|
196
|
+
HH: String(hours).padStart(2, '0'),
|
|
197
|
+
hh: String(hours12).padStart(2, '0'),
|
|
198
|
+
mm: String(date.getMinutes()).padStart(2, '0'),
|
|
199
|
+
ss: String(date.getSeconds()).padStart(2, '0'),
|
|
200
|
+
};
|
|
201
|
+
let result = format;
|
|
202
|
+
for (const [token, value] of Object.entries(tokens)) {
|
|
203
|
+
result = result.replace(token, value);
|
|
204
|
+
}
|
|
205
|
+
return result;
|
|
206
|
+
};
|
|
207
|
+
const parseDate = (dateString, format) => {
|
|
208
|
+
if (!dateString) {
|
|
209
|
+
return null;
|
|
210
|
+
}
|
|
211
|
+
const pattern = format
|
|
212
|
+
.replace(/YYYY/g, '\\d{4}')
|
|
213
|
+
.replace(/MM/g, '\\d{1,2}')
|
|
214
|
+
.replace(/DD/g, '\\d{1,2}')
|
|
215
|
+
.replace(/HH/g, '\\d{1,2}')
|
|
216
|
+
.replace(/hh/g, '\\d{1,2}')
|
|
217
|
+
.replace(/mm/g, '\\d{1,2}')
|
|
218
|
+
.replace(/ss/g, '\\d{1,2}')
|
|
219
|
+
.replace(/\//g, '\\/')
|
|
220
|
+
.replace(/-/g, '\\-')
|
|
221
|
+
.replace(/:/g, '\\:')
|
|
222
|
+
.replace(/\s+/g, '\\s*');
|
|
223
|
+
const datePattern = new RegExp(`^${pattern}(\\s*(AM|PM))?$`, 'i');
|
|
224
|
+
if (!datePattern.test(dateString.trim())) {
|
|
225
|
+
return null;
|
|
226
|
+
}
|
|
227
|
+
const numbers = dateString.match(/\d+/g)?.map(n => parseInt(n, 10)) ?? [];
|
|
228
|
+
if (numbers.length === 0) {
|
|
229
|
+
return null;
|
|
230
|
+
}
|
|
231
|
+
const currentYear = new Date().getFullYear();
|
|
232
|
+
const values = {
|
|
233
|
+
YYYY: currentYear,
|
|
234
|
+
MM: 1,
|
|
235
|
+
DD: 1,
|
|
236
|
+
HH: 0,
|
|
237
|
+
hh: 0,
|
|
238
|
+
mm: 0,
|
|
239
|
+
ss: 0,
|
|
240
|
+
};
|
|
241
|
+
const allTokens = ['YYYY', 'MM', 'DD', 'HH', 'hh', 'mm', 'ss'];
|
|
242
|
+
const tokensInFormat = allTokens
|
|
243
|
+
.filter(token => format.includes(token))
|
|
244
|
+
.sort((a, b) => format.indexOf(a) - format.indexOf(b));
|
|
245
|
+
for (let i = 0; i < Math.min(numbers.length, tokensInFormat.length); i++) {
|
|
246
|
+
values[tokensInFormat[i]] = numbers[i];
|
|
247
|
+
}
|
|
248
|
+
const isPM = /PM/i.test(dateString);
|
|
249
|
+
const isAM = /AM/i.test(dateString);
|
|
250
|
+
let hour = values['HH'];
|
|
251
|
+
if (format.includes('hh')) {
|
|
252
|
+
hour = values['hh'];
|
|
253
|
+
if (isPM && hour < 12) {
|
|
254
|
+
hour += 12;
|
|
255
|
+
}
|
|
256
|
+
if (isAM && hour === 12) {
|
|
257
|
+
hour = 0;
|
|
258
|
+
}
|
|
259
|
+
}
|
|
260
|
+
try {
|
|
261
|
+
const date = createDate(values['YYYY'], values['MM'] - 1, values['DD'], hour, values['mm'], values['ss']);
|
|
262
|
+
// Validate the date is valid (e.g., not 31/02/2025)
|
|
263
|
+
if (isNaN(date.getTime())) {
|
|
264
|
+
return null;
|
|
265
|
+
}
|
|
266
|
+
return date;
|
|
267
|
+
}
|
|
268
|
+
catch {
|
|
269
|
+
return null;
|
|
270
|
+
}
|
|
271
|
+
};
|
|
272
|
+
const toISOString = (date) => {
|
|
273
|
+
if (!date) {
|
|
274
|
+
return '';
|
|
275
|
+
}
|
|
276
|
+
return date.toISOString();
|
|
277
|
+
};
|
|
278
|
+
const fromISOString = (isoString) => {
|
|
279
|
+
if (!isoString) {
|
|
280
|
+
return null;
|
|
281
|
+
}
|
|
282
|
+
const date = new Date(isoString);
|
|
283
|
+
return isNaN(date.getTime()) ? null : date;
|
|
284
|
+
};
|
|
285
|
+
const getQuickSelectPresets = () => [
|
|
286
|
+
{
|
|
287
|
+
key: 'today',
|
|
288
|
+
label: 'Hôm nay',
|
|
289
|
+
getValue: () => ({ start: getToday(), end: getToday() }),
|
|
290
|
+
},
|
|
291
|
+
{
|
|
292
|
+
key: '7days',
|
|
293
|
+
label: '7 ngày qua',
|
|
294
|
+
getValue: () => ({
|
|
295
|
+
start: addDays(getToday(), -6),
|
|
296
|
+
end: getToday(),
|
|
297
|
+
}),
|
|
298
|
+
},
|
|
299
|
+
{
|
|
300
|
+
key: '14days',
|
|
301
|
+
label: '14 ngày qua',
|
|
302
|
+
getValue: () => ({
|
|
303
|
+
start: addDays(getToday(), -13),
|
|
304
|
+
end: getToday(),
|
|
305
|
+
}),
|
|
306
|
+
},
|
|
307
|
+
{
|
|
308
|
+
key: '1month',
|
|
309
|
+
label: '1 tháng qua',
|
|
310
|
+
getValue: () => ({
|
|
311
|
+
start: addMonths(getToday(), -1),
|
|
312
|
+
end: getToday(),
|
|
313
|
+
}),
|
|
314
|
+
},
|
|
315
|
+
{
|
|
316
|
+
key: '2months',
|
|
317
|
+
label: '2 tháng qua',
|
|
318
|
+
getValue: () => ({
|
|
319
|
+
start: addMonths(getToday(), -2),
|
|
320
|
+
end: getToday(),
|
|
321
|
+
}),
|
|
322
|
+
},
|
|
323
|
+
{
|
|
324
|
+
key: '3months',
|
|
325
|
+
label: '3 tháng qua',
|
|
326
|
+
getValue: () => ({
|
|
327
|
+
start: addMonths(getToday(), -3),
|
|
328
|
+
end: getToday(),
|
|
329
|
+
}),
|
|
330
|
+
},
|
|
331
|
+
{
|
|
332
|
+
key: '6months',
|
|
333
|
+
label: '6 tháng qua',
|
|
334
|
+
getValue: () => ({
|
|
335
|
+
start: addMonths(getToday(), -6),
|
|
336
|
+
end: getToday(),
|
|
337
|
+
}),
|
|
338
|
+
},
|
|
339
|
+
{
|
|
340
|
+
key: 'custom',
|
|
341
|
+
label: 'Tùy chỉnh',
|
|
342
|
+
getValue: () => null,
|
|
343
|
+
},
|
|
344
|
+
];
|
|
345
|
+
const normalizeRange = (start, end) => {
|
|
346
|
+
if (!start || !end) {
|
|
347
|
+
return { start, end };
|
|
348
|
+
}
|
|
349
|
+
if (isBefore(end, start)) {
|
|
350
|
+
return { start: end, end: start };
|
|
351
|
+
}
|
|
352
|
+
return { start, end };
|
|
353
|
+
};
|
|
354
|
+
const isValidRange = (range) => range.start !== null && range.end !== null;
|
|
355
|
+
const clampTime = (value, min, max) => Math.max(min, Math.min(max, value));
|
|
356
|
+
const parseTimeValue = (value, max) => {
|
|
357
|
+
const parsed = parseInt(value, 10);
|
|
358
|
+
if (isNaN(parsed)) {
|
|
359
|
+
return 0;
|
|
360
|
+
}
|
|
361
|
+
return clampTime(parsed, 0, max);
|
|
362
|
+
};
|
|
363
|
+
const formatTimeValue = (value) => String(value).padStart(2, '0');
|
|
364
|
+
const getDayState = (day) => {
|
|
365
|
+
if (day.isDisabled) {
|
|
366
|
+
return 'disabled';
|
|
367
|
+
}
|
|
368
|
+
if (!day.isCurrentMonth) {
|
|
369
|
+
return 'otherMonth';
|
|
370
|
+
}
|
|
371
|
+
if (day.isRangeStart && day.isRangeEnd) {
|
|
372
|
+
return 'rangeSingle';
|
|
373
|
+
}
|
|
374
|
+
if (day.isRangeStart) {
|
|
375
|
+
return 'rangeStart';
|
|
376
|
+
}
|
|
377
|
+
if (day.isRangeEnd) {
|
|
378
|
+
return 'rangeEnd';
|
|
379
|
+
}
|
|
380
|
+
if (day.isInRange) {
|
|
381
|
+
return 'inRange';
|
|
382
|
+
}
|
|
383
|
+
if (day.isHovered) {
|
|
384
|
+
return 'hovered';
|
|
385
|
+
}
|
|
386
|
+
if (day.isSelected) {
|
|
387
|
+
return 'selected';
|
|
388
|
+
}
|
|
389
|
+
if (day.isToday) {
|
|
390
|
+
return 'today';
|
|
391
|
+
}
|
|
392
|
+
return 'default';
|
|
393
|
+
};
|
|
394
|
+
const getMonthState = (monthIndex, currentMonthIndex) => monthIndex === currentMonthIndex ? 'selected' : 'default';
|
|
395
|
+
const getQuarterState = (quarterIndex, currentQuarterIndex) => quarterIndex === currentQuarterIndex ? 'selected' : 'default';
|
|
396
|
+
const getYearState = (year, currentYear) => year === currentYear ? 'selected' : 'default';
|
|
397
|
+
|
|
398
|
+
const zCalendarVariants = cva([
|
|
399
|
+
'group flex w-fit items-center rounded-[6px] border border-input bg-white shadow-xs cursor-pointer',
|
|
400
|
+
'transition-[border-color,box-shadow,background-color,color,opacity] duration-200',
|
|
401
|
+
'dark:bg-input/30 dark:border-input dark:hover:bg-input/50',
|
|
402
|
+
'outline-none',
|
|
403
|
+
'text-sm',
|
|
404
|
+
], {
|
|
405
|
+
variants: {
|
|
406
|
+
zSize: {
|
|
407
|
+
sm: 'h-8 px-2 gap-2 text-sm',
|
|
408
|
+
default: 'h-9 px-2 gap-2 text-sm',
|
|
409
|
+
lg: 'h-10 px-2 gap-2.5 text-sm',
|
|
410
|
+
},
|
|
411
|
+
zStatus: {
|
|
412
|
+
default: 'focus-within:border-ring focus-within:ring-ring/50 focus-within:ring-[3px]',
|
|
413
|
+
open: 'border-ring ring-ring/50 ring-[3px]',
|
|
414
|
+
error: 'border-destructive! ring-destructive/20 ring-[3px] focus-within:border-destructive! focus-within:ring-destructive/30',
|
|
415
|
+
disabled: 'opacity-50 cursor-not-allowed bg-muted! text-muted-foreground',
|
|
416
|
+
readonly: 'cursor-default bg-muted/50 text-muted-foreground',
|
|
417
|
+
},
|
|
418
|
+
},
|
|
419
|
+
defaultVariants: {
|
|
420
|
+
zSize: 'default',
|
|
421
|
+
zStatus: 'default',
|
|
422
|
+
},
|
|
423
|
+
});
|
|
424
|
+
const zCalendarDayVariants = cva([
|
|
425
|
+
'flex items-center justify-center size-7 text-sm rounded-[4px] cursor-pointer',
|
|
426
|
+
'transition-all duration-150',
|
|
427
|
+
'outline-none focus-visible:ring-2 focus-visible:ring-ring',
|
|
428
|
+
], {
|
|
429
|
+
variants: {
|
|
430
|
+
state: {
|
|
431
|
+
default: 'hover:bg-primary/10 text-foreground',
|
|
432
|
+
today: 'bg-primary/10 text-primary border border-primary',
|
|
433
|
+
selected: 'bg-primary text-primary-foreground',
|
|
434
|
+
inRange: 'bg-primary/10 text-foreground',
|
|
435
|
+
rangeStart: 'bg-primary text-primary-foreground rounded-r-none',
|
|
436
|
+
rangeEnd: 'bg-primary text-primary-foreground rounded-l-none',
|
|
437
|
+
rangeSingle: 'bg-primary text-primary-foreground',
|
|
438
|
+
disabled: 'text-muted-foreground/50 cursor-not-allowed',
|
|
439
|
+
otherMonth: 'text-muted-foreground/40 hover:bg-primary/5',
|
|
440
|
+
hovered: 'bg-primary/15 text-foreground',
|
|
441
|
+
},
|
|
442
|
+
},
|
|
443
|
+
defaultVariants: {
|
|
444
|
+
state: 'default',
|
|
445
|
+
},
|
|
446
|
+
});
|
|
447
|
+
const zCalendarMonthVariants = cva([
|
|
448
|
+
'flex items-center justify-center text-sm rounded-[4px] cursor-pointer px-8 py-1.5',
|
|
449
|
+
'transition-colors duration-150',
|
|
450
|
+
'outline-none focus-visible:ring-2 focus-visible:ring-ring',
|
|
451
|
+
], {
|
|
452
|
+
variants: {
|
|
453
|
+
state: {
|
|
454
|
+
default: 'hover:bg-primary/10 text-foreground',
|
|
455
|
+
current: 'bg-primary/15 text-primary',
|
|
456
|
+
selected: 'bg-primary text-primary-foreground',
|
|
457
|
+
disabled: 'text-muted-foreground/50 cursor-not-allowed',
|
|
458
|
+
},
|
|
459
|
+
},
|
|
460
|
+
defaultVariants: {
|
|
461
|
+
state: 'default',
|
|
462
|
+
},
|
|
463
|
+
});
|
|
464
|
+
const zCalendarYearVariants = cva([
|
|
465
|
+
'flex items-center justify-center text-sm rounded-[4px] cursor-pointer px-6 py-1.5',
|
|
466
|
+
'transition-colors duration-150',
|
|
467
|
+
'outline-none focus-visible:ring-2 focus-visible:ring-ring',
|
|
468
|
+
], {
|
|
469
|
+
variants: {
|
|
470
|
+
state: {
|
|
471
|
+
default: 'hover:bg-primary/10 text-foreground',
|
|
472
|
+
current: 'bg-primary/15 text-primary',
|
|
473
|
+
selected: 'bg-primary text-primary-foreground',
|
|
474
|
+
disabled: 'text-muted-foreground/50 cursor-not-allowed',
|
|
475
|
+
},
|
|
476
|
+
},
|
|
477
|
+
defaultVariants: {
|
|
478
|
+
state: 'default',
|
|
479
|
+
},
|
|
480
|
+
});
|
|
481
|
+
const zCalendarQuarterVariants = cva([
|
|
482
|
+
'flex items-center justify-center text-sm rounded-[4px] cursor-pointer px-15 py-1.5',
|
|
483
|
+
'transition-colors duration-150',
|
|
484
|
+
'outline-none focus-visible:ring-2 focus-visible:ring-ring',
|
|
485
|
+
], {
|
|
486
|
+
variants: {
|
|
487
|
+
state: {
|
|
488
|
+
default: 'hover:bg-primary/10 text-foreground',
|
|
489
|
+
selected: 'bg-primary text-primary-foreground',
|
|
490
|
+
},
|
|
491
|
+
},
|
|
492
|
+
defaultVariants: {
|
|
493
|
+
state: 'default',
|
|
494
|
+
},
|
|
495
|
+
});
|
|
496
|
+
|
|
497
|
+
class ZDayClassesPipe {
|
|
498
|
+
transform(day) {
|
|
499
|
+
const state = getDayState(day);
|
|
500
|
+
return zCalendarDayVariants({ state });
|
|
501
|
+
}
|
|
502
|
+
static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "21.0.6", ngImport: i0, type: ZDayClassesPipe, deps: [], target: i0.ɵɵFactoryTarget.Pipe });
|
|
503
|
+
static ɵpipe = i0.ɵɵngDeclarePipe({ minVersion: "14.0.0", version: "21.0.6", ngImport: i0, type: ZDayClassesPipe, isStandalone: true, name: "zDayClasses" });
|
|
504
|
+
}
|
|
505
|
+
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.0.6", ngImport: i0, type: ZDayClassesPipe, decorators: [{
|
|
506
|
+
type: Pipe,
|
|
507
|
+
args: [{
|
|
508
|
+
name: 'zDayClasses',
|
|
509
|
+
standalone: true,
|
|
510
|
+
pure: true,
|
|
511
|
+
}]
|
|
512
|
+
}] });
|
|
513
|
+
|
|
514
|
+
class ZIsPresetDisabledPipe {
|
|
515
|
+
transform(preset, disabledDateFn) {
|
|
516
|
+
if (preset.key === 'custom' || !disabledDateFn) {
|
|
517
|
+
return false;
|
|
518
|
+
}
|
|
519
|
+
const value = preset.getValue();
|
|
520
|
+
if (!value) {
|
|
521
|
+
return false;
|
|
522
|
+
}
|
|
523
|
+
if (value instanceof Date) {
|
|
524
|
+
return disabledDateFn(value);
|
|
525
|
+
}
|
|
526
|
+
if (value.start && disabledDateFn(value.start)) {
|
|
527
|
+
return true;
|
|
528
|
+
}
|
|
529
|
+
if (value.end && disabledDateFn(value.end)) {
|
|
530
|
+
return true;
|
|
531
|
+
}
|
|
532
|
+
return false;
|
|
533
|
+
}
|
|
534
|
+
static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "21.0.6", ngImport: i0, type: ZIsPresetDisabledPipe, deps: [], target: i0.ɵɵFactoryTarget.Pipe });
|
|
535
|
+
static ɵpipe = i0.ɵɵngDeclarePipe({ minVersion: "14.0.0", version: "21.0.6", ngImport: i0, type: ZIsPresetDisabledPipe, isStandalone: true, name: "zIsPresetDisabled" });
|
|
536
|
+
}
|
|
537
|
+
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.0.6", ngImport: i0, type: ZIsPresetDisabledPipe, decorators: [{
|
|
538
|
+
type: Pipe,
|
|
539
|
+
args: [{
|
|
540
|
+
name: 'zIsPresetDisabled',
|
|
541
|
+
standalone: true,
|
|
542
|
+
pure: true,
|
|
543
|
+
}]
|
|
544
|
+
}] });
|
|
545
|
+
|
|
546
|
+
class ZMonthClassesPipe {
|
|
547
|
+
transform(monthIndex, currentMonthIndex) {
|
|
548
|
+
const state = getMonthState(monthIndex, currentMonthIndex);
|
|
549
|
+
return zCalendarMonthVariants({ state });
|
|
550
|
+
}
|
|
551
|
+
static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "21.0.6", ngImport: i0, type: ZMonthClassesPipe, deps: [], target: i0.ɵɵFactoryTarget.Pipe });
|
|
552
|
+
static ɵpipe = i0.ɵɵngDeclarePipe({ minVersion: "14.0.0", version: "21.0.6", ngImport: i0, type: ZMonthClassesPipe, isStandalone: true, name: "zMonthClasses" });
|
|
553
|
+
}
|
|
554
|
+
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.0.6", ngImport: i0, type: ZMonthClassesPipe, decorators: [{
|
|
555
|
+
type: Pipe,
|
|
556
|
+
args: [{
|
|
557
|
+
name: 'zMonthClasses',
|
|
558
|
+
standalone: true,
|
|
559
|
+
pure: true,
|
|
560
|
+
}]
|
|
561
|
+
}] });
|
|
562
|
+
|
|
563
|
+
class ZYearClassesPipe {
|
|
564
|
+
transform(year, currentYear) {
|
|
565
|
+
const state = getYearState(year, currentYear);
|
|
566
|
+
return zCalendarYearVariants({ state });
|
|
567
|
+
}
|
|
568
|
+
static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "21.0.6", ngImport: i0, type: ZYearClassesPipe, deps: [], target: i0.ɵɵFactoryTarget.Pipe });
|
|
569
|
+
static ɵpipe = i0.ɵɵngDeclarePipe({ minVersion: "14.0.0", version: "21.0.6", ngImport: i0, type: ZYearClassesPipe, isStandalone: true, name: "zYearClasses" });
|
|
570
|
+
}
|
|
571
|
+
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.0.6", ngImport: i0, type: ZYearClassesPipe, decorators: [{
|
|
572
|
+
type: Pipe,
|
|
573
|
+
args: [{
|
|
574
|
+
name: 'zYearClasses',
|
|
575
|
+
standalone: true,
|
|
576
|
+
pure: true,
|
|
577
|
+
}]
|
|
578
|
+
}] });
|
|
579
|
+
|
|
580
|
+
class ZQuarterClassesPipe {
|
|
581
|
+
transform(quarterIndex, currentQuarterIndex) {
|
|
582
|
+
const state = getQuarterState(quarterIndex, currentQuarterIndex);
|
|
583
|
+
return zCalendarQuarterVariants({ state });
|
|
584
|
+
}
|
|
585
|
+
static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "21.0.6", ngImport: i0, type: ZQuarterClassesPipe, deps: [], target: i0.ɵɵFactoryTarget.Pipe });
|
|
586
|
+
static ɵpipe = i0.ɵɵngDeclarePipe({ minVersion: "14.0.0", version: "21.0.6", ngImport: i0, type: ZQuarterClassesPipe, isStandalone: true, name: "zQuarterClasses" });
|
|
587
|
+
}
|
|
588
|
+
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.0.6", ngImport: i0, type: ZQuarterClassesPipe, decorators: [{
|
|
589
|
+
type: Pipe,
|
|
590
|
+
args: [{
|
|
591
|
+
name: 'zQuarterClasses',
|
|
592
|
+
standalone: true,
|
|
593
|
+
pure: true,
|
|
594
|
+
}]
|
|
595
|
+
}] });
|
|
596
|
+
|
|
597
|
+
class ZCalendarComponent {
|
|
598
|
+
class = input('', ...(ngDevMode ? [{ debugName: "class" }] : []));
|
|
599
|
+
zMode = input('single', ...(ngDevMode ? [{ debugName: "zMode" }] : []));
|
|
600
|
+
zSize = input('default', ...(ngDevMode ? [{ debugName: "zSize" }] : []));
|
|
601
|
+
zLabel = input('', ...(ngDevMode ? [{ debugName: "zLabel" }] : []));
|
|
602
|
+
zLabelClass = input('', ...(ngDevMode ? [{ debugName: "zLabelClass" }] : []));
|
|
603
|
+
zPlaceholder = input('Chọn ngày...', ...(ngDevMode ? [{ debugName: "zPlaceholder" }] : []));
|
|
604
|
+
zRequired = input(false, { ...(ngDevMode ? { debugName: "zRequired" } : {}), transform: zTransform });
|
|
605
|
+
zDisabled = input(false, { ...(ngDevMode ? { debugName: "zDisabled" } : {}), transform: zTransform });
|
|
606
|
+
zReadonly = input(false, { ...(ngDevMode ? { debugName: "zReadonly" } : {}), transform: zTransform });
|
|
607
|
+
zShowTime = input(false, { ...(ngDevMode ? { debugName: "zShowTime" } : {}), transform: zTransform });
|
|
608
|
+
zTimeFormat = input('24h', ...(ngDevMode ? [{ debugName: "zTimeFormat" }] : []));
|
|
609
|
+
zShowHour = input(true, { ...(ngDevMode ? { debugName: "zShowHour" } : {}), transform: zTransform });
|
|
610
|
+
zShowMinute = input(true, { ...(ngDevMode ? { debugName: "zShowMinute" } : {}), transform: zTransform });
|
|
611
|
+
zShowSecond = input(true, { ...(ngDevMode ? { debugName: "zShowSecond" } : {}), transform: zTransform });
|
|
612
|
+
zQuickSelect = input(false, { ...(ngDevMode ? { debugName: "zQuickSelect" } : {}), transform: zTransform });
|
|
613
|
+
zAllowClear = input(true, { ...(ngDevMode ? { debugName: "zAllowClear" } : {}), transform: zTransform });
|
|
614
|
+
zFormat = input('DD/MM/YYYY', ...(ngDevMode ? [{ debugName: "zFormat" }] : []));
|
|
615
|
+
zMinDate = input(null, ...(ngDevMode ? [{ debugName: "zMinDate" }] : []));
|
|
616
|
+
zMaxDate = input(null, ...(ngDevMode ? [{ debugName: "zMaxDate" }] : []));
|
|
617
|
+
zValueType = input('date', ...(ngDevMode ? [{ debugName: "zValueType" }] : []));
|
|
618
|
+
zValidators = input([], ...(ngDevMode ? [{ debugName: "zValidators" }] : []));
|
|
619
|
+
zLocale = input('vi-VN', ...(ngDevMode ? [{ debugName: "zLocale" }] : []));
|
|
620
|
+
zShowOk = input(false, { ...(ngDevMode ? { debugName: "zShowOk" } : {}), transform: zTransform });
|
|
621
|
+
zOkText = input('Áp dụng', ...(ngDevMode ? [{ debugName: "zOkText" }] : []));
|
|
622
|
+
zShowCancel = input(false, { ...(ngDevMode ? { debugName: "zShowCancel" } : {}), transform: zTransform });
|
|
623
|
+
zCancelText = input('Huỷ', ...(ngDevMode ? [{ debugName: "zCancelText" }] : []));
|
|
624
|
+
zDisabledDate = input(null, ...(ngDevMode ? [{ debugName: "zDisabledDate" }] : []));
|
|
625
|
+
zControl = output();
|
|
626
|
+
zChange = output();
|
|
627
|
+
triggerRef = viewChild('triggerEl', ...(ngDevMode ? [{ debugName: "triggerRef" }] : []));
|
|
628
|
+
inputRef = viewChild('inputEl', ...(ngDevMode ? [{ debugName: "inputRef" }] : []));
|
|
629
|
+
pickerId = zGenerateId('z-calendar');
|
|
630
|
+
weekdayNames = getWeekdayNames('vi-VN');
|
|
631
|
+
monthNames = getMonthNames('vi-VN');
|
|
632
|
+
quickSelectPresets = getQuickSelectPresets();
|
|
633
|
+
formattedHour = computed(() => {
|
|
634
|
+
const h = this._hour();
|
|
635
|
+
if (this.zTimeFormat() === '12h') {
|
|
636
|
+
const h12 = h % 12 || 12;
|
|
637
|
+
return formatTimeValue(h12);
|
|
638
|
+
}
|
|
639
|
+
return formatTimeValue(h);
|
|
640
|
+
}, ...(ngDevMode ? [{ debugName: "formattedHour" }] : []));
|
|
641
|
+
formattedMinute = computed(() => formatTimeValue(this._minute()), ...(ngDevMode ? [{ debugName: "formattedMinute" }] : []));
|
|
642
|
+
formattedSecond = computed(() => formatTimeValue(this._second()), ...(ngDevMode ? [{ debugName: "formattedSecond" }] : []));
|
|
643
|
+
_popoverControl = signal(null, ...(ngDevMode ? [{ debugName: "_popoverControl" }] : []));
|
|
644
|
+
_selectedDate = signal(null, ...(ngDevMode ? [{ debugName: "_selectedDate" }] : []));
|
|
645
|
+
_rangeStart = signal(null, ...(ngDevMode ? [{ debugName: "_rangeStart" }] : []));
|
|
646
|
+
_rangeEnd = signal(null, ...(ngDevMode ? [{ debugName: "_rangeEnd" }] : []));
|
|
647
|
+
_hoveredDate = signal(null, ...(ngDevMode ? [{ debugName: "_hoveredDate" }] : []));
|
|
648
|
+
_currentMonth = signal(getToday(), ...(ngDevMode ? [{ debugName: "_currentMonth" }] : []));
|
|
649
|
+
_endMonth = signal(addMonths(getToday(), 1), ...(ngDevMode ? [{ debugName: "_endMonth" }] : []));
|
|
650
|
+
_currentView = signal('day', ...(ngDevMode ? [{ debugName: "_currentView" }] : []));
|
|
651
|
+
_endView = signal('day', ...(ngDevMode ? [{ debugName: "_endView" }] : []));
|
|
652
|
+
_hour = signal(0, ...(ngDevMode ? [{ debugName: "_hour" }] : []));
|
|
653
|
+
_minute = signal(0, ...(ngDevMode ? [{ debugName: "_minute" }] : []));
|
|
654
|
+
_second = signal(0, ...(ngDevMode ? [{ debugName: "_second" }] : []));
|
|
655
|
+
_period = signal('AM', ...(ngDevMode ? [{ debugName: "_period" }] : []));
|
|
656
|
+
_hourEnd = signal(0, ...(ngDevMode ? [{ debugName: "_hourEnd" }] : []));
|
|
657
|
+
_minuteEnd = signal(0, ...(ngDevMode ? [{ debugName: "_minuteEnd" }] : []));
|
|
658
|
+
_secondEnd = signal(0, ...(ngDevMode ? [{ debugName: "_secondEnd" }] : []));
|
|
659
|
+
_periodEnd = signal('AM', ...(ngDevMode ? [{ debugName: "_periodEnd" }] : []));
|
|
660
|
+
_disabled = signal(false, ...(ngDevMode ? [{ debugName: "_disabled" }] : []));
|
|
661
|
+
_touched = signal(false, ...(ngDevMode ? [{ debugName: "_touched" }] : []));
|
|
662
|
+
_dirty = signal(false, ...(ngDevMode ? [{ debugName: "_dirty" }] : []));
|
|
663
|
+
_formControl = signal(null, ...(ngDevMode ? [{ debugName: "_formControl" }] : []));
|
|
664
|
+
_formStateVersion = signal(0, ...(ngDevMode ? [{ debugName: "_formStateVersion" }] : []));
|
|
665
|
+
_inputDisplayValue = signal('', ...(ngDevMode ? [{ debugName: "_inputDisplayValue" }] : []));
|
|
666
|
+
_backupSelectedDate = signal(null, ...(ngDevMode ? [{ debugName: "_backupSelectedDate" }] : []));
|
|
667
|
+
_backupRangeStart = signal(null, ...(ngDevMode ? [{ debugName: "_backupRangeStart" }] : []));
|
|
668
|
+
_backupRangeEnd = signal(null, ...(ngDevMode ? [{ debugName: "_backupRangeEnd" }] : []));
|
|
669
|
+
_activePresetKey = signal(null, ...(ngDevMode ? [{ debugName: "_activePresetKey" }] : []));
|
|
670
|
+
_hasViewChanged = signal(false, ...(ngDevMode ? [{ debugName: "_hasViewChanged" }] : []));
|
|
671
|
+
_hasEndViewChanged = signal(false, ...(ngDevMode ? [{ debugName: "_hasEndViewChanged" }] : []));
|
|
672
|
+
_appliedViaOk = signal(false, ...(ngDevMode ? [{ debugName: "_appliedViaOk" }] : []));
|
|
673
|
+
_skipBlurHandler = signal(false, ...(ngDevMode ? [{ debugName: "_skipBlurHandler" }] : []));
|
|
674
|
+
_injector = inject(Injector);
|
|
675
|
+
_destroyRef = inject(DestroyRef);
|
|
676
|
+
_cdr = inject(ChangeDetectorRef);
|
|
677
|
+
_onChange = () => void 0;
|
|
678
|
+
_onTouched = () => void 0;
|
|
679
|
+
_ngControl = null;
|
|
680
|
+
isOpen = computed(() => this._popoverControl()?.isVisible() ?? false, ...(ngDevMode ? [{ debugName: "isOpen" }] : []));
|
|
681
|
+
hoveredDate = this._hoveredDate.asReadonly();
|
|
682
|
+
currentView = this._currentView.asReadonly();
|
|
683
|
+
hour = this._hour.asReadonly();
|
|
684
|
+
minute = this._minute.asReadonly();
|
|
685
|
+
second = this._second.asReadonly();
|
|
686
|
+
period = this._period.asReadonly();
|
|
687
|
+
inputDisplayValue = this._inputDisplayValue.asReadonly();
|
|
688
|
+
activePresetKey = this._activePresetKey.asReadonly();
|
|
689
|
+
hasViewChanged = this._hasViewChanged.asReadonly();
|
|
690
|
+
hasEndViewChanged = this._hasEndViewChanged.asReadonly();
|
|
691
|
+
quarterNames = ['Q1', 'Q2', 'Q3', 'Q4'];
|
|
692
|
+
currentQuarterIndex = computed(() => {
|
|
693
|
+
const date = this._selectedDate();
|
|
694
|
+
return date ? Math.floor(date.getMonth() / 3) : -1;
|
|
695
|
+
}, ...(ngDevMode ? [{ debugName: "currentQuarterIndex" }] : []));
|
|
696
|
+
isDisabled = computed(() => this._disabled() || this.zDisabled(), ...(ngDevMode ? [{ debugName: "isDisabled" }] : []));
|
|
697
|
+
isRangeMode = computed(() => this.zMode() === 'range', ...(ngDevMode ? [{ debugName: "isRangeMode" }] : []));
|
|
698
|
+
canApply = computed(() => {
|
|
699
|
+
if (this.isTimeMode()) {
|
|
700
|
+
return true;
|
|
701
|
+
}
|
|
702
|
+
if (this.isRangeMode()) {
|
|
703
|
+
return this._rangeStart() !== null && this._rangeEnd() !== null;
|
|
704
|
+
}
|
|
705
|
+
return this._selectedDate() !== null;
|
|
706
|
+
}, ...(ngDevMode ? [{ debugName: "canApply" }] : []));
|
|
707
|
+
showOkButton = computed(() => this.zShowOk() || this.zShowTime() || this.isTimeMode(), ...(ngDevMode ? [{ debugName: "showOkButton" }] : []));
|
|
708
|
+
showCancelButton = computed(() => this.zShowCancel() || this.zShowTime() || this.isTimeMode(), ...(ngDevMode ? [{ debugName: "showCancelButton" }] : []));
|
|
709
|
+
isTimeMode = computed(() => this.zMode() === 'time', ...(ngDevMode ? [{ debugName: "isTimeMode" }] : []));
|
|
710
|
+
isMonthMode = computed(() => this.zMode() === 'month', ...(ngDevMode ? [{ debugName: "isMonthMode" }] : []));
|
|
711
|
+
isYearMode = computed(() => this.zMode() === 'year', ...(ngDevMode ? [{ debugName: "isYearMode" }] : []));
|
|
712
|
+
isQuarterMode = computed(() => this.zMode() === 'quarter', ...(ngDevMode ? [{ debugName: "isQuarterMode" }] : []));
|
|
713
|
+
todayButtonText = computed(() => {
|
|
714
|
+
if (this.isQuarterMode()) {
|
|
715
|
+
return 'Quý này';
|
|
716
|
+
}
|
|
717
|
+
if (this.isYearMode()) {
|
|
718
|
+
return 'Năm này';
|
|
719
|
+
}
|
|
720
|
+
if (this.isMonthMode()) {
|
|
721
|
+
return 'Tháng này';
|
|
722
|
+
}
|
|
723
|
+
if (this.zShowTime() || this.isTimeMode()) {
|
|
724
|
+
return 'Bây giờ';
|
|
725
|
+
}
|
|
726
|
+
return 'Hôm nay';
|
|
727
|
+
}, ...(ngDevMode ? [{ debugName: "todayButtonText" }] : []));
|
|
728
|
+
currentMonth = computed(() => this._currentMonth(), ...(ngDevMode ? [{ debugName: "currentMonth" }] : []));
|
|
729
|
+
currentYear = computed(() => this._currentMonth().getFullYear(), ...(ngDevMode ? [{ debugName: "currentYear" }] : []));
|
|
730
|
+
currentMonthIndex = computed(() => this._currentMonth().getMonth(), ...(ngDevMode ? [{ debugName: "currentMonthIndex" }] : []));
|
|
731
|
+
currentMonthName = computed(() => {
|
|
732
|
+
const month = this._currentMonth();
|
|
733
|
+
return month.toLocaleDateString(this.zLocale(), { month: 'long' });
|
|
734
|
+
}, ...(ngDevMode ? [{ debugName: "currentMonthName" }] : []));
|
|
735
|
+
yearRange = computed(() => {
|
|
736
|
+
const currentYear = this._currentMonth().getFullYear();
|
|
737
|
+
return getYearRange(currentYear, 12);
|
|
738
|
+
}, ...(ngDevMode ? [{ debugName: "yearRange" }] : []));
|
|
739
|
+
yearRangeSmall = computed(() => {
|
|
740
|
+
const currentYear = this._currentMonth().getFullYear();
|
|
741
|
+
return getYearRange(currentYear, 9);
|
|
742
|
+
}, ...(ngDevMode ? [{ debugName: "yearRangeSmall" }] : []));
|
|
743
|
+
calendarDays = computed(() => {
|
|
744
|
+
const month = this._currentMonth();
|
|
745
|
+
const year = month.getFullYear();
|
|
746
|
+
const monthIndex = month.getMonth();
|
|
747
|
+
return generateCalendarGrid(year, monthIndex, {
|
|
748
|
+
selectedDate: this._selectedDate(),
|
|
749
|
+
rangeStart: this._rangeStart(),
|
|
750
|
+
rangeEnd: this._rangeEnd(),
|
|
751
|
+
hoveredDate: this._hoveredDate(),
|
|
752
|
+
minDate: this.zMinDate(),
|
|
753
|
+
maxDate: this.zMaxDate(),
|
|
754
|
+
disabledDate: this.zDisabledDate(),
|
|
755
|
+
});
|
|
756
|
+
}, ...(ngDevMode ? [{ debugName: "calendarDays" }] : []));
|
|
757
|
+
endMonth = computed(() => this._endMonth(), ...(ngDevMode ? [{ debugName: "endMonth" }] : []));
|
|
758
|
+
endMonthName = computed(() => {
|
|
759
|
+
const month = this._endMonth();
|
|
760
|
+
return month.toLocaleDateString(this.zLocale(), { month: 'long' });
|
|
761
|
+
}, ...(ngDevMode ? [{ debugName: "endMonthName" }] : []));
|
|
762
|
+
endMonthYear = computed(() => this._endMonth().getFullYear(), ...(ngDevMode ? [{ debugName: "endMonthYear" }] : []));
|
|
763
|
+
calendarDaysEnd = computed(() => {
|
|
764
|
+
const month = this._endMonth();
|
|
765
|
+
const year = month.getFullYear();
|
|
766
|
+
const monthIndex = month.getMonth();
|
|
767
|
+
return generateCalendarGrid(year, monthIndex, {
|
|
768
|
+
selectedDate: this._selectedDate(),
|
|
769
|
+
rangeStart: this._rangeStart(),
|
|
770
|
+
rangeEnd: this._rangeEnd(),
|
|
771
|
+
hoveredDate: this._hoveredDate(),
|
|
772
|
+
minDate: this.zMinDate(),
|
|
773
|
+
maxDate: this.zMaxDate(),
|
|
774
|
+
disabledDate: this.zDisabledDate(),
|
|
775
|
+
});
|
|
776
|
+
}, ...(ngDevMode ? [{ debugName: "calendarDaysEnd" }] : []));
|
|
777
|
+
formattedHourEnd = computed(() => formatTimeValue(this.zTimeFormat() === '12h' ? this._hourEnd() % 12 || 12 : this._hourEnd()), ...(ngDevMode ? [{ debugName: "formattedHourEnd" }] : []));
|
|
778
|
+
formattedMinuteEnd = computed(() => formatTimeValue(this._minuteEnd()), ...(ngDevMode ? [{ debugName: "formattedMinuteEnd" }] : []));
|
|
779
|
+
formattedSecondEnd = computed(() => formatTimeValue(this._secondEnd()), ...(ngDevMode ? [{ debugName: "formattedSecondEnd" }] : []));
|
|
780
|
+
periodEnd = computed(() => this._periodEnd(), ...(ngDevMode ? [{ debugName: "periodEnd" }] : []));
|
|
781
|
+
endView = this._endView.asReadonly();
|
|
782
|
+
endYearRange = computed(() => {
|
|
783
|
+
const currentYear = this._endMonth().getFullYear();
|
|
784
|
+
return getYearRange(currentYear);
|
|
785
|
+
}, ...(ngDevMode ? [{ debugName: "endYearRange" }] : []));
|
|
786
|
+
isStartMonthDisabled(monthIndex) {
|
|
787
|
+
const disabledDateFn = this.zDisabledDate();
|
|
788
|
+
if (disabledDateFn) {
|
|
789
|
+
const year = this._currentMonth().getFullYear();
|
|
790
|
+
const monthDate = new Date(year, monthIndex, 1);
|
|
791
|
+
if (disabledDateFn(monthDate)) {
|
|
792
|
+
return true;
|
|
793
|
+
}
|
|
794
|
+
}
|
|
795
|
+
if (!this.isRangeMode()) {
|
|
796
|
+
return false;
|
|
797
|
+
}
|
|
798
|
+
const startYear = this._currentMonth().getFullYear();
|
|
799
|
+
const endMonth = this._endMonth();
|
|
800
|
+
const endYear = endMonth.getFullYear();
|
|
801
|
+
const endMonthIndex = endMonth.getMonth();
|
|
802
|
+
if (startYear > endYear) {
|
|
803
|
+
return true;
|
|
804
|
+
}
|
|
805
|
+
if (startYear === endYear && monthIndex > endMonthIndex) {
|
|
806
|
+
return true;
|
|
807
|
+
}
|
|
808
|
+
return false;
|
|
809
|
+
}
|
|
810
|
+
isEndMonthDisabled(monthIndex) {
|
|
811
|
+
const disabledDateFn = this.zDisabledDate();
|
|
812
|
+
if (disabledDateFn) {
|
|
813
|
+
const year = this._endMonth().getFullYear();
|
|
814
|
+
const monthDate = new Date(year, monthIndex, 1);
|
|
815
|
+
if (disabledDateFn(monthDate)) {
|
|
816
|
+
return true;
|
|
817
|
+
}
|
|
818
|
+
}
|
|
819
|
+
if (!this.isRangeMode()) {
|
|
820
|
+
return false;
|
|
821
|
+
}
|
|
822
|
+
const startMonth = this._currentMonth();
|
|
823
|
+
const startYear = startMonth.getFullYear();
|
|
824
|
+
const startMonthIndex = startMonth.getMonth();
|
|
825
|
+
const endYear = this._endMonth().getFullYear();
|
|
826
|
+
if (endYear < startYear) {
|
|
827
|
+
return true;
|
|
828
|
+
}
|
|
829
|
+
if (endYear === startYear && monthIndex < startMonthIndex) {
|
|
830
|
+
return true;
|
|
831
|
+
}
|
|
832
|
+
return false;
|
|
833
|
+
}
|
|
834
|
+
isStartYearDisabled(year) {
|
|
835
|
+
const disabledDateFn = this.zDisabledDate();
|
|
836
|
+
if (disabledDateFn) {
|
|
837
|
+
const yearDate = new Date(year, 0, 1);
|
|
838
|
+
if (disabledDateFn(yearDate)) {
|
|
839
|
+
return true;
|
|
840
|
+
}
|
|
841
|
+
}
|
|
842
|
+
if (!this.isRangeMode()) {
|
|
843
|
+
return false;
|
|
844
|
+
}
|
|
845
|
+
const endYear = this._endMonth().getFullYear();
|
|
846
|
+
const startMonthIndex = this._currentMonth().getMonth();
|
|
847
|
+
const endMonthIndex = this._endMonth().getMonth();
|
|
848
|
+
if (year > endYear) {
|
|
849
|
+
return true;
|
|
850
|
+
}
|
|
851
|
+
if (year === endYear && startMonthIndex >= endMonthIndex) {
|
|
852
|
+
return true;
|
|
853
|
+
}
|
|
854
|
+
return false;
|
|
855
|
+
}
|
|
856
|
+
isEndYearDisabled(year) {
|
|
857
|
+
const disabledDateFn = this.zDisabledDate();
|
|
858
|
+
if (disabledDateFn) {
|
|
859
|
+
const yearDate = new Date(year, 0, 1);
|
|
860
|
+
if (disabledDateFn(yearDate)) {
|
|
861
|
+
return true;
|
|
862
|
+
}
|
|
863
|
+
}
|
|
864
|
+
if (!this.isRangeMode()) {
|
|
865
|
+
return false;
|
|
866
|
+
}
|
|
867
|
+
const startYear = this._currentMonth().getFullYear();
|
|
868
|
+
const startMonthIndex = this._currentMonth().getMonth();
|
|
869
|
+
const endMonthIndex = this._endMonth().getMonth();
|
|
870
|
+
if (year < startYear) {
|
|
871
|
+
return true;
|
|
872
|
+
}
|
|
873
|
+
if (year === startYear && endMonthIndex <= startMonthIndex) {
|
|
874
|
+
return true;
|
|
875
|
+
}
|
|
876
|
+
return false;
|
|
877
|
+
}
|
|
878
|
+
canNavigateStartNext = computed(() => {
|
|
879
|
+
if (!this.isRangeMode()) {
|
|
880
|
+
return true;
|
|
881
|
+
}
|
|
882
|
+
const current = this._currentMonth();
|
|
883
|
+
const end = this._endMonth();
|
|
884
|
+
const view = this._currentView();
|
|
885
|
+
if (view === 'day') {
|
|
886
|
+
const startNext = addMonths(current, 1);
|
|
887
|
+
return (startNext.getFullYear() < end.getFullYear() ||
|
|
888
|
+
(startNext.getFullYear() === end.getFullYear() && startNext.getMonth() < end.getMonth()));
|
|
889
|
+
}
|
|
890
|
+
if (view === 'month' || view === 'quarter') {
|
|
891
|
+
const startNextYear = addYears(current, 1);
|
|
892
|
+
return startNextYear.getFullYear() < end.getFullYear();
|
|
893
|
+
}
|
|
894
|
+
if (view === 'year') {
|
|
895
|
+
const yearRange = getYearRange(current.getFullYear());
|
|
896
|
+
const lastYearInRange = yearRange[yearRange.length - 1];
|
|
897
|
+
return lastYearInRange < end.getFullYear() - 1;
|
|
898
|
+
}
|
|
899
|
+
return true;
|
|
900
|
+
}, ...(ngDevMode ? [{ debugName: "canNavigateStartNext" }] : []));
|
|
901
|
+
canNavigateEndPrev = computed(() => {
|
|
902
|
+
if (!this.isRangeMode()) {
|
|
903
|
+
return true;
|
|
904
|
+
}
|
|
905
|
+
const start = this._currentMonth();
|
|
906
|
+
const end = this._endMonth();
|
|
907
|
+
const view = this._endView();
|
|
908
|
+
if (view === 'day') {
|
|
909
|
+
const endPrev = addMonths(end, -1);
|
|
910
|
+
return (endPrev.getFullYear() > start.getFullYear() ||
|
|
911
|
+
(endPrev.getFullYear() === start.getFullYear() && endPrev.getMonth() > start.getMonth()));
|
|
912
|
+
}
|
|
913
|
+
if (view === 'month' || view === 'quarter') {
|
|
914
|
+
const endPrevYear = addYears(end, -1);
|
|
915
|
+
return endPrevYear.getFullYear() > start.getFullYear();
|
|
916
|
+
}
|
|
917
|
+
if (view === 'year') {
|
|
918
|
+
const yearRange = getYearRange(end.getFullYear());
|
|
919
|
+
const firstYearInRange = yearRange[0];
|
|
920
|
+
return firstYearInRange > start.getFullYear() + 1;
|
|
921
|
+
}
|
|
922
|
+
return true;
|
|
923
|
+
}, ...(ngDevMode ? [{ debugName: "canNavigateEndPrev" }] : []));
|
|
924
|
+
displayValue = computed(() => {
|
|
925
|
+
let format = this.zFormat();
|
|
926
|
+
if (this.zShowTime() || this.isTimeMode()) {
|
|
927
|
+
const timeParts = [];
|
|
928
|
+
if (this.zShowHour()) {
|
|
929
|
+
timeParts.push(this.zTimeFormat() === '12h' ? 'hh' : 'HH');
|
|
930
|
+
}
|
|
931
|
+
if (this.zShowMinute()) {
|
|
932
|
+
timeParts.push('mm');
|
|
933
|
+
}
|
|
934
|
+
if (this.zShowSecond()) {
|
|
935
|
+
timeParts.push('ss');
|
|
936
|
+
}
|
|
937
|
+
const timeFormat = timeParts.join(':');
|
|
938
|
+
const periodSuffix = this.zTimeFormat() === '12h' ? ` ${this._period()}` : '';
|
|
939
|
+
format = this.isTimeMode() ? timeFormat + periodSuffix : `${this.zFormat()} ${timeFormat}${periodSuffix}`;
|
|
940
|
+
}
|
|
941
|
+
if (this.isRangeMode()) {
|
|
942
|
+
const start = this._rangeStart();
|
|
943
|
+
const end = this._rangeEnd();
|
|
944
|
+
if (!start || !end) {
|
|
945
|
+
return '';
|
|
946
|
+
}
|
|
947
|
+
return `${formatDate(start, format)} - ${formatDate(end, format)}`;
|
|
948
|
+
}
|
|
949
|
+
const date = this._selectedDate();
|
|
950
|
+
if (!date) {
|
|
951
|
+
return '';
|
|
952
|
+
}
|
|
953
|
+
if (this.isMonthMode()) {
|
|
954
|
+
return date.toLocaleDateString(this.zLocale(), { month: 'long', year: 'numeric' });
|
|
955
|
+
}
|
|
956
|
+
if (this.isYearMode()) {
|
|
957
|
+
return date.getFullYear().toString();
|
|
958
|
+
}
|
|
959
|
+
if (this.isQuarterMode()) {
|
|
960
|
+
const quarter = Math.floor(date.getMonth() / 3) + 1;
|
|
961
|
+
return `Q${quarter} ${date.getFullYear()}`;
|
|
962
|
+
}
|
|
963
|
+
return formatDate(date, format);
|
|
964
|
+
}, ...(ngDevMode ? [{ debugName: "displayValue" }] : []));
|
|
965
|
+
_inputDisplayStart = signal('', ...(ngDevMode ? [{ debugName: "_inputDisplayStart" }] : []));
|
|
966
|
+
_inputDisplayEnd = signal('', ...(ngDevMode ? [{ debugName: "_inputDisplayEnd" }] : []));
|
|
967
|
+
inputDisplayStart = computed(() => this._inputDisplayStart(), ...(ngDevMode ? [{ debugName: "inputDisplayStart" }] : []));
|
|
968
|
+
inputDisplayEnd = computed(() => this._inputDisplayEnd(), ...(ngDevMode ? [{ debugName: "inputDisplayEnd" }] : []));
|
|
969
|
+
displayValueStart = computed(() => {
|
|
970
|
+
const format = this._getDisplayFormat();
|
|
971
|
+
const start = this._rangeStart();
|
|
972
|
+
return start ? formatDate(start, format) : '';
|
|
973
|
+
}, ...(ngDevMode ? [{ debugName: "displayValueStart" }] : []));
|
|
974
|
+
displayValueEnd = computed(() => {
|
|
975
|
+
const format = this._getDisplayFormat();
|
|
976
|
+
const end = this._rangeEnd();
|
|
977
|
+
return end ? formatDate(end, format) : '';
|
|
978
|
+
}, ...(ngDevMode ? [{ debugName: "displayValueEnd" }] : []));
|
|
979
|
+
_getDisplayFormat() {
|
|
980
|
+
let format = this.zFormat();
|
|
981
|
+
if (this.zShowTime() || this.isTimeMode()) {
|
|
982
|
+
const timeParts = [];
|
|
983
|
+
if (this.zShowHour()) {
|
|
984
|
+
timeParts.push(this.zTimeFormat() === '12h' ? 'hh' : 'HH');
|
|
985
|
+
}
|
|
986
|
+
if (this.zShowMinute()) {
|
|
987
|
+
timeParts.push('mm');
|
|
988
|
+
}
|
|
989
|
+
if (this.zShowSecond()) {
|
|
990
|
+
timeParts.push('ss');
|
|
991
|
+
}
|
|
992
|
+
const timeFormat = timeParts.join(':');
|
|
993
|
+
const periodSuffix = this.zTimeFormat() === '12h' ? ` ${this._period()}` : '';
|
|
994
|
+
format = this.isTimeMode() ? timeFormat + periodSuffix : `${this.zFormat()} ${timeFormat}${periodSuffix}`;
|
|
995
|
+
}
|
|
996
|
+
return format;
|
|
997
|
+
}
|
|
998
|
+
showClearButton = computed(() => {
|
|
999
|
+
if (!this.zAllowClear() || this.isDisabled() || this.zReadonly() || this.isOpen()) {
|
|
1000
|
+
return false;
|
|
1001
|
+
}
|
|
1002
|
+
return this.displayValue() !== '';
|
|
1003
|
+
}, ...(ngDevMode ? [{ debugName: "showClearButton" }] : []));
|
|
1004
|
+
hasValue = computed(() => {
|
|
1005
|
+
if (this.isRangeMode()) {
|
|
1006
|
+
return this._rangeStart() !== null && this._rangeEnd() !== null;
|
|
1007
|
+
}
|
|
1008
|
+
return this._selectedDate() !== null;
|
|
1009
|
+
}, ...(ngDevMode ? [{ debugName: "hasValue" }] : []));
|
|
1010
|
+
currentStatus = computed(() => {
|
|
1011
|
+
if (this.isDisabled()) {
|
|
1012
|
+
return 'disabled';
|
|
1013
|
+
}
|
|
1014
|
+
if (this.zReadonly()) {
|
|
1015
|
+
return 'readonly';
|
|
1016
|
+
}
|
|
1017
|
+
if (this.isOpen()) {
|
|
1018
|
+
return 'open';
|
|
1019
|
+
}
|
|
1020
|
+
if (this.hasError()) {
|
|
1021
|
+
return 'error';
|
|
1022
|
+
}
|
|
1023
|
+
return 'default';
|
|
1024
|
+
}, ...(ngDevMode ? [{ debugName: "currentStatus" }] : []));
|
|
1025
|
+
triggerClasses = computed(() => zMergeClasses(zCalendarVariants({
|
|
1026
|
+
zSize: this.zSize(),
|
|
1027
|
+
zStatus: this.currentStatus(),
|
|
1028
|
+
}), this.class()), ...(ngDevMode ? [{ debugName: "triggerClasses" }] : []));
|
|
1029
|
+
_shouldShowValidation = computed(() => {
|
|
1030
|
+
const control = this._formControl();
|
|
1031
|
+
this._formStateVersion();
|
|
1032
|
+
if (control) {
|
|
1033
|
+
return control.dirty;
|
|
1034
|
+
}
|
|
1035
|
+
return this._dirty() || this._touched();
|
|
1036
|
+
}, ...(ngDevMode ? [{ debugName: "_shouldShowValidation" }] : []));
|
|
1037
|
+
hasError = computed(() => {
|
|
1038
|
+
const customErrors = this._getValidationErrors();
|
|
1039
|
+
if (customErrors.length > 0) {
|
|
1040
|
+
return true;
|
|
1041
|
+
}
|
|
1042
|
+
const control = this._formControl();
|
|
1043
|
+
this._formStateVersion();
|
|
1044
|
+
if (!control) {
|
|
1045
|
+
return false;
|
|
1046
|
+
}
|
|
1047
|
+
return control.invalid && this._shouldShowValidation();
|
|
1048
|
+
}, ...(ngDevMode ? [{ debugName: "hasError" }] : []));
|
|
1049
|
+
showError = computed(() => this.hasError(), ...(ngDevMode ? [{ debugName: "showError" }] : []));
|
|
1050
|
+
errorMessage = computed(() => {
|
|
1051
|
+
const customErrors = this._getValidationErrors();
|
|
1052
|
+
if (customErrors.length > 0) {
|
|
1053
|
+
return customErrors[0];
|
|
1054
|
+
}
|
|
1055
|
+
const control = this._formControl();
|
|
1056
|
+
const errors = control?.errors;
|
|
1057
|
+
if (!errors) {
|
|
1058
|
+
return '';
|
|
1059
|
+
}
|
|
1060
|
+
const validators = this.zValidators();
|
|
1061
|
+
for (const validator of validators) {
|
|
1062
|
+
if (errors[validator.error]) {
|
|
1063
|
+
return validator.message;
|
|
1064
|
+
}
|
|
1065
|
+
}
|
|
1066
|
+
if (errors['required']) {
|
|
1067
|
+
return 'Vui lòng chọn ngày';
|
|
1068
|
+
}
|
|
1069
|
+
return '';
|
|
1070
|
+
}, ...(ngDevMode ? [{ debugName: "errorMessage" }] : []));
|
|
1071
|
+
constructor() {
|
|
1072
|
+
effect(() => {
|
|
1073
|
+
const date = this._selectedDate();
|
|
1074
|
+
if (date && this.zShowTime()) {
|
|
1075
|
+
this._hour.set(date.getHours());
|
|
1076
|
+
this._minute.set(date.getMinutes());
|
|
1077
|
+
this._second.set(date.getSeconds());
|
|
1078
|
+
}
|
|
1079
|
+
});
|
|
1080
|
+
}
|
|
1081
|
+
ngOnInit() {
|
|
1082
|
+
void Promise.resolve().then(() => {
|
|
1083
|
+
try {
|
|
1084
|
+
this._ngControl = this._injector.get(NgControl, null);
|
|
1085
|
+
if (!this._ngControl?.control) {
|
|
1086
|
+
return;
|
|
1087
|
+
}
|
|
1088
|
+
const { control } = this._ngControl;
|
|
1089
|
+
this._formControl.set(control);
|
|
1090
|
+
merge(control.statusChanges, control.valueChanges, control.events)
|
|
1091
|
+
.pipe(takeUntilDestroyed(this._destroyRef))
|
|
1092
|
+
.subscribe(() => {
|
|
1093
|
+
this._formStateVersion.update(v => v + 1);
|
|
1094
|
+
this._cdr.markForCheck();
|
|
1095
|
+
});
|
|
1096
|
+
}
|
|
1097
|
+
catch {
|
|
1098
|
+
this._ngControl = null;
|
|
1099
|
+
}
|
|
1100
|
+
});
|
|
1101
|
+
setTimeout(() => this._emitControl());
|
|
1102
|
+
}
|
|
1103
|
+
writeValue(value) {
|
|
1104
|
+
if (value === null || value === undefined) {
|
|
1105
|
+
this._selectedDate.set(null);
|
|
1106
|
+
this._rangeStart.set(null);
|
|
1107
|
+
this._rangeEnd.set(null);
|
|
1108
|
+
return;
|
|
1109
|
+
}
|
|
1110
|
+
const valueType = this.zValueType();
|
|
1111
|
+
if (this.isRangeMode()) {
|
|
1112
|
+
if (typeof value === 'object' && 'start' in value && 'end' in value) {
|
|
1113
|
+
const range = value;
|
|
1114
|
+
this._rangeStart.set(range.start);
|
|
1115
|
+
this._rangeEnd.set(range.end);
|
|
1116
|
+
}
|
|
1117
|
+
return;
|
|
1118
|
+
}
|
|
1119
|
+
let date = null;
|
|
1120
|
+
if (value instanceof Date) {
|
|
1121
|
+
date = value;
|
|
1122
|
+
}
|
|
1123
|
+
if (!date && typeof value === 'string') {
|
|
1124
|
+
date = valueType === 'iso' ? fromISOString(value) : parseDate(value, this.zFormat());
|
|
1125
|
+
}
|
|
1126
|
+
if (!date) {
|
|
1127
|
+
return;
|
|
1128
|
+
}
|
|
1129
|
+
this._selectedDate.set(date);
|
|
1130
|
+
this._currentMonth.set(date);
|
|
1131
|
+
this._syncTimeSignals(date);
|
|
1132
|
+
this._updateInputDisplay();
|
|
1133
|
+
}
|
|
1134
|
+
registerOnChange(fn) {
|
|
1135
|
+
this._onChange = fn;
|
|
1136
|
+
}
|
|
1137
|
+
registerOnTouched(fn) {
|
|
1138
|
+
this._onTouched = fn;
|
|
1139
|
+
}
|
|
1140
|
+
setDisabledState(isDisabled) {
|
|
1141
|
+
this._disabled.set(isDisabled);
|
|
1142
|
+
}
|
|
1143
|
+
open() {
|
|
1144
|
+
if (this.isDisabled() || this.zReadonly()) {
|
|
1145
|
+
return;
|
|
1146
|
+
}
|
|
1147
|
+
this._popoverControl()?.show();
|
|
1148
|
+
}
|
|
1149
|
+
close() {
|
|
1150
|
+
this._popoverControl()?.close();
|
|
1151
|
+
}
|
|
1152
|
+
toggle() {
|
|
1153
|
+
if (this.isDisabled() || this.zReadonly()) {
|
|
1154
|
+
return;
|
|
1155
|
+
}
|
|
1156
|
+
const popover = this._popoverControl();
|
|
1157
|
+
if (!popover) {
|
|
1158
|
+
return;
|
|
1159
|
+
}
|
|
1160
|
+
if (popover.isVisible()) {
|
|
1161
|
+
if (!this.showCancelButton()) {
|
|
1162
|
+
this.close();
|
|
1163
|
+
}
|
|
1164
|
+
return;
|
|
1165
|
+
}
|
|
1166
|
+
this.open();
|
|
1167
|
+
}
|
|
1168
|
+
clear() {
|
|
1169
|
+
this.onClear(new MouseEvent('click'));
|
|
1170
|
+
}
|
|
1171
|
+
focus() {
|
|
1172
|
+
this.triggerRef()?.nativeElement.focus();
|
|
1173
|
+
}
|
|
1174
|
+
blur() {
|
|
1175
|
+
this.triggerRef()?.nativeElement.blur();
|
|
1176
|
+
}
|
|
1177
|
+
reset() {
|
|
1178
|
+
this._selectedDate.set(null);
|
|
1179
|
+
this._rangeStart.set(null);
|
|
1180
|
+
this._rangeEnd.set(null);
|
|
1181
|
+
this._hour.set(0);
|
|
1182
|
+
this._minute.set(0);
|
|
1183
|
+
this._second.set(0);
|
|
1184
|
+
this._touched.set(false);
|
|
1185
|
+
this._dirty.set(false);
|
|
1186
|
+
this._inputDisplayValue.set('');
|
|
1187
|
+
const emitValue = this._getEmitValue();
|
|
1188
|
+
this._onChange(emitValue);
|
|
1189
|
+
if (this._ngControl?.control) {
|
|
1190
|
+
this._ngControl.control.markAsPristine();
|
|
1191
|
+
this._ngControl.control.markAsUntouched();
|
|
1192
|
+
}
|
|
1193
|
+
}
|
|
1194
|
+
validate() {
|
|
1195
|
+
this._touched.set(true);
|
|
1196
|
+
this._dirty.set(true);
|
|
1197
|
+
this._onTouched();
|
|
1198
|
+
if (this._ngControl?.control) {
|
|
1199
|
+
this._ngControl.control.markAsDirty();
|
|
1200
|
+
this._ngControl.control.markAsTouched();
|
|
1201
|
+
}
|
|
1202
|
+
}
|
|
1203
|
+
markAsTouched() {
|
|
1204
|
+
this._touched.set(true);
|
|
1205
|
+
this._onTouched();
|
|
1206
|
+
}
|
|
1207
|
+
markAsUntouched() {
|
|
1208
|
+
this._touched.set(false);
|
|
1209
|
+
}
|
|
1210
|
+
markAsDirty() {
|
|
1211
|
+
this._dirty.set(true);
|
|
1212
|
+
}
|
|
1213
|
+
markAsPristine() {
|
|
1214
|
+
this._dirty.set(false);
|
|
1215
|
+
}
|
|
1216
|
+
onPopoverShow() {
|
|
1217
|
+
this._backupIfNeeded();
|
|
1218
|
+
this._appliedViaOk.set(false);
|
|
1219
|
+
this._hasViewChanged.set(false);
|
|
1220
|
+
this._hasEndViewChanged.set(false);
|
|
1221
|
+
if (this.isMonthMode()) {
|
|
1222
|
+
this._currentView.set('month');
|
|
1223
|
+
this._initializeTimeIfNeeded();
|
|
1224
|
+
return;
|
|
1225
|
+
}
|
|
1226
|
+
if (this.isYearMode()) {
|
|
1227
|
+
this._currentView.set('year');
|
|
1228
|
+
this._initializeTimeIfNeeded();
|
|
1229
|
+
return;
|
|
1230
|
+
}
|
|
1231
|
+
if (this.isQuarterMode()) {
|
|
1232
|
+
this._currentView.set('quarter');
|
|
1233
|
+
this._initializeTimeIfNeeded();
|
|
1234
|
+
return;
|
|
1235
|
+
}
|
|
1236
|
+
this._currentView.set('day');
|
|
1237
|
+
this._initializeTimeIfNeeded();
|
|
1238
|
+
if (this.isRangeMode()) {
|
|
1239
|
+
this._endView.set('day');
|
|
1240
|
+
this._inputDisplayStart.set(this.displayValueStart());
|
|
1241
|
+
this._inputDisplayEnd.set(this.displayValueEnd());
|
|
1242
|
+
}
|
|
1243
|
+
if (!this.isRangeMode()) {
|
|
1244
|
+
this._activePresetKey.set(null);
|
|
1245
|
+
const selected = this._selectedDate();
|
|
1246
|
+
if (selected) {
|
|
1247
|
+
this._currentMonth.set(selected);
|
|
1248
|
+
return;
|
|
1249
|
+
}
|
|
1250
|
+
this._resetCalendarsToDefault();
|
|
1251
|
+
return;
|
|
1252
|
+
}
|
|
1253
|
+
const start = this._rangeStart();
|
|
1254
|
+
const end = this._rangeEnd();
|
|
1255
|
+
if (start && end) {
|
|
1256
|
+
this._currentMonth.set(start);
|
|
1257
|
+
this._endMonth.set(isSameMonth(start, end) ? addMonths(end, 1) : end);
|
|
1258
|
+
this._activePresetKey.set(this._detectMatchingPreset(start, end));
|
|
1259
|
+
return;
|
|
1260
|
+
}
|
|
1261
|
+
if (this.zQuickSelect()) {
|
|
1262
|
+
this._activePresetKey.set(null);
|
|
1263
|
+
this._resetCalendarsToDefault();
|
|
1264
|
+
return;
|
|
1265
|
+
}
|
|
1266
|
+
this._activePresetKey.set(null);
|
|
1267
|
+
this._resetCalendarsToDefault();
|
|
1268
|
+
}
|
|
1269
|
+
_initializeTimeIfNeeded() {
|
|
1270
|
+
if (!this.zShowTime() && !this.isTimeMode()) {
|
|
1271
|
+
return;
|
|
1272
|
+
}
|
|
1273
|
+
const now = new Date();
|
|
1274
|
+
const selected = this._selectedDate();
|
|
1275
|
+
this._syncTimeSignals(selected ?? now);
|
|
1276
|
+
if (!this.isRangeMode()) {
|
|
1277
|
+
return;
|
|
1278
|
+
}
|
|
1279
|
+
const end = this._rangeEnd();
|
|
1280
|
+
this._syncEndTimeSignals(end ?? now);
|
|
1281
|
+
}
|
|
1282
|
+
_syncEndTimeSignals(date) {
|
|
1283
|
+
const hours = date.getHours();
|
|
1284
|
+
this._hourEnd.set(hours);
|
|
1285
|
+
this._minuteEnd.set(date.getMinutes());
|
|
1286
|
+
this._secondEnd.set(date.getSeconds());
|
|
1287
|
+
this._periodEnd.set(hours >= 12 ? 'PM' : 'AM');
|
|
1288
|
+
}
|
|
1289
|
+
_resetCalendarsToDefault() {
|
|
1290
|
+
const today = getToday();
|
|
1291
|
+
this._currentMonth.set(today);
|
|
1292
|
+
this._endMonth.set(addMonths(today, 1));
|
|
1293
|
+
this._currentView.set('day');
|
|
1294
|
+
this._endView.set('day');
|
|
1295
|
+
}
|
|
1296
|
+
_backupIfNeeded() {
|
|
1297
|
+
const needsConfirmation = this.showOkButton() || this.showCancelButton();
|
|
1298
|
+
if (needsConfirmation) {
|
|
1299
|
+
this._backupSelectedDate.set(this._selectedDate());
|
|
1300
|
+
this._backupRangeStart.set(this._rangeStart());
|
|
1301
|
+
this._backupRangeEnd.set(this._rangeEnd());
|
|
1302
|
+
}
|
|
1303
|
+
}
|
|
1304
|
+
onPopoverHide() {
|
|
1305
|
+
this._hoveredDate.set(null);
|
|
1306
|
+
const needsConfirmation = this.showOkButton() || this.showCancelButton();
|
|
1307
|
+
if (needsConfirmation && !this._appliedViaOk()) {
|
|
1308
|
+
this._restoreFromBackup();
|
|
1309
|
+
}
|
|
1310
|
+
if (this._dirty()) {
|
|
1311
|
+
this._touched.set(true);
|
|
1312
|
+
}
|
|
1313
|
+
this._onTouched();
|
|
1314
|
+
this._inputDisplayValue.set(this.displayValue());
|
|
1315
|
+
if (this.isRangeMode()) {
|
|
1316
|
+
this._inputDisplayStart.set(this.displayValueStart());
|
|
1317
|
+
this._inputDisplayEnd.set(this.displayValueEnd());
|
|
1318
|
+
}
|
|
1319
|
+
}
|
|
1320
|
+
_restoreFromBackup() {
|
|
1321
|
+
this._selectedDate.set(this._backupSelectedDate());
|
|
1322
|
+
this._rangeStart.set(this._backupRangeStart());
|
|
1323
|
+
this._rangeEnd.set(this._backupRangeEnd());
|
|
1324
|
+
this._dirty.set(false);
|
|
1325
|
+
const backup = this._backupSelectedDate();
|
|
1326
|
+
if (backup) {
|
|
1327
|
+
this._syncTimeSignals(backup);
|
|
1328
|
+
}
|
|
1329
|
+
}
|
|
1330
|
+
onPopoverControl(control) {
|
|
1331
|
+
this._popoverControl.set(control);
|
|
1332
|
+
}
|
|
1333
|
+
onTriggerKeydown(event) {
|
|
1334
|
+
if (this.isDisabled() || this.zReadonly()) {
|
|
1335
|
+
return;
|
|
1336
|
+
}
|
|
1337
|
+
if (event.key === 'Enter' || event.key === ' ') {
|
|
1338
|
+
event.preventDefault();
|
|
1339
|
+
this._popoverControl()?.toggle();
|
|
1340
|
+
return;
|
|
1341
|
+
}
|
|
1342
|
+
if (event.key === 'Escape' && this.isOpen()) {
|
|
1343
|
+
this.close();
|
|
1344
|
+
}
|
|
1345
|
+
}
|
|
1346
|
+
onInputChange(event) {
|
|
1347
|
+
const input = event.target;
|
|
1348
|
+
const { value } = input;
|
|
1349
|
+
this._inputDisplayValue.set(value);
|
|
1350
|
+
const trimmedValue = value.trim();
|
|
1351
|
+
if (!trimmedValue) {
|
|
1352
|
+
return;
|
|
1353
|
+
}
|
|
1354
|
+
const format = this._getParseFormat();
|
|
1355
|
+
const expectedLength = this._getExpectedFormatLength(format);
|
|
1356
|
+
if (trimmedValue.length < expectedLength) {
|
|
1357
|
+
return;
|
|
1358
|
+
}
|
|
1359
|
+
if (this.isRangeMode()) {
|
|
1360
|
+
const parts = trimmedValue.split(' - ');
|
|
1361
|
+
if (parts.length === 2) {
|
|
1362
|
+
const start = parseDate(parts[0].trim(), format);
|
|
1363
|
+
const end = parseDate(parts[1].trim(), format);
|
|
1364
|
+
if (start) {
|
|
1365
|
+
this._rangeStart.set(start);
|
|
1366
|
+
this._currentMonth.set(start);
|
|
1367
|
+
}
|
|
1368
|
+
if (end) {
|
|
1369
|
+
this._rangeEnd.set(end);
|
|
1370
|
+
this._endMonth.set(end);
|
|
1371
|
+
}
|
|
1372
|
+
}
|
|
1373
|
+
return;
|
|
1374
|
+
}
|
|
1375
|
+
const date = parseDate(trimmedValue, format);
|
|
1376
|
+
if (date) {
|
|
1377
|
+
this._selectedDate.set(date);
|
|
1378
|
+
this._currentMonth.set(date);
|
|
1379
|
+
this._syncTimeSignals(date);
|
|
1380
|
+
}
|
|
1381
|
+
}
|
|
1382
|
+
_getExpectedFormatLength(format) {
|
|
1383
|
+
return format.replace(/\[.*?\]/g, ' ').length;
|
|
1384
|
+
}
|
|
1385
|
+
onStartInputChange(event) {
|
|
1386
|
+
const input = event.target;
|
|
1387
|
+
const { value } = input;
|
|
1388
|
+
this._inputDisplayStart.set(value);
|
|
1389
|
+
const trimmedValue = value.trim();
|
|
1390
|
+
if (!trimmedValue) {
|
|
1391
|
+
return;
|
|
1392
|
+
}
|
|
1393
|
+
const format = this._getParseFormat();
|
|
1394
|
+
const expectedLength = this._getExpectedFormatLength(format);
|
|
1395
|
+
if (trimmedValue.length < expectedLength) {
|
|
1396
|
+
return;
|
|
1397
|
+
}
|
|
1398
|
+
const date = parseDate(trimmedValue, format);
|
|
1399
|
+
if (!date) {
|
|
1400
|
+
return;
|
|
1401
|
+
}
|
|
1402
|
+
const endDate = this._rangeEnd();
|
|
1403
|
+
if (endDate && date >= endDate) {
|
|
1404
|
+
this._inputDisplayStart.set(this.displayValueStart());
|
|
1405
|
+
return;
|
|
1406
|
+
}
|
|
1407
|
+
this._rangeStart.set(date);
|
|
1408
|
+
this._currentMonth.set(date);
|
|
1409
|
+
this._syncTimeSignals(date);
|
|
1410
|
+
}
|
|
1411
|
+
onEndInputChange(event) {
|
|
1412
|
+
const input = event.target;
|
|
1413
|
+
const { value } = input;
|
|
1414
|
+
this._inputDisplayEnd.set(value);
|
|
1415
|
+
const trimmedValue = value.trim();
|
|
1416
|
+
if (!trimmedValue) {
|
|
1417
|
+
return;
|
|
1418
|
+
}
|
|
1419
|
+
const format = this._getParseFormat();
|
|
1420
|
+
const expectedLength = this._getExpectedFormatLength(format);
|
|
1421
|
+
if (trimmedValue.length < expectedLength) {
|
|
1422
|
+
return;
|
|
1423
|
+
}
|
|
1424
|
+
const date = parseDate(trimmedValue, format);
|
|
1425
|
+
if (!date) {
|
|
1426
|
+
return;
|
|
1427
|
+
}
|
|
1428
|
+
const startDate = this._rangeStart();
|
|
1429
|
+
if (startDate && date <= startDate) {
|
|
1430
|
+
this._inputDisplayEnd.set(this.displayValueEnd());
|
|
1431
|
+
return;
|
|
1432
|
+
}
|
|
1433
|
+
this._rangeEnd.set(date);
|
|
1434
|
+
this._endMonth.set(date);
|
|
1435
|
+
this._syncEndTimeSignals(date);
|
|
1436
|
+
}
|
|
1437
|
+
onStartInputEnter(event) {
|
|
1438
|
+
event.preventDefault();
|
|
1439
|
+
const input = event.target;
|
|
1440
|
+
const value = input.value.trim();
|
|
1441
|
+
const format = this._getParseFormat();
|
|
1442
|
+
const date = parseDate(value, format);
|
|
1443
|
+
if (!date) {
|
|
1444
|
+
input.value = this.displayValueStart();
|
|
1445
|
+
input.blur();
|
|
1446
|
+
return;
|
|
1447
|
+
}
|
|
1448
|
+
const endDate = this._rangeEnd();
|
|
1449
|
+
if (endDate && date >= endDate) {
|
|
1450
|
+
input.value = this.displayValueStart();
|
|
1451
|
+
input.blur();
|
|
1452
|
+
return;
|
|
1453
|
+
}
|
|
1454
|
+
this._skipBlurHandler.set(true);
|
|
1455
|
+
this._rangeStart.set(date);
|
|
1456
|
+
this._currentMonth.set(date);
|
|
1457
|
+
this._syncTimeSignals(date);
|
|
1458
|
+
this._dirty.set(true);
|
|
1459
|
+
input.blur();
|
|
1460
|
+
}
|
|
1461
|
+
onEndInputEnter(event) {
|
|
1462
|
+
event.preventDefault();
|
|
1463
|
+
const input = event.target;
|
|
1464
|
+
const value = input.value.trim();
|
|
1465
|
+
const format = this._getParseFormat();
|
|
1466
|
+
const date = parseDate(value, format);
|
|
1467
|
+
if (!date) {
|
|
1468
|
+
input.value = this.displayValueEnd();
|
|
1469
|
+
input.blur();
|
|
1470
|
+
return;
|
|
1471
|
+
}
|
|
1472
|
+
const startDate = this._rangeStart();
|
|
1473
|
+
if (startDate && date <= startDate) {
|
|
1474
|
+
input.value = this.displayValueEnd();
|
|
1475
|
+
input.blur();
|
|
1476
|
+
return;
|
|
1477
|
+
}
|
|
1478
|
+
this._skipBlurHandler.set(true);
|
|
1479
|
+
this._rangeEnd.set(date);
|
|
1480
|
+
this._endMonth.set(date);
|
|
1481
|
+
this._syncEndTimeSignals(date);
|
|
1482
|
+
this._dirty.set(true);
|
|
1483
|
+
input.blur();
|
|
1484
|
+
}
|
|
1485
|
+
onInputFocus(_event) {
|
|
1486
|
+
this._backupSelectedDate.set(this._selectedDate());
|
|
1487
|
+
}
|
|
1488
|
+
onInputBlur(event) {
|
|
1489
|
+
if (this._skipBlurHandler()) {
|
|
1490
|
+
this._skipBlurHandler.set(false);
|
|
1491
|
+
return;
|
|
1492
|
+
}
|
|
1493
|
+
const needsConfirmation = this.showOkButton() || this.showCancelButton();
|
|
1494
|
+
if (needsConfirmation && this.isOpen()) {
|
|
1495
|
+
return;
|
|
1496
|
+
}
|
|
1497
|
+
const input = event.target;
|
|
1498
|
+
const currentValue = input.value.trim();
|
|
1499
|
+
const format = this._getParseFormat();
|
|
1500
|
+
if (!currentValue) {
|
|
1501
|
+
this._selectedDate.set(null);
|
|
1502
|
+
this._backupSelectedDate.set(null);
|
|
1503
|
+
this._inputDisplayValue.set('');
|
|
1504
|
+
this._applyValue();
|
|
1505
|
+
return;
|
|
1506
|
+
}
|
|
1507
|
+
const parsed = parseDate(currentValue, format);
|
|
1508
|
+
if (parsed) {
|
|
1509
|
+
this._selectedDate.set(parsed);
|
|
1510
|
+
this._currentMonth.set(parsed);
|
|
1511
|
+
this._syncTimeSignals(parsed);
|
|
1512
|
+
this._backupSelectedDate.set(parsed);
|
|
1513
|
+
this._inputDisplayValue.set(this.displayValue());
|
|
1514
|
+
this._applyValue();
|
|
1515
|
+
return;
|
|
1516
|
+
}
|
|
1517
|
+
const backup = this._backupSelectedDate();
|
|
1518
|
+
this._selectedDate.set(backup);
|
|
1519
|
+
this._inputDisplayValue.set(this.displayValue());
|
|
1520
|
+
}
|
|
1521
|
+
onInputEnter(event) {
|
|
1522
|
+
event.preventDefault();
|
|
1523
|
+
const input = event.target;
|
|
1524
|
+
const value = input.value.trim();
|
|
1525
|
+
if (!value) {
|
|
1526
|
+
this._skipBlurHandler.set(true);
|
|
1527
|
+
this._clearDateValues();
|
|
1528
|
+
this._dirty.set(true);
|
|
1529
|
+
this._appliedViaOk.set(true);
|
|
1530
|
+
this._applyValue();
|
|
1531
|
+
this.close();
|
|
1532
|
+
input.blur();
|
|
1533
|
+
return;
|
|
1534
|
+
}
|
|
1535
|
+
const format = this._getParseFormat();
|
|
1536
|
+
if (this.isRangeMode()) {
|
|
1537
|
+
const parts = value.split(' - ');
|
|
1538
|
+
if (parts.length === 2) {
|
|
1539
|
+
const start = parseDate(parts[0].trim(), format);
|
|
1540
|
+
const end = parseDate(parts[1].trim(), format);
|
|
1541
|
+
if (start && end) {
|
|
1542
|
+
this._skipBlurHandler.set(true);
|
|
1543
|
+
const swapped = start > end;
|
|
1544
|
+
const rangeStart = swapped ? end : start;
|
|
1545
|
+
const rangeEnd = swapped ? start : end;
|
|
1546
|
+
this._rangeStart.set(rangeStart);
|
|
1547
|
+
this._rangeEnd.set(rangeEnd);
|
|
1548
|
+
this._currentMonth.set(rangeStart);
|
|
1549
|
+
this._endMonth.set(rangeEnd);
|
|
1550
|
+
this._dirty.set(true);
|
|
1551
|
+
this._appliedViaOk.set(true);
|
|
1552
|
+
this._applyValue();
|
|
1553
|
+
this.close();
|
|
1554
|
+
input.blur();
|
|
1555
|
+
return;
|
|
1556
|
+
}
|
|
1557
|
+
}
|
|
1558
|
+
this._restoreFromBackup();
|
|
1559
|
+
this._updateInputDisplay();
|
|
1560
|
+
this.close();
|
|
1561
|
+
input.blur();
|
|
1562
|
+
return;
|
|
1563
|
+
}
|
|
1564
|
+
const date = parseDate(value, format);
|
|
1565
|
+
if (date) {
|
|
1566
|
+
this._skipBlurHandler.set(true);
|
|
1567
|
+
this._selectedDate.set(date);
|
|
1568
|
+
this._currentMonth.set(date);
|
|
1569
|
+
this._syncTimeSignals(date);
|
|
1570
|
+
this._dirty.set(true);
|
|
1571
|
+
this._appliedViaOk.set(true);
|
|
1572
|
+
this._applyValue();
|
|
1573
|
+
this.close();
|
|
1574
|
+
input.blur();
|
|
1575
|
+
return;
|
|
1576
|
+
}
|
|
1577
|
+
this._restoreFromBackup();
|
|
1578
|
+
this._updateInputDisplay();
|
|
1579
|
+
this.close();
|
|
1580
|
+
input.blur();
|
|
1581
|
+
}
|
|
1582
|
+
onCalendarKeydown(event) {
|
|
1583
|
+
if (this._currentView() !== 'day') {
|
|
1584
|
+
return;
|
|
1585
|
+
}
|
|
1586
|
+
const { key } = event;
|
|
1587
|
+
if (key === 'Escape') {
|
|
1588
|
+
this.close();
|
|
1589
|
+
return;
|
|
1590
|
+
}
|
|
1591
|
+
if (key === 'Enter') {
|
|
1592
|
+
if (!this.isRangeMode() || this.zShowTime()) {
|
|
1593
|
+
this.onOkClick();
|
|
1594
|
+
}
|
|
1595
|
+
return;
|
|
1596
|
+
}
|
|
1597
|
+
if (['ArrowUp', 'ArrowDown', 'ArrowLeft', 'ArrowRight'].includes(key)) {
|
|
1598
|
+
event.preventDefault();
|
|
1599
|
+
this._navigateByArrowKey(key);
|
|
1600
|
+
}
|
|
1601
|
+
}
|
|
1602
|
+
onDayClick(day) {
|
|
1603
|
+
if (day.isDisabled) {
|
|
1604
|
+
return;
|
|
1605
|
+
}
|
|
1606
|
+
const clickedDate = day.date;
|
|
1607
|
+
if (this.isRangeMode()) {
|
|
1608
|
+
this._handleRangeSelection(clickedDate);
|
|
1609
|
+
return;
|
|
1610
|
+
}
|
|
1611
|
+
this._handleSingleSelection(clickedDate);
|
|
1612
|
+
}
|
|
1613
|
+
onDayHover(day) {
|
|
1614
|
+
if (this.isRangeMode() && this._rangeStart() && !this._rangeEnd()) {
|
|
1615
|
+
this._hoveredDate.set(day.date);
|
|
1616
|
+
}
|
|
1617
|
+
}
|
|
1618
|
+
onDayLeave() {
|
|
1619
|
+
if (this.isRangeMode()) {
|
|
1620
|
+
this._hoveredDate.set(null);
|
|
1621
|
+
}
|
|
1622
|
+
}
|
|
1623
|
+
onMonthClick(monthIndex) {
|
|
1624
|
+
const currentDate = this._currentMonth();
|
|
1625
|
+
let newMonth = setMonth(currentDate, monthIndex);
|
|
1626
|
+
if (this.isRangeMode()) {
|
|
1627
|
+
const endMonth = this._endMonth();
|
|
1628
|
+
const isExceedingEnd = newMonth.getFullYear() > endMonth.getFullYear() ||
|
|
1629
|
+
(newMonth.getFullYear() === endMonth.getFullYear() && newMonth.getMonth() >= endMonth.getMonth());
|
|
1630
|
+
if (isExceedingEnd) {
|
|
1631
|
+
newMonth = addMonths(endMonth, -1);
|
|
1632
|
+
}
|
|
1633
|
+
}
|
|
1634
|
+
this._currentMonth.set(newMonth);
|
|
1635
|
+
this._hasViewChanged.set(true);
|
|
1636
|
+
this._currentView.set('day');
|
|
1637
|
+
}
|
|
1638
|
+
onYearClick(year) {
|
|
1639
|
+
const currentDate = this._currentMonth();
|
|
1640
|
+
if (this.isYearMode()) {
|
|
1641
|
+
this._selectedDate.set(setYear(new Date(year, 0, 1), year));
|
|
1642
|
+
this._dirty.set(true);
|
|
1643
|
+
this._applyValue();
|
|
1644
|
+
this.close();
|
|
1645
|
+
return;
|
|
1646
|
+
}
|
|
1647
|
+
let newYear = year;
|
|
1648
|
+
if (this.isRangeMode()) {
|
|
1649
|
+
const endYear = this._endMonth().getFullYear();
|
|
1650
|
+
if (newYear >= endYear) {
|
|
1651
|
+
newYear = endYear - 1;
|
|
1652
|
+
}
|
|
1653
|
+
}
|
|
1654
|
+
this._currentMonth.set(setYear(currentDate, newYear));
|
|
1655
|
+
this._hasViewChanged.set(true);
|
|
1656
|
+
this._currentView.set(this.isQuarterMode() ? 'quarter' : 'month');
|
|
1657
|
+
}
|
|
1658
|
+
onQuarterClick(quarterIndex) {
|
|
1659
|
+
const currentYear = this._currentMonth().getFullYear();
|
|
1660
|
+
const firstMonthOfQuarter = quarterIndex * 3;
|
|
1661
|
+
const date = new Date(currentYear, firstMonthOfQuarter, 1);
|
|
1662
|
+
this._selectedDate.set(date);
|
|
1663
|
+
this._dirty.set(true);
|
|
1664
|
+
this._applyValue();
|
|
1665
|
+
this.close();
|
|
1666
|
+
}
|
|
1667
|
+
onMonthSelect(monthIndex) {
|
|
1668
|
+
if (this.isMonthMode()) {
|
|
1669
|
+
const currentYear = this._currentMonth().getFullYear();
|
|
1670
|
+
this._selectedDate.set(new Date(currentYear, monthIndex, 1));
|
|
1671
|
+
this._dirty.set(true);
|
|
1672
|
+
this._applyValue();
|
|
1673
|
+
this.close();
|
|
1674
|
+
return;
|
|
1675
|
+
}
|
|
1676
|
+
this.onMonthClick(monthIndex);
|
|
1677
|
+
}
|
|
1678
|
+
onQuickSelect(preset) {
|
|
1679
|
+
this._activePresetKey.set(preset.key);
|
|
1680
|
+
if (preset.key === 'custom') {
|
|
1681
|
+
this._rangeStart.set(null);
|
|
1682
|
+
this._rangeEnd.set(null);
|
|
1683
|
+
this._inputDisplayStart.set('');
|
|
1684
|
+
this._inputDisplayEnd.set('');
|
|
1685
|
+
return;
|
|
1686
|
+
}
|
|
1687
|
+
const value = preset.getValue();
|
|
1688
|
+
if (!value) {
|
|
1689
|
+
return;
|
|
1690
|
+
}
|
|
1691
|
+
if (value instanceof Date) {
|
|
1692
|
+
this._rangeStart.set(value);
|
|
1693
|
+
this._rangeEnd.set(value);
|
|
1694
|
+
this._currentMonth.set(value);
|
|
1695
|
+
this._endMonth.set(addMonths(value, 1));
|
|
1696
|
+
this._dirty.set(true);
|
|
1697
|
+
this._inputDisplayStart.set(this.displayValueStart());
|
|
1698
|
+
this._inputDisplayEnd.set(this.displayValueEnd());
|
|
1699
|
+
return;
|
|
1700
|
+
}
|
|
1701
|
+
this._rangeStart.set(value.start);
|
|
1702
|
+
this._rangeEnd.set(value.end);
|
|
1703
|
+
const start = value.start ?? getToday();
|
|
1704
|
+
const end = value.end ?? getToday();
|
|
1705
|
+
this._currentMonth.set(start);
|
|
1706
|
+
this._endMonth.set(isSameMonth(start, end) ? addMonths(end, 1) : end);
|
|
1707
|
+
this._dirty.set(true);
|
|
1708
|
+
this._inputDisplayStart.set(this.displayValueStart());
|
|
1709
|
+
this._inputDisplayEnd.set(this.displayValueEnd());
|
|
1710
|
+
}
|
|
1711
|
+
onTodayClick() {
|
|
1712
|
+
const now = new Date();
|
|
1713
|
+
const today = getToday();
|
|
1714
|
+
this._currentMonth.set(today);
|
|
1715
|
+
if (this.zShowTime() || this.isTimeMode()) {
|
|
1716
|
+
this._hour.set(now.getHours());
|
|
1717
|
+
this._minute.set(now.getMinutes());
|
|
1718
|
+
this._second.set(now.getSeconds());
|
|
1719
|
+
this._period.set(now.getHours() >= 12 ? 'PM' : 'AM');
|
|
1720
|
+
}
|
|
1721
|
+
if (this.isMonthMode()) {
|
|
1722
|
+
this._selectedDate.set(new Date(now.getFullYear(), now.getMonth(), 1));
|
|
1723
|
+
this._dirty.set(true);
|
|
1724
|
+
this._applyValue();
|
|
1725
|
+
this.close();
|
|
1726
|
+
return;
|
|
1727
|
+
}
|
|
1728
|
+
if (this.isYearMode()) {
|
|
1729
|
+
this._selectedDate.set(new Date(now.getFullYear(), 0, 1));
|
|
1730
|
+
this._dirty.set(true);
|
|
1731
|
+
this._applyValue();
|
|
1732
|
+
this.close();
|
|
1733
|
+
return;
|
|
1734
|
+
}
|
|
1735
|
+
if (this.isQuarterMode()) {
|
|
1736
|
+
const currentQuarter = Math.floor(now.getMonth() / 3);
|
|
1737
|
+
this._selectedDate.set(new Date(now.getFullYear(), currentQuarter * 3, 1));
|
|
1738
|
+
this._dirty.set(true);
|
|
1739
|
+
this._applyValue();
|
|
1740
|
+
this.close();
|
|
1741
|
+
return;
|
|
1742
|
+
}
|
|
1743
|
+
if (this.isTimeMode()) {
|
|
1744
|
+
this._selectedDate.set(now);
|
|
1745
|
+
this._dirty.set(true);
|
|
1746
|
+
if (!this.showOkButton()) {
|
|
1747
|
+
this._applyValue();
|
|
1748
|
+
this.close();
|
|
1749
|
+
}
|
|
1750
|
+
return;
|
|
1751
|
+
}
|
|
1752
|
+
if (this.isRangeMode()) {
|
|
1753
|
+
const rangeDate = this.zShowTime() ? now : today;
|
|
1754
|
+
this._rangeStart.set(rangeDate);
|
|
1755
|
+
this._rangeEnd.set(rangeDate);
|
|
1756
|
+
this._endMonth.set(addMonths(today, 1));
|
|
1757
|
+
if (this.zShowTime()) {
|
|
1758
|
+
this._syncEndTimeSignals(now);
|
|
1759
|
+
}
|
|
1760
|
+
this._dirty.set(true);
|
|
1761
|
+
this._inputDisplayStart.set(this.displayValueStart());
|
|
1762
|
+
this._inputDisplayEnd.set(this.displayValueEnd());
|
|
1763
|
+
if (!this.showOkButton() && !this.showCancelButton()) {
|
|
1764
|
+
this._applyValue();
|
|
1765
|
+
this.close();
|
|
1766
|
+
}
|
|
1767
|
+
return;
|
|
1768
|
+
}
|
|
1769
|
+
const selectedDate = this.zShowTime() ? now : today;
|
|
1770
|
+
this._selectedDate.set(selectedDate);
|
|
1771
|
+
this._dirty.set(true);
|
|
1772
|
+
if (!this.showOkButton()) {
|
|
1773
|
+
this._applyValue();
|
|
1774
|
+
this.close();
|
|
1775
|
+
}
|
|
1776
|
+
}
|
|
1777
|
+
onClear(event) {
|
|
1778
|
+
event.stopPropagation();
|
|
1779
|
+
event.preventDefault();
|
|
1780
|
+
this._selectedDate.set(null);
|
|
1781
|
+
this._rangeStart.set(null);
|
|
1782
|
+
this._rangeEnd.set(null);
|
|
1783
|
+
this._hour.set(0);
|
|
1784
|
+
this._minute.set(0);
|
|
1785
|
+
this._second.set(0);
|
|
1786
|
+
this._dirty.set(true);
|
|
1787
|
+
this._backupSelectedDate.set(null);
|
|
1788
|
+
this._backupRangeStart.set(null);
|
|
1789
|
+
this._backupRangeEnd.set(null);
|
|
1790
|
+
this._appliedViaOk.set(true);
|
|
1791
|
+
const emitValue = this._getEmitValue();
|
|
1792
|
+
this._onChange(emitValue);
|
|
1793
|
+
this.zChange.emit(emitValue);
|
|
1794
|
+
this._inputDisplayValue.set('');
|
|
1795
|
+
if (this.isRangeMode()) {
|
|
1796
|
+
this._inputDisplayStart.set('');
|
|
1797
|
+
this._inputDisplayEnd.set('');
|
|
1798
|
+
}
|
|
1799
|
+
this.close();
|
|
1800
|
+
}
|
|
1801
|
+
onCancelClick() {
|
|
1802
|
+
this.close();
|
|
1803
|
+
}
|
|
1804
|
+
onOkClick() {
|
|
1805
|
+
if (!this.canApply()) {
|
|
1806
|
+
return;
|
|
1807
|
+
}
|
|
1808
|
+
if (this.isTimeMode()) {
|
|
1809
|
+
let hour = this._hour();
|
|
1810
|
+
if (this.zTimeFormat() === '12h') {
|
|
1811
|
+
if (this._period() === 'PM' && hour < 12) {
|
|
1812
|
+
hour += 12;
|
|
1813
|
+
}
|
|
1814
|
+
if (this._period() === 'AM' && hour === 12) {
|
|
1815
|
+
hour = 0;
|
|
1816
|
+
}
|
|
1817
|
+
}
|
|
1818
|
+
const baseDate = this._selectedDate() ?? new Date();
|
|
1819
|
+
this._selectedDate.set(setTime(baseDate, hour, this._minute(), this._second()));
|
|
1820
|
+
}
|
|
1821
|
+
this._appliedViaOk.set(true);
|
|
1822
|
+
this._applyValue();
|
|
1823
|
+
this.close();
|
|
1824
|
+
}
|
|
1825
|
+
navigatePrevious() {
|
|
1826
|
+
const view = this._currentView();
|
|
1827
|
+
const current = this._currentMonth();
|
|
1828
|
+
const yearStep = this.isYearMode() || this.isQuarterMode() ? 9 : 12;
|
|
1829
|
+
const navigationMap = {
|
|
1830
|
+
day: addMonths(current, -1),
|
|
1831
|
+
month: addYears(current, -1),
|
|
1832
|
+
year: addYears(current, -yearStep),
|
|
1833
|
+
quarter: addYears(current, -1),
|
|
1834
|
+
};
|
|
1835
|
+
this._currentMonth.set(navigationMap[view]);
|
|
1836
|
+
}
|
|
1837
|
+
navigateNext() {
|
|
1838
|
+
const view = this._currentView();
|
|
1839
|
+
const current = this._currentMonth();
|
|
1840
|
+
const yearStep = this.isYearMode() || this.isQuarterMode() ? 9 : 12;
|
|
1841
|
+
const navigationMap = {
|
|
1842
|
+
day: addMonths(current, 1),
|
|
1843
|
+
month: addYears(current, 1),
|
|
1844
|
+
year: addYears(current, yearStep),
|
|
1845
|
+
quarter: addYears(current, 1),
|
|
1846
|
+
};
|
|
1847
|
+
this._currentMonth.set(navigationMap[view]);
|
|
1848
|
+
}
|
|
1849
|
+
navigatePreviousFast() {
|
|
1850
|
+
const current = this._currentMonth();
|
|
1851
|
+
this._currentMonth.set(addYears(current, -1));
|
|
1852
|
+
}
|
|
1853
|
+
navigateNextFast() {
|
|
1854
|
+
const current = this._currentMonth();
|
|
1855
|
+
this._currentMonth.set(addYears(current, 1));
|
|
1856
|
+
}
|
|
1857
|
+
setView(view) {
|
|
1858
|
+
this._hasViewChanged.set(true);
|
|
1859
|
+
this._currentView.set(view);
|
|
1860
|
+
}
|
|
1861
|
+
setEndView(view) {
|
|
1862
|
+
this._hasEndViewChanged.set(true);
|
|
1863
|
+
this._endView.set(view);
|
|
1864
|
+
}
|
|
1865
|
+
onEndMonthClick(monthIndex) {
|
|
1866
|
+
const currentDate = this._endMonth();
|
|
1867
|
+
let newMonth = setMonth(currentDate, monthIndex);
|
|
1868
|
+
const startMonth = this._currentMonth();
|
|
1869
|
+
const isBeforeStart = newMonth.getFullYear() < startMonth.getFullYear() ||
|
|
1870
|
+
(newMonth.getFullYear() === startMonth.getFullYear() && newMonth.getMonth() <= startMonth.getMonth());
|
|
1871
|
+
if (isBeforeStart) {
|
|
1872
|
+
newMonth = addMonths(startMonth, 1);
|
|
1873
|
+
}
|
|
1874
|
+
this._endMonth.set(newMonth);
|
|
1875
|
+
this._hasEndViewChanged.set(true);
|
|
1876
|
+
this._endView.set('day');
|
|
1877
|
+
}
|
|
1878
|
+
onEndYearClick(year) {
|
|
1879
|
+
const currentDate = this._endMonth();
|
|
1880
|
+
let newYear = year;
|
|
1881
|
+
const startYear = this._currentMonth().getFullYear();
|
|
1882
|
+
if (newYear <= startYear) {
|
|
1883
|
+
newYear = startYear + 1;
|
|
1884
|
+
}
|
|
1885
|
+
this._endMonth.set(setYear(currentDate, newYear));
|
|
1886
|
+
this._hasEndViewChanged.set(true);
|
|
1887
|
+
this._endView.set('month');
|
|
1888
|
+
}
|
|
1889
|
+
onHourInput(event) {
|
|
1890
|
+
const input = event.target;
|
|
1891
|
+
const digits = input.value.replace(/\D/g, '');
|
|
1892
|
+
if (digits.length !== 2) {
|
|
1893
|
+
return;
|
|
1894
|
+
}
|
|
1895
|
+
const value = parseTimeValue(digits, 23);
|
|
1896
|
+
this._hour.set(value);
|
|
1897
|
+
this._updateTimeToDate();
|
|
1898
|
+
}
|
|
1899
|
+
onMinuteInput(event) {
|
|
1900
|
+
const input = event.target;
|
|
1901
|
+
const digits = input.value.replace(/\D/g, '');
|
|
1902
|
+
if (digits.length !== 2) {
|
|
1903
|
+
return;
|
|
1904
|
+
}
|
|
1905
|
+
const value = parseTimeValue(digits, 59);
|
|
1906
|
+
this._minute.set(value);
|
|
1907
|
+
this._updateTimeToDate();
|
|
1908
|
+
}
|
|
1909
|
+
onSecondInput(event) {
|
|
1910
|
+
const input = event.target;
|
|
1911
|
+
const digits = input.value.replace(/\D/g, '');
|
|
1912
|
+
if (digits.length !== 2) {
|
|
1913
|
+
return;
|
|
1914
|
+
}
|
|
1915
|
+
const value = parseTimeValue(digits, 59);
|
|
1916
|
+
this._second.set(value);
|
|
1917
|
+
this._updateTimeToDate();
|
|
1918
|
+
}
|
|
1919
|
+
onTimeBlur(event) {
|
|
1920
|
+
const input = event.target;
|
|
1921
|
+
const dataType = input.getAttribute('data-time-type');
|
|
1922
|
+
if (dataType === 'hour') {
|
|
1923
|
+
input.value = this.formattedHour();
|
|
1924
|
+
}
|
|
1925
|
+
if (dataType === 'minute') {
|
|
1926
|
+
input.value = this.formattedMinute();
|
|
1927
|
+
}
|
|
1928
|
+
if (dataType === 'second') {
|
|
1929
|
+
input.value = this.formattedSecond();
|
|
1930
|
+
}
|
|
1931
|
+
}
|
|
1932
|
+
navigateEndPrevious() {
|
|
1933
|
+
const current = this._endMonth();
|
|
1934
|
+
this._endMonth.set(addMonths(current, -1));
|
|
1935
|
+
}
|
|
1936
|
+
navigateEndNext() {
|
|
1937
|
+
const current = this._endMonth();
|
|
1938
|
+
this._endMonth.set(addMonths(current, 1));
|
|
1939
|
+
}
|
|
1940
|
+
navigateEndPreviousFast() {
|
|
1941
|
+
const current = this._endMonth();
|
|
1942
|
+
this._endMonth.set(addYears(current, -1));
|
|
1943
|
+
}
|
|
1944
|
+
navigateEndNextFast() {
|
|
1945
|
+
const current = this._endMonth();
|
|
1946
|
+
this._endMonth.set(addYears(current, 1));
|
|
1947
|
+
}
|
|
1948
|
+
onHourEndInput(event) {
|
|
1949
|
+
const input = event.target;
|
|
1950
|
+
const digits = input.value.replace(/\D/g, '');
|
|
1951
|
+
if (digits.length !== 2) {
|
|
1952
|
+
return;
|
|
1953
|
+
}
|
|
1954
|
+
const value = parseTimeValue(digits, 23);
|
|
1955
|
+
this._hourEnd.set(value);
|
|
1956
|
+
this._updateEndTimeToDate();
|
|
1957
|
+
}
|
|
1958
|
+
onMinuteEndInput(event) {
|
|
1959
|
+
const input = event.target;
|
|
1960
|
+
const digits = input.value.replace(/\D/g, '');
|
|
1961
|
+
if (digits.length !== 2) {
|
|
1962
|
+
return;
|
|
1963
|
+
}
|
|
1964
|
+
const value = parseTimeValue(digits, 59);
|
|
1965
|
+
this._minuteEnd.set(value);
|
|
1966
|
+
this._updateEndTimeToDate();
|
|
1967
|
+
}
|
|
1968
|
+
onSecondEndInput(event) {
|
|
1969
|
+
const input = event.target;
|
|
1970
|
+
const digits = input.value.replace(/\D/g, '');
|
|
1971
|
+
if (digits.length !== 2) {
|
|
1972
|
+
return;
|
|
1973
|
+
}
|
|
1974
|
+
const value = parseTimeValue(digits, 59);
|
|
1975
|
+
this._secondEnd.set(value);
|
|
1976
|
+
this._updateEndTimeToDate();
|
|
1977
|
+
}
|
|
1978
|
+
onTimeBlurEnd(event) {
|
|
1979
|
+
const input = event.target;
|
|
1980
|
+
const dataType = input.getAttribute('data-time-type');
|
|
1981
|
+
if (dataType === 'hour-end') {
|
|
1982
|
+
input.value = this.formattedHourEnd();
|
|
1983
|
+
}
|
|
1984
|
+
if (dataType === 'minute-end') {
|
|
1985
|
+
input.value = this.formattedMinuteEnd();
|
|
1986
|
+
}
|
|
1987
|
+
if (dataType === 'second-end') {
|
|
1988
|
+
input.value = this.formattedSecondEnd();
|
|
1989
|
+
}
|
|
1990
|
+
}
|
|
1991
|
+
togglePeriodEnd() {
|
|
1992
|
+
const currentPeriod = this._periodEnd();
|
|
1993
|
+
const newPeriod = currentPeriod === 'AM' ? 'PM' : 'AM';
|
|
1994
|
+
this._periodEnd.set(newPeriod);
|
|
1995
|
+
const currentHour = this._hourEnd();
|
|
1996
|
+
if (newPeriod === 'PM' && currentHour < 12) {
|
|
1997
|
+
this._hourEnd.set(currentHour + 12);
|
|
1998
|
+
}
|
|
1999
|
+
if (newPeriod === 'AM' && currentHour >= 12) {
|
|
2000
|
+
this._hourEnd.set(currentHour - 12);
|
|
2001
|
+
}
|
|
2002
|
+
this._updateEndTimeToDate();
|
|
2003
|
+
}
|
|
2004
|
+
_updateEndTimeToDate() {
|
|
2005
|
+
const end = this._rangeEnd();
|
|
2006
|
+
if (!end) {
|
|
2007
|
+
return;
|
|
2008
|
+
}
|
|
2009
|
+
let hour = this._hourEnd();
|
|
2010
|
+
if (this.zTimeFormat() === '12h') {
|
|
2011
|
+
if (this._periodEnd() === 'PM' && hour < 12) {
|
|
2012
|
+
hour += 12;
|
|
2013
|
+
}
|
|
2014
|
+
if (this._periodEnd() === 'AM' && hour === 12) {
|
|
2015
|
+
hour = 0;
|
|
2016
|
+
}
|
|
2017
|
+
}
|
|
2018
|
+
const newDate = setTime(end, hour, this._minuteEnd(), this._secondEnd());
|
|
2019
|
+
this._rangeEnd.set(newDate);
|
|
2020
|
+
this._dirty.set(true);
|
|
2021
|
+
}
|
|
2022
|
+
_handleSingleSelection(date) {
|
|
2023
|
+
let finalDate = date;
|
|
2024
|
+
if (this.zShowTime()) {
|
|
2025
|
+
finalDate = setTime(date, this._hour(), this._minute(), this._second());
|
|
2026
|
+
}
|
|
2027
|
+
this._selectedDate.set(finalDate);
|
|
2028
|
+
this._dirty.set(true);
|
|
2029
|
+
this._inputDisplayValue.set(this.displayValue());
|
|
2030
|
+
if (!this.zShowTime() && !this.zShowOk()) {
|
|
2031
|
+
this._applyValue();
|
|
2032
|
+
this.close();
|
|
2033
|
+
}
|
|
2034
|
+
}
|
|
2035
|
+
_handleRangeSelection(date) {
|
|
2036
|
+
const start = this._rangeStart();
|
|
2037
|
+
const end = this._rangeEnd();
|
|
2038
|
+
if (!start || (start && end)) {
|
|
2039
|
+
let startDate = date;
|
|
2040
|
+
if (this.zShowTime()) {
|
|
2041
|
+
let hour = this._hour();
|
|
2042
|
+
if (this.zTimeFormat() === '12h') {
|
|
2043
|
+
if (this._period() === 'PM' && hour < 12) {
|
|
2044
|
+
hour += 12;
|
|
2045
|
+
}
|
|
2046
|
+
if (this._period() === 'AM' && hour === 12) {
|
|
2047
|
+
hour = 0;
|
|
2048
|
+
}
|
|
2049
|
+
}
|
|
2050
|
+
startDate = setTime(date, hour, this._minute(), this._second());
|
|
2051
|
+
}
|
|
2052
|
+
this._rangeStart.set(startDate);
|
|
2053
|
+
this._rangeEnd.set(null);
|
|
2054
|
+
this._activePresetKey.set('custom');
|
|
2055
|
+
this._inputDisplayStart.set(this.displayValueStart());
|
|
2056
|
+
this._inputDisplayEnd.set('');
|
|
2057
|
+
return;
|
|
2058
|
+
}
|
|
2059
|
+
let endDate = date;
|
|
2060
|
+
if (this.zShowTime()) {
|
|
2061
|
+
let hour = this._hourEnd();
|
|
2062
|
+
if (this.zTimeFormat() === '12h') {
|
|
2063
|
+
if (this._periodEnd() === 'PM' && hour < 12) {
|
|
2064
|
+
hour += 12;
|
|
2065
|
+
}
|
|
2066
|
+
if (this._periodEnd() === 'AM' && hour === 12) {
|
|
2067
|
+
hour = 0;
|
|
2068
|
+
}
|
|
2069
|
+
}
|
|
2070
|
+
endDate = setTime(date, hour, this._minuteEnd(), this._secondEnd());
|
|
2071
|
+
}
|
|
2072
|
+
const normalized = normalizeRange(start, endDate);
|
|
2073
|
+
this._rangeStart.set(normalized.start);
|
|
2074
|
+
this._rangeEnd.set(normalized.end);
|
|
2075
|
+
this._dirty.set(true);
|
|
2076
|
+
this._inputDisplayStart.set(this.displayValueStart());
|
|
2077
|
+
this._inputDisplayEnd.set(this.displayValueEnd());
|
|
2078
|
+
if (normalized.start && normalized.end) {
|
|
2079
|
+
this._activePresetKey.set(this._detectMatchingPreset(normalized.start, normalized.end));
|
|
2080
|
+
}
|
|
2081
|
+
if (!this.showOkButton() && !this.showCancelButton()) {
|
|
2082
|
+
this._applyValue();
|
|
2083
|
+
this.close();
|
|
2084
|
+
}
|
|
2085
|
+
}
|
|
2086
|
+
_updateTimeToDate() {
|
|
2087
|
+
if (!this.zShowTime()) {
|
|
2088
|
+
return;
|
|
2089
|
+
}
|
|
2090
|
+
let hour = this._hour();
|
|
2091
|
+
if (this.zTimeFormat() === '12h') {
|
|
2092
|
+
if (this._period() === 'PM' && hour < 12) {
|
|
2093
|
+
hour += 12;
|
|
2094
|
+
}
|
|
2095
|
+
if (this._period() === 'AM' && hour === 12) {
|
|
2096
|
+
hour = 0;
|
|
2097
|
+
}
|
|
2098
|
+
}
|
|
2099
|
+
if (this.isRangeMode()) {
|
|
2100
|
+
const start = this._rangeStart();
|
|
2101
|
+
if (start) {
|
|
2102
|
+
this._rangeStart.set(setTime(start, hour, this._minute(), this._second()));
|
|
2103
|
+
this._dirty.set(true);
|
|
2104
|
+
}
|
|
2105
|
+
return;
|
|
2106
|
+
}
|
|
2107
|
+
const selected = this._selectedDate();
|
|
2108
|
+
if (selected) {
|
|
2109
|
+
this._selectedDate.set(setTime(selected, hour, this._minute(), this._second()));
|
|
2110
|
+
}
|
|
2111
|
+
}
|
|
2112
|
+
_detectMatchingPreset(start, end) {
|
|
2113
|
+
for (const preset of this.quickSelectPresets) {
|
|
2114
|
+
if (preset.key === 'custom') {
|
|
2115
|
+
continue;
|
|
2116
|
+
}
|
|
2117
|
+
const value = preset.getValue();
|
|
2118
|
+
if (value && !(value instanceof Date)) {
|
|
2119
|
+
if (value.start && value.end && isSameDay(start, value.start) && isSameDay(end, value.end)) {
|
|
2120
|
+
return preset.key;
|
|
2121
|
+
}
|
|
2122
|
+
}
|
|
2123
|
+
}
|
|
2124
|
+
return 'custom';
|
|
2125
|
+
}
|
|
2126
|
+
_applyValue() {
|
|
2127
|
+
const emitValue = this._getEmitValue();
|
|
2128
|
+
this._onChange(emitValue);
|
|
2129
|
+
this.zChange.emit(emitValue);
|
|
2130
|
+
this._dirty.set(true);
|
|
2131
|
+
this._inputDisplayValue.set(this.displayValue());
|
|
2132
|
+
if (this.isRangeMode()) {
|
|
2133
|
+
this._inputDisplayStart.set(this.displayValueStart());
|
|
2134
|
+
this._inputDisplayEnd.set(this.displayValueEnd());
|
|
2135
|
+
}
|
|
2136
|
+
}
|
|
2137
|
+
_getEmitValue() {
|
|
2138
|
+
const valueType = this.zValueType();
|
|
2139
|
+
const format = this.zShowTime() ? `${this.zFormat()} HH:mm:ss` : this.zFormat();
|
|
2140
|
+
if (this.isRangeMode()) {
|
|
2141
|
+
const start = this._rangeStart();
|
|
2142
|
+
const end = this._rangeEnd();
|
|
2143
|
+
if (!start || !end) {
|
|
2144
|
+
return null;
|
|
2145
|
+
}
|
|
2146
|
+
if (valueType === 'iso') {
|
|
2147
|
+
return { start: toISOString(start), end: toISOString(end) };
|
|
2148
|
+
}
|
|
2149
|
+
if (valueType === 'string') {
|
|
2150
|
+
return { start: formatDate(start, format), end: formatDate(end, format) };
|
|
2151
|
+
}
|
|
2152
|
+
return { start, end };
|
|
2153
|
+
}
|
|
2154
|
+
const date = this._selectedDate();
|
|
2155
|
+
if (!date) {
|
|
2156
|
+
return null;
|
|
2157
|
+
}
|
|
2158
|
+
if (valueType === 'iso') {
|
|
2159
|
+
return toISOString(date);
|
|
2160
|
+
}
|
|
2161
|
+
if (valueType === 'string') {
|
|
2162
|
+
return formatDate(date, format);
|
|
2163
|
+
}
|
|
2164
|
+
return date;
|
|
2165
|
+
}
|
|
2166
|
+
_getValidationErrors() {
|
|
2167
|
+
const validators = this.zValidators();
|
|
2168
|
+
const errors = [];
|
|
2169
|
+
if (!this._shouldShowValidation()) {
|
|
2170
|
+
return errors;
|
|
2171
|
+
}
|
|
2172
|
+
const isRequired = this.zRequired() || this._formControl()?.errors?.['required'];
|
|
2173
|
+
if (isRequired) {
|
|
2174
|
+
const hasValidValue = this.isRangeMode() ? !!(this._rangeStart() && this._rangeEnd()) : !!this._selectedDate();
|
|
2175
|
+
if (!hasValidValue) {
|
|
2176
|
+
errors.push('Vui lòng chọn ngày');
|
|
2177
|
+
}
|
|
2178
|
+
}
|
|
2179
|
+
const value = this._getEmitValue();
|
|
2180
|
+
for (const validator of validators) {
|
|
2181
|
+
if (!validator.validate(value)) {
|
|
2182
|
+
errors.push(validator.message);
|
|
2183
|
+
}
|
|
2184
|
+
}
|
|
2185
|
+
return errors;
|
|
2186
|
+
}
|
|
2187
|
+
_navigateByArrowKey(key) {
|
|
2188
|
+
const currentDate = this._selectedDate() ?? getToday();
|
|
2189
|
+
let newDate;
|
|
2190
|
+
switch (key) {
|
|
2191
|
+
case 'ArrowUp':
|
|
2192
|
+
newDate = addDays(currentDate, -7);
|
|
2193
|
+
break;
|
|
2194
|
+
case 'ArrowDown':
|
|
2195
|
+
newDate = addDays(currentDate, 7);
|
|
2196
|
+
break;
|
|
2197
|
+
case 'ArrowLeft':
|
|
2198
|
+
newDate = addDays(currentDate, -1);
|
|
2199
|
+
break;
|
|
2200
|
+
case 'ArrowRight':
|
|
2201
|
+
newDate = addDays(currentDate, 1);
|
|
2202
|
+
break;
|
|
2203
|
+
default:
|
|
2204
|
+
return;
|
|
2205
|
+
}
|
|
2206
|
+
const minDate = this.zMinDate();
|
|
2207
|
+
const maxDate = this.zMaxDate();
|
|
2208
|
+
if (minDate && newDate < minDate) {
|
|
2209
|
+
return;
|
|
2210
|
+
}
|
|
2211
|
+
if (maxDate && newDate > maxDate) {
|
|
2212
|
+
return;
|
|
2213
|
+
}
|
|
2214
|
+
this._selectedDate.set(newDate);
|
|
2215
|
+
if (!isSameMonth(newDate, this._currentMonth())) {
|
|
2216
|
+
this._currentMonth.set(newDate);
|
|
2217
|
+
}
|
|
2218
|
+
}
|
|
2219
|
+
_syncTimeSignals(date) {
|
|
2220
|
+
this._hour.set(date.getHours());
|
|
2221
|
+
this._minute.set(date.getMinutes());
|
|
2222
|
+
this._second.set(date.getSeconds());
|
|
2223
|
+
this._period.set(date.getHours() >= 12 ? 'PM' : 'AM');
|
|
2224
|
+
}
|
|
2225
|
+
_getParseFormat() {
|
|
2226
|
+
if (!this.zShowTime() && !this.isTimeMode()) {
|
|
2227
|
+
return this.zFormat();
|
|
2228
|
+
}
|
|
2229
|
+
const timeParts = [];
|
|
2230
|
+
if (this.zShowHour()) {
|
|
2231
|
+
timeParts.push(this.zTimeFormat() === '12h' ? 'hh' : 'HH');
|
|
2232
|
+
}
|
|
2233
|
+
if (this.zShowMinute()) {
|
|
2234
|
+
timeParts.push('mm');
|
|
2235
|
+
}
|
|
2236
|
+
if (this.zShowSecond()) {
|
|
2237
|
+
timeParts.push('ss');
|
|
2238
|
+
}
|
|
2239
|
+
const timeFormat = timeParts.join(':');
|
|
2240
|
+
if (this.isTimeMode()) {
|
|
2241
|
+
return timeFormat;
|
|
2242
|
+
}
|
|
2243
|
+
return `${this.zFormat()} ${timeFormat}`;
|
|
2244
|
+
}
|
|
2245
|
+
_updateInputDisplay() {
|
|
2246
|
+
this._inputDisplayValue.set(this.displayValue());
|
|
2247
|
+
}
|
|
2248
|
+
_clearDateValues() {
|
|
2249
|
+
if (this.isRangeMode()) {
|
|
2250
|
+
this._rangeStart.set(null);
|
|
2251
|
+
this._rangeEnd.set(null);
|
|
2252
|
+
return;
|
|
2253
|
+
}
|
|
2254
|
+
this._selectedDate.set(null);
|
|
2255
|
+
}
|
|
2256
|
+
_emitControl() {
|
|
2257
|
+
this.zControl.emit({
|
|
2258
|
+
validate: () => this.validate(),
|
|
2259
|
+
reset: () => this.reset(),
|
|
2260
|
+
focus: () => this.focus(),
|
|
2261
|
+
blur: () => this.blur(),
|
|
2262
|
+
open: () => this.open(),
|
|
2263
|
+
close: () => this.close(),
|
|
2264
|
+
clear: () => this.clear(),
|
|
2265
|
+
markAsTouched: () => this.markAsTouched(),
|
|
2266
|
+
markAsUntouched: () => this.markAsUntouched(),
|
|
2267
|
+
markAsDirty: () => this.markAsDirty(),
|
|
2268
|
+
markAsPristine: () => this.markAsPristine(),
|
|
2269
|
+
hasError: this.hasError,
|
|
2270
|
+
isOpen: this.isOpen,
|
|
2271
|
+
value: computed(() => this._getEmitValue()),
|
|
2272
|
+
errorMessage: this.errorMessage,
|
|
2273
|
+
});
|
|
2274
|
+
}
|
|
2275
|
+
togglePeriod() {
|
|
2276
|
+
const currentPeriod = this._period();
|
|
2277
|
+
const newPeriod = currentPeriod === 'AM' ? 'PM' : 'AM';
|
|
2278
|
+
this._period.set(newPeriod);
|
|
2279
|
+
const currentHour = this._hour();
|
|
2280
|
+
if (newPeriod === 'PM' && currentHour < 12) {
|
|
2281
|
+
this._hour.set(currentHour + 12);
|
|
2282
|
+
}
|
|
2283
|
+
if (newPeriod === 'AM' && currentHour >= 12) {
|
|
2284
|
+
this._hour.set(currentHour - 12);
|
|
2285
|
+
}
|
|
2286
|
+
this._updateTimeToDate();
|
|
2287
|
+
}
|
|
2288
|
+
onPeriodChange(event) {
|
|
2289
|
+
const select = event.target;
|
|
2290
|
+
const newPeriod = select.value;
|
|
2291
|
+
const currentHour = this._hour();
|
|
2292
|
+
this._period.set(newPeriod);
|
|
2293
|
+
if (newPeriod === 'PM' && currentHour < 12) {
|
|
2294
|
+
this._hour.set(currentHour + 12);
|
|
2295
|
+
}
|
|
2296
|
+
if (newPeriod === 'AM' && currentHour >= 12) {
|
|
2297
|
+
this._hour.set(currentHour - 12);
|
|
2298
|
+
}
|
|
2299
|
+
this._updateTimeToDate();
|
|
2300
|
+
}
|
|
2301
|
+
static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "21.0.6", ngImport: i0, type: ZCalendarComponent, deps: [], target: i0.ɵɵFactoryTarget.Component });
|
|
2302
|
+
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 } }, outputs: { zControl: "zControl", zChange: "zChange" }, providers: [
|
|
2303
|
+
{
|
|
2304
|
+
provide: NG_VALUE_ACCESSOR,
|
|
2305
|
+
useExisting: forwardRef(() => ZCalendarComponent),
|
|
2306
|
+
multi: true,
|
|
2307
|
+
},
|
|
2308
|
+
], 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 w-fit\">\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 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=\"T\u1EEB ng\u00E0y\"\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 <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=\"\u0110\u1EBFn ng\u00E0y\"\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 } @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 }\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 rounded-[6px] border shadow-lg\"\n (keydown)=\"onCalendarKeydown($event)\">\n @if (zQuickSelect() && zMode() === 'range') {\n <div class=\"border-border flex flex-col space-y-1 border-r p-2\">\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-col gap-2 p-3\">\n @if (!isTimeMode()) {\n <div class=\"z-calendars-wrapper flex gap-4\">\n <!-- First Calendar -->\n <div class=\"z-calendar-section flex flex-col justify-center 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\n <!-- Start Time Picker for Range Mode -->\n @if (isRangeMode() && zShowTime() && currentView() === 'day') {\n <div class=\"flex items-center justify-center gap-2 pt-2\">\n <span class=\"text-muted-foreground text-xs\">B\u1EAFt \u0111\u1EA7u:</span>\n <div class=\"flex items-center gap-0.5\">\n @if (zShowHour()) {\n <input\n type=\"text\"\n tabindex=\"0\"\n inputmode=\"numeric\"\n data-time-type=\"hour\"\n class=\"border-input bg-background focus:border-ring focus:ring-ring/30 w-10 rounded border px-1.5 py-1 text-center text-sm outline-none focus:ring-2\"\n [value]=\"formattedHour()\"\n (input)=\"onHourInput($event)\"\n (blur)=\"onTimeBlur($event)\"\n maxlength=\"2\" />\n }\n @if (zShowHour() && zShowMinute()) {\n <span class=\"text-muted-foreground\">:</span>\n }\n @if (zShowMinute()) {\n <input\n type=\"text\"\n tabindex=\"0\"\n inputmode=\"numeric\"\n data-time-type=\"minute\"\n class=\"border-input bg-background focus:border-ring focus:ring-ring/30 w-10 rounded border px-1.5 py-1 text-center text-sm outline-none focus:ring-2\"\n [value]=\"formattedMinute()\"\n (input)=\"onMinuteInput($event)\"\n (blur)=\"onTimeBlur($event)\"\n maxlength=\"2\" />\n }\n @if (zShowMinute() && zShowSecond()) {\n <span class=\"text-muted-foreground\">:</span>\n }\n @if (zShowSecond()) {\n <input\n type=\"text\"\n tabindex=\"0\"\n inputmode=\"numeric\"\n data-time-type=\"second\"\n class=\"border-input bg-background focus:border-ring focus:ring-ring/30 w-10 rounded border px-1.5 py-1 text-center text-sm outline-none focus:ring-2\"\n [value]=\"formattedSecond()\"\n (input)=\"onSecondInput($event)\"\n (blur)=\"onTimeBlur($event)\"\n maxlength=\"2\" />\n }\n @if (zTimeFormat() === '12h') {\n <button\n type=\"button\"\n tabindex=\"0\"\n class=\"border-input bg-background hover:bg-muted focus:border-ring focus:ring-ring/30 ml-1 cursor-pointer rounded border px-2 py-1 text-sm font-medium transition-colors outline-none focus:ring-2\"\n (click)=\"togglePeriod()\">\n {{ period() }}\n </button>\n }\n </div>\n </div>\n }\n </div>\n\n <!-- Second Calendar (Range Mode Only) -->\n @if (isRangeMode()) {\n <!-- Divider -->\n <div class=\"border-border bg-border w-px self-stretch\"></div>\n\n <div class=\"z-calendar-section flex flex-col justify-center 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\n <!-- End Time Picker for Range Mode -->\n @if (zShowTime()) {\n <div class=\"flex items-center justify-center gap-2 pt-2\">\n <span class=\"text-muted-foreground text-xs\">K\u1EBFt th\u00FAc:</span>\n <div class=\"flex items-center gap-0.5\">\n @if (zShowHour()) {\n <input\n type=\"text\"\n tabindex=\"0\"\n inputmode=\"numeric\"\n data-time-type=\"hour-end\"\n class=\"border-input bg-background focus:border-ring focus:ring-ring/30 w-10 rounded border px-1.5 py-1 text-center text-sm outline-none focus:ring-2\"\n [value]=\"formattedHourEnd()\"\n (input)=\"onHourEndInput($event)\"\n (blur)=\"onTimeBlurEnd($event)\"\n maxlength=\"2\" />\n }\n @if (zShowHour() && zShowMinute()) {\n <span class=\"text-muted-foreground\">:</span>\n }\n @if (zShowMinute()) {\n <input\n type=\"text\"\n tabindex=\"0\"\n inputmode=\"numeric\"\n data-time-type=\"minute-end\"\n class=\"border-input bg-background focus:border-ring focus:ring-ring/30 w-10 rounded border px-1.5 py-1 text-center text-sm outline-none focus:ring-2\"\n [value]=\"formattedMinuteEnd()\"\n (input)=\"onMinuteEndInput($event)\"\n (blur)=\"onTimeBlurEnd($event)\"\n maxlength=\"2\" />\n }\n @if (zShowMinute() && zShowSecond()) {\n <span class=\"text-muted-foreground\">:</span>\n }\n @if (zShowSecond()) {\n <input\n type=\"text\"\n tabindex=\"0\"\n inputmode=\"numeric\"\n data-time-type=\"second-end\"\n class=\"border-input bg-background focus:border-ring focus:ring-ring/30 w-10 rounded border px-1.5 py-1 text-center text-sm outline-none focus:ring-2\"\n [value]=\"formattedSecondEnd()\"\n (input)=\"onSecondEndInput($event)\"\n (blur)=\"onTimeBlurEnd($event)\"\n maxlength=\"2\" />\n }\n @if (zTimeFormat() === '12h') {\n <button\n type=\"button\"\n tabindex=\"0\"\n class=\"border-input bg-background hover:bg-muted focus:border-ring focus:ring-ring/30 ml-1 cursor-pointer rounded border px-2 py-1 text-sm font-medium transition-colors outline-none focus:ring-2\"\n (click)=\"togglePeriodEnd()\">\n {{ periodEnd() }}\n </button>\n }\n </div>\n </div>\n }\n </div>\n }\n </div>\n }\n\n @if (((zShowTime() && currentView() === 'day') || isTimeMode()) && !isRangeMode()) {\n <div class=\"flex items-center justify-center gap-2\">\n <div class=\"flex items-center gap-0.5\">\n @if (zShowHour()) {\n <input\n type=\"text\"\n tabindex=\"0\"\n inputmode=\"numeric\"\n data-time-type=\"hour\"\n class=\"border-input bg-background focus:border-ring focus:ring-ring/30 w-10 rounded border px-1.5 py-1 text-center text-sm outline-none focus:ring-2\"\n [value]=\"formattedHour()\"\n (input)=\"onHourInput($event)\"\n (blur)=\"onTimeBlur($event)\"\n maxlength=\"2\" />\n }\n\n @if (zShowHour() && zShowMinute()) {\n <span class=\"text-muted-foreground\">:</span>\n }\n\n @if (zShowMinute()) {\n <input\n type=\"text\"\n tabindex=\"0\"\n inputmode=\"numeric\"\n data-time-type=\"minute\"\n class=\"border-input bg-background focus:border-ring focus:ring-ring/30 w-10 rounded border px-1.5 py-1 text-center text-sm outline-none focus:ring-2\"\n [value]=\"formattedMinute()\"\n (input)=\"onMinuteInput($event)\"\n (blur)=\"onTimeBlur($event)\"\n maxlength=\"2\" />\n }\n\n @if (zShowMinute() && zShowSecond()) {\n <span class=\"text-muted-foreground\">:</span>\n }\n\n @if (zShowSecond()) {\n <input\n type=\"text\"\n tabindex=\"0\"\n inputmode=\"numeric\"\n data-time-type=\"second\"\n class=\"border-input bg-background focus:border-ring focus:ring-ring/30 w-10 rounded border px-1.5 py-1 text-center text-sm outline-none focus:ring-2\"\n [value]=\"formattedSecond()\"\n (input)=\"onSecondInput($event)\"\n (blur)=\"onTimeBlur($event)\"\n maxlength=\"2\" />\n }\n\n @if (zTimeFormat() === '12h') {\n <button\n type=\"button\"\n tabindex=\"0\"\n class=\"border-input bg-background hover:bg-muted focus:border-ring focus:ring-ring/30 ml-1 cursor-pointer rounded border px-2 py-1 text-sm font-medium transition-colors outline-none focus:ring-2\"\n (click)=\"togglePeriod()\">\n {{ period() }}\n </button>\n }\n </div>\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() }}\n </button>\n }\n @if (showOkButton()) {\n <button type=\"button\" z-button zSize=\"sm\" [zDisabled]=\"!canApply()\" (click)=\"onOkClick()\">\n {{ zOkText() }}\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}@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: 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: 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" }], changeDetection: i0.ChangeDetectionStrategy.OnPush, encapsulation: i0.ViewEncapsulation.None });
|
|
2309
|
+
}
|
|
2310
|
+
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.0.6", ngImport: i0, type: ZCalendarComponent, decorators: [{
|
|
2311
|
+
type: Component,
|
|
2312
|
+
args: [{ selector: 'z-calendar', imports: [
|
|
2313
|
+
ZIconComponent,
|
|
2314
|
+
ZPopoverDirective,
|
|
2315
|
+
ZButtonComponent,
|
|
2316
|
+
ZDayClassesPipe,
|
|
2317
|
+
ZMonthClassesPipe,
|
|
2318
|
+
ZQuarterClassesPipe,
|
|
2319
|
+
ZYearClassesPipe,
|
|
2320
|
+
ZIsPresetDisabledPipe,
|
|
2321
|
+
], standalone: true, providers: [
|
|
2322
|
+
{
|
|
2323
|
+
provide: NG_VALUE_ACCESSOR,
|
|
2324
|
+
useExisting: forwardRef(() => ZCalendarComponent),
|
|
2325
|
+
multi: true,
|
|
2326
|
+
},
|
|
2327
|
+
], 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 w-fit\">\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 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=\"T\u1EEB ng\u00E0y\"\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 <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=\"\u0110\u1EBFn ng\u00E0y\"\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 } @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 }\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 rounded-[6px] border shadow-lg\"\n (keydown)=\"onCalendarKeydown($event)\">\n @if (zQuickSelect() && zMode() === 'range') {\n <div class=\"border-border flex flex-col space-y-1 border-r p-2\">\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-col gap-2 p-3\">\n @if (!isTimeMode()) {\n <div class=\"z-calendars-wrapper flex gap-4\">\n <!-- First Calendar -->\n <div class=\"z-calendar-section flex flex-col justify-center 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\n <!-- Start Time Picker for Range Mode -->\n @if (isRangeMode() && zShowTime() && currentView() === 'day') {\n <div class=\"flex items-center justify-center gap-2 pt-2\">\n <span class=\"text-muted-foreground text-xs\">B\u1EAFt \u0111\u1EA7u:</span>\n <div class=\"flex items-center gap-0.5\">\n @if (zShowHour()) {\n <input\n type=\"text\"\n tabindex=\"0\"\n inputmode=\"numeric\"\n data-time-type=\"hour\"\n class=\"border-input bg-background focus:border-ring focus:ring-ring/30 w-10 rounded border px-1.5 py-1 text-center text-sm outline-none focus:ring-2\"\n [value]=\"formattedHour()\"\n (input)=\"onHourInput($event)\"\n (blur)=\"onTimeBlur($event)\"\n maxlength=\"2\" />\n }\n @if (zShowHour() && zShowMinute()) {\n <span class=\"text-muted-foreground\">:</span>\n }\n @if (zShowMinute()) {\n <input\n type=\"text\"\n tabindex=\"0\"\n inputmode=\"numeric\"\n data-time-type=\"minute\"\n class=\"border-input bg-background focus:border-ring focus:ring-ring/30 w-10 rounded border px-1.5 py-1 text-center text-sm outline-none focus:ring-2\"\n [value]=\"formattedMinute()\"\n (input)=\"onMinuteInput($event)\"\n (blur)=\"onTimeBlur($event)\"\n maxlength=\"2\" />\n }\n @if (zShowMinute() && zShowSecond()) {\n <span class=\"text-muted-foreground\">:</span>\n }\n @if (zShowSecond()) {\n <input\n type=\"text\"\n tabindex=\"0\"\n inputmode=\"numeric\"\n data-time-type=\"second\"\n class=\"border-input bg-background focus:border-ring focus:ring-ring/30 w-10 rounded border px-1.5 py-1 text-center text-sm outline-none focus:ring-2\"\n [value]=\"formattedSecond()\"\n (input)=\"onSecondInput($event)\"\n (blur)=\"onTimeBlur($event)\"\n maxlength=\"2\" />\n }\n @if (zTimeFormat() === '12h') {\n <button\n type=\"button\"\n tabindex=\"0\"\n class=\"border-input bg-background hover:bg-muted focus:border-ring focus:ring-ring/30 ml-1 cursor-pointer rounded border px-2 py-1 text-sm font-medium transition-colors outline-none focus:ring-2\"\n (click)=\"togglePeriod()\">\n {{ period() }}\n </button>\n }\n </div>\n </div>\n }\n </div>\n\n <!-- Second Calendar (Range Mode Only) -->\n @if (isRangeMode()) {\n <!-- Divider -->\n <div class=\"border-border bg-border w-px self-stretch\"></div>\n\n <div class=\"z-calendar-section flex flex-col justify-center 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\n <!-- End Time Picker for Range Mode -->\n @if (zShowTime()) {\n <div class=\"flex items-center justify-center gap-2 pt-2\">\n <span class=\"text-muted-foreground text-xs\">K\u1EBFt th\u00FAc:</span>\n <div class=\"flex items-center gap-0.5\">\n @if (zShowHour()) {\n <input\n type=\"text\"\n tabindex=\"0\"\n inputmode=\"numeric\"\n data-time-type=\"hour-end\"\n class=\"border-input bg-background focus:border-ring focus:ring-ring/30 w-10 rounded border px-1.5 py-1 text-center text-sm outline-none focus:ring-2\"\n [value]=\"formattedHourEnd()\"\n (input)=\"onHourEndInput($event)\"\n (blur)=\"onTimeBlurEnd($event)\"\n maxlength=\"2\" />\n }\n @if (zShowHour() && zShowMinute()) {\n <span class=\"text-muted-foreground\">:</span>\n }\n @if (zShowMinute()) {\n <input\n type=\"text\"\n tabindex=\"0\"\n inputmode=\"numeric\"\n data-time-type=\"minute-end\"\n class=\"border-input bg-background focus:border-ring focus:ring-ring/30 w-10 rounded border px-1.5 py-1 text-center text-sm outline-none focus:ring-2\"\n [value]=\"formattedMinuteEnd()\"\n (input)=\"onMinuteEndInput($event)\"\n (blur)=\"onTimeBlurEnd($event)\"\n maxlength=\"2\" />\n }\n @if (zShowMinute() && zShowSecond()) {\n <span class=\"text-muted-foreground\">:</span>\n }\n @if (zShowSecond()) {\n <input\n type=\"text\"\n tabindex=\"0\"\n inputmode=\"numeric\"\n data-time-type=\"second-end\"\n class=\"border-input bg-background focus:border-ring focus:ring-ring/30 w-10 rounded border px-1.5 py-1 text-center text-sm outline-none focus:ring-2\"\n [value]=\"formattedSecondEnd()\"\n (input)=\"onSecondEndInput($event)\"\n (blur)=\"onTimeBlurEnd($event)\"\n maxlength=\"2\" />\n }\n @if (zTimeFormat() === '12h') {\n <button\n type=\"button\"\n tabindex=\"0\"\n class=\"border-input bg-background hover:bg-muted focus:border-ring focus:ring-ring/30 ml-1 cursor-pointer rounded border px-2 py-1 text-sm font-medium transition-colors outline-none focus:ring-2\"\n (click)=\"togglePeriodEnd()\">\n {{ periodEnd() }}\n </button>\n }\n </div>\n </div>\n }\n </div>\n }\n </div>\n }\n\n @if (((zShowTime() && currentView() === 'day') || isTimeMode()) && !isRangeMode()) {\n <div class=\"flex items-center justify-center gap-2\">\n <div class=\"flex items-center gap-0.5\">\n @if (zShowHour()) {\n <input\n type=\"text\"\n tabindex=\"0\"\n inputmode=\"numeric\"\n data-time-type=\"hour\"\n class=\"border-input bg-background focus:border-ring focus:ring-ring/30 w-10 rounded border px-1.5 py-1 text-center text-sm outline-none focus:ring-2\"\n [value]=\"formattedHour()\"\n (input)=\"onHourInput($event)\"\n (blur)=\"onTimeBlur($event)\"\n maxlength=\"2\" />\n }\n\n @if (zShowHour() && zShowMinute()) {\n <span class=\"text-muted-foreground\">:</span>\n }\n\n @if (zShowMinute()) {\n <input\n type=\"text\"\n tabindex=\"0\"\n inputmode=\"numeric\"\n data-time-type=\"minute\"\n class=\"border-input bg-background focus:border-ring focus:ring-ring/30 w-10 rounded border px-1.5 py-1 text-center text-sm outline-none focus:ring-2\"\n [value]=\"formattedMinute()\"\n (input)=\"onMinuteInput($event)\"\n (blur)=\"onTimeBlur($event)\"\n maxlength=\"2\" />\n }\n\n @if (zShowMinute() && zShowSecond()) {\n <span class=\"text-muted-foreground\">:</span>\n }\n\n @if (zShowSecond()) {\n <input\n type=\"text\"\n tabindex=\"0\"\n inputmode=\"numeric\"\n data-time-type=\"second\"\n class=\"border-input bg-background focus:border-ring focus:ring-ring/30 w-10 rounded border px-1.5 py-1 text-center text-sm outline-none focus:ring-2\"\n [value]=\"formattedSecond()\"\n (input)=\"onSecondInput($event)\"\n (blur)=\"onTimeBlur($event)\"\n maxlength=\"2\" />\n }\n\n @if (zTimeFormat() === '12h') {\n <button\n type=\"button\"\n tabindex=\"0\"\n class=\"border-input bg-background hover:bg-muted focus:border-ring focus:ring-ring/30 ml-1 cursor-pointer rounded border px-2 py-1 text-sm font-medium transition-colors outline-none focus:ring-2\"\n (click)=\"togglePeriod()\">\n {{ period() }}\n </button>\n }\n </div>\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() }}\n </button>\n }\n @if (showOkButton()) {\n <button type=\"button\" z-button zSize=\"sm\" [zDisabled]=\"!canApply()\" (click)=\"onOkClick()\">\n {{ zOkText() }}\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}@keyframes z-calendar-view-enter{0%{opacity:0;transform:scale(.95) translateY(4px)}to{opacity:1;transform:scale(1) translateY(0)}}\n"] }]
|
|
2328
|
+
}], 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 }] }], 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 }] }] } });
|
|
2329
|
+
|
|
2330
|
+
/**
|
|
2331
|
+
* Generated bundle index. Do not edit.
|
|
2332
|
+
*/
|
|
2333
|
+
|
|
2334
|
+
export { ZCalendarComponent, zCalendarDayVariants, zCalendarMonthVariants, zCalendarVariants, zCalendarYearVariants };
|
|
2335
|
+
//# sourceMappingURL=shival99-z-ui-components-z-calendar.mjs.map
|