@lilydesignsystem/angular-date-time-picker 0.1.2 → 0.2.1
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/README.md +21 -10
- package/fesm2022/lilydesignsystem-angular-date-time-picker.mjs +1684 -1358
- package/fesm2022/lilydesignsystem-angular-date-time-picker.mjs.map +1 -1
- package/package.json +6 -6
- package/types/lilydesignsystem-angular-date-time-picker.d.ts +566 -401
- package/types/lilydesignsystem-angular-date-time-picker.d.ts.map +1 -1
|
@@ -1,1392 +1,1391 @@
|
|
|
1
|
-
import { NgTemplateOutlet } from
|
|
2
|
-
import * as i0 from
|
|
3
|
-
import {
|
|
4
|
-
import { IconButton } from
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
1
|
+
import { NgTemplateOutlet } from "@angular/common";
|
|
2
|
+
import * as i0 from "@angular/core";
|
|
3
|
+
import { ChangeDetectionStrategy, ChangeDetectorRef, Component, DestroyRef, Directive, TemplateRef, afterNextRender, computed, contentChild, effect, inject, input, model, output, signal, viewChild } from "@angular/core";
|
|
4
|
+
import { IconButton } from "@lilydesignsystem/angular-headless";
|
|
5
|
+
const DAY_MS = 864e5;
|
|
6
|
+
const toMs = (iso) => Date.parse(`${iso}T00:00:00Z`);
|
|
7
|
+
const toIso = (ms) => new Date(ms).toISOString().slice(0, 10);
|
|
8
|
+
const shift = (iso, days) => toIso(toMs(iso) + days * DAY_MS);
|
|
9
|
+
const formatters = /* @__PURE__ */ new Map();
|
|
10
|
+
function dayFormatter(calendar) {
|
|
11
|
+
let formatter = formatters.get(calendar);
|
|
12
|
+
if (!formatter) {
|
|
13
|
+
formatter = new Intl.DateTimeFormat(`en-u-ca-${calendar}-nu-latn`, {
|
|
14
|
+
day: "numeric",
|
|
15
|
+
timeZone: "UTC"
|
|
16
|
+
});
|
|
17
|
+
formatters.set(calendar, formatter);
|
|
18
|
+
}
|
|
19
|
+
return formatter;
|
|
20
|
+
}
|
|
21
|
+
function calendarDay(iso, calendar = "gregory") {
|
|
22
|
+
const part = dayFormatter(calendar).formatToParts(new Date(toMs(iso))).find((p) => p.type === "day");
|
|
23
|
+
return Number(part?.value);
|
|
24
|
+
}
|
|
25
|
+
function calendarMonthStart(iso, calendar = "gregory") {
|
|
26
|
+
return shift(iso, 1 - calendarDay(iso, calendar));
|
|
27
|
+
}
|
|
28
|
+
function calendarMonthLength(start, calendar = "gregory") {
|
|
29
|
+
for (let length = 1; length < 40; length++) if (calendarDay(shift(start, length), calendar) === 1) return length;
|
|
30
|
+
throw new RangeError(`calendar-system: no month end after ${start} in ${calendar}`);
|
|
31
|
+
}
|
|
32
|
+
function calendarAddMonths(start, delta, calendar = "gregory") {
|
|
33
|
+
let month = start;
|
|
34
|
+
for (let i = 0; i < delta; i++) month = shift(month, calendarMonthLength(month, calendar));
|
|
35
|
+
for (let i = 0; i > delta; i--) month = calendarMonthStart(shift(month, -1), calendar);
|
|
36
|
+
return month;
|
|
37
|
+
}
|
|
38
|
+
function calendarMonthMatrix(start, firstDayOfWeek, calendar = "gregory") {
|
|
39
|
+
const weekday = new Date(toMs(start)).getUTCDay();
|
|
40
|
+
let date = shift(start, -((weekday - firstDayOfWeek + 7) % 7));
|
|
41
|
+
const rows = [];
|
|
42
|
+
for (let row = 0; row < 6; row++) {
|
|
43
|
+
const days = [];
|
|
44
|
+
for (let column = 0; column < 7; column++) {
|
|
45
|
+
days.push(date);
|
|
46
|
+
date = shift(date, 1);
|
|
47
|
+
}
|
|
48
|
+
rows.push(days);
|
|
49
|
+
}
|
|
50
|
+
return rows;
|
|
51
|
+
}
|
|
52
|
+
function calendarLocale(locale, calendar = "gregory") {
|
|
53
|
+
if (!locale) return locale;
|
|
54
|
+
try {
|
|
55
|
+
return new Intl.Locale(locale, { calendar }).toString();
|
|
56
|
+
} catch {
|
|
57
|
+
return locale;
|
|
58
|
+
}
|
|
59
|
+
}
|
|
60
|
+
function isRtl(element) {
|
|
61
|
+
if (!element) return false;
|
|
62
|
+
const attr = element.closest("[dir]")?.getAttribute("dir")?.toLowerCase();
|
|
63
|
+
if (attr === "rtl") return true;
|
|
64
|
+
if (attr === "ltr") return false;
|
|
65
|
+
if (typeof getComputedStyle === "function") return getComputedStyle(element).direction === "rtl";
|
|
66
|
+
return false;
|
|
67
|
+
}
|
|
68
|
+
function logicalKey(key, rtl) {
|
|
69
|
+
if (!rtl) return key;
|
|
70
|
+
if (key === "ArrowLeft") return "ArrowRight";
|
|
71
|
+
if (key === "ArrowRight") return "ArrowLeft";
|
|
72
|
+
return key;
|
|
73
|
+
}
|
|
18
74
|
const CALENDAR = "📅︎";
|
|
19
|
-
// -----------------------------------------------------------------
|
|
20
|
-
// Civil-date arithmetic
|
|
21
|
-
//
|
|
22
|
-
// Pure and total: no local-time `Date` values, no throwing, null for
|
|
23
|
-
// "not a date". Exported so the acceptance tests can exercise the
|
|
24
|
-
// arithmetic directly rather than only through the rendered grid.
|
|
25
|
-
// -----------------------------------------------------------------
|
|
26
|
-
/** Zero-pad to `width`. */
|
|
27
75
|
function pad(n, width = 2) {
|
|
28
|
-
|
|
76
|
+
return String(Math.abs(n)).padStart(width, "0");
|
|
29
77
|
}
|
|
30
|
-
/** Days in a month. `month` is 1-12. */
|
|
31
78
|
function daysInMonth(year, month) {
|
|
32
|
-
|
|
33
|
-
return new Date(Date.UTC(year, month, 0)).getUTCDate();
|
|
79
|
+
return new Date(Date.UTC(year, month, 0)).getUTCDate();
|
|
34
80
|
}
|
|
35
|
-
/** `{2026, 3, 1}` → `"2026-03-01"`. */
|
|
36
81
|
function formatIsoDate(date) {
|
|
37
|
-
|
|
82
|
+
return `${pad(date.year, 4)}-${pad(date.month)}-${pad(date.day)}`;
|
|
38
83
|
}
|
|
39
|
-
/**
|
|
40
|
-
* `"2026-03-01"` → `{2026, 3, 1}`, or null.
|
|
41
|
-
*
|
|
42
|
-
* Rejects impossible components rather than rolling them over, so
|
|
43
|
-
* `"2026-02-31"` is null and not the 3rd of March. A field that silently
|
|
44
|
-
* reinterprets an impossible date is worse than one that refuses it.
|
|
45
|
-
*/
|
|
46
84
|
function parseIsoDate(text) {
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
|
|
85
|
+
const m = /^(\d{4})-(\d{2})-(\d{2})$/.exec(text.trim());
|
|
86
|
+
if (!m) return null;
|
|
87
|
+
const year = Number(m[1]);
|
|
88
|
+
const month = Number(m[2]);
|
|
89
|
+
const day = Number(m[3]);
|
|
90
|
+
if (month < 1 || month > 12) return null;
|
|
91
|
+
if (day < 1 || day > daysInMonth(year, month)) return null;
|
|
92
|
+
return {
|
|
93
|
+
year,
|
|
94
|
+
month,
|
|
95
|
+
day
|
|
96
|
+
};
|
|
58
97
|
}
|
|
59
|
-
/** Days since the Unix epoch. The unit all date arithmetic goes through. */
|
|
60
98
|
function toEpochDay(date) {
|
|
61
|
-
|
|
99
|
+
return Date.UTC(date.year, date.month - 1, date.day) / 864e5;
|
|
62
100
|
}
|
|
63
|
-
/** Inverse of `toEpochDay`. */
|
|
64
101
|
function fromEpochDay(epochDay) {
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
|
|
69
|
-
|
|
70
|
-
|
|
102
|
+
const d = /* @__PURE__ */ new Date(epochDay * 864e5);
|
|
103
|
+
return {
|
|
104
|
+
year: d.getUTCFullYear(),
|
|
105
|
+
month: d.getUTCMonth() + 1,
|
|
106
|
+
day: d.getUTCDate()
|
|
107
|
+
};
|
|
71
108
|
}
|
|
72
|
-
/** Shift an ISO date by whole days. */
|
|
73
109
|
function addDays(isoDate, days) {
|
|
74
|
-
|
|
75
|
-
|
|
76
|
-
|
|
77
|
-
return formatIsoDate(fromEpochDay(toEpochDay(date) + days));
|
|
110
|
+
const date = parseIsoDate(isoDate);
|
|
111
|
+
if (!date) return isoDate;
|
|
112
|
+
return formatIsoDate(fromEpochDay(toEpochDay(date) + days));
|
|
78
113
|
}
|
|
79
|
-
/**
|
|
80
|
-
* Shift an ISO date by whole months, clamping the day.
|
|
81
|
-
*
|
|
82
|
-
* 31 January + 1 month is 28 February (29 in a leap year), not 3 March.
|
|
83
|
-
* Rolling over is what `Date.prototype.setMonth` does and it is almost
|
|
84
|
-
* never what someone paging a calendar means.
|
|
85
|
-
*/
|
|
86
114
|
function addMonths(isoDate, months) {
|
|
87
|
-
|
|
88
|
-
|
|
89
|
-
|
|
90
|
-
|
|
91
|
-
|
|
92
|
-
|
|
93
|
-
|
|
94
|
-
|
|
95
|
-
|
|
96
|
-
|
|
97
|
-
});
|
|
115
|
+
const date = parseIsoDate(isoDate);
|
|
116
|
+
if (!date) return isoDate;
|
|
117
|
+
const total = date.year * 12 + (date.month - 1) + months;
|
|
118
|
+
const year = Math.floor(total / 12);
|
|
119
|
+
const month = (total % 12 + 12) % 12 + 1;
|
|
120
|
+
return formatIsoDate({
|
|
121
|
+
year,
|
|
122
|
+
month,
|
|
123
|
+
day: Math.min(date.day, daysInMonth(year, month))
|
|
124
|
+
});
|
|
98
125
|
}
|
|
99
|
-
/** Day of week: 0 = Sunday … 6 = Saturday. */
|
|
100
126
|
function weekdayOf(isoDate) {
|
|
101
|
-
|
|
102
|
-
|
|
103
|
-
|
|
104
|
-
return new Date(Date.UTC(date.year, date.month - 1, date.day)).getUTCDay();
|
|
127
|
+
const date = parseIsoDate(isoDate);
|
|
128
|
+
if (!date) return 0;
|
|
129
|
+
return new Date(Date.UTC(date.year, date.month - 1, date.day)).getUTCDay();
|
|
105
130
|
}
|
|
106
|
-
/**
|
|
107
|
-
* ISO-8601 week number.
|
|
108
|
-
*
|
|
109
|
-
* Weeks start Monday and week 1 is the one containing the first Thursday,
|
|
110
|
-
* which is why this pivots on Thursday rather than counting from 1
|
|
111
|
-
* January. Public-sector and clinical rotas quote ISO week numbers, so
|
|
112
|
-
* the column is worth getting exactly right.
|
|
113
|
-
*/
|
|
114
131
|
function isoWeek(isoDate) {
|
|
115
|
-
|
|
116
|
-
|
|
117
|
-
|
|
118
|
-
|
|
119
|
-
|
|
120
|
-
|
|
121
|
-
|
|
122
|
-
|
|
123
|
-
|
|
124
|
-
|
|
125
|
-
return Math.floor((toEpochDay(parsed) - toEpochDay(jan1)) / 7) + 1;
|
|
132
|
+
if (!parseIsoDate(isoDate)) return 0;
|
|
133
|
+
const parsed = parseIsoDate(addDays(isoDate, 3 - (weekdayOf(isoDate) + 6) % 7));
|
|
134
|
+
if (!parsed) return 0;
|
|
135
|
+
const jan1 = parseIsoDate(formatIsoDate({
|
|
136
|
+
year: parsed.year,
|
|
137
|
+
month: 1,
|
|
138
|
+
day: 1
|
|
139
|
+
}));
|
|
140
|
+
if (!jan1) return 0;
|
|
141
|
+
return Math.floor((toEpochDay(parsed) - toEpochDay(jan1)) / 7) + 1;
|
|
126
142
|
}
|
|
127
|
-
/** `"09:30"` → `{9, 30}`, or null. */
|
|
128
143
|
function parseIsoTime(text) {
|
|
129
|
-
|
|
130
|
-
|
|
131
|
-
|
|
132
|
-
|
|
133
|
-
|
|
134
|
-
|
|
135
|
-
|
|
136
|
-
|
|
144
|
+
const m = /^(\d{2}):(\d{2})$/.exec(text.trim());
|
|
145
|
+
if (!m) return null;
|
|
146
|
+
const hour = Number(m[1]);
|
|
147
|
+
const minute = Number(m[2]);
|
|
148
|
+
if (hour > 23 || minute > 59) return null;
|
|
149
|
+
return {
|
|
150
|
+
hour,
|
|
151
|
+
minute
|
|
152
|
+
};
|
|
137
153
|
}
|
|
138
|
-
/** `{9, 30}` → `"09:30"`. */
|
|
139
154
|
function formatIsoTime(time) {
|
|
140
|
-
|
|
155
|
+
return `${pad(time.hour)}:${pad(time.minute)}`;
|
|
141
156
|
}
|
|
142
|
-
/** Pull the date and time halves out of a mode-appropriate ISO value. */
|
|
143
157
|
function splitValue(value, mode) {
|
|
144
|
-
|
|
145
|
-
|
|
146
|
-
|
|
147
|
-
|
|
148
|
-
|
|
149
|
-
|
|
150
|
-
|
|
151
|
-
|
|
152
|
-
|
|
153
|
-
|
|
158
|
+
if (!value) return {
|
|
159
|
+
date: "",
|
|
160
|
+
time: ""
|
|
161
|
+
};
|
|
162
|
+
if (mode === "time") return {
|
|
163
|
+
date: "",
|
|
164
|
+
time: parseIsoTime(value) ? value : ""
|
|
165
|
+
};
|
|
166
|
+
const [datePart = "", timePart = ""] = value.split("T");
|
|
167
|
+
return {
|
|
168
|
+
date: parseIsoDate(datePart) ? datePart : "",
|
|
169
|
+
time: mode === "datetime" && parseIsoTime(timePart) ? timePart : ""
|
|
170
|
+
};
|
|
154
171
|
}
|
|
155
|
-
/** Recombine the halves. Returns "" when the value is incomplete. */
|
|
156
172
|
function joinValue(date, time, mode) {
|
|
157
|
-
|
|
158
|
-
|
|
159
|
-
|
|
160
|
-
return time;
|
|
161
|
-
return date && time ? `${date}T${time}` : "";
|
|
173
|
+
if (mode === "date") return date;
|
|
174
|
+
if (mode === "time") return time;
|
|
175
|
+
return date && time ? `${date}T${time}` : "";
|
|
162
176
|
}
|
|
163
|
-
/** Is `isoDate` inside the inclusive [min, max] window? Empty bounds pass. */
|
|
164
177
|
function withinRange(isoDate, min, max) {
|
|
165
|
-
|
|
166
|
-
|
|
167
|
-
|
|
168
|
-
return false;
|
|
169
|
-
return true;
|
|
178
|
+
if (min && isoDate < min) return false;
|
|
179
|
+
if (max && isoDate > max) return false;
|
|
180
|
+
return true;
|
|
170
181
|
}
|
|
171
|
-
/** Uppercase region subtag of a BCP 47 tag, or "". */
|
|
172
182
|
function regionOf(locale) {
|
|
173
|
-
|
|
174
|
-
|
|
175
|
-
|
|
176
|
-
if (/^[A-Za-z]{2}$/.test(part))
|
|
177
|
-
return part.toUpperCase();
|
|
178
|
-
}
|
|
179
|
-
return "";
|
|
183
|
+
if (!locale) return "";
|
|
184
|
+
for (const part of locale.split(/[-_]/).slice(1)) if (/^[A-Za-z]{2}$/.test(part)) return part.toUpperCase();
|
|
185
|
+
return "";
|
|
180
186
|
}
|
|
181
|
-
const SUNDAY_FIRST_REGIONS = new Set([
|
|
182
|
-
|
|
183
|
-
|
|
187
|
+
const SUNDAY_FIRST_REGIONS = /* @__PURE__ */ new Set([
|
|
188
|
+
"AR",
|
|
189
|
+
"BR",
|
|
190
|
+
"CA",
|
|
191
|
+
"CL",
|
|
192
|
+
"CO",
|
|
193
|
+
"DO",
|
|
194
|
+
"GT",
|
|
195
|
+
"HK",
|
|
196
|
+
"IL",
|
|
197
|
+
"IN",
|
|
198
|
+
"JP",
|
|
199
|
+
"KR",
|
|
200
|
+
"MO",
|
|
201
|
+
"MX",
|
|
202
|
+
"PE",
|
|
203
|
+
"PH",
|
|
204
|
+
"PK",
|
|
205
|
+
"TH",
|
|
206
|
+
"TW",
|
|
207
|
+
"US",
|
|
208
|
+
"VE",
|
|
209
|
+
"ZA"
|
|
184
210
|
]);
|
|
185
|
-
const SATURDAY_FIRST_REGIONS = new Set([
|
|
186
|
-
|
|
187
|
-
|
|
211
|
+
const SATURDAY_FIRST_REGIONS = /* @__PURE__ */ new Set([
|
|
212
|
+
"AE",
|
|
213
|
+
"AF",
|
|
214
|
+
"BH",
|
|
215
|
+
"DJ",
|
|
216
|
+
"DZ",
|
|
217
|
+
"EG",
|
|
218
|
+
"IQ",
|
|
219
|
+
"IR",
|
|
220
|
+
"JO",
|
|
221
|
+
"KW",
|
|
222
|
+
"LY",
|
|
223
|
+
"OM",
|
|
224
|
+
"QA",
|
|
225
|
+
"SA",
|
|
226
|
+
"SD",
|
|
227
|
+
"SY",
|
|
228
|
+
"YE"
|
|
188
229
|
]);
|
|
189
|
-
/**
|
|
190
|
-
* First day of the week for a locale: 0 = Sunday … 6 = Saturday.
|
|
191
|
-
*
|
|
192
|
-
* `Intl.Locale.prototype.getWeekInfo` is the right answer, but it is
|
|
193
|
-
* recent enough that a fallback still earns its place — and it is
|
|
194
|
-
* missing from some SSR runtimes entirely. The fallback is a short
|
|
195
|
-
* region table plus a Monday default, Monday being both the ISO-8601
|
|
196
|
-
* rule and the majority convention worldwide.
|
|
197
|
-
*/
|
|
198
230
|
function firstDayOfWeekFor(locale) {
|
|
199
|
-
|
|
200
|
-
|
|
201
|
-
|
|
202
|
-
|
|
203
|
-
|
|
204
|
-
|
|
205
|
-
|
|
206
|
-
|
|
207
|
-
|
|
208
|
-
}
|
|
209
|
-
catch {
|
|
210
|
-
// Malformed tag — fall through to the table.
|
|
211
|
-
}
|
|
212
|
-
}
|
|
213
|
-
const region = regionOf(locale);
|
|
214
|
-
if (SUNDAY_FIRST_REGIONS.has(region))
|
|
215
|
-
return 0;
|
|
216
|
-
if (SATURDAY_FIRST_REGIONS.has(region))
|
|
217
|
-
return 6;
|
|
218
|
-
return 1;
|
|
231
|
+
if (locale) try {
|
|
232
|
+
const loc = new Intl.Locale(locale);
|
|
233
|
+
const info = loc.getWeekInfo?.() ?? loc.weekInfo;
|
|
234
|
+
if (info && typeof info.firstDay === "number") return info.firstDay % 7;
|
|
235
|
+
} catch {}
|
|
236
|
+
const region = regionOf(locale);
|
|
237
|
+
if (SUNDAY_FIRST_REGIONS.has(region)) return 0;
|
|
238
|
+
if (SATURDAY_FIRST_REGIONS.has(region)) return 6;
|
|
239
|
+
return 1;
|
|
219
240
|
}
|
|
220
|
-
/**
|
|
221
|
-
* The dates of one month's grid, always six rows of seven.
|
|
222
|
-
*
|
|
223
|
-
* Fixed height on purpose. A grid sized to its month runs four to six
|
|
224
|
-
* rows, so the footer — and the confirm button in it — moves vertically
|
|
225
|
-
* as you page months. That is a Fitts's-law tax on every subsequent click
|
|
226
|
-
* and it makes the dialog jump under the pointer. A constant six rows
|
|
227
|
-
* costs at most one extra trailing week.
|
|
228
|
-
*/
|
|
229
241
|
function monthMatrix(year, month, firstDayOfWeek) {
|
|
230
|
-
|
|
231
|
-
|
|
232
|
-
|
|
233
|
-
|
|
234
|
-
|
|
235
|
-
|
|
236
|
-
|
|
237
|
-
|
|
238
|
-
|
|
239
|
-
|
|
240
|
-
|
|
241
|
-
|
|
242
|
+
const first = formatIsoDate({
|
|
243
|
+
year,
|
|
244
|
+
month,
|
|
245
|
+
day: 1
|
|
246
|
+
});
|
|
247
|
+
const start = addDays(first, -((weekdayOf(first) - firstDayOfWeek + 7) % 7));
|
|
248
|
+
const weeks = [];
|
|
249
|
+
for (let row = 0; row < 6; row++) {
|
|
250
|
+
const week = [];
|
|
251
|
+
for (let col = 0; col < 7; col++) week.push(addDays(start, row * 7 + col));
|
|
252
|
+
weeks.push(week);
|
|
253
|
+
}
|
|
254
|
+
return weeks;
|
|
242
255
|
}
|
|
243
|
-
/** Long and short month names for a locale, index 0 = January. */
|
|
244
256
|
function monthNames(locale) {
|
|
245
|
-
|
|
246
|
-
|
|
247
|
-
|
|
248
|
-
|
|
249
|
-
|
|
250
|
-
|
|
251
|
-
|
|
252
|
-
|
|
253
|
-
|
|
254
|
-
|
|
255
|
-
|
|
256
|
-
|
|
257
|
-
|
|
257
|
+
const build = (month) => {
|
|
258
|
+
try {
|
|
259
|
+
const fmt = new Intl.DateTimeFormat(gregorian(locale), {
|
|
260
|
+
month,
|
|
261
|
+
timeZone: "UTC"
|
|
262
|
+
});
|
|
263
|
+
return Array.from({ length: 12 }, (_, i) => fmt.format(new Date(Date.UTC(2021, i, 15))));
|
|
264
|
+
} catch {
|
|
265
|
+
return [];
|
|
266
|
+
}
|
|
267
|
+
};
|
|
268
|
+
return {
|
|
269
|
+
long: build("long"),
|
|
270
|
+
short: build("short")
|
|
271
|
+
};
|
|
258
272
|
}
|
|
259
|
-
/** Match a token against a locale's month names. Returns 1-12, or 0. */
|
|
260
273
|
function matchMonthName(token, names) {
|
|
261
|
-
|
|
262
|
-
|
|
263
|
-
|
|
264
|
-
|
|
265
|
-
|
|
266
|
-
|
|
267
|
-
|
|
268
|
-
|
|
269
|
-
|
|
270
|
-
|
|
271
|
-
|
|
272
|
-
|
|
273
|
-
// worse than refusing.
|
|
274
|
-
if (t.length >= 3) {
|
|
275
|
-
for (let i = 0; i < 12; i++) {
|
|
276
|
-
const long = norm(names.long[i] ?? "");
|
|
277
|
-
if (long && long.startsWith(t))
|
|
278
|
-
return i + 1;
|
|
279
|
-
}
|
|
280
|
-
}
|
|
281
|
-
return 0;
|
|
274
|
+
const norm = (s) => s.toLocaleLowerCase().replace(/\.$/, "").normalize("NFKD");
|
|
275
|
+
const t = norm(token);
|
|
276
|
+
if (!t || /^\d+$/.test(t)) return 0;
|
|
277
|
+
for (let i = 0; i < 12; i++) {
|
|
278
|
+
if (norm(names.long[i] ?? "") === t) return i + 1;
|
|
279
|
+
if (norm(names.short[i] ?? "") === t) return i + 1;
|
|
280
|
+
}
|
|
281
|
+
if (t.length >= 3) for (let i = 0; i < 12; i++) {
|
|
282
|
+
const long = norm(names.long[i] ?? "");
|
|
283
|
+
if (long && long.startsWith(t)) return i + 1;
|
|
284
|
+
}
|
|
285
|
+
return 0;
|
|
282
286
|
}
|
|
283
|
-
/**
|
|
284
|
-
* The order a locale writes a numeric date in — `["day","month","year"]`
|
|
285
|
-
* for en-GB, `["month","day","year"]` for en-US.
|
|
286
|
-
*/
|
|
287
287
|
function numericFieldOrder(locale) {
|
|
288
|
-
|
|
289
|
-
|
|
290
|
-
|
|
291
|
-
|
|
292
|
-
|
|
293
|
-
|
|
294
|
-
|
|
295
|
-
|
|
296
|
-
|
|
297
|
-
|
|
298
|
-
|
|
299
|
-
|
|
300
|
-
|
|
301
|
-
|
|
302
|
-
// Fall through.
|
|
303
|
-
}
|
|
304
|
-
return ["day", "month", "year"];
|
|
288
|
+
try {
|
|
289
|
+
const order = new Intl.DateTimeFormat(gregorian(locale), {
|
|
290
|
+
day: "2-digit",
|
|
291
|
+
month: "2-digit",
|
|
292
|
+
year: "numeric",
|
|
293
|
+
timeZone: "UTC"
|
|
294
|
+
}).formatToParts(new Date(Date.UTC(2021, 4, 6))).map((p) => p.type).filter((t) => t === "day" || t === "month" || t === "year");
|
|
295
|
+
if (order.length === 3) return order;
|
|
296
|
+
} catch {}
|
|
297
|
+
return [
|
|
298
|
+
"day",
|
|
299
|
+
"month",
|
|
300
|
+
"year"
|
|
301
|
+
];
|
|
305
302
|
}
|
|
306
|
-
/**
|
|
307
|
-
* Parse typed text into an ISO date.
|
|
308
|
-
*
|
|
309
|
-
* Accepts, in order: ISO `YYYY-MM-DD`; a numeric form whose field order
|
|
310
|
-
* follows the locale, so `03/04/2026` is 3 April in en-GB and 4 March in
|
|
311
|
-
* en-US — which is what each user means; and a form with a written month
|
|
312
|
-
* matched against the locale's own long and short month names, which is
|
|
313
|
-
* what lets DHCW's `27-Jun-2025` round-trip.
|
|
314
|
-
*
|
|
315
|
-
* Anything else is null. Guessing harder than this is how date fields
|
|
316
|
-
* silently record the wrong day.
|
|
317
|
-
*/
|
|
318
303
|
function parseDateInput(text, locale) {
|
|
319
|
-
|
|
320
|
-
|
|
321
|
-
|
|
322
|
-
|
|
323
|
-
|
|
324
|
-
|
|
325
|
-
|
|
326
|
-
|
|
327
|
-
|
|
328
|
-
|
|
329
|
-
|
|
330
|
-
|
|
331
|
-
|
|
332
|
-
|
|
333
|
-
|
|
334
|
-
|
|
335
|
-
|
|
336
|
-
|
|
337
|
-
|
|
338
|
-
|
|
339
|
-
|
|
340
|
-
|
|
341
|
-
|
|
342
|
-
|
|
343
|
-
|
|
344
|
-
|
|
345
|
-
|
|
346
|
-
|
|
347
|
-
|
|
348
|
-
|
|
349
|
-
|
|
350
|
-
|
|
351
|
-
|
|
352
|
-
|
|
353
|
-
|
|
354
|
-
|
|
355
|
-
|
|
356
|
-
|
|
357
|
-
|
|
358
|
-
|
|
359
|
-
|
|
360
|
-
|
|
361
|
-
|
|
362
|
-
|
|
363
|
-
|
|
364
|
-
|
|
365
|
-
|
|
366
|
-
|
|
367
|
-
|
|
368
|
-
|
|
369
|
-
|
|
304
|
+
const trimmed = normalizeDigits(text).trim();
|
|
305
|
+
if (!trimmed) return null;
|
|
306
|
+
const iso = parseIsoDate(trimmed);
|
|
307
|
+
if (iso) return formatIsoDate(iso);
|
|
308
|
+
const parts = trimmed.split(/[\s./-]+/).filter(Boolean);
|
|
309
|
+
if (parts.length !== 3) return null;
|
|
310
|
+
const names = monthNames(locale);
|
|
311
|
+
let month = 0;
|
|
312
|
+
let monthIndex = -1;
|
|
313
|
+
for (let i = 0; i < parts.length; i++) {
|
|
314
|
+
const found = matchMonthName(parts[i], names);
|
|
315
|
+
if (found) {
|
|
316
|
+
month = found;
|
|
317
|
+
monthIndex = i;
|
|
318
|
+
break;
|
|
319
|
+
}
|
|
320
|
+
}
|
|
321
|
+
let day = 0;
|
|
322
|
+
let year = 0;
|
|
323
|
+
if (monthIndex >= 0) {
|
|
324
|
+
const rest = parts.filter((_, i) => i !== monthIndex).map((p) => Number(p));
|
|
325
|
+
if (rest.some((n) => Number.isNaN(n))) return null;
|
|
326
|
+
[day, year] = rest[0] > rest[1] ? [rest[1], rest[0]] : rest;
|
|
327
|
+
} else {
|
|
328
|
+
const nums = parts.map((p) => Number(p));
|
|
329
|
+
if (nums.some((n) => Number.isNaN(n))) return null;
|
|
330
|
+
const order = numericFieldOrder(locale);
|
|
331
|
+
year = nums[order.indexOf("year")];
|
|
332
|
+
day = nums[order.indexOf("day")];
|
|
333
|
+
month = nums[order.indexOf("month")];
|
|
334
|
+
}
|
|
335
|
+
if (year < 100) year += year < 70 ? 2e3 : 1900;
|
|
336
|
+
if (month < 1 || month > 12) return null;
|
|
337
|
+
if (day < 1 || day > daysInMonth(year, month)) return null;
|
|
338
|
+
return formatIsoDate({
|
|
339
|
+
year,
|
|
340
|
+
month,
|
|
341
|
+
day
|
|
342
|
+
});
|
|
343
|
+
}
|
|
344
|
+
function gregorian(locale) {
|
|
345
|
+
if (!locale) return locale;
|
|
346
|
+
try {
|
|
347
|
+
return new Intl.Locale(locale, { calendar: "gregory" }).toString();
|
|
348
|
+
} catch {
|
|
349
|
+
return locale;
|
|
350
|
+
}
|
|
351
|
+
}
|
|
352
|
+
const NATIVE_DIGITS = /* @__PURE__ */ new Map();
|
|
353
|
+
function nativeDigits() {
|
|
354
|
+
if (NATIVE_DIGITS.size > 0) return NATIVE_DIGITS;
|
|
355
|
+
for (const system of [
|
|
356
|
+
"adlm",
|
|
357
|
+
"ahom",
|
|
358
|
+
"arab",
|
|
359
|
+
"arabext",
|
|
360
|
+
"bali",
|
|
361
|
+
"beng",
|
|
362
|
+
"bhks",
|
|
363
|
+
"brah",
|
|
364
|
+
"cakm",
|
|
365
|
+
"cham",
|
|
366
|
+
"deva",
|
|
367
|
+
"fullwide",
|
|
368
|
+
"gong",
|
|
369
|
+
"gonm",
|
|
370
|
+
"gujr",
|
|
371
|
+
"guru",
|
|
372
|
+
"hanidec",
|
|
373
|
+
"hmng",
|
|
374
|
+
"hmnp",
|
|
375
|
+
"java",
|
|
376
|
+
"kali",
|
|
377
|
+
"kawi",
|
|
378
|
+
"khmr",
|
|
379
|
+
"knda",
|
|
380
|
+
"lana",
|
|
381
|
+
"lanatham",
|
|
382
|
+
"laoo",
|
|
383
|
+
"lepc",
|
|
384
|
+
"limb",
|
|
385
|
+
"mathbold",
|
|
386
|
+
"mathdbl",
|
|
387
|
+
"mathmono",
|
|
388
|
+
"mathsanb",
|
|
389
|
+
"mathsans",
|
|
390
|
+
"mlym",
|
|
391
|
+
"modi",
|
|
392
|
+
"mong",
|
|
393
|
+
"mroo",
|
|
394
|
+
"mtei",
|
|
395
|
+
"mymr",
|
|
396
|
+
"mymrshan",
|
|
397
|
+
"mymrtlng",
|
|
398
|
+
"nagm",
|
|
399
|
+
"newa",
|
|
400
|
+
"nkoo",
|
|
401
|
+
"olck",
|
|
402
|
+
"orya",
|
|
403
|
+
"osma",
|
|
404
|
+
"rohg",
|
|
405
|
+
"saur",
|
|
406
|
+
"segment",
|
|
407
|
+
"shrd",
|
|
408
|
+
"sind",
|
|
409
|
+
"sinh",
|
|
410
|
+
"sora",
|
|
411
|
+
"sund",
|
|
412
|
+
"takr",
|
|
413
|
+
"talu",
|
|
414
|
+
"tamldec",
|
|
415
|
+
"telu",
|
|
416
|
+
"thai",
|
|
417
|
+
"tibt",
|
|
418
|
+
"tirh",
|
|
419
|
+
"tnsa",
|
|
420
|
+
"vaii",
|
|
421
|
+
"wara",
|
|
422
|
+
"wcho"
|
|
423
|
+
]) try {
|
|
424
|
+
const format = new Intl.NumberFormat(`en-u-nu-${system}`, { useGrouping: false });
|
|
425
|
+
for (let digit = 0; digit < 10; digit++) NATIVE_DIGITS.set(format.format(digit), String(digit));
|
|
426
|
+
} catch {}
|
|
427
|
+
return NATIVE_DIGITS;
|
|
370
428
|
}
|
|
371
|
-
|
|
372
|
-
|
|
373
|
-
|
|
374
|
-
|
|
375
|
-
|
|
376
|
-
|
|
377
|
-
|
|
378
|
-
|
|
379
|
-
|
|
380
|
-
|
|
381
|
-
|
|
382
|
-
|
|
383
|
-
|
|
384
|
-
|
|
385
|
-
|
|
429
|
+
function normalizeDigits(text) {
|
|
430
|
+
const map = nativeDigits();
|
|
431
|
+
return text.replace(/\p{Nd}/gu, (d) => map.get(d) ?? d);
|
|
432
|
+
}
|
|
433
|
+
function dayPeriodWords(locale) {
|
|
434
|
+
try {
|
|
435
|
+
const word = (hour) => new Intl.DateTimeFormat(locale, {
|
|
436
|
+
hour: "numeric",
|
|
437
|
+
hourCycle: "h12",
|
|
438
|
+
timeZone: "UTC"
|
|
439
|
+
}).formatToParts(new Date(Date.UTC(2021, 4, 6, hour))).find((p) => p.type === "dayPeriod")?.value.toLowerCase().replace(/[.\s\u00a0\u202f]/g, "") ?? "";
|
|
440
|
+
const am = word(9);
|
|
441
|
+
const pm = word(15);
|
|
442
|
+
return am && pm && am !== pm ? {
|
|
443
|
+
am,
|
|
444
|
+
pm
|
|
445
|
+
} : null;
|
|
446
|
+
} catch {
|
|
447
|
+
return null;
|
|
448
|
+
}
|
|
449
|
+
}
|
|
450
|
+
function parseTimeInput(text, locale) {
|
|
451
|
+
let typed = normalizeDigits(text).trim().toLowerCase();
|
|
452
|
+
const words = dayPeriodWords(locale);
|
|
453
|
+
if (words) {
|
|
454
|
+
const compact = typed.replace(/[.\s\u00a0\u202f]/g, "");
|
|
455
|
+
if (compact.endsWith(words.pm)) typed = `${compact.slice(0, -words.pm.length)} pm`;
|
|
456
|
+
else if (compact.endsWith(words.am)) typed = `${compact.slice(0, -words.am.length)} am`;
|
|
457
|
+
else if (compact.startsWith(words.pm)) typed = `${compact.slice(words.pm.length)} pm`;
|
|
458
|
+
else if (compact.startsWith(words.am)) typed = `${compact.slice(words.am.length)} am`;
|
|
459
|
+
}
|
|
460
|
+
const m = /^(\d{1,2})[:.]?(\d{2})\s*([ap])\.?m\.?$|^(\d{1,2})[:.]?(\d{2})$/.exec(typed);
|
|
461
|
+
if (!m) return null;
|
|
462
|
+
let hour = Number(m[1] ?? m[4]);
|
|
463
|
+
const minute = Number(m[2] ?? m[5]);
|
|
464
|
+
const meridiem = m[3];
|
|
465
|
+
if (meridiem === "p" && hour < 12) hour += 12;
|
|
466
|
+
if (meridiem === "a" && hour === 12) hour = 0;
|
|
467
|
+
if (hour > 23 || minute > 59) return null;
|
|
468
|
+
return formatIsoTime({
|
|
469
|
+
hour,
|
|
470
|
+
minute
|
|
471
|
+
});
|
|
386
472
|
}
|
|
387
|
-
/** Does this locale write times on a 12-hour clock? */
|
|
388
473
|
function localeUsesHour12(loc) {
|
|
389
|
-
|
|
390
|
-
|
|
391
|
-
|
|
392
|
-
|
|
393
|
-
|
|
394
|
-
|
|
395
|
-
|
|
396
|
-
|
|
397
|
-
return false;
|
|
398
|
-
}
|
|
474
|
+
try {
|
|
475
|
+
return new Intl.DateTimeFormat(loc, {
|
|
476
|
+
hour: "numeric",
|
|
477
|
+
timeZone: "UTC"
|
|
478
|
+
}).formatToParts(new Date(Date.UTC(2021, 0, 1, 13))).some((p) => p.type === "dayPeriod");
|
|
479
|
+
} catch {
|
|
480
|
+
return false;
|
|
481
|
+
}
|
|
399
482
|
}
|
|
400
|
-
/** The host's current calendar day, read via the *local* getters. */
|
|
401
483
|
function todayIso() {
|
|
402
|
-
|
|
403
|
-
|
|
404
|
-
|
|
405
|
-
|
|
406
|
-
|
|
407
|
-
|
|
484
|
+
const now = /* @__PURE__ */ new Date();
|
|
485
|
+
return formatIsoDate({
|
|
486
|
+
year: now.getFullYear(),
|
|
487
|
+
month: now.getMonth() + 1,
|
|
488
|
+
day: now.getDate()
|
|
489
|
+
});
|
|
408
490
|
}
|
|
409
491
|
let uid = 0;
|
|
410
|
-
/** Stable per-instance id prefix; SSR-safe (no Math.random / Date.now). */
|
|
411
492
|
function nextDateTimePickerId() {
|
|
412
|
-
|
|
413
|
-
|
|
414
|
-
}
|
|
415
|
-
/**
|
|
416
|
-
* Optional marker for the projected icon template. Gives consumers typed
|
|
417
|
-
* `let-` variables:
|
|
418
|
-
*
|
|
419
|
-
* ```html
|
|
420
|
-
* <lily-date-time-picker label="Choose a date" [labels]="labels">
|
|
421
|
-
* <ng-template lilyDateTimePickerIcon let-args>{{ args.open ? "×" : "📅" }}</ng-template>
|
|
422
|
-
* </lily-date-time-picker>
|
|
423
|
-
* ```
|
|
424
|
-
*
|
|
425
|
-
* The component queries any projected `<ng-template>`, so the marker is
|
|
426
|
-
* for type-checking and readability, not for matching.
|
|
427
|
-
*/
|
|
428
|
-
class DateTimePickerIcon {
|
|
429
|
-
static ngTemplateContextGuard(_dir, _ctx) {
|
|
430
|
-
return true;
|
|
431
|
-
}
|
|
432
|
-
static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "22.1.7", ngImport: i0, type: DateTimePickerIcon, deps: [], target: i0.ɵɵFactoryTarget.Directive }); }
|
|
433
|
-
static { this.ɵdir = i0.ɵɵngDeclareDirective({ minVersion: "14.0.0", version: "22.1.7", type: DateTimePickerIcon, isStandalone: true, selector: "ng-template[lilyDateTimePickerIcon]", ngImport: i0 }); }
|
|
493
|
+
uid += 1;
|
|
494
|
+
return `date-time-picker-${uid}`;
|
|
434
495
|
}
|
|
435
|
-
|
|
436
|
-
|
|
437
|
-
|
|
438
|
-
|
|
439
|
-
|
|
440
|
-
|
|
441
|
-
|
|
442
|
-
|
|
443
|
-
|
|
444
|
-
|
|
445
|
-
|
|
446
|
-
|
|
447
|
-
|
|
448
|
-
|
|
449
|
-
|
|
450
|
-
|
|
451
|
-
|
|
452
|
-
|
|
453
|
-
|
|
454
|
-
|
|
455
|
-
|
|
456
|
-
|
|
457
|
-
|
|
458
|
-
|
|
459
|
-
|
|
460
|
-
|
|
461
|
-
|
|
462
|
-
|
|
463
|
-
|
|
464
|
-
|
|
465
|
-
|
|
466
|
-
|
|
467
|
-
|
|
468
|
-
|
|
469
|
-
|
|
470
|
-
|
|
471
|
-
|
|
472
|
-
|
|
473
|
-
|
|
474
|
-
|
|
475
|
-
|
|
476
|
-
|
|
477
|
-
|
|
478
|
-
|
|
479
|
-
|
|
480
|
-
|
|
481
|
-
|
|
482
|
-
|
|
483
|
-
|
|
484
|
-
|
|
485
|
-
|
|
486
|
-
|
|
487
|
-
|
|
488
|
-
|
|
489
|
-
|
|
490
|
-
|
|
491
|
-
|
|
492
|
-
|
|
493
|
-
|
|
494
|
-
|
|
495
|
-
|
|
496
|
-
|
|
497
|
-
|
|
498
|
-
|
|
499
|
-
|
|
500
|
-
|
|
501
|
-
|
|
502
|
-
|
|
503
|
-
|
|
504
|
-
|
|
505
|
-
|
|
506
|
-
|
|
507
|
-
|
|
508
|
-
|
|
509
|
-
|
|
510
|
-
|
|
511
|
-
|
|
512
|
-
|
|
513
|
-
|
|
514
|
-
|
|
515
|
-
|
|
516
|
-
|
|
517
|
-
|
|
518
|
-
|
|
519
|
-
|
|
520
|
-
|
|
521
|
-
|
|
522
|
-
|
|
523
|
-
|
|
524
|
-
|
|
525
|
-
|
|
526
|
-
|
|
527
|
-
|
|
528
|
-
|
|
529
|
-
|
|
530
|
-
|
|
531
|
-
|
|
532
|
-
|
|
533
|
-
|
|
534
|
-
|
|
535
|
-
|
|
536
|
-
|
|
537
|
-
|
|
538
|
-
|
|
539
|
-
|
|
540
|
-
|
|
541
|
-
|
|
542
|
-
|
|
543
|
-
|
|
544
|
-
|
|
545
|
-
|
|
546
|
-
|
|
547
|
-
|
|
548
|
-
|
|
549
|
-
|
|
550
|
-
|
|
551
|
-
|
|
552
|
-
|
|
553
|
-
|
|
554
|
-
|
|
555
|
-
|
|
556
|
-
|
|
557
|
-
|
|
558
|
-
|
|
559
|
-
|
|
560
|
-
|
|
561
|
-
|
|
562
|
-
|
|
563
|
-
|
|
564
|
-
|
|
565
|
-
|
|
566
|
-
|
|
567
|
-
|
|
568
|
-
|
|
569
|
-
|
|
570
|
-
|
|
571
|
-
|
|
572
|
-
|
|
573
|
-
|
|
574
|
-
|
|
575
|
-
|
|
576
|
-
|
|
577
|
-
|
|
578
|
-
|
|
579
|
-
|
|
580
|
-
|
|
581
|
-
|
|
582
|
-
|
|
583
|
-
|
|
584
|
-
|
|
585
|
-
|
|
586
|
-
|
|
587
|
-
|
|
588
|
-
|
|
589
|
-
|
|
590
|
-
|
|
591
|
-
|
|
592
|
-
|
|
593
|
-
|
|
594
|
-
|
|
595
|
-
|
|
596
|
-
|
|
597
|
-
|
|
598
|
-
|
|
599
|
-
|
|
600
|
-
|
|
601
|
-
|
|
602
|
-
|
|
603
|
-
|
|
604
|
-
|
|
605
|
-
|
|
606
|
-
|
|
607
|
-
|
|
608
|
-
|
|
609
|
-
|
|
610
|
-
|
|
611
|
-
|
|
612
|
-
|
|
613
|
-
|
|
614
|
-
|
|
615
|
-
|
|
616
|
-
|
|
617
|
-
|
|
618
|
-
|
|
619
|
-
|
|
620
|
-
|
|
621
|
-
|
|
622
|
-
|
|
623
|
-
|
|
624
|
-
|
|
625
|
-
|
|
626
|
-
|
|
627
|
-
|
|
628
|
-
|
|
629
|
-
|
|
630
|
-
|
|
631
|
-
|
|
632
|
-
|
|
633
|
-
|
|
634
|
-
|
|
635
|
-
|
|
636
|
-
|
|
637
|
-
|
|
638
|
-
|
|
639
|
-
|
|
640
|
-
|
|
641
|
-
|
|
642
|
-
|
|
643
|
-
|
|
644
|
-
|
|
645
|
-
|
|
646
|
-
|
|
647
|
-
|
|
648
|
-
|
|
649
|
-
|
|
650
|
-
|
|
651
|
-
|
|
652
|
-
|
|
653
|
-
|
|
654
|
-
|
|
655
|
-
|
|
656
|
-
|
|
657
|
-
|
|
658
|
-
|
|
659
|
-
|
|
660
|
-
|
|
661
|
-
|
|
662
|
-
|
|
663
|
-
|
|
664
|
-
|
|
665
|
-
|
|
666
|
-
|
|
667
|
-
|
|
668
|
-
|
|
669
|
-
|
|
670
|
-
|
|
671
|
-
|
|
672
|
-
|
|
673
|
-
|
|
674
|
-
|
|
675
|
-
|
|
676
|
-
|
|
677
|
-
|
|
678
|
-
|
|
679
|
-
|
|
680
|
-
|
|
681
|
-
|
|
682
|
-
|
|
683
|
-
|
|
684
|
-
|
|
685
|
-
|
|
686
|
-
|
|
687
|
-
|
|
688
|
-
|
|
689
|
-
|
|
690
|
-
|
|
691
|
-
|
|
692
|
-
|
|
693
|
-
|
|
694
|
-
|
|
695
|
-
|
|
696
|
-
|
|
697
|
-
|
|
698
|
-
|
|
699
|
-
|
|
700
|
-
|
|
701
|
-
|
|
702
|
-
|
|
703
|
-
|
|
704
|
-
|
|
705
|
-
|
|
706
|
-
|
|
707
|
-
|
|
708
|
-
|
|
709
|
-
|
|
710
|
-
|
|
711
|
-
|
|
712
|
-
|
|
713
|
-
|
|
714
|
-
|
|
715
|
-
|
|
716
|
-
|
|
717
|
-
|
|
718
|
-
|
|
719
|
-
|
|
720
|
-
|
|
721
|
-
|
|
722
|
-
|
|
723
|
-
|
|
724
|
-
|
|
725
|
-
|
|
726
|
-
|
|
727
|
-
|
|
728
|
-
|
|
729
|
-
|
|
730
|
-
|
|
731
|
-
|
|
732
|
-
|
|
733
|
-
|
|
734
|
-
|
|
735
|
-
|
|
736
|
-
|
|
737
|
-
|
|
738
|
-
|
|
739
|
-
|
|
740
|
-
|
|
741
|
-
|
|
742
|
-
|
|
743
|
-
|
|
744
|
-
|
|
745
|
-
|
|
746
|
-
|
|
747
|
-
|
|
748
|
-
|
|
749
|
-
|
|
750
|
-
|
|
751
|
-
|
|
752
|
-
|
|
753
|
-
|
|
754
|
-
|
|
755
|
-
|
|
756
|
-
|
|
757
|
-
|
|
758
|
-
|
|
759
|
-
|
|
760
|
-
|
|
761
|
-
|
|
762
|
-
|
|
763
|
-
|
|
764
|
-
|
|
765
|
-
|
|
766
|
-
|
|
767
|
-
|
|
768
|
-
|
|
769
|
-
|
|
770
|
-
|
|
771
|
-
|
|
772
|
-
|
|
773
|
-
|
|
774
|
-
|
|
775
|
-
|
|
776
|
-
|
|
777
|
-
|
|
778
|
-
|
|
779
|
-
|
|
780
|
-
|
|
781
|
-
|
|
782
|
-
|
|
783
|
-
|
|
784
|
-
|
|
785
|
-
|
|
786
|
-
|
|
787
|
-
|
|
788
|
-
|
|
789
|
-
|
|
790
|
-
|
|
791
|
-
|
|
792
|
-
|
|
793
|
-
|
|
794
|
-
|
|
795
|
-
|
|
796
|
-
|
|
797
|
-
|
|
798
|
-
|
|
799
|
-
|
|
800
|
-
|
|
801
|
-
|
|
802
|
-
|
|
803
|
-
|
|
804
|
-
|
|
805
|
-
|
|
806
|
-
|
|
807
|
-
|
|
808
|
-
|
|
809
|
-
|
|
810
|
-
|
|
811
|
-
|
|
812
|
-
|
|
813
|
-
|
|
814
|
-
|
|
815
|
-
|
|
816
|
-
|
|
817
|
-
|
|
818
|
-
|
|
819
|
-
|
|
820
|
-
|
|
821
|
-
|
|
822
|
-
|
|
823
|
-
|
|
824
|
-
|
|
825
|
-
|
|
826
|
-
|
|
827
|
-
|
|
828
|
-
|
|
829
|
-
|
|
830
|
-
|
|
831
|
-
|
|
832
|
-
|
|
833
|
-
|
|
834
|
-
|
|
835
|
-
|
|
836
|
-
|
|
837
|
-
|
|
838
|
-
|
|
839
|
-
|
|
840
|
-
|
|
841
|
-
|
|
842
|
-
|
|
843
|
-
|
|
844
|
-
|
|
845
|
-
|
|
846
|
-
|
|
847
|
-
|
|
848
|
-
|
|
849
|
-
|
|
850
|
-
|
|
851
|
-
|
|
852
|
-
|
|
853
|
-
|
|
854
|
-
|
|
855
|
-
|
|
856
|
-
|
|
857
|
-
|
|
858
|
-
|
|
859
|
-
|
|
860
|
-
|
|
861
|
-
|
|
862
|
-
|
|
863
|
-
|
|
864
|
-
|
|
865
|
-
|
|
866
|
-
|
|
867
|
-
|
|
868
|
-
|
|
869
|
-
|
|
870
|
-
|
|
871
|
-
|
|
872
|
-
|
|
873
|
-
|
|
874
|
-
|
|
875
|
-
|
|
876
|
-
|
|
877
|
-
|
|
878
|
-
|
|
879
|
-
|
|
880
|
-
|
|
881
|
-
|
|
882
|
-
|
|
883
|
-
|
|
884
|
-
|
|
885
|
-
|
|
886
|
-
|
|
887
|
-
|
|
888
|
-
|
|
889
|
-
|
|
890
|
-
|
|
891
|
-
|
|
892
|
-
|
|
893
|
-
|
|
894
|
-
|
|
895
|
-
|
|
896
|
-
|
|
897
|
-
|
|
898
|
-
|
|
899
|
-
|
|
900
|
-
|
|
901
|
-
|
|
902
|
-
|
|
903
|
-
|
|
904
|
-
|
|
905
|
-
|
|
906
|
-
|
|
907
|
-
|
|
908
|
-
|
|
909
|
-
|
|
910
|
-
|
|
911
|
-
|
|
912
|
-
|
|
913
|
-
|
|
914
|
-
|
|
915
|
-
|
|
916
|
-
|
|
917
|
-
|
|
918
|
-
|
|
919
|
-
|
|
920
|
-
|
|
921
|
-
|
|
922
|
-
|
|
923
|
-
|
|
924
|
-
|
|
925
|
-
|
|
926
|
-
|
|
927
|
-
|
|
928
|
-
|
|
929
|
-
|
|
930
|
-
|
|
931
|
-
|
|
932
|
-
|
|
933
|
-
|
|
934
|
-
|
|
935
|
-
|
|
936
|
-
|
|
937
|
-
|
|
938
|
-
|
|
939
|
-
|
|
940
|
-
|
|
941
|
-
|
|
942
|
-
|
|
943
|
-
|
|
944
|
-
|
|
945
|
-
|
|
946
|
-
|
|
947
|
-
|
|
948
|
-
|
|
949
|
-
|
|
950
|
-
|
|
951
|
-
|
|
952
|
-
|
|
953
|
-
|
|
954
|
-
|
|
955
|
-
|
|
956
|
-
|
|
957
|
-
|
|
958
|
-
|
|
959
|
-
|
|
960
|
-
|
|
961
|
-
|
|
962
|
-
|
|
963
|
-
|
|
964
|
-
|
|
965
|
-
|
|
966
|
-
|
|
967
|
-
|
|
968
|
-
|
|
969
|
-
|
|
970
|
-
|
|
971
|
-
|
|
972
|
-
|
|
973
|
-
|
|
974
|
-
|
|
975
|
-
|
|
976
|
-
|
|
977
|
-
|
|
978
|
-
|
|
979
|
-
|
|
980
|
-
|
|
981
|
-
|
|
982
|
-
|
|
983
|
-
|
|
984
|
-
|
|
985
|
-
|
|
986
|
-
|
|
987
|
-
|
|
988
|
-
|
|
989
|
-
|
|
990
|
-
|
|
991
|
-
|
|
992
|
-
|
|
993
|
-
|
|
994
|
-
|
|
995
|
-
|
|
996
|
-
|
|
997
|
-
|
|
998
|
-
|
|
999
|
-
|
|
1000
|
-
|
|
1001
|
-
|
|
1002
|
-
|
|
1003
|
-
|
|
1004
|
-
|
|
1005
|
-
|
|
1006
|
-
|
|
1007
|
-
|
|
1008
|
-
|
|
1009
|
-
|
|
1010
|
-
|
|
1011
|
-
|
|
1012
|
-
|
|
1013
|
-
|
|
1014
|
-
|
|
1015
|
-
|
|
1016
|
-
|
|
1017
|
-
|
|
1018
|
-
|
|
1019
|
-
|
|
1020
|
-
|
|
1021
|
-
|
|
1022
|
-
|
|
1023
|
-
|
|
1024
|
-
|
|
1025
|
-
|
|
1026
|
-
|
|
1027
|
-
|
|
1028
|
-
|
|
1029
|
-
|
|
1030
|
-
|
|
1031
|
-
|
|
1032
|
-
|
|
1033
|
-
|
|
1034
|
-
|
|
1035
|
-
|
|
1036
|
-
|
|
1037
|
-
|
|
1038
|
-
|
|
1039
|
-
|
|
1040
|
-
|
|
1041
|
-
|
|
1042
|
-
|
|
1043
|
-
|
|
1044
|
-
|
|
1045
|
-
|
|
1046
|
-
|
|
1047
|
-
|
|
1048
|
-
|
|
1049
|
-
|
|
1050
|
-
|
|
1051
|
-
|
|
1052
|
-
|
|
1053
|
-
|
|
1054
|
-
|
|
1055
|
-
|
|
1056
|
-
|
|
1057
|
-
|
|
1058
|
-
|
|
1059
|
-
|
|
1060
|
-
|
|
1061
|
-
|
|
1062
|
-
|
|
1063
|
-
|
|
1064
|
-
|
|
1065
|
-
|
|
1066
|
-
|
|
1067
|
-
|
|
1068
|
-
|
|
1069
|
-
|
|
1070
|
-
|
|
1071
|
-
|
|
1072
|
-
|
|
1073
|
-
|
|
1074
|
-
|
|
1075
|
-
|
|
1076
|
-
|
|
1077
|
-
|
|
1078
|
-
|
|
1079
|
-
|
|
1080
|
-
|
|
1081
|
-
|
|
1082
|
-
|
|
1083
|
-
|
|
1084
|
-
|
|
1085
|
-
|
|
1086
|
-
|
|
1087
|
-
|
|
1088
|
-
|
|
1089
|
-
|
|
1090
|
-
|
|
1091
|
-
|
|
1092
|
-
|
|
1093
|
-
|
|
1094
|
-
|
|
1095
|
-
|
|
1096
|
-
|
|
1097
|
-
|
|
1098
|
-
|
|
1099
|
-
|
|
1100
|
-
|
|
1101
|
-
|
|
1102
|
-
|
|
1103
|
-
|
|
1104
|
-
|
|
1105
|
-
|
|
1106
|
-
|
|
1107
|
-
|
|
1108
|
-
|
|
1109
|
-
|
|
1110
|
-
|
|
1111
|
-
|
|
1112
|
-
|
|
1113
|
-
|
|
1114
|
-
|
|
1115
|
-
|
|
1116
|
-
|
|
1117
|
-
|
|
1118
|
-
|
|
1119
|
-
|
|
1120
|
-
|
|
1121
|
-
|
|
1122
|
-
|
|
1123
|
-
|
|
1124
|
-
|
|
1125
|
-
|
|
1126
|
-
|
|
1127
|
-
|
|
1128
|
-
|
|
1129
|
-
|
|
1130
|
-
|
|
1131
|
-
|
|
1132
|
-
|
|
1133
|
-
|
|
1134
|
-
|
|
1135
|
-
|
|
1136
|
-
|
|
1137
|
-
|
|
1138
|
-
|
|
1139
|
-
|
|
1140
|
-
|
|
1141
|
-
|
|
1142
|
-
|
|
1143
|
-
|
|
1144
|
-
|
|
1145
|
-
|
|
1146
|
-
|
|
1147
|
-
|
|
1148
|
-
|
|
1149
|
-
|
|
1150
|
-
|
|
1151
|
-
|
|
1152
|
-
|
|
1153
|
-
|
|
1154
|
-
|
|
1155
|
-
|
|
1156
|
-
|
|
1157
|
-
|
|
1158
|
-
|
|
1159
|
-
|
|
1160
|
-
|
|
1161
|
-
|
|
1162
|
-
|
|
1163
|
-
|
|
1164
|
-
|
|
1165
|
-
|
|
1166
|
-
|
|
1167
|
-
|
|
1168
|
-
|
|
1169
|
-
|
|
1170
|
-
|
|
1171
|
-
|
|
1172
|
-
|
|
1173
|
-
|
|
1174
|
-
|
|
1175
|
-
|
|
1176
|
-
|
|
1177
|
-
|
|
1178
|
-
|
|
1179
|
-
|
|
1180
|
-
|
|
1181
|
-
|
|
1182
|
-
|
|
1183
|
-
|
|
1184
|
-
|
|
1185
|
-
|
|
1186
|
-
|
|
1187
|
-
|
|
1188
|
-
|
|
1189
|
-
|
|
1190
|
-
|
|
1191
|
-
|
|
1192
|
-
|
|
1193
|
-
|
|
1194
|
-
|
|
1195
|
-
|
|
1196
|
-
|
|
1197
|
-
|
|
1198
|
-
|
|
1199
|
-
|
|
1200
|
-
|
|
1201
|
-
|
|
1202
|
-
|
|
1203
|
-
|
|
1204
|
-
|
|
1205
|
-
|
|
1206
|
-
|
|
1207
|
-
|
|
1208
|
-
|
|
1209
|
-
|
|
1210
|
-
|
|
1211
|
-
|
|
1212
|
-
|
|
1213
|
-
|
|
1214
|
-
|
|
1215
|
-
|
|
1216
|
-
|
|
1217
|
-
|
|
1218
|
-
|
|
1219
|
-
|
|
1220
|
-
|
|
1221
|
-
|
|
1222
|
-
|
|
1223
|
-
|
|
1224
|
-
|
|
1225
|
-
|
|
1226
|
-
|
|
1227
|
-
|
|
1228
|
-
|
|
1229
|
-
|
|
1230
|
-
|
|
1231
|
-
|
|
1232
|
-
|
|
1233
|
-
|
|
1234
|
-
|
|
1235
|
-
|
|
1236
|
-
|
|
1237
|
-
|
|
1238
|
-
|
|
1239
|
-
|
|
1240
|
-
|
|
1241
|
-
|
|
1242
|
-
|
|
1243
|
-
|
|
1244
|
-
|
|
1245
|
-
|
|
1246
|
-
|
|
1247
|
-
|
|
1248
|
-
|
|
1249
|
-
|
|
1250
|
-
|
|
1251
|
-
|
|
1252
|
-
|
|
1253
|
-
|
|
1254
|
-
|
|
1255
|
-
|
|
1256
|
-
|
|
1257
|
-
|
|
1258
|
-
|
|
1259
|
-
|
|
1260
|
-
|
|
1261
|
-
|
|
1262
|
-
|
|
1263
|
-
|
|
1264
|
-
|
|
1265
|
-
|
|
1266
|
-
|
|
1267
|
-
|
|
1268
|
-
|
|
1269
|
-
|
|
1270
|
-
|
|
1271
|
-
|
|
1272
|
-
|
|
1273
|
-
|
|
1274
|
-
|
|
1275
|
-
|
|
1276
|
-
|
|
1277
|
-
|
|
1278
|
-
|
|
1279
|
-
|
|
1280
|
-
|
|
1281
|
-
|
|
1282
|
-
|
|
1283
|
-
|
|
1284
|
-
|
|
1285
|
-
|
|
1286
|
-
|
|
1287
|
-
|
|
1288
|
-
|
|
1289
|
-
|
|
1290
|
-
|
|
1291
|
-
|
|
1292
|
-
|
|
1293
|
-
|
|
1294
|
-
|
|
1295
|
-
|
|
1296
|
-
|
|
1297
|
-
|
|
1298
|
-
|
|
1299
|
-
|
|
1300
|
-
|
|
1301
|
-
|
|
1302
|
-
|
|
1303
|
-
|
|
1304
|
-
|
|
1305
|
-
|
|
1306
|
-
|
|
1307
|
-
|
|
1308
|
-
|
|
1309
|
-
|
|
1310
|
-
|
|
1311
|
-
|
|
1312
|
-
|
|
1313
|
-
|
|
1314
|
-
|
|
1315
|
-
|
|
1316
|
-
|
|
1317
|
-
|
|
1318
|
-
|
|
1319
|
-
|
|
1320
|
-
|
|
1321
|
-
|
|
1322
|
-
|
|
1323
|
-
|
|
1324
|
-
|
|
1325
|
-
|
|
1326
|
-
|
|
1327
|
-
|
|
1328
|
-
setMinute(minute) {
|
|
1329
|
-
this.pendingTime.set(formatIsoTime({ hour: this.pendingHour(), minute }));
|
|
1330
|
-
}
|
|
1331
|
-
/** Cross between AM and PM without changing the minute of the hour. */
|
|
1332
|
-
setMeridiem(pm) {
|
|
1333
|
-
this.setHour((this.pendingHour() % 12) + (pm ? 12 : 0));
|
|
1334
|
-
}
|
|
1335
|
-
// ---------------------------------------------------------------
|
|
1336
|
-
// Shortcuts
|
|
1337
|
-
// ---------------------------------------------------------------
|
|
1338
|
-
applyShortcut(shortcut) {
|
|
1339
|
-
const base = todayIso();
|
|
1340
|
-
let target = shortcut.date ?? base;
|
|
1341
|
-
if (shortcut.days !== undefined)
|
|
1342
|
-
target = addDays(base, shortcut.days);
|
|
1343
|
-
else if (shortcut.months !== undefined) {
|
|
1344
|
-
target = addMonths(base, shortcut.months);
|
|
1345
|
-
}
|
|
1346
|
-
// A shortcut to a blocked date does nothing rather than landing
|
|
1347
|
-
// somewhere near it: "+4 weeks" that quietly means "+27 days" is a
|
|
1348
|
-
// booking error waiting to happen.
|
|
1349
|
-
if (this.dayDisabled(target))
|
|
1350
|
-
return;
|
|
1351
|
-
this.pendingDate.set(target);
|
|
1352
|
-
this.cursor.set(target);
|
|
1353
|
-
const parsed = parseIsoDate(target);
|
|
1354
|
-
if (parsed) {
|
|
1355
|
-
this.viewYear.set(parsed.year);
|
|
1356
|
-
this.viewMonth.set(parsed.month);
|
|
1357
|
-
}
|
|
1358
|
-
this.shortcut.emit({ id: shortcut.id, isoDate: target });
|
|
1359
|
-
if (this.commitOnDay())
|
|
1360
|
-
this.commit();
|
|
1361
|
-
else {
|
|
1362
|
-
// Render-then-focus: the shortcut may have paged to a month whose
|
|
1363
|
-
// cells do not exist until change detection has run. See `cdr`.
|
|
1364
|
-
this.cdr.detectChanges();
|
|
1365
|
-
this.focusCursor();
|
|
1366
|
-
}
|
|
1367
|
-
}
|
|
1368
|
-
// ---------------------------------------------------------------
|
|
1369
|
-
// Dismissal
|
|
1370
|
-
// ---------------------------------------------------------------
|
|
1371
|
-
onDocumentClick(event) {
|
|
1372
|
-
if (!this.open())
|
|
1373
|
-
return;
|
|
1374
|
-
const target = event.target;
|
|
1375
|
-
if (!target)
|
|
1376
|
-
return;
|
|
1377
|
-
// Anything outside the dialog closes it — including the component's
|
|
1378
|
-
// own text field. The dialog says aria-modal="true", and a modal
|
|
1379
|
-
// that stays open while the user edits the field behind it is
|
|
1380
|
-
// telling assistive technology one thing and doing another. The
|
|
1381
|
-
// trigger button is exempt because its own handler already toggles.
|
|
1382
|
-
if (this.dialogRef().nativeElement.contains(target) ||
|
|
1383
|
-
(this.buttonRef().element?.contains(target) ?? false)) {
|
|
1384
|
-
return;
|
|
1385
|
-
}
|
|
1386
|
-
this.closeDialog(false);
|
|
1387
|
-
}
|
|
1388
|
-
static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "22.1.7", ngImport: i0, type: DateTimePicker, deps: [], target: i0.ɵɵFactoryTarget.Component }); }
|
|
1389
|
-
static { this.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "22.1.7", type: DateTimePicker, isStandalone: true, selector: "lily-date-time-picker", inputs: { label: { classPropertyName: "label", publicName: "label", isSignal: true, isRequired: true, transformFunction: null }, labels: { classPropertyName: "labels", publicName: "labels", isSignal: true, isRequired: true, transformFunction: null }, mode: { classPropertyName: "mode", publicName: "mode", isSignal: true, isRequired: false, transformFunction: null }, value: { classPropertyName: "value", publicName: "value", isSignal: true, isRequired: false, transformFunction: null }, locale: { classPropertyName: "locale", publicName: "locale", isSignal: true, isRequired: false, transformFunction: null }, min: { classPropertyName: "min", publicName: "min", isSignal: true, isRequired: false, transformFunction: null }, max: { classPropertyName: "max", publicName: "max", isSignal: true, isRequired: false, transformFunction: null }, isDateDisabled: { classPropertyName: "isDateDisabled", publicName: "isDateDisabled", isSignal: true, isRequired: false, transformFunction: null }, firstDayOfWeek: { classPropertyName: "firstDayOfWeek", publicName: "firstDayOfWeek", isSignal: true, isRequired: false, transformFunction: null }, minuteStep: { classPropertyName: "minuteStep", publicName: "minuteStep", isSignal: true, isRequired: false, transformFunction: null }, hour12: { classPropertyName: "hour12", publicName: "hour12", isSignal: true, isRequired: false, transformFunction: null }, showWeekNumbers: { classPropertyName: "showWeekNumbers", publicName: "showWeekNumbers", isSignal: true, isRequired: false, transformFunction: null }, shortcuts: { classPropertyName: "shortcuts", publicName: "shortcuts", isSignal: true, isRequired: false, transformFunction: null }, confirmOnSelect: { classPropertyName: "confirmOnSelect", publicName: "confirmOnSelect", isSignal: true, isRequired: false, transformFunction: null }, name: { classPropertyName: "name", publicName: "name", isSignal: true, isRequired: false, transformFunction: null }, timeZone: { classPropertyName: "timeZone", publicName: "timeZone", isSignal: true, isRequired: false, transformFunction: null }, timeZones: { classPropertyName: "timeZones", publicName: "timeZones", isSignal: true, isRequired: false, transformFunction: null }, timeZoneLabels: { classPropertyName: "timeZoneLabels", publicName: "timeZoneLabels", isSignal: true, isRequired: false, transformFunction: null }, inputId: { classPropertyName: "inputId", publicName: "inputId", isSignal: true, isRequired: false, transformFunction: null }, describedBy: { classPropertyName: "describedBy", publicName: "describedBy", isSignal: true, isRequired: false, transformFunction: null }, placeholder: { classPropertyName: "placeholder", publicName: "placeholder", isSignal: true, isRequired: false, transformFunction: null }, disabled: { classPropertyName: "disabled", publicName: "disabled", isSignal: true, isRequired: false, transformFunction: null }, readOnly: { classPropertyName: "readOnly", publicName: "readOnly", isSignal: true, isRequired: false, transformFunction: null }, required: { classPropertyName: "required", publicName: "required", isSignal: true, isRequired: false, transformFunction: null }, formatValue: { classPropertyName: "formatValue", publicName: "formatValue", isSignal: true, isRequired: false, transformFunction: null }, parseInput: { classPropertyName: "parseInput", publicName: "parseInput", isSignal: true, isRequired: false, transformFunction: null }, className: { classPropertyName: "className", publicName: "className", isSignal: true, isRequired: false, transformFunction: null } }, outputs: { value: "valueChange", timeZone: "timeZoneChange", change: "change", shortcut: "shortcut", invalidInput: "invalidInput" }, host: { listeners: { "document:click": "onDocumentClick($event)" } }, queries: [{ propertyName: "iconTemplate", first: true, predicate: TemplateRef, descendants: true, isSignal: true }], viewQueries: [{ propertyName: "rootRef", first: true, predicate: ["rootEl"], descendants: true, isSignal: true }, { propertyName: "buttonRef", first: true, predicate: ["buttonEl"], descendants: true, isSignal: true }, { propertyName: "dialogRef", first: true, predicate: ["dialogEl"], descendants: true, isSignal: true }, { propertyName: "gridRef", first: true, predicate: ["gridEl"], descendants: true, isSignal: true }], ngImport: i0, template: `
|
|
496
|
+
var DateTimePickerIcon = class DateTimePickerIcon {
|
|
497
|
+
static ngTemplateContextGuard(_dir, _ctx) {
|
|
498
|
+
return true;
|
|
499
|
+
}
|
|
500
|
+
static {
|
|
501
|
+
this.ɵfac = i0.ɵɵngDeclareFactory({
|
|
502
|
+
minVersion: "12.0.0",
|
|
503
|
+
version: "22.2.4",
|
|
504
|
+
ngImport: i0,
|
|
505
|
+
type: DateTimePickerIcon,
|
|
506
|
+
deps: [],
|
|
507
|
+
target: i0.ɵɵFactoryTarget.Directive
|
|
508
|
+
});
|
|
509
|
+
}
|
|
510
|
+
static {
|
|
511
|
+
this.ɵdir = i0.ɵɵngDeclareDirective({
|
|
512
|
+
minVersion: "14.0.0",
|
|
513
|
+
version: "22.2.4",
|
|
514
|
+
type: DateTimePickerIcon,
|
|
515
|
+
isStandalone: true,
|
|
516
|
+
selector: "ng-template[lilyDateTimePickerIcon]",
|
|
517
|
+
ngImport: i0
|
|
518
|
+
});
|
|
519
|
+
}
|
|
520
|
+
};
|
|
521
|
+
i0.ɵɵngDeclareClassMetadata({
|
|
522
|
+
minVersion: "12.0.0",
|
|
523
|
+
version: "22.2.4",
|
|
524
|
+
ngImport: i0,
|
|
525
|
+
type: DateTimePickerIcon,
|
|
526
|
+
decorators: [{
|
|
527
|
+
type: Directive,
|
|
528
|
+
args: [{
|
|
529
|
+
selector: "ng-template[lilyDateTimePickerIcon]",
|
|
530
|
+
standalone: true
|
|
531
|
+
}]
|
|
532
|
+
}]
|
|
533
|
+
});
|
|
534
|
+
var DateTimePicker = class DateTimePicker {
|
|
535
|
+
onTooltipButtonEnter() {
|
|
536
|
+
this.hoverButton.set(true);
|
|
537
|
+
this.dismissed.set(false);
|
|
538
|
+
}
|
|
539
|
+
onTooltipButtonFocusIn() {
|
|
540
|
+
try {
|
|
541
|
+
this.focusButton.set(this.buttonRef().element?.matches(":focus-visible") ?? false);
|
|
542
|
+
} catch {
|
|
543
|
+
this.focusButton.set(true);
|
|
544
|
+
}
|
|
545
|
+
}
|
|
546
|
+
onTooltipButtonFocusOut() {
|
|
547
|
+
this.focusButton.set(false);
|
|
548
|
+
this.dismissed.set(false);
|
|
549
|
+
}
|
|
550
|
+
onTooltipKeydown(event) {
|
|
551
|
+
if (event.key === "Escape" && this.tooltipVisible()) this.dismissed.set(true);
|
|
552
|
+
}
|
|
553
|
+
constructor() {
|
|
554
|
+
this.label = input.required(...ngDevMode ? [{ debugName: "label" }] : /* istanbul ignore next */ []);
|
|
555
|
+
this.labels = input.required(...ngDevMode ? [{ debugName: "labels" }] : /* istanbul ignore next */ []);
|
|
556
|
+
this.mode = input("date", ...ngDevMode ? [{ debugName: "mode" }] : /* istanbul ignore next */ []);
|
|
557
|
+
this.value = model("", ...ngDevMode ? [{ debugName: "value" }] : /* istanbul ignore next */ []);
|
|
558
|
+
this.locale = input("", ...ngDevMode ? [{ debugName: "locale" }] : /* istanbul ignore next */ []);
|
|
559
|
+
this.calendar = input("gregory", ...ngDevMode ? [{ debugName: "calendar" }] : /* istanbul ignore next */ []);
|
|
560
|
+
this.min = input("", ...ngDevMode ? [{ debugName: "min" }] : /* istanbul ignore next */ []);
|
|
561
|
+
this.max = input("", ...ngDevMode ? [{ debugName: "max" }] : /* istanbul ignore next */ []);
|
|
562
|
+
this.isDateDisabled = input(void 0, ...ngDevMode ? [{ debugName: "isDateDisabled" }] : /* istanbul ignore next */ []);
|
|
563
|
+
this.firstDayOfWeek = input(void 0, ...ngDevMode ? [{ debugName: "firstDayOfWeek" }] : /* istanbul ignore next */ []);
|
|
564
|
+
this.minuteStep = input(1, ...ngDevMode ? [{ debugName: "minuteStep" }] : /* istanbul ignore next */ []);
|
|
565
|
+
this.hour12 = input(void 0, ...ngDevMode ? [{ debugName: "hour12" }] : /* istanbul ignore next */ []);
|
|
566
|
+
this.showWeekNumbers = input(false, ...ngDevMode ? [{ debugName: "showWeekNumbers" }] : /* istanbul ignore next */ []);
|
|
567
|
+
this.shortcuts = input([], ...ngDevMode ? [{ debugName: "shortcuts" }] : /* istanbul ignore next */ []);
|
|
568
|
+
this.confirmOnSelect = input(void 0, ...ngDevMode ? [{ debugName: "confirmOnSelect" }] : /* istanbul ignore next */ []);
|
|
569
|
+
this.name = input("date-time", ...ngDevMode ? [{ debugName: "name" }] : /* istanbul ignore next */ []);
|
|
570
|
+
this.timeZone = model("", ...ngDevMode ? [{ debugName: "timeZone" }] : /* istanbul ignore next */ []);
|
|
571
|
+
this.timeZones = input(void 0, ...ngDevMode ? [{ debugName: "timeZones" }] : /* istanbul ignore next */ []);
|
|
572
|
+
this.timeZoneLabels = input({}, ...ngDevMode ? [{ debugName: "timeZoneLabels" }] : /* istanbul ignore next */ []);
|
|
573
|
+
this.inputId = input("", ...ngDevMode ? [{ debugName: "inputId" }] : /* istanbul ignore next */ []);
|
|
574
|
+
this.describedBy = input("", ...ngDevMode ? [{ debugName: "describedBy" }] : /* istanbul ignore next */ []);
|
|
575
|
+
this.placeholder = input("", ...ngDevMode ? [{ debugName: "placeholder" }] : /* istanbul ignore next */ []);
|
|
576
|
+
this.disabled = input(false, ...ngDevMode ? [{ debugName: "disabled" }] : /* istanbul ignore next */ []);
|
|
577
|
+
this.readOnly = input(false, ...ngDevMode ? [{ debugName: "readOnly" }] : /* istanbul ignore next */ []);
|
|
578
|
+
this.required = input(false, ...ngDevMode ? [{ debugName: "required" }] : /* istanbul ignore next */ []);
|
|
579
|
+
this.formatValue = input(void 0, ...ngDevMode ? [{ debugName: "formatValue" }] : /* istanbul ignore next */ []);
|
|
580
|
+
this.parseInput = input(void 0, ...ngDevMode ? [{ debugName: "parseInput" }] : /* istanbul ignore next */ []);
|
|
581
|
+
this.className = input("", ...ngDevMode ? [{ debugName: "className" }] : /* istanbul ignore next */ []);
|
|
582
|
+
this.change = output();
|
|
583
|
+
this.shortcut = output();
|
|
584
|
+
this.invalidInput = output();
|
|
585
|
+
this.iconTemplate = contentChild(TemplateRef, ...ngDevMode ? [{ debugName: "iconTemplate" }] : /* istanbul ignore next */ []);
|
|
586
|
+
this.rootRef = viewChild.required("rootEl", ...ngDevMode ? [{ debugName: "rootRef" }] : /* istanbul ignore next */ []);
|
|
587
|
+
this.buttonRef = viewChild.required("buttonEl", ...ngDevMode ? [{ debugName: "buttonRef" }] : /* istanbul ignore next */ []);
|
|
588
|
+
this.dialogRef = viewChild.required("dialogEl", ...ngDevMode ? [{ debugName: "dialogRef" }] : /* istanbul ignore next */ []);
|
|
589
|
+
this.gridRef = viewChild("gridEl", ...ngDevMode ? [{ debugName: "gridRef" }] : /* istanbul ignore next */ []);
|
|
590
|
+
this.glyph = CALENDAR;
|
|
591
|
+
this.cdr = inject(ChangeDetectorRef);
|
|
592
|
+
this.baseId = nextDateTimePickerId();
|
|
593
|
+
this.dialogId = `${this.baseId}-dialog`;
|
|
594
|
+
this.periodId = `${this.baseId}-period`;
|
|
595
|
+
this.hourId = `${this.baseId}-hour`;
|
|
596
|
+
this.minuteId = `${this.baseId}-minute`;
|
|
597
|
+
this.meridiemId = `${this.baseId}-meridiem`;
|
|
598
|
+
this.statusId = `${this.baseId}-status`;
|
|
599
|
+
this.instructionsId = `${this.baseId}-instructions`;
|
|
600
|
+
this.timeZoneId = `${this.baseId}-time-zone`;
|
|
601
|
+
this.open = signal(false, ...ngDevMode ? [{ debugName: "open" }] : /* istanbul ignore next */ []);
|
|
602
|
+
this.tooltipId = `${this.baseId}-tooltip`;
|
|
603
|
+
this.hoverButton = signal(false, ...ngDevMode ? [{ debugName: "hoverButton" }] : /* istanbul ignore next */ []);
|
|
604
|
+
this.hoverTooltip = signal(false, ...ngDevMode ? [{ debugName: "hoverTooltip" }] : /* istanbul ignore next */ []);
|
|
605
|
+
this.focusButton = signal(false, ...ngDevMode ? [{ debugName: "focusButton" }] : /* istanbul ignore next */ []);
|
|
606
|
+
this.dismissed = signal(false, ...ngDevMode ? [{ debugName: "dismissed" }] : /* istanbul ignore next */ []);
|
|
607
|
+
this.tooltipVisible = computed(() => !this.open() && !this.dismissed() && (this.hoverButton() || this.hoverTooltip() || this.focusButton()), ...ngDevMode ? [{ debugName: "tooltipVisible" }] : /* istanbul ignore next */ []);
|
|
608
|
+
this.tooltipEscapeListener = effect((onCleanup) => {
|
|
609
|
+
if (!this.tooltipVisible() || typeof document === "undefined") return;
|
|
610
|
+
const onKey = (event) => {
|
|
611
|
+
if (event.key === "Escape") this.dismissed.set(true);
|
|
612
|
+
};
|
|
613
|
+
document.addEventListener("keydown", onKey);
|
|
614
|
+
onCleanup(() => document.removeEventListener("keydown", onKey));
|
|
615
|
+
}, ...ngDevMode ? [{ debugName: "tooltipEscapeListener" }] : /* istanbul ignore next */ []);
|
|
616
|
+
this.invalid = signal(false, ...ngDevMode ? [{ debugName: "invalid" }] : /* istanbul ignore next */ []);
|
|
617
|
+
this.openerEl = null;
|
|
618
|
+
this.typed = signal(null, ...ngDevMode ? [{ debugName: "typed" }] : /* istanbul ignore next */ []);
|
|
619
|
+
this.pendingDate = signal("", ...ngDevMode ? [{ debugName: "pendingDate" }] : /* istanbul ignore next */ []);
|
|
620
|
+
this.pendingTime = signal("", ...ngDevMode ? [{ debugName: "pendingTime" }] : /* istanbul ignore next */ []);
|
|
621
|
+
this.viewStart = signal("1970-01-01", ...ngDevMode ? [{ debugName: "viewStart" }] : /* istanbul ignore next */ []);
|
|
622
|
+
this.cursor = signal("", ...ngDevMode ? [{ debugName: "cursor" }] : /* istanbul ignore next */ []);
|
|
623
|
+
this.today = signal("", ...ngDevMode ? [{ debugName: "today" }] : /* istanbul ignore next */ []);
|
|
624
|
+
this.fieldId = computed(() => this.inputId() || `${this.baseId}-input`, ...ngDevMode ? [{ debugName: "fieldId" }] : /* istanbul ignore next */ []);
|
|
625
|
+
this.committed = computed(() => splitValue(this.value(), this.mode()), ...ngDevMode ? [{ debugName: "committed" }] : /* istanbul ignore next */ []);
|
|
626
|
+
this.weekStart = computed(() => this.firstDayOfWeek() ?? firstDayOfWeekFor(this.locale() || void 0), ...ngDevMode ? [{ debugName: "weekStart" }] : /* istanbul ignore next */ []);
|
|
627
|
+
this.commitOnDay = computed(() => this.confirmOnSelect() ?? this.mode() === "date", ...ngDevMode ? [{ debugName: "commitOnDay" }] : /* istanbul ignore next */ []);
|
|
628
|
+
this.usesDate = computed(() => this.mode() !== "time", ...ngDevMode ? [{ debugName: "usesDate" }] : /* istanbul ignore next */ []);
|
|
629
|
+
this.usesTime = computed(() => this.mode() !== "date", ...ngDevMode ? [{ debugName: "usesTime" }] : /* istanbul ignore next */ []);
|
|
630
|
+
this.clock12 = computed(() => this.hour12() ?? localeUsesHour12(this.locale() || void 0), ...ngDevMode ? [{ debugName: "clock12" }] : /* istanbul ignore next */ []);
|
|
631
|
+
this.fieldDescribedBy = computed(() => [this.describedBy() || void 0, this.invalid() && this.labels().invalid ? this.statusId : void 0].filter(Boolean).join(" ") || null, ...ngDevMode ? [{ debugName: "fieldDescribedBy" }] : /* istanbul ignore next */ []);
|
|
632
|
+
this.display = computed(() => {
|
|
633
|
+
const t = this.typed();
|
|
634
|
+
if (t !== null) return t;
|
|
635
|
+
return (this.formatValue() ?? ((v) => this.defaultFormat(v)))(this.value());
|
|
636
|
+
}, ...ngDevMode ? [{ debugName: "display" }] : /* istanbul ignore next */ []);
|
|
637
|
+
this.zoneOptions = computed(() => {
|
|
638
|
+
if (this.timeZones() !== void 0) return this.timeZones();
|
|
639
|
+
return typeof Intl.supportedValuesOf === "function" ? Intl.supportedValuesOf("timeZone") : [];
|
|
640
|
+
}, ...ngDevMode ? [{ debugName: "zoneOptions" }] : /* istanbul ignore next */ []);
|
|
641
|
+
this.periodText = computed(() => {
|
|
642
|
+
const viewStart = this.viewStart();
|
|
643
|
+
try {
|
|
644
|
+
return new Intl.DateTimeFormat(calendarLocale(this.locale() || void 0, this.calendar()), {
|
|
645
|
+
month: "long",
|
|
646
|
+
year: "numeric",
|
|
647
|
+
timeZone: "UTC"
|
|
648
|
+
}).format(/* @__PURE__ */ new Date(`${viewStart}T00:00:00Z`));
|
|
649
|
+
} catch {
|
|
650
|
+
return viewStart.slice(0, 7);
|
|
651
|
+
}
|
|
652
|
+
}, ...ngDevMode ? [{ debugName: "periodText" }] : /* istanbul ignore next */ []);
|
|
653
|
+
this.weekdays = computed(() => {
|
|
654
|
+
const weekStart = this.weekStart();
|
|
655
|
+
const locale = this.locale() || void 0;
|
|
656
|
+
const out = [];
|
|
657
|
+
for (let i = 0; i < 7; i++) {
|
|
658
|
+
const d = new Date(Date.UTC(2021, 7, 1 + (weekStart + i) % 7));
|
|
659
|
+
try {
|
|
660
|
+
out.push({
|
|
661
|
+
short: new Intl.DateTimeFormat(gregorian(locale), {
|
|
662
|
+
weekday: "short",
|
|
663
|
+
timeZone: "UTC"
|
|
664
|
+
}).format(d),
|
|
665
|
+
long: new Intl.DateTimeFormat(gregorian(locale), {
|
|
666
|
+
weekday: "long",
|
|
667
|
+
timeZone: "UTC"
|
|
668
|
+
}).format(d)
|
|
669
|
+
});
|
|
670
|
+
} catch {
|
|
671
|
+
out.push({
|
|
672
|
+
short: "",
|
|
673
|
+
long: ""
|
|
674
|
+
});
|
|
675
|
+
}
|
|
676
|
+
}
|
|
677
|
+
return out;
|
|
678
|
+
}, ...ngDevMode ? [{ debugName: "weekdays" }] : /* istanbul ignore next */ []);
|
|
679
|
+
this.weeks = computed(() => calendarMonthMatrix(this.viewStart(), this.weekStart(), this.calendar()), ...ngDevMode ? [{ debugName: "weeks" }] : /* istanbul ignore next */ []);
|
|
680
|
+
this.pendingHour = computed(() => parseIsoTime(this.pendingTime())?.hour ?? 0, ...ngDevMode ? [{ debugName: "pendingHour" }] : /* istanbul ignore next */ []);
|
|
681
|
+
this.pendingMinute = computed(() => parseIsoTime(this.pendingTime())?.minute ?? 0, ...ngDevMode ? [{ debugName: "pendingMinute" }] : /* istanbul ignore next */ []);
|
|
682
|
+
this.hourOptions = computed(() => {
|
|
683
|
+
const clock12 = this.clock12();
|
|
684
|
+
const pendingHour = this.pendingHour();
|
|
685
|
+
const out = [];
|
|
686
|
+
for (let h = 0; h < 24; h++) {
|
|
687
|
+
if (clock12 && h < 12 !== pendingHour < 12) continue;
|
|
688
|
+
out.push({
|
|
689
|
+
value: h,
|
|
690
|
+
label: clock12 ? String((h + 11) % 12 + 1) : pad(h)
|
|
691
|
+
});
|
|
692
|
+
}
|
|
693
|
+
return out;
|
|
694
|
+
}, ...ngDevMode ? [{ debugName: "hourOptions" }] : /* istanbul ignore next */ []);
|
|
695
|
+
this.minuteOptions = computed(() => {
|
|
696
|
+
const step = Math.max(1, this.minuteStep());
|
|
697
|
+
const out = [];
|
|
698
|
+
for (let m = 0; m < 60; m += step) out.push(m);
|
|
699
|
+
return out;
|
|
700
|
+
}, ...ngDevMode ? [{ debugName: "minuteOptions" }] : /* istanbul ignore next */ []);
|
|
701
|
+
this.childContext = computed(() => {
|
|
702
|
+
const args = {
|
|
703
|
+
value: this.value(),
|
|
704
|
+
open: this.open(),
|
|
705
|
+
display: this.display()
|
|
706
|
+
};
|
|
707
|
+
return {
|
|
708
|
+
$implicit: args,
|
|
709
|
+
...args
|
|
710
|
+
};
|
|
711
|
+
}, ...ngDevMode ? [{ debugName: "childContext" }] : /* istanbul ignore next */ []);
|
|
712
|
+
this.initialised = false;
|
|
713
|
+
effect(() => {
|
|
714
|
+
const committed = this.committed();
|
|
715
|
+
if (this.initialised) return;
|
|
716
|
+
this.initialised = true;
|
|
717
|
+
const today = todayIso();
|
|
718
|
+
this.today.set(today);
|
|
719
|
+
const anchor = parseIsoDate(committed.date) ?? parseIsoDate(today);
|
|
720
|
+
if (anchor) {
|
|
721
|
+
this.viewStart.set(calendarMonthStart(formatIsoDate(anchor), this.calendar()));
|
|
722
|
+
this.cursor.set(formatIsoDate(anchor));
|
|
723
|
+
}
|
|
724
|
+
});
|
|
725
|
+
const destroyRef = inject(DestroyRef);
|
|
726
|
+
afterNextRender(() => {
|
|
727
|
+
const root = this.rootRef().nativeElement;
|
|
728
|
+
const form = root.closest("form");
|
|
729
|
+
if (!form) return;
|
|
730
|
+
const initialValue = this.value();
|
|
731
|
+
const initialZone = this.timeZone();
|
|
732
|
+
let timer;
|
|
733
|
+
const onReset = (event) => {
|
|
734
|
+
clearTimeout(timer);
|
|
735
|
+
timer = setTimeout(() => {
|
|
736
|
+
if (event.defaultPrevented) return;
|
|
737
|
+
this.closeDialog(false);
|
|
738
|
+
this.typed.set(null);
|
|
739
|
+
this.invalid.set(false);
|
|
740
|
+
this.value.set(initialValue);
|
|
741
|
+
this.timeZone.set(initialZone);
|
|
742
|
+
const field = root.querySelector(".date-time-picker-input");
|
|
743
|
+
const formatter = this.formatValue() ?? ((v) => this.defaultFormat(v));
|
|
744
|
+
if (field) field.value = formatter(initialValue ?? "");
|
|
745
|
+
this.cdr.markForCheck();
|
|
746
|
+
}, 0);
|
|
747
|
+
};
|
|
748
|
+
form.addEventListener("reset", onReset);
|
|
749
|
+
destroyRef.onDestroy(() => {
|
|
750
|
+
clearTimeout(timer);
|
|
751
|
+
form.removeEventListener("reset", onReset);
|
|
752
|
+
});
|
|
753
|
+
});
|
|
754
|
+
}
|
|
755
|
+
pad2(n) {
|
|
756
|
+
return pad(n);
|
|
757
|
+
}
|
|
758
|
+
isoWeekOf(isoDate) {
|
|
759
|
+
return isoWeek(isoDate);
|
|
760
|
+
}
|
|
761
|
+
parseCell(isoDate) {
|
|
762
|
+
return {
|
|
763
|
+
day: parseIsoDate(isoDate) ? String(calendarDay(isoDate, this.calendar())) : "",
|
|
764
|
+
outside: isoDate < this.viewStart() || isoDate >= calendarAddMonths(this.viewStart(), 1, this.calendar())
|
|
765
|
+
};
|
|
766
|
+
}
|
|
767
|
+
dayLabel(isoDate) {
|
|
768
|
+
const parsed = parseIsoDate(isoDate);
|
|
769
|
+
if (!parsed) return isoDate;
|
|
770
|
+
try {
|
|
771
|
+
return new Intl.DateTimeFormat(calendarLocale(this.locale() || void 0, this.calendar()), {
|
|
772
|
+
weekday: "long",
|
|
773
|
+
day: "numeric",
|
|
774
|
+
month: "long",
|
|
775
|
+
year: "numeric",
|
|
776
|
+
timeZone: "UTC"
|
|
777
|
+
}).format(new Date(Date.UTC(parsed.year, parsed.month - 1, parsed.day)));
|
|
778
|
+
} catch {
|
|
779
|
+
return isoDate;
|
|
780
|
+
}
|
|
781
|
+
}
|
|
782
|
+
dayPeriodName(pm) {
|
|
783
|
+
try {
|
|
784
|
+
const found = new Intl.DateTimeFormat(gregorian(this.locale() || void 0), {
|
|
785
|
+
hour: "numeric",
|
|
786
|
+
hour12: true,
|
|
787
|
+
timeZone: "UTC"
|
|
788
|
+
}).formatToParts(new Date(Date.UTC(2021, 0, 1, pm ? 13 : 1))).find((p) => p.type === "dayPeriod")?.value;
|
|
789
|
+
if (found) return found;
|
|
790
|
+
} catch {}
|
|
791
|
+
return pm ? "PM" : "AM";
|
|
792
|
+
}
|
|
793
|
+
formatTimeForDisplay(isoTime) {
|
|
794
|
+
const parsed = parseIsoTime(isoTime);
|
|
795
|
+
if (!parsed) return isoTime;
|
|
796
|
+
try {
|
|
797
|
+
return new Intl.DateTimeFormat(gregorian(this.locale() || void 0), {
|
|
798
|
+
hour: "2-digit",
|
|
799
|
+
minute: "2-digit",
|
|
800
|
+
hour12: this.clock12(),
|
|
801
|
+
timeZone: "UTC"
|
|
802
|
+
}).format(new Date(Date.UTC(2021, 0, 1, parsed.hour, parsed.minute)));
|
|
803
|
+
} catch {
|
|
804
|
+
return isoTime;
|
|
805
|
+
}
|
|
806
|
+
}
|
|
807
|
+
defaultFormat(isoValue) {
|
|
808
|
+
if (!isoValue) return "";
|
|
809
|
+
const { date, time } = splitValue(isoValue, this.mode());
|
|
810
|
+
const chunks = [];
|
|
811
|
+
const parsed = date ? parseIsoDate(date) : null;
|
|
812
|
+
if (parsed) try {
|
|
813
|
+
chunks.push(new Intl.DateTimeFormat(gregorian(this.locale() || void 0), {
|
|
814
|
+
day: "2-digit",
|
|
815
|
+
month: "short",
|
|
816
|
+
year: "numeric",
|
|
817
|
+
timeZone: "UTC"
|
|
818
|
+
}).format(new Date(Date.UTC(parsed.year, parsed.month - 1, parsed.day))));
|
|
819
|
+
} catch {
|
|
820
|
+
chunks.push(date);
|
|
821
|
+
}
|
|
822
|
+
if (time) chunks.push(this.formatTimeForDisplay(time));
|
|
823
|
+
return chunks.join(" ");
|
|
824
|
+
}
|
|
825
|
+
dayDisabled(isoDate) {
|
|
826
|
+
if (!withinRange(isoDate, this.min() || void 0, this.max() || void 0)) return true;
|
|
827
|
+
return this.isDateDisabled()?.(isoDate) === true;
|
|
828
|
+
}
|
|
829
|
+
nearestSelectable(isoDate) {
|
|
830
|
+
if (!this.dayDisabled(isoDate)) return isoDate;
|
|
831
|
+
for (let delta = 1; delta <= 366; delta++) {
|
|
832
|
+
const after = addDays(isoDate, delta);
|
|
833
|
+
if (!this.dayDisabled(after)) return after;
|
|
834
|
+
const before = addDays(isoDate, -delta);
|
|
835
|
+
if (!this.dayDisabled(before)) return before;
|
|
836
|
+
}
|
|
837
|
+
return isoDate;
|
|
838
|
+
}
|
|
839
|
+
openDialog() {
|
|
840
|
+
if (this.disabled() || this.readOnly()) return;
|
|
841
|
+
const active = document.activeElement;
|
|
842
|
+
this.openerEl = active instanceof HTMLElement && this.rootRef().nativeElement.contains(active) ? active : this.buttonRef().element ?? null;
|
|
843
|
+
const today = todayIso();
|
|
844
|
+
this.today.set(today);
|
|
845
|
+
const pendingDate = this.committed().date || this.nearestSelectable(today);
|
|
846
|
+
this.pendingDate.set(pendingDate);
|
|
847
|
+
this.pendingTime.set(this.committed().time || this.defaultTime());
|
|
848
|
+
this.cursor.set(pendingDate);
|
|
849
|
+
const anchor = parseIsoDate(pendingDate) ?? parseIsoDate(today);
|
|
850
|
+
if (anchor) this.viewStart.set(calendarMonthStart(formatIsoDate(anchor), this.calendar()));
|
|
851
|
+
this.open.set(true);
|
|
852
|
+
this.cdr.detectChanges();
|
|
853
|
+
this.focusInitial();
|
|
854
|
+
}
|
|
855
|
+
defaultTime() {
|
|
856
|
+
if (!this.usesTime()) return "";
|
|
857
|
+
const now = /* @__PURE__ */ new Date();
|
|
858
|
+
const step = Math.max(1, this.minuteStep());
|
|
859
|
+
return formatIsoTime({
|
|
860
|
+
hour: now.getHours(),
|
|
861
|
+
minute: Math.floor(now.getMinutes() / step) * step
|
|
862
|
+
});
|
|
863
|
+
}
|
|
864
|
+
focusInitial() {
|
|
865
|
+
if (this.usesDate()) {
|
|
866
|
+
this.focusCursor();
|
|
867
|
+
return;
|
|
868
|
+
}
|
|
869
|
+
this.focusables()[0]?.focus?.();
|
|
870
|
+
}
|
|
871
|
+
closeDialog(refocus = true) {
|
|
872
|
+
if (!this.open()) return;
|
|
873
|
+
this.open.set(false);
|
|
874
|
+
if (refocus) {
|
|
875
|
+
const target = this.openerEl ?? this.buttonRef().element;
|
|
876
|
+
queueMicrotask(() => target?.focus?.());
|
|
877
|
+
}
|
|
878
|
+
}
|
|
879
|
+
commit() {
|
|
880
|
+
const next = joinValue(this.pendingDate(), this.pendingTime(), this.mode());
|
|
881
|
+
if (!next) return;
|
|
882
|
+
this.typed.set(null);
|
|
883
|
+
this.invalid.set(false);
|
|
884
|
+
if (next !== this.value()) {
|
|
885
|
+
this.value.set(next);
|
|
886
|
+
this.change.emit(next);
|
|
887
|
+
}
|
|
888
|
+
this.closeDialog();
|
|
889
|
+
}
|
|
890
|
+
clear() {
|
|
891
|
+
this.typed.set(null);
|
|
892
|
+
this.invalid.set(false);
|
|
893
|
+
if (this.value() !== "") {
|
|
894
|
+
this.value.set("");
|
|
895
|
+
this.change.emit("");
|
|
896
|
+
}
|
|
897
|
+
this.closeDialog();
|
|
898
|
+
}
|
|
899
|
+
moveCursor(nextIso) {
|
|
900
|
+
if (!withinRange(nextIso, this.min() || void 0, this.max() || void 0)) return;
|
|
901
|
+
this.cursor.set(nextIso);
|
|
902
|
+
const parsed = parseIsoDate(nextIso);
|
|
903
|
+
if (parsed) this.viewStart.set(calendarMonthStart(formatIsoDate(parsed), this.calendar()));
|
|
904
|
+
this.cdr.detectChanges();
|
|
905
|
+
this.focusCursor();
|
|
906
|
+
}
|
|
907
|
+
focusCursor() {
|
|
908
|
+
const dialogEl = this.dialogRef()?.nativeElement;
|
|
909
|
+
const cursor = this.cursor();
|
|
910
|
+
if (!dialogEl || !cursor) return;
|
|
911
|
+
const el = dialogEl.querySelector(`[data-date="${cursor}"]`);
|
|
912
|
+
el?.focus?.();
|
|
913
|
+
el?.scrollIntoView?.({ block: "nearest" });
|
|
914
|
+
}
|
|
915
|
+
selectDay(isoDate) {
|
|
916
|
+
if (this.dayDisabled(isoDate)) return;
|
|
917
|
+
this.pendingDate.set(isoDate);
|
|
918
|
+
this.cursor.set(isoDate);
|
|
919
|
+
if (this.commitOnDay()) this.commit();
|
|
920
|
+
}
|
|
921
|
+
shiftMonth(delta) {
|
|
922
|
+
const next = calendarAddMonths(this.viewStart(), delta, this.calendar());
|
|
923
|
+
const hadGridFocus = this.gridRef()?.nativeElement.contains(document.activeElement) === true;
|
|
924
|
+
this.viewStart.set(next);
|
|
925
|
+
const c = parseIsoDate(this.cursor());
|
|
926
|
+
if (c) {
|
|
927
|
+
this.cursor.set(addDays(next, Math.min(calendarDay(formatIsoDate(c), this.calendar()), calendarMonthLength(next, this.calendar())) - 1));
|
|
928
|
+
if (hadGridFocus) {
|
|
929
|
+
this.cdr.detectChanges();
|
|
930
|
+
this.focusCursor();
|
|
931
|
+
}
|
|
932
|
+
}
|
|
933
|
+
}
|
|
934
|
+
shiftYear(delta) {
|
|
935
|
+
this.shiftMonth(delta * 12);
|
|
936
|
+
}
|
|
937
|
+
shiftDays(delta) {
|
|
938
|
+
const from = parseIsoDate(this.cursor()) ? this.cursor() : this.pendingDate();
|
|
939
|
+
if (!from) return;
|
|
940
|
+
const next = addDays(from, delta);
|
|
941
|
+
if (!withinRange(next, this.min() || void 0, this.max() || void 0)) return;
|
|
942
|
+
const hadGridFocus = this.gridRef()?.nativeElement.contains(document.activeElement) === true;
|
|
943
|
+
const parsed = parseIsoDate(next);
|
|
944
|
+
if (parsed) this.viewStart.set(calendarMonthStart(formatIsoDate(parsed), this.calendar()));
|
|
945
|
+
this.cursor.set(next);
|
|
946
|
+
if (!this.dayDisabled(next)) this.pendingDate.set(next);
|
|
947
|
+
if (hadGridFocus) {
|
|
948
|
+
this.cdr.detectChanges();
|
|
949
|
+
this.focusCursor();
|
|
950
|
+
}
|
|
951
|
+
}
|
|
952
|
+
onTimeZoneSelect(event) {
|
|
953
|
+
this.timeZone.set(event.target.value);
|
|
954
|
+
}
|
|
955
|
+
zoneLabel(zone) {
|
|
956
|
+
return this.timeZoneLabels()[zone] ?? zone;
|
|
957
|
+
}
|
|
958
|
+
onGridKeydown(event) {
|
|
959
|
+
switch (logicalKey(event.key, isRtl(this.gridRef()?.nativeElement))) {
|
|
960
|
+
case "ArrowLeft":
|
|
961
|
+
event.preventDefault();
|
|
962
|
+
this.moveCursor(addDays(this.cursor(), -1));
|
|
963
|
+
break;
|
|
964
|
+
case "ArrowRight":
|
|
965
|
+
event.preventDefault();
|
|
966
|
+
this.moveCursor(addDays(this.cursor(), 1));
|
|
967
|
+
break;
|
|
968
|
+
case "ArrowUp":
|
|
969
|
+
event.preventDefault();
|
|
970
|
+
this.moveCursor(addDays(this.cursor(), -7));
|
|
971
|
+
break;
|
|
972
|
+
case "ArrowDown":
|
|
973
|
+
event.preventDefault();
|
|
974
|
+
this.moveCursor(addDays(this.cursor(), 7));
|
|
975
|
+
break;
|
|
976
|
+
case "Home": {
|
|
977
|
+
event.preventDefault();
|
|
978
|
+
const offset = (weekdayOf(this.cursor()) - this.weekStart() + 7) % 7;
|
|
979
|
+
this.moveCursor(addDays(this.cursor(), -offset));
|
|
980
|
+
break;
|
|
981
|
+
}
|
|
982
|
+
case "End": {
|
|
983
|
+
event.preventDefault();
|
|
984
|
+
const offset = (weekdayOf(this.cursor()) - this.weekStart() + 7) % 7;
|
|
985
|
+
this.moveCursor(addDays(this.cursor(), 6 - offset));
|
|
986
|
+
break;
|
|
987
|
+
}
|
|
988
|
+
case "PageUp":
|
|
989
|
+
event.preventDefault();
|
|
990
|
+
if (event.shiftKey) this.shiftYear(-1);
|
|
991
|
+
else this.shiftMonth(-1);
|
|
992
|
+
break;
|
|
993
|
+
case "PageDown":
|
|
994
|
+
event.preventDefault();
|
|
995
|
+
if (event.shiftKey) this.shiftYear(1);
|
|
996
|
+
else this.shiftMonth(1);
|
|
997
|
+
break;
|
|
998
|
+
case "Enter":
|
|
999
|
+
case " ":
|
|
1000
|
+
event.preventDefault();
|
|
1001
|
+
this.selectDay(this.cursor());
|
|
1002
|
+
}
|
|
1003
|
+
}
|
|
1004
|
+
focusables() {
|
|
1005
|
+
const dialogEl = this.dialogRef()?.nativeElement;
|
|
1006
|
+
if (!dialogEl) return [];
|
|
1007
|
+
return Array.from(dialogEl.querySelectorAll("button:not([disabled]):not([tabindex=\"-1\"]), select:not([disabled])"));
|
|
1008
|
+
}
|
|
1009
|
+
onDialogKeydown(event) {
|
|
1010
|
+
if (event.key === "Escape") {
|
|
1011
|
+
event.preventDefault();
|
|
1012
|
+
this.closeDialog();
|
|
1013
|
+
return;
|
|
1014
|
+
}
|
|
1015
|
+
if (event.key !== "Tab") return;
|
|
1016
|
+
const all = this.focusables();
|
|
1017
|
+
if (all.length === 0) return;
|
|
1018
|
+
const first = all[0];
|
|
1019
|
+
const last = all[all.length - 1];
|
|
1020
|
+
const active = document.activeElement;
|
|
1021
|
+
const dialogEl = this.dialogRef()?.nativeElement;
|
|
1022
|
+
if (event.shiftKey && (active === first || !dialogEl?.contains(active))) {
|
|
1023
|
+
event.preventDefault();
|
|
1024
|
+
last.focus?.();
|
|
1025
|
+
} else if (!event.shiftKey && active === last) {
|
|
1026
|
+
event.preventDefault();
|
|
1027
|
+
first.focus?.();
|
|
1028
|
+
}
|
|
1029
|
+
}
|
|
1030
|
+
parseTypedForMode(text) {
|
|
1031
|
+
if (this.mode() === "time") return parseTimeInput(text, this.locale() || void 0);
|
|
1032
|
+
if (this.mode() === "date") return parseDateInput(text, this.locale() || void 0);
|
|
1033
|
+
const m = /^(.*?)[T\s]+([^\sT]+)$/.exec(text.trim());
|
|
1034
|
+
if (!m) return null;
|
|
1035
|
+
const date = parseDateInput(m[1], this.locale() || void 0);
|
|
1036
|
+
const time = parseTimeInput(m[2], this.locale() || void 0);
|
|
1037
|
+
return date && time ? `${date}T${time}` : null;
|
|
1038
|
+
}
|
|
1039
|
+
resolveTyped() {
|
|
1040
|
+
const text = this.typed();
|
|
1041
|
+
if (text === null) return;
|
|
1042
|
+
if (!text.trim()) {
|
|
1043
|
+
this.typed.set(null);
|
|
1044
|
+
this.invalid.set(false);
|
|
1045
|
+
if (this.value() !== "") {
|
|
1046
|
+
this.value.set("");
|
|
1047
|
+
this.change.emit("");
|
|
1048
|
+
}
|
|
1049
|
+
return;
|
|
1050
|
+
}
|
|
1051
|
+
const parser = this.parseInput();
|
|
1052
|
+
const parsed = parser ? parser(text) : this.parseTypedForMode(text);
|
|
1053
|
+
if (!parsed) {
|
|
1054
|
+
this.invalid.set(true);
|
|
1055
|
+
this.invalidInput.emit(text);
|
|
1056
|
+
return;
|
|
1057
|
+
}
|
|
1058
|
+
const { date } = splitValue(parsed, this.mode());
|
|
1059
|
+
if (this.usesDate() && date && this.dayDisabled(date)) {
|
|
1060
|
+
this.invalid.set(true);
|
|
1061
|
+
this.invalidInput.emit(text);
|
|
1062
|
+
return;
|
|
1063
|
+
}
|
|
1064
|
+
this.typed.set(null);
|
|
1065
|
+
this.invalid.set(false);
|
|
1066
|
+
if (parsed !== this.value()) {
|
|
1067
|
+
this.value.set(parsed);
|
|
1068
|
+
this.change.emit(parsed);
|
|
1069
|
+
}
|
|
1070
|
+
}
|
|
1071
|
+
onFieldKeydown(event) {
|
|
1072
|
+
if (event.key === "Enter") {
|
|
1073
|
+
event.preventDefault();
|
|
1074
|
+
this.resolveTyped();
|
|
1075
|
+
} else if (event.key === "ArrowDown" && event.altKey) {
|
|
1076
|
+
event.preventDefault();
|
|
1077
|
+
this.openDialog();
|
|
1078
|
+
} else if (event.key === "Escape" && this.typed() !== null) {
|
|
1079
|
+
event.preventDefault();
|
|
1080
|
+
event.stopPropagation();
|
|
1081
|
+
this.typed.set(null);
|
|
1082
|
+
this.invalid.set(false);
|
|
1083
|
+
}
|
|
1084
|
+
}
|
|
1085
|
+
setHour(hour) {
|
|
1086
|
+
this.pendingTime.set(formatIsoTime({
|
|
1087
|
+
hour,
|
|
1088
|
+
minute: this.pendingMinute()
|
|
1089
|
+
}));
|
|
1090
|
+
}
|
|
1091
|
+
setMinute(minute) {
|
|
1092
|
+
this.pendingTime.set(formatIsoTime({
|
|
1093
|
+
hour: this.pendingHour(),
|
|
1094
|
+
minute
|
|
1095
|
+
}));
|
|
1096
|
+
}
|
|
1097
|
+
setMeridiem(pm) {
|
|
1098
|
+
this.setHour(this.pendingHour() % 12 + (pm ? 12 : 0));
|
|
1099
|
+
}
|
|
1100
|
+
applyShortcut(shortcut) {
|
|
1101
|
+
const base = todayIso();
|
|
1102
|
+
let target = shortcut.date ?? base;
|
|
1103
|
+
if (shortcut.days !== void 0) target = addDays(base, shortcut.days);
|
|
1104
|
+
else if (shortcut.months !== void 0) target = addMonths(base, shortcut.months);
|
|
1105
|
+
if (this.dayDisabled(target)) return;
|
|
1106
|
+
this.pendingDate.set(target);
|
|
1107
|
+
this.cursor.set(target);
|
|
1108
|
+
const parsed = parseIsoDate(target);
|
|
1109
|
+
if (parsed) this.viewStart.set(calendarMonthStart(formatIsoDate(parsed), this.calendar()));
|
|
1110
|
+
this.shortcut.emit({
|
|
1111
|
+
id: shortcut.id,
|
|
1112
|
+
isoDate: target
|
|
1113
|
+
});
|
|
1114
|
+
if (this.commitOnDay()) this.commit();
|
|
1115
|
+
else {
|
|
1116
|
+
this.cdr.detectChanges();
|
|
1117
|
+
this.focusCursor();
|
|
1118
|
+
}
|
|
1119
|
+
}
|
|
1120
|
+
onDocumentClick(event) {
|
|
1121
|
+
if (!this.open()) return;
|
|
1122
|
+
const target = event.target;
|
|
1123
|
+
if (!target) return;
|
|
1124
|
+
if (this.dialogRef().nativeElement.contains(target) || (this.buttonRef().element?.contains(target) ?? false)) return;
|
|
1125
|
+
this.closeDialog(false);
|
|
1126
|
+
}
|
|
1127
|
+
static {
|
|
1128
|
+
this.ɵfac = i0.ɵɵngDeclareFactory({
|
|
1129
|
+
minVersion: "12.0.0",
|
|
1130
|
+
version: "22.2.4",
|
|
1131
|
+
ngImport: i0,
|
|
1132
|
+
type: DateTimePicker,
|
|
1133
|
+
deps: [],
|
|
1134
|
+
target: i0.ɵɵFactoryTarget.Component
|
|
1135
|
+
});
|
|
1136
|
+
}
|
|
1137
|
+
static {
|
|
1138
|
+
this.ɵcmp = i0.ɵɵngDeclareComponent({
|
|
1139
|
+
minVersion: "17.0.0",
|
|
1140
|
+
version: "22.2.4",
|
|
1141
|
+
type: DateTimePicker,
|
|
1142
|
+
isStandalone: true,
|
|
1143
|
+
selector: "lily-date-time-picker",
|
|
1144
|
+
inputs: {
|
|
1145
|
+
label: {
|
|
1146
|
+
classPropertyName: "label",
|
|
1147
|
+
publicName: "label",
|
|
1148
|
+
isSignal: true,
|
|
1149
|
+
isRequired: true,
|
|
1150
|
+
transformFunction: null
|
|
1151
|
+
},
|
|
1152
|
+
labels: {
|
|
1153
|
+
classPropertyName: "labels",
|
|
1154
|
+
publicName: "labels",
|
|
1155
|
+
isSignal: true,
|
|
1156
|
+
isRequired: true,
|
|
1157
|
+
transformFunction: null
|
|
1158
|
+
},
|
|
1159
|
+
mode: {
|
|
1160
|
+
classPropertyName: "mode",
|
|
1161
|
+
publicName: "mode",
|
|
1162
|
+
isSignal: true,
|
|
1163
|
+
isRequired: false,
|
|
1164
|
+
transformFunction: null
|
|
1165
|
+
},
|
|
1166
|
+
value: {
|
|
1167
|
+
classPropertyName: "value",
|
|
1168
|
+
publicName: "value",
|
|
1169
|
+
isSignal: true,
|
|
1170
|
+
isRequired: false,
|
|
1171
|
+
transformFunction: null
|
|
1172
|
+
},
|
|
1173
|
+
locale: {
|
|
1174
|
+
classPropertyName: "locale",
|
|
1175
|
+
publicName: "locale",
|
|
1176
|
+
isSignal: true,
|
|
1177
|
+
isRequired: false,
|
|
1178
|
+
transformFunction: null
|
|
1179
|
+
},
|
|
1180
|
+
calendar: {
|
|
1181
|
+
classPropertyName: "calendar",
|
|
1182
|
+
publicName: "calendar",
|
|
1183
|
+
isSignal: true,
|
|
1184
|
+
isRequired: false,
|
|
1185
|
+
transformFunction: null
|
|
1186
|
+
},
|
|
1187
|
+
min: {
|
|
1188
|
+
classPropertyName: "min",
|
|
1189
|
+
publicName: "min",
|
|
1190
|
+
isSignal: true,
|
|
1191
|
+
isRequired: false,
|
|
1192
|
+
transformFunction: null
|
|
1193
|
+
},
|
|
1194
|
+
max: {
|
|
1195
|
+
classPropertyName: "max",
|
|
1196
|
+
publicName: "max",
|
|
1197
|
+
isSignal: true,
|
|
1198
|
+
isRequired: false,
|
|
1199
|
+
transformFunction: null
|
|
1200
|
+
},
|
|
1201
|
+
isDateDisabled: {
|
|
1202
|
+
classPropertyName: "isDateDisabled",
|
|
1203
|
+
publicName: "isDateDisabled",
|
|
1204
|
+
isSignal: true,
|
|
1205
|
+
isRequired: false,
|
|
1206
|
+
transformFunction: null
|
|
1207
|
+
},
|
|
1208
|
+
firstDayOfWeek: {
|
|
1209
|
+
classPropertyName: "firstDayOfWeek",
|
|
1210
|
+
publicName: "firstDayOfWeek",
|
|
1211
|
+
isSignal: true,
|
|
1212
|
+
isRequired: false,
|
|
1213
|
+
transformFunction: null
|
|
1214
|
+
},
|
|
1215
|
+
minuteStep: {
|
|
1216
|
+
classPropertyName: "minuteStep",
|
|
1217
|
+
publicName: "minuteStep",
|
|
1218
|
+
isSignal: true,
|
|
1219
|
+
isRequired: false,
|
|
1220
|
+
transformFunction: null
|
|
1221
|
+
},
|
|
1222
|
+
hour12: {
|
|
1223
|
+
classPropertyName: "hour12",
|
|
1224
|
+
publicName: "hour12",
|
|
1225
|
+
isSignal: true,
|
|
1226
|
+
isRequired: false,
|
|
1227
|
+
transformFunction: null
|
|
1228
|
+
},
|
|
1229
|
+
showWeekNumbers: {
|
|
1230
|
+
classPropertyName: "showWeekNumbers",
|
|
1231
|
+
publicName: "showWeekNumbers",
|
|
1232
|
+
isSignal: true,
|
|
1233
|
+
isRequired: false,
|
|
1234
|
+
transformFunction: null
|
|
1235
|
+
},
|
|
1236
|
+
shortcuts: {
|
|
1237
|
+
classPropertyName: "shortcuts",
|
|
1238
|
+
publicName: "shortcuts",
|
|
1239
|
+
isSignal: true,
|
|
1240
|
+
isRequired: false,
|
|
1241
|
+
transformFunction: null
|
|
1242
|
+
},
|
|
1243
|
+
confirmOnSelect: {
|
|
1244
|
+
classPropertyName: "confirmOnSelect",
|
|
1245
|
+
publicName: "confirmOnSelect",
|
|
1246
|
+
isSignal: true,
|
|
1247
|
+
isRequired: false,
|
|
1248
|
+
transformFunction: null
|
|
1249
|
+
},
|
|
1250
|
+
name: {
|
|
1251
|
+
classPropertyName: "name",
|
|
1252
|
+
publicName: "name",
|
|
1253
|
+
isSignal: true,
|
|
1254
|
+
isRequired: false,
|
|
1255
|
+
transformFunction: null
|
|
1256
|
+
},
|
|
1257
|
+
timeZone: {
|
|
1258
|
+
classPropertyName: "timeZone",
|
|
1259
|
+
publicName: "timeZone",
|
|
1260
|
+
isSignal: true,
|
|
1261
|
+
isRequired: false,
|
|
1262
|
+
transformFunction: null
|
|
1263
|
+
},
|
|
1264
|
+
timeZones: {
|
|
1265
|
+
classPropertyName: "timeZones",
|
|
1266
|
+
publicName: "timeZones",
|
|
1267
|
+
isSignal: true,
|
|
1268
|
+
isRequired: false,
|
|
1269
|
+
transformFunction: null
|
|
1270
|
+
},
|
|
1271
|
+
timeZoneLabels: {
|
|
1272
|
+
classPropertyName: "timeZoneLabels",
|
|
1273
|
+
publicName: "timeZoneLabels",
|
|
1274
|
+
isSignal: true,
|
|
1275
|
+
isRequired: false,
|
|
1276
|
+
transformFunction: null
|
|
1277
|
+
},
|
|
1278
|
+
inputId: {
|
|
1279
|
+
classPropertyName: "inputId",
|
|
1280
|
+
publicName: "inputId",
|
|
1281
|
+
isSignal: true,
|
|
1282
|
+
isRequired: false,
|
|
1283
|
+
transformFunction: null
|
|
1284
|
+
},
|
|
1285
|
+
describedBy: {
|
|
1286
|
+
classPropertyName: "describedBy",
|
|
1287
|
+
publicName: "describedBy",
|
|
1288
|
+
isSignal: true,
|
|
1289
|
+
isRequired: false,
|
|
1290
|
+
transformFunction: null
|
|
1291
|
+
},
|
|
1292
|
+
placeholder: {
|
|
1293
|
+
classPropertyName: "placeholder",
|
|
1294
|
+
publicName: "placeholder",
|
|
1295
|
+
isSignal: true,
|
|
1296
|
+
isRequired: false,
|
|
1297
|
+
transformFunction: null
|
|
1298
|
+
},
|
|
1299
|
+
disabled: {
|
|
1300
|
+
classPropertyName: "disabled",
|
|
1301
|
+
publicName: "disabled",
|
|
1302
|
+
isSignal: true,
|
|
1303
|
+
isRequired: false,
|
|
1304
|
+
transformFunction: null
|
|
1305
|
+
},
|
|
1306
|
+
readOnly: {
|
|
1307
|
+
classPropertyName: "readOnly",
|
|
1308
|
+
publicName: "readOnly",
|
|
1309
|
+
isSignal: true,
|
|
1310
|
+
isRequired: false,
|
|
1311
|
+
transformFunction: null
|
|
1312
|
+
},
|
|
1313
|
+
required: {
|
|
1314
|
+
classPropertyName: "required",
|
|
1315
|
+
publicName: "required",
|
|
1316
|
+
isSignal: true,
|
|
1317
|
+
isRequired: false,
|
|
1318
|
+
transformFunction: null
|
|
1319
|
+
},
|
|
1320
|
+
formatValue: {
|
|
1321
|
+
classPropertyName: "formatValue",
|
|
1322
|
+
publicName: "formatValue",
|
|
1323
|
+
isSignal: true,
|
|
1324
|
+
isRequired: false,
|
|
1325
|
+
transformFunction: null
|
|
1326
|
+
},
|
|
1327
|
+
parseInput: {
|
|
1328
|
+
classPropertyName: "parseInput",
|
|
1329
|
+
publicName: "parseInput",
|
|
1330
|
+
isSignal: true,
|
|
1331
|
+
isRequired: false,
|
|
1332
|
+
transformFunction: null
|
|
1333
|
+
},
|
|
1334
|
+
className: {
|
|
1335
|
+
classPropertyName: "className",
|
|
1336
|
+
publicName: "className",
|
|
1337
|
+
isSignal: true,
|
|
1338
|
+
isRequired: false,
|
|
1339
|
+
transformFunction: null
|
|
1340
|
+
}
|
|
1341
|
+
},
|
|
1342
|
+
outputs: {
|
|
1343
|
+
value: "valueChange",
|
|
1344
|
+
timeZone: "timeZoneChange",
|
|
1345
|
+
change: "change",
|
|
1346
|
+
shortcut: "shortcut",
|
|
1347
|
+
invalidInput: "invalidInput"
|
|
1348
|
+
},
|
|
1349
|
+
host: { listeners: { "document:click": "onDocumentClick($event)" } },
|
|
1350
|
+
queries: [{
|
|
1351
|
+
propertyName: "iconTemplate",
|
|
1352
|
+
first: true,
|
|
1353
|
+
predicate: TemplateRef,
|
|
1354
|
+
descendants: true,
|
|
1355
|
+
isSignal: true
|
|
1356
|
+
}],
|
|
1357
|
+
viewQueries: [
|
|
1358
|
+
{
|
|
1359
|
+
propertyName: "rootRef",
|
|
1360
|
+
first: true,
|
|
1361
|
+
predicate: ["rootEl"],
|
|
1362
|
+
descendants: true,
|
|
1363
|
+
isSignal: true
|
|
1364
|
+
},
|
|
1365
|
+
{
|
|
1366
|
+
propertyName: "buttonRef",
|
|
1367
|
+
first: true,
|
|
1368
|
+
predicate: ["buttonEl"],
|
|
1369
|
+
descendants: true,
|
|
1370
|
+
isSignal: true
|
|
1371
|
+
},
|
|
1372
|
+
{
|
|
1373
|
+
propertyName: "dialogRef",
|
|
1374
|
+
first: true,
|
|
1375
|
+
predicate: ["dialogEl"],
|
|
1376
|
+
descendants: true,
|
|
1377
|
+
isSignal: true
|
|
1378
|
+
},
|
|
1379
|
+
{
|
|
1380
|
+
propertyName: "gridRef",
|
|
1381
|
+
first: true,
|
|
1382
|
+
predicate: ["gridEl"],
|
|
1383
|
+
descendants: true,
|
|
1384
|
+
isSignal: true
|
|
1385
|
+
}
|
|
1386
|
+
],
|
|
1387
|
+
ngImport: i0,
|
|
1388
|
+
template: `
|
|
1390
1389
|
<div
|
|
1391
1390
|
#rootEl
|
|
1392
1391
|
class="date-time-picker {{ className() }}"
|
|
@@ -1431,7 +1430,12 @@ class DateTimePicker {
|
|
|
1431
1430
|
[ariaExpanded]="open()"
|
|
1432
1431
|
[ariaControls]="dialogId"
|
|
1433
1432
|
[disabled]="disabled() || readOnly()"
|
|
1434
|
-
(click)="open() ? closeDialog() : openDialog()"
|
|
1433
|
+
(click)="open() ? closeDialog() : openDialog(); hoverButton.set(false)"
|
|
1434
|
+
(mouseenter)="onTooltipButtonEnter()"
|
|
1435
|
+
(mouseleave)="hoverButton.set(false)"
|
|
1436
|
+
(focusin)="onTooltipButtonFocusIn()"
|
|
1437
|
+
(focusout)="onTooltipButtonFocusOut()"
|
|
1438
|
+
(keydown)="onTooltipKeydown($event)"
|
|
1435
1439
|
>
|
|
1436
1440
|
@if (iconTemplate(); as tpl) {
|
|
1437
1441
|
<ng-container
|
|
@@ -1444,6 +1448,18 @@ class DateTimePicker {
|
|
|
1444
1448
|
}}</span>
|
|
1445
1449
|
}
|
|
1446
1450
|
</lily-icon-button>
|
|
1451
|
+
|
|
1452
|
+
<!-- Purely visual: the same text is already the button's aria-label,
|
|
1453
|
+
so it is not wired with aria-describedby (that would announce
|
|
1454
|
+
the name twice). -->
|
|
1455
|
+
<div
|
|
1456
|
+
class="date-time-picker-tooltip"
|
|
1457
|
+
role="tooltip"
|
|
1458
|
+
[id]="tooltipId"
|
|
1459
|
+
[attr.hidden]="tooltipVisible() ? null : ''"
|
|
1460
|
+
(mouseenter)="hoverTooltip.set(true)"
|
|
1461
|
+
(mouseleave)="hoverTooltip.set(false)"
|
|
1462
|
+
>{{ label() }}</div>
|
|
1447
1463
|
</div>
|
|
1448
1464
|
|
|
1449
1465
|
@if (labels().invalid) {
|
|
@@ -1759,19 +1775,50 @@ class DateTimePicker {
|
|
|
1759
1775
|
</div>
|
|
1760
1776
|
</div>
|
|
1761
1777
|
</div>
|
|
1762
|
-
`,
|
|
1763
|
-
|
|
1764
|
-
|
|
1765
|
-
|
|
1766
|
-
|
|
1767
|
-
|
|
1768
|
-
|
|
1769
|
-
|
|
1770
|
-
|
|
1771
|
-
|
|
1772
|
-
|
|
1773
|
-
|
|
1774
|
-
|
|
1778
|
+
`,
|
|
1779
|
+
isInline: true,
|
|
1780
|
+
dependencies: [{
|
|
1781
|
+
kind: "directive",
|
|
1782
|
+
type: NgTemplateOutlet,
|
|
1783
|
+
selector: "[ngTemplateOutlet]",
|
|
1784
|
+
inputs: [
|
|
1785
|
+
"ngTemplateOutletContext",
|
|
1786
|
+
"ngTemplateOutlet",
|
|
1787
|
+
"ngTemplateOutletInjector"
|
|
1788
|
+
]
|
|
1789
|
+
}, {
|
|
1790
|
+
kind: "component",
|
|
1791
|
+
type: IconButton,
|
|
1792
|
+
selector: "lily-icon-button",
|
|
1793
|
+
inputs: [
|
|
1794
|
+
"label",
|
|
1795
|
+
"className",
|
|
1796
|
+
"baseClass",
|
|
1797
|
+
"ariaHaspopup",
|
|
1798
|
+
"ariaExpanded",
|
|
1799
|
+
"ariaControls",
|
|
1800
|
+
"tabIndex",
|
|
1801
|
+
"disabled"
|
|
1802
|
+
]
|
|
1803
|
+
}],
|
|
1804
|
+
changeDetection: i0.ChangeDetectionStrategy.OnPush
|
|
1805
|
+
});
|
|
1806
|
+
}
|
|
1807
|
+
};
|
|
1808
|
+
i0.ɵɵngDeclareClassMetadata({
|
|
1809
|
+
minVersion: "12.0.0",
|
|
1810
|
+
version: "22.2.4",
|
|
1811
|
+
ngImport: i0,
|
|
1812
|
+
type: DateTimePicker,
|
|
1813
|
+
decorators: [{
|
|
1814
|
+
type: Component,
|
|
1815
|
+
args: [{
|
|
1816
|
+
selector: "lily-date-time-picker",
|
|
1817
|
+
standalone: true,
|
|
1818
|
+
imports: [NgTemplateOutlet, IconButton],
|
|
1819
|
+
changeDetection: ChangeDetectionStrategy.OnPush,
|
|
1820
|
+
host: { "(document:click)": "onDocumentClick($event)" },
|
|
1821
|
+
template: `
|
|
1775
1822
|
<div
|
|
1776
1823
|
#rootEl
|
|
1777
1824
|
class="date-time-picker {{ className() }}"
|
|
@@ -1816,7 +1863,12 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "22.1.7", ngImpor
|
|
|
1816
1863
|
[ariaExpanded]="open()"
|
|
1817
1864
|
[ariaControls]="dialogId"
|
|
1818
1865
|
[disabled]="disabled() || readOnly()"
|
|
1819
|
-
(click)="open() ? closeDialog() : openDialog()"
|
|
1866
|
+
(click)="open() ? closeDialog() : openDialog(); hoverButton.set(false)"
|
|
1867
|
+
(mouseenter)="onTooltipButtonEnter()"
|
|
1868
|
+
(mouseleave)="hoverButton.set(false)"
|
|
1869
|
+
(focusin)="onTooltipButtonFocusIn()"
|
|
1870
|
+
(focusout)="onTooltipButtonFocusOut()"
|
|
1871
|
+
(keydown)="onTooltipKeydown($event)"
|
|
1820
1872
|
>
|
|
1821
1873
|
@if (iconTemplate(); as tpl) {
|
|
1822
1874
|
<ng-container
|
|
@@ -1829,6 +1881,18 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "22.1.7", ngImpor
|
|
|
1829
1881
|
}}</span>
|
|
1830
1882
|
}
|
|
1831
1883
|
</lily-icon-button>
|
|
1884
|
+
|
|
1885
|
+
<!-- Purely visual: the same text is already the button's aria-label,
|
|
1886
|
+
so it is not wired with aria-describedby (that would announce
|
|
1887
|
+
the name twice). -->
|
|
1888
|
+
<div
|
|
1889
|
+
class="date-time-picker-tooltip"
|
|
1890
|
+
role="tooltip"
|
|
1891
|
+
[id]="tooltipId"
|
|
1892
|
+
[attr.hidden]="tooltipVisible() ? null : ''"
|
|
1893
|
+
(mouseenter)="hoverTooltip.set(true)"
|
|
1894
|
+
(mouseleave)="hoverTooltip.set(false)"
|
|
1895
|
+
>{{ label() }}</div>
|
|
1832
1896
|
</div>
|
|
1833
1897
|
|
|
1834
1898
|
@if (labels().invalid) {
|
|
@@ -2144,13 +2208,275 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "22.1.7", ngImpor
|
|
|
2144
2208
|
</div>
|
|
2145
2209
|
</div>
|
|
2146
2210
|
</div>
|
|
2147
|
-
|
|
2148
|
-
|
|
2149
|
-
|
|
2150
|
-
|
|
2151
|
-
|
|
2152
|
-
|
|
2153
|
-
|
|
2211
|
+
`
|
|
2212
|
+
}]
|
|
2213
|
+
}],
|
|
2214
|
+
ctorParameters: () => [],
|
|
2215
|
+
propDecorators: {
|
|
2216
|
+
label: [{
|
|
2217
|
+
type: i0.Input,
|
|
2218
|
+
args: [{
|
|
2219
|
+
isSignal: true,
|
|
2220
|
+
alias: "label",
|
|
2221
|
+
required: true
|
|
2222
|
+
}]
|
|
2223
|
+
}],
|
|
2224
|
+
labels: [{
|
|
2225
|
+
type: i0.Input,
|
|
2226
|
+
args: [{
|
|
2227
|
+
isSignal: true,
|
|
2228
|
+
alias: "labels",
|
|
2229
|
+
required: true
|
|
2230
|
+
}]
|
|
2231
|
+
}],
|
|
2232
|
+
mode: [{
|
|
2233
|
+
type: i0.Input,
|
|
2234
|
+
args: [{
|
|
2235
|
+
isSignal: true,
|
|
2236
|
+
alias: "mode",
|
|
2237
|
+
required: false
|
|
2238
|
+
}]
|
|
2239
|
+
}],
|
|
2240
|
+
value: [{
|
|
2241
|
+
type: i0.Input,
|
|
2242
|
+
args: [{
|
|
2243
|
+
isSignal: true,
|
|
2244
|
+
alias: "value",
|
|
2245
|
+
required: false
|
|
2246
|
+
}]
|
|
2247
|
+
}, {
|
|
2248
|
+
type: i0.Output,
|
|
2249
|
+
args: ["valueChange"]
|
|
2250
|
+
}],
|
|
2251
|
+
locale: [{
|
|
2252
|
+
type: i0.Input,
|
|
2253
|
+
args: [{
|
|
2254
|
+
isSignal: true,
|
|
2255
|
+
alias: "locale",
|
|
2256
|
+
required: false
|
|
2257
|
+
}]
|
|
2258
|
+
}],
|
|
2259
|
+
calendar: [{
|
|
2260
|
+
type: i0.Input,
|
|
2261
|
+
args: [{
|
|
2262
|
+
isSignal: true,
|
|
2263
|
+
alias: "calendar",
|
|
2264
|
+
required: false
|
|
2265
|
+
}]
|
|
2266
|
+
}],
|
|
2267
|
+
min: [{
|
|
2268
|
+
type: i0.Input,
|
|
2269
|
+
args: [{
|
|
2270
|
+
isSignal: true,
|
|
2271
|
+
alias: "min",
|
|
2272
|
+
required: false
|
|
2273
|
+
}]
|
|
2274
|
+
}],
|
|
2275
|
+
max: [{
|
|
2276
|
+
type: i0.Input,
|
|
2277
|
+
args: [{
|
|
2278
|
+
isSignal: true,
|
|
2279
|
+
alias: "max",
|
|
2280
|
+
required: false
|
|
2281
|
+
}]
|
|
2282
|
+
}],
|
|
2283
|
+
isDateDisabled: [{
|
|
2284
|
+
type: i0.Input,
|
|
2285
|
+
args: [{
|
|
2286
|
+
isSignal: true,
|
|
2287
|
+
alias: "isDateDisabled",
|
|
2288
|
+
required: false
|
|
2289
|
+
}]
|
|
2290
|
+
}],
|
|
2291
|
+
firstDayOfWeek: [{
|
|
2292
|
+
type: i0.Input,
|
|
2293
|
+
args: [{
|
|
2294
|
+
isSignal: true,
|
|
2295
|
+
alias: "firstDayOfWeek",
|
|
2296
|
+
required: false
|
|
2297
|
+
}]
|
|
2298
|
+
}],
|
|
2299
|
+
minuteStep: [{
|
|
2300
|
+
type: i0.Input,
|
|
2301
|
+
args: [{
|
|
2302
|
+
isSignal: true,
|
|
2303
|
+
alias: "minuteStep",
|
|
2304
|
+
required: false
|
|
2305
|
+
}]
|
|
2306
|
+
}],
|
|
2307
|
+
hour12: [{
|
|
2308
|
+
type: i0.Input,
|
|
2309
|
+
args: [{
|
|
2310
|
+
isSignal: true,
|
|
2311
|
+
alias: "hour12",
|
|
2312
|
+
required: false
|
|
2313
|
+
}]
|
|
2314
|
+
}],
|
|
2315
|
+
showWeekNumbers: [{
|
|
2316
|
+
type: i0.Input,
|
|
2317
|
+
args: [{
|
|
2318
|
+
isSignal: true,
|
|
2319
|
+
alias: "showWeekNumbers",
|
|
2320
|
+
required: false
|
|
2321
|
+
}]
|
|
2322
|
+
}],
|
|
2323
|
+
shortcuts: [{
|
|
2324
|
+
type: i0.Input,
|
|
2325
|
+
args: [{
|
|
2326
|
+
isSignal: true,
|
|
2327
|
+
alias: "shortcuts",
|
|
2328
|
+
required: false
|
|
2329
|
+
}]
|
|
2330
|
+
}],
|
|
2331
|
+
confirmOnSelect: [{
|
|
2332
|
+
type: i0.Input,
|
|
2333
|
+
args: [{
|
|
2334
|
+
isSignal: true,
|
|
2335
|
+
alias: "confirmOnSelect",
|
|
2336
|
+
required: false
|
|
2337
|
+
}]
|
|
2338
|
+
}],
|
|
2339
|
+
name: [{
|
|
2340
|
+
type: i0.Input,
|
|
2341
|
+
args: [{
|
|
2342
|
+
isSignal: true,
|
|
2343
|
+
alias: "name",
|
|
2344
|
+
required: false
|
|
2345
|
+
}]
|
|
2346
|
+
}],
|
|
2347
|
+
timeZone: [{
|
|
2348
|
+
type: i0.Input,
|
|
2349
|
+
args: [{
|
|
2350
|
+
isSignal: true,
|
|
2351
|
+
alias: "timeZone",
|
|
2352
|
+
required: false
|
|
2353
|
+
}]
|
|
2354
|
+
}, {
|
|
2355
|
+
type: i0.Output,
|
|
2356
|
+
args: ["timeZoneChange"]
|
|
2357
|
+
}],
|
|
2358
|
+
timeZones: [{
|
|
2359
|
+
type: i0.Input,
|
|
2360
|
+
args: [{
|
|
2361
|
+
isSignal: true,
|
|
2362
|
+
alias: "timeZones",
|
|
2363
|
+
required: false
|
|
2364
|
+
}]
|
|
2365
|
+
}],
|
|
2366
|
+
timeZoneLabels: [{
|
|
2367
|
+
type: i0.Input,
|
|
2368
|
+
args: [{
|
|
2369
|
+
isSignal: true,
|
|
2370
|
+
alias: "timeZoneLabels",
|
|
2371
|
+
required: false
|
|
2372
|
+
}]
|
|
2373
|
+
}],
|
|
2374
|
+
inputId: [{
|
|
2375
|
+
type: i0.Input,
|
|
2376
|
+
args: [{
|
|
2377
|
+
isSignal: true,
|
|
2378
|
+
alias: "inputId",
|
|
2379
|
+
required: false
|
|
2380
|
+
}]
|
|
2381
|
+
}],
|
|
2382
|
+
describedBy: [{
|
|
2383
|
+
type: i0.Input,
|
|
2384
|
+
args: [{
|
|
2385
|
+
isSignal: true,
|
|
2386
|
+
alias: "describedBy",
|
|
2387
|
+
required: false
|
|
2388
|
+
}]
|
|
2389
|
+
}],
|
|
2390
|
+
placeholder: [{
|
|
2391
|
+
type: i0.Input,
|
|
2392
|
+
args: [{
|
|
2393
|
+
isSignal: true,
|
|
2394
|
+
alias: "placeholder",
|
|
2395
|
+
required: false
|
|
2396
|
+
}]
|
|
2397
|
+
}],
|
|
2398
|
+
disabled: [{
|
|
2399
|
+
type: i0.Input,
|
|
2400
|
+
args: [{
|
|
2401
|
+
isSignal: true,
|
|
2402
|
+
alias: "disabled",
|
|
2403
|
+
required: false
|
|
2404
|
+
}]
|
|
2405
|
+
}],
|
|
2406
|
+
readOnly: [{
|
|
2407
|
+
type: i0.Input,
|
|
2408
|
+
args: [{
|
|
2409
|
+
isSignal: true,
|
|
2410
|
+
alias: "readOnly",
|
|
2411
|
+
required: false
|
|
2412
|
+
}]
|
|
2413
|
+
}],
|
|
2414
|
+
required: [{
|
|
2415
|
+
type: i0.Input,
|
|
2416
|
+
args: [{
|
|
2417
|
+
isSignal: true,
|
|
2418
|
+
alias: "required",
|
|
2419
|
+
required: false
|
|
2420
|
+
}]
|
|
2421
|
+
}],
|
|
2422
|
+
formatValue: [{
|
|
2423
|
+
type: i0.Input,
|
|
2424
|
+
args: [{
|
|
2425
|
+
isSignal: true,
|
|
2426
|
+
alias: "formatValue",
|
|
2427
|
+
required: false
|
|
2428
|
+
}]
|
|
2429
|
+
}],
|
|
2430
|
+
parseInput: [{
|
|
2431
|
+
type: i0.Input,
|
|
2432
|
+
args: [{
|
|
2433
|
+
isSignal: true,
|
|
2434
|
+
alias: "parseInput",
|
|
2435
|
+
required: false
|
|
2436
|
+
}]
|
|
2437
|
+
}],
|
|
2438
|
+
className: [{
|
|
2439
|
+
type: i0.Input,
|
|
2440
|
+
args: [{
|
|
2441
|
+
isSignal: true,
|
|
2442
|
+
alias: "className",
|
|
2443
|
+
required: false
|
|
2444
|
+
}]
|
|
2445
|
+
}],
|
|
2446
|
+
change: [{
|
|
2447
|
+
type: i0.Output,
|
|
2448
|
+
args: ["change"]
|
|
2449
|
+
}],
|
|
2450
|
+
shortcut: [{
|
|
2451
|
+
type: i0.Output,
|
|
2452
|
+
args: ["shortcut"]
|
|
2453
|
+
}],
|
|
2454
|
+
invalidInput: [{
|
|
2455
|
+
type: i0.Output,
|
|
2456
|
+
args: ["invalidInput"]
|
|
2457
|
+
}],
|
|
2458
|
+
iconTemplate: [{
|
|
2459
|
+
type: i0.ContentChild,
|
|
2460
|
+
args: [i0.forwardRef(() => TemplateRef), { isSignal: true }]
|
|
2461
|
+
}],
|
|
2462
|
+
rootRef: [{
|
|
2463
|
+
type: i0.ViewChild,
|
|
2464
|
+
args: ["rootEl", { isSignal: true }]
|
|
2465
|
+
}],
|
|
2466
|
+
buttonRef: [{
|
|
2467
|
+
type: i0.ViewChild,
|
|
2468
|
+
args: ["buttonEl", { isSignal: true }]
|
|
2469
|
+
}],
|
|
2470
|
+
dialogRef: [{
|
|
2471
|
+
type: i0.ViewChild,
|
|
2472
|
+
args: ["dialogEl", { isSignal: true }]
|
|
2473
|
+
}],
|
|
2474
|
+
gridRef: [{
|
|
2475
|
+
type: i0.ViewChild,
|
|
2476
|
+
args: ["gridEl", { isSignal: true }]
|
|
2477
|
+
}]
|
|
2478
|
+
}
|
|
2479
|
+
});
|
|
2480
|
+
export { CALENDAR, DateTimePicker, DateTimePickerIcon, addDays, addMonths, daysInMonth, firstDayOfWeekFor, formatIsoDate, formatIsoTime, fromEpochDay, gregorian, isoWeek, joinValue, monthMatrix, monthNames, nextDateTimePickerId, normalizeDigits, numericFieldOrder, pad, parseDateInput, parseIsoDate, parseIsoTime, parseTimeInput, splitValue, toEpochDay, weekdayOf, withinRange };
|
|
2154
2481
|
|
|
2155
|
-
|
|
2156
|
-
//# sourceMappingURL=lilydesignsystem-angular-date-time-picker.mjs.map
|
|
2482
|
+
//# sourceMappingURL=lilydesignsystem-angular-date-time-picker.mjs.map
|