@lilydesignsystem/angular-date-time-picker 0.2.0 → 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 +267 -64
- 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 +79 -64
- package/types/lilydesignsystem-angular-date-time-picker.d.ts.map +1 -1
package/README.md
CHANGED
|
@@ -10,7 +10,7 @@ order, 12- vs 24-hour clock and AM/PM names all come from `Intl`.
|
|
|
10
10
|
|
|
11
11
|
Canonical contract: [spec/index.md](./spec/index.md). This package is the
|
|
12
12
|
Angular port of the Svelte-canonical
|
|
13
|
-
[`@lilydesignsystem/svelte-date-time-picker`](
|
|
13
|
+
[`@lilydesignsystem/svelte-date-time-picker`](../lily-design-system-svelte-date-time-picker/).
|
|
14
14
|
|
|
15
15
|
## Install
|
|
16
16
|
|
|
@@ -62,11 +62,11 @@ export class BookingComponent {
|
|
|
62
62
|
|
|
63
63
|
## The value is always ISO
|
|
64
64
|
|
|
65
|
-
| `mode`
|
|
66
|
-
|
|
|
67
|
-
| `"date"` (default) | `"2026-03-15"`
|
|
68
|
-
| `"time"`
|
|
69
|
-
| `"datetime"`
|
|
65
|
+
| `mode` | `value` |
|
|
66
|
+
| ------------------ | -------------------- |
|
|
67
|
+
| `"date"` (default) | `"2026-03-15"` |
|
|
68
|
+
| `"time"` | `"09:30"` |
|
|
69
|
+
| `"datetime"` | `"2026-03-15T09:30"` |
|
|
70
70
|
|
|
71
71
|
Sortable as a string, unambiguous in every locale, and identical to what
|
|
72
72
|
`<input type="date">` posts — so you can swap the native control in or out
|
|
@@ -193,10 +193,16 @@ once on open — hide it visually with your own CSS if you prefer.
|
|
|
193
193
|
### Replace the glyph
|
|
194
194
|
|
|
195
195
|
```html
|
|
196
|
-
<lily-date-time-picker
|
|
197
|
-
|
|
196
|
+
<lily-date-time-picker
|
|
197
|
+
[label]="label"
|
|
198
|
+
[labels]="labels"
|
|
199
|
+
>
|
|
200
|
+
<ng-template
|
|
201
|
+
lilyDateTimePickerIcon
|
|
202
|
+
let-args
|
|
203
|
+
>
|
|
198
204
|
<my-calendar-icon [expanded]="args.open" />
|
|
199
|
-
<span class="
|
|
205
|
+
<span class="screen-reader-span">{{ args.display }}</span>
|
|
200
206
|
</ng-template>
|
|
201
207
|
</lily-date-time-picker>
|
|
202
208
|
```
|
|
@@ -269,13 +275,18 @@ nobody wants to page a calendar back forty years.
|
|
|
269
275
|
- [`@lilydesignsystem/angular-locale-picker`](../lily-design-system-angular-locale-picker/)
|
|
270
276
|
- [`@lilydesignsystem/angular-text-size-picker`](../lily-design-system-angular-text-size-picker/)
|
|
271
277
|
- [`@lilydesignsystem/angular-share-picker`](../lily-design-system-angular-share-picker/)
|
|
272
|
-
- [`@lilydesignsystem/svelte-date-time-picker`](
|
|
278
|
+
- [`@lilydesignsystem/svelte-date-time-picker`](../lily-design-system-svelte-date-time-picker/) — the canonical Svelte original.
|
|
273
279
|
|
|
274
280
|
## License
|
|
275
281
|
|
|
276
282
|
MIT or Apache-2.0 or GPL-2.0 or GPL-3.0 or BSD-3-Clause. Contact
|
|
277
283
|
joel@joelparkerhenderson.com for other terms.
|
|
278
284
|
|
|
285
|
+
## Known limitations
|
|
286
|
+
|
|
287
|
+
- **Week numbers are ISO 8601 only.** `showWeekNumbers` numbers weeks the ISO 8601 way: weeks start on Monday and week 1 is the week containing the year's first Thursday. Other systems are not available yet: the US, Canada and Japan number from a Sunday-first week containing 1 January, and some countries use a Saturday-first week. This is a documented gap against the worldwide target, not a decision; it is planned as `weekNumbering: "iso" | "us" | "locale"` (tasks.md P17-T4, worldwide audit (`spec/internationalization/worldwide-audit.md` in the monorepo) finding 4). Until then, leave week numbers off for an audience that does not use ISO weeks, or compute them yourself and show them in your own markup.
|
|
288
|
+
- **The column header is yours.** The visible header (`labels.week`) and any accessible name for a week number are supplied by the app, never English defaults, so you can label the column "Wk", "KW" or "Week (ISO)" and make it clear which system is shown.
|
|
289
|
+
|
|
279
290
|
---
|
|
280
291
|
|
|
281
292
|
Lily™ and Lily Design System™ are trademarks.
|
|
@@ -1,7 +1,76 @@
|
|
|
1
1
|
import { NgTemplateOutlet } from "@angular/common";
|
|
2
2
|
import * as i0 from "@angular/core";
|
|
3
|
-
import { ChangeDetectionStrategy, ChangeDetectorRef, Component, Directive, TemplateRef, computed, contentChild, effect, inject, input, model, output, signal, viewChild } 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
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
|
+
}
|
|
5
74
|
const CALENDAR = "📅︎";
|
|
6
75
|
function pad(n, width = 2) {
|
|
7
76
|
return String(Math.abs(n)).padStart(width, "0");
|
|
@@ -187,7 +256,7 @@ function monthMatrix(year, month, firstDayOfWeek) {
|
|
|
187
256
|
function monthNames(locale) {
|
|
188
257
|
const build = (month) => {
|
|
189
258
|
try {
|
|
190
|
-
const fmt = new Intl.DateTimeFormat(locale, {
|
|
259
|
+
const fmt = new Intl.DateTimeFormat(gregorian(locale), {
|
|
191
260
|
month,
|
|
192
261
|
timeZone: "UTC"
|
|
193
262
|
});
|
|
@@ -217,7 +286,7 @@ function matchMonthName(token, names) {
|
|
|
217
286
|
}
|
|
218
287
|
function numericFieldOrder(locale) {
|
|
219
288
|
try {
|
|
220
|
-
const order = new Intl.DateTimeFormat(locale, {
|
|
289
|
+
const order = new Intl.DateTimeFormat(gregorian(locale), {
|
|
221
290
|
day: "2-digit",
|
|
222
291
|
month: "2-digit",
|
|
223
292
|
year: "numeric",
|
|
@@ -232,7 +301,7 @@ function numericFieldOrder(locale) {
|
|
|
232
301
|
];
|
|
233
302
|
}
|
|
234
303
|
function parseDateInput(text, locale) {
|
|
235
|
-
const trimmed = text.trim();
|
|
304
|
+
const trimmed = normalizeDigits(text).trim();
|
|
236
305
|
if (!trimmed) return null;
|
|
237
306
|
const iso = parseIsoDate(trimmed);
|
|
238
307
|
if (iso) return formatIsoDate(iso);
|
|
@@ -272,8 +341,123 @@ function parseDateInput(text, locale) {
|
|
|
272
341
|
day
|
|
273
342
|
});
|
|
274
343
|
}
|
|
275
|
-
function
|
|
276
|
-
|
|
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;
|
|
428
|
+
}
|
|
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);
|
|
277
461
|
if (!m) return null;
|
|
278
462
|
let hour = Number(m[1] ?? m[4]);
|
|
279
463
|
const minute = Number(m[2] ?? m[5]);
|
|
@@ -316,7 +500,7 @@ var DateTimePickerIcon = class DateTimePickerIcon {
|
|
|
316
500
|
static {
|
|
317
501
|
this.ɵfac = i0.ɵɵngDeclareFactory({
|
|
318
502
|
minVersion: "12.0.0",
|
|
319
|
-
version: "22.2.
|
|
503
|
+
version: "22.2.4",
|
|
320
504
|
ngImport: i0,
|
|
321
505
|
type: DateTimePickerIcon,
|
|
322
506
|
deps: [],
|
|
@@ -326,7 +510,7 @@ var DateTimePickerIcon = class DateTimePickerIcon {
|
|
|
326
510
|
static {
|
|
327
511
|
this.ɵdir = i0.ɵɵngDeclareDirective({
|
|
328
512
|
minVersion: "14.0.0",
|
|
329
|
-
version: "22.2.
|
|
513
|
+
version: "22.2.4",
|
|
330
514
|
type: DateTimePickerIcon,
|
|
331
515
|
isStandalone: true,
|
|
332
516
|
selector: "ng-template[lilyDateTimePickerIcon]",
|
|
@@ -336,7 +520,7 @@ var DateTimePickerIcon = class DateTimePickerIcon {
|
|
|
336
520
|
};
|
|
337
521
|
i0.ɵɵngDeclareClassMetadata({
|
|
338
522
|
minVersion: "12.0.0",
|
|
339
|
-
version: "22.2.
|
|
523
|
+
version: "22.2.4",
|
|
340
524
|
ngImport: i0,
|
|
341
525
|
type: DateTimePickerIcon,
|
|
342
526
|
decorators: [{
|
|
@@ -372,6 +556,7 @@ var DateTimePicker = class DateTimePicker {
|
|
|
372
556
|
this.mode = input("date", ...ngDevMode ? [{ debugName: "mode" }] : /* istanbul ignore next */ []);
|
|
373
557
|
this.value = model("", ...ngDevMode ? [{ debugName: "value" }] : /* istanbul ignore next */ []);
|
|
374
558
|
this.locale = input("", ...ngDevMode ? [{ debugName: "locale" }] : /* istanbul ignore next */ []);
|
|
559
|
+
this.calendar = input("gregory", ...ngDevMode ? [{ debugName: "calendar" }] : /* istanbul ignore next */ []);
|
|
375
560
|
this.min = input("", ...ngDevMode ? [{ debugName: "min" }] : /* istanbul ignore next */ []);
|
|
376
561
|
this.max = input("", ...ngDevMode ? [{ debugName: "max" }] : /* istanbul ignore next */ []);
|
|
377
562
|
this.isDateDisabled = input(void 0, ...ngDevMode ? [{ debugName: "isDateDisabled" }] : /* istanbul ignore next */ []);
|
|
@@ -433,8 +618,7 @@ var DateTimePicker = class DateTimePicker {
|
|
|
433
618
|
this.typed = signal(null, ...ngDevMode ? [{ debugName: "typed" }] : /* istanbul ignore next */ []);
|
|
434
619
|
this.pendingDate = signal("", ...ngDevMode ? [{ debugName: "pendingDate" }] : /* istanbul ignore next */ []);
|
|
435
620
|
this.pendingTime = signal("", ...ngDevMode ? [{ debugName: "pendingTime" }] : /* istanbul ignore next */ []);
|
|
436
|
-
this.
|
|
437
|
-
this.viewMonth = signal(1, ...ngDevMode ? [{ debugName: "viewMonth" }] : /* istanbul ignore next */ []);
|
|
621
|
+
this.viewStart = signal("1970-01-01", ...ngDevMode ? [{ debugName: "viewStart" }] : /* istanbul ignore next */ []);
|
|
438
622
|
this.cursor = signal("", ...ngDevMode ? [{ debugName: "cursor" }] : /* istanbul ignore next */ []);
|
|
439
623
|
this.today = signal("", ...ngDevMode ? [{ debugName: "today" }] : /* istanbul ignore next */ []);
|
|
440
624
|
this.fieldId = computed(() => this.inputId() || `${this.baseId}-input`, ...ngDevMode ? [{ debugName: "fieldId" }] : /* istanbul ignore next */ []);
|
|
@@ -455,16 +639,15 @@ var DateTimePicker = class DateTimePicker {
|
|
|
455
639
|
return typeof Intl.supportedValuesOf === "function" ? Intl.supportedValuesOf("timeZone") : [];
|
|
456
640
|
}, ...ngDevMode ? [{ debugName: "zoneOptions" }] : /* istanbul ignore next */ []);
|
|
457
641
|
this.periodText = computed(() => {
|
|
458
|
-
const
|
|
459
|
-
const viewMonth = this.viewMonth();
|
|
642
|
+
const viewStart = this.viewStart();
|
|
460
643
|
try {
|
|
461
|
-
return new Intl.DateTimeFormat(this.locale() || void 0, {
|
|
644
|
+
return new Intl.DateTimeFormat(calendarLocale(this.locale() || void 0, this.calendar()), {
|
|
462
645
|
month: "long",
|
|
463
646
|
year: "numeric",
|
|
464
647
|
timeZone: "UTC"
|
|
465
|
-
}).format(new Date(
|
|
648
|
+
}).format(/* @__PURE__ */ new Date(`${viewStart}T00:00:00Z`));
|
|
466
649
|
} catch {
|
|
467
|
-
return
|
|
650
|
+
return viewStart.slice(0, 7);
|
|
468
651
|
}
|
|
469
652
|
}, ...ngDevMode ? [{ debugName: "periodText" }] : /* istanbul ignore next */ []);
|
|
470
653
|
this.weekdays = computed(() => {
|
|
@@ -475,11 +658,11 @@ var DateTimePicker = class DateTimePicker {
|
|
|
475
658
|
const d = new Date(Date.UTC(2021, 7, 1 + (weekStart + i) % 7));
|
|
476
659
|
try {
|
|
477
660
|
out.push({
|
|
478
|
-
short: new Intl.DateTimeFormat(locale, {
|
|
661
|
+
short: new Intl.DateTimeFormat(gregorian(locale), {
|
|
479
662
|
weekday: "short",
|
|
480
663
|
timeZone: "UTC"
|
|
481
664
|
}).format(d),
|
|
482
|
-
long: new Intl.DateTimeFormat(locale, {
|
|
665
|
+
long: new Intl.DateTimeFormat(gregorian(locale), {
|
|
483
666
|
weekday: "long",
|
|
484
667
|
timeZone: "UTC"
|
|
485
668
|
}).format(d)
|
|
@@ -493,7 +676,7 @@ var DateTimePicker = class DateTimePicker {
|
|
|
493
676
|
}
|
|
494
677
|
return out;
|
|
495
678
|
}, ...ngDevMode ? [{ debugName: "weekdays" }] : /* istanbul ignore next */ []);
|
|
496
|
-
this.weeks = computed(() =>
|
|
679
|
+
this.weeks = computed(() => calendarMonthMatrix(this.viewStart(), this.weekStart(), this.calendar()), ...ngDevMode ? [{ debugName: "weeks" }] : /* istanbul ignore next */ []);
|
|
497
680
|
this.pendingHour = computed(() => parseIsoTime(this.pendingTime())?.hour ?? 0, ...ngDevMode ? [{ debugName: "pendingHour" }] : /* istanbul ignore next */ []);
|
|
498
681
|
this.pendingMinute = computed(() => parseIsoTime(this.pendingTime())?.minute ?? 0, ...ngDevMode ? [{ debugName: "pendingMinute" }] : /* istanbul ignore next */ []);
|
|
499
682
|
this.hourOptions = computed(() => {
|
|
@@ -535,11 +718,39 @@ var DateTimePicker = class DateTimePicker {
|
|
|
535
718
|
this.today.set(today);
|
|
536
719
|
const anchor = parseIsoDate(committed.date) ?? parseIsoDate(today);
|
|
537
720
|
if (anchor) {
|
|
538
|
-
this.
|
|
539
|
-
this.viewMonth.set(anchor.month);
|
|
721
|
+
this.viewStart.set(calendarMonthStart(formatIsoDate(anchor), this.calendar()));
|
|
540
722
|
this.cursor.set(formatIsoDate(anchor));
|
|
541
723
|
}
|
|
542
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
|
+
});
|
|
543
754
|
}
|
|
544
755
|
pad2(n) {
|
|
545
756
|
return pad(n);
|
|
@@ -548,17 +759,16 @@ var DateTimePicker = class DateTimePicker {
|
|
|
548
759
|
return isoWeek(isoDate);
|
|
549
760
|
}
|
|
550
761
|
parseCell(isoDate) {
|
|
551
|
-
const parsed = parseIsoDate(isoDate);
|
|
552
762
|
return {
|
|
553
|
-
day:
|
|
554
|
-
outside:
|
|
763
|
+
day: parseIsoDate(isoDate) ? String(calendarDay(isoDate, this.calendar())) : "",
|
|
764
|
+
outside: isoDate < this.viewStart() || isoDate >= calendarAddMonths(this.viewStart(), 1, this.calendar())
|
|
555
765
|
};
|
|
556
766
|
}
|
|
557
767
|
dayLabel(isoDate) {
|
|
558
768
|
const parsed = parseIsoDate(isoDate);
|
|
559
769
|
if (!parsed) return isoDate;
|
|
560
770
|
try {
|
|
561
|
-
return new Intl.DateTimeFormat(this.locale() || void 0, {
|
|
771
|
+
return new Intl.DateTimeFormat(calendarLocale(this.locale() || void 0, this.calendar()), {
|
|
562
772
|
weekday: "long",
|
|
563
773
|
day: "numeric",
|
|
564
774
|
month: "long",
|
|
@@ -571,7 +781,7 @@ var DateTimePicker = class DateTimePicker {
|
|
|
571
781
|
}
|
|
572
782
|
dayPeriodName(pm) {
|
|
573
783
|
try {
|
|
574
|
-
const found = new Intl.DateTimeFormat(this.locale() || void 0, {
|
|
784
|
+
const found = new Intl.DateTimeFormat(gregorian(this.locale() || void 0), {
|
|
575
785
|
hour: "numeric",
|
|
576
786
|
hour12: true,
|
|
577
787
|
timeZone: "UTC"
|
|
@@ -584,7 +794,7 @@ var DateTimePicker = class DateTimePicker {
|
|
|
584
794
|
const parsed = parseIsoTime(isoTime);
|
|
585
795
|
if (!parsed) return isoTime;
|
|
586
796
|
try {
|
|
587
|
-
return new Intl.DateTimeFormat(this.locale() || void 0, {
|
|
797
|
+
return new Intl.DateTimeFormat(gregorian(this.locale() || void 0), {
|
|
588
798
|
hour: "2-digit",
|
|
589
799
|
minute: "2-digit",
|
|
590
800
|
hour12: this.clock12(),
|
|
@@ -600,7 +810,7 @@ var DateTimePicker = class DateTimePicker {
|
|
|
600
810
|
const chunks = [];
|
|
601
811
|
const parsed = date ? parseIsoDate(date) : null;
|
|
602
812
|
if (parsed) try {
|
|
603
|
-
chunks.push(new Intl.DateTimeFormat(this.locale() || void 0, {
|
|
813
|
+
chunks.push(new Intl.DateTimeFormat(gregorian(this.locale() || void 0), {
|
|
604
814
|
day: "2-digit",
|
|
605
815
|
month: "short",
|
|
606
816
|
year: "numeric",
|
|
@@ -637,10 +847,7 @@ var DateTimePicker = class DateTimePicker {
|
|
|
637
847
|
this.pendingTime.set(this.committed().time || this.defaultTime());
|
|
638
848
|
this.cursor.set(pendingDate);
|
|
639
849
|
const anchor = parseIsoDate(pendingDate) ?? parseIsoDate(today);
|
|
640
|
-
if (anchor)
|
|
641
|
-
this.viewYear.set(anchor.year);
|
|
642
|
-
this.viewMonth.set(anchor.month);
|
|
643
|
-
}
|
|
850
|
+
if (anchor) this.viewStart.set(calendarMonthStart(formatIsoDate(anchor), this.calendar()));
|
|
644
851
|
this.open.set(true);
|
|
645
852
|
this.cdr.detectChanges();
|
|
646
853
|
this.focusInitial();
|
|
@@ -693,10 +900,7 @@ var DateTimePicker = class DateTimePicker {
|
|
|
693
900
|
if (!withinRange(nextIso, this.min() || void 0, this.max() || void 0)) return;
|
|
694
901
|
this.cursor.set(nextIso);
|
|
695
902
|
const parsed = parseIsoDate(nextIso);
|
|
696
|
-
if (parsed
|
|
697
|
-
this.viewYear.set(parsed.year);
|
|
698
|
-
this.viewMonth.set(parsed.month);
|
|
699
|
-
}
|
|
903
|
+
if (parsed) this.viewStart.set(calendarMonthStart(formatIsoDate(parsed), this.calendar()));
|
|
700
904
|
this.cdr.detectChanges();
|
|
701
905
|
this.focusCursor();
|
|
702
906
|
}
|
|
@@ -715,22 +919,12 @@ var DateTimePicker = class DateTimePicker {
|
|
|
715
919
|
if (this.commitOnDay()) this.commit();
|
|
716
920
|
}
|
|
717
921
|
shiftMonth(delta) {
|
|
718
|
-
const next =
|
|
719
|
-
year: this.viewYear(),
|
|
720
|
-
month: this.viewMonth(),
|
|
721
|
-
day: 1
|
|
722
|
-
}), delta));
|
|
723
|
-
if (!next) return;
|
|
922
|
+
const next = calendarAddMonths(this.viewStart(), delta, this.calendar());
|
|
724
923
|
const hadGridFocus = this.gridRef()?.nativeElement.contains(document.activeElement) === true;
|
|
725
|
-
this.
|
|
726
|
-
this.viewMonth.set(next.month);
|
|
924
|
+
this.viewStart.set(next);
|
|
727
925
|
const c = parseIsoDate(this.cursor());
|
|
728
926
|
if (c) {
|
|
729
|
-
this.cursor.set(formatIsoDate(
|
|
730
|
-
year: next.year,
|
|
731
|
-
month: next.month,
|
|
732
|
-
day: Math.min(c.day, daysInMonth(next.year, next.month))
|
|
733
|
-
}));
|
|
927
|
+
this.cursor.set(addDays(next, Math.min(calendarDay(formatIsoDate(c), this.calendar()), calendarMonthLength(next, this.calendar())) - 1));
|
|
734
928
|
if (hadGridFocus) {
|
|
735
929
|
this.cdr.detectChanges();
|
|
736
930
|
this.focusCursor();
|
|
@@ -747,10 +941,7 @@ var DateTimePicker = class DateTimePicker {
|
|
|
747
941
|
if (!withinRange(next, this.min() || void 0, this.max() || void 0)) return;
|
|
748
942
|
const hadGridFocus = this.gridRef()?.nativeElement.contains(document.activeElement) === true;
|
|
749
943
|
const parsed = parseIsoDate(next);
|
|
750
|
-
if (parsed
|
|
751
|
-
this.viewYear.set(parsed.year);
|
|
752
|
-
this.viewMonth.set(parsed.month);
|
|
753
|
-
}
|
|
944
|
+
if (parsed) this.viewStart.set(calendarMonthStart(formatIsoDate(parsed), this.calendar()));
|
|
754
945
|
this.cursor.set(next);
|
|
755
946
|
if (!this.dayDisabled(next)) this.pendingDate.set(next);
|
|
756
947
|
if (hadGridFocus) {
|
|
@@ -765,7 +956,7 @@ var DateTimePicker = class DateTimePicker {
|
|
|
765
956
|
return this.timeZoneLabels()[zone] ?? zone;
|
|
766
957
|
}
|
|
767
958
|
onGridKeydown(event) {
|
|
768
|
-
switch (event.key) {
|
|
959
|
+
switch (logicalKey(event.key, isRtl(this.gridRef()?.nativeElement))) {
|
|
769
960
|
case "ArrowLeft":
|
|
770
961
|
event.preventDefault();
|
|
771
962
|
this.moveCursor(addDays(this.cursor(), -1));
|
|
@@ -837,12 +1028,12 @@ var DateTimePicker = class DateTimePicker {
|
|
|
837
1028
|
}
|
|
838
1029
|
}
|
|
839
1030
|
parseTypedForMode(text) {
|
|
840
|
-
if (this.mode() === "time") return parseTimeInput(text);
|
|
1031
|
+
if (this.mode() === "time") return parseTimeInput(text, this.locale() || void 0);
|
|
841
1032
|
if (this.mode() === "date") return parseDateInput(text, this.locale() || void 0);
|
|
842
1033
|
const m = /^(.*?)[T\s]+([^\sT]+)$/.exec(text.trim());
|
|
843
1034
|
if (!m) return null;
|
|
844
1035
|
const date = parseDateInput(m[1], this.locale() || void 0);
|
|
845
|
-
const time = parseTimeInput(m[2]);
|
|
1036
|
+
const time = parseTimeInput(m[2], this.locale() || void 0);
|
|
846
1037
|
return date && time ? `${date}T${time}` : null;
|
|
847
1038
|
}
|
|
848
1039
|
resolveTyped() {
|
|
@@ -915,10 +1106,7 @@ var DateTimePicker = class DateTimePicker {
|
|
|
915
1106
|
this.pendingDate.set(target);
|
|
916
1107
|
this.cursor.set(target);
|
|
917
1108
|
const parsed = parseIsoDate(target);
|
|
918
|
-
if (parsed)
|
|
919
|
-
this.viewYear.set(parsed.year);
|
|
920
|
-
this.viewMonth.set(parsed.month);
|
|
921
|
-
}
|
|
1109
|
+
if (parsed) this.viewStart.set(calendarMonthStart(formatIsoDate(parsed), this.calendar()));
|
|
922
1110
|
this.shortcut.emit({
|
|
923
1111
|
id: shortcut.id,
|
|
924
1112
|
isoDate: target
|
|
@@ -939,7 +1127,7 @@ var DateTimePicker = class DateTimePicker {
|
|
|
939
1127
|
static {
|
|
940
1128
|
this.ɵfac = i0.ɵɵngDeclareFactory({
|
|
941
1129
|
minVersion: "12.0.0",
|
|
942
|
-
version: "22.2.
|
|
1130
|
+
version: "22.2.4",
|
|
943
1131
|
ngImport: i0,
|
|
944
1132
|
type: DateTimePicker,
|
|
945
1133
|
deps: [],
|
|
@@ -949,7 +1137,7 @@ var DateTimePicker = class DateTimePicker {
|
|
|
949
1137
|
static {
|
|
950
1138
|
this.ɵcmp = i0.ɵɵngDeclareComponent({
|
|
951
1139
|
minVersion: "17.0.0",
|
|
952
|
-
version: "22.2.
|
|
1140
|
+
version: "22.2.4",
|
|
953
1141
|
type: DateTimePicker,
|
|
954
1142
|
isStandalone: true,
|
|
955
1143
|
selector: "lily-date-time-picker",
|
|
@@ -989,6 +1177,13 @@ var DateTimePicker = class DateTimePicker {
|
|
|
989
1177
|
isRequired: false,
|
|
990
1178
|
transformFunction: null
|
|
991
1179
|
},
|
|
1180
|
+
calendar: {
|
|
1181
|
+
classPropertyName: "calendar",
|
|
1182
|
+
publicName: "calendar",
|
|
1183
|
+
isSignal: true,
|
|
1184
|
+
isRequired: false,
|
|
1185
|
+
transformFunction: null
|
|
1186
|
+
},
|
|
992
1187
|
min: {
|
|
993
1188
|
classPropertyName: "min",
|
|
994
1189
|
publicName: "min",
|
|
@@ -1612,7 +1807,7 @@ var DateTimePicker = class DateTimePicker {
|
|
|
1612
1807
|
};
|
|
1613
1808
|
i0.ɵɵngDeclareClassMetadata({
|
|
1614
1809
|
minVersion: "12.0.0",
|
|
1615
|
-
version: "22.2.
|
|
1810
|
+
version: "22.2.4",
|
|
1616
1811
|
ngImport: i0,
|
|
1617
1812
|
type: DateTimePicker,
|
|
1618
1813
|
decorators: [{
|
|
@@ -2061,6 +2256,14 @@ i0.ɵɵngDeclareClassMetadata({
|
|
|
2061
2256
|
required: false
|
|
2062
2257
|
}]
|
|
2063
2258
|
}],
|
|
2259
|
+
calendar: [{
|
|
2260
|
+
type: i0.Input,
|
|
2261
|
+
args: [{
|
|
2262
|
+
isSignal: true,
|
|
2263
|
+
alias: "calendar",
|
|
2264
|
+
required: false
|
|
2265
|
+
}]
|
|
2266
|
+
}],
|
|
2064
2267
|
min: [{
|
|
2065
2268
|
type: i0.Input,
|
|
2066
2269
|
args: [{
|
|
@@ -2274,6 +2477,6 @@ i0.ɵɵngDeclareClassMetadata({
|
|
|
2274
2477
|
}]
|
|
2275
2478
|
}
|
|
2276
2479
|
});
|
|
2277
|
-
export { CALENDAR, DateTimePicker, DateTimePickerIcon, addDays, addMonths, daysInMonth, firstDayOfWeekFor, formatIsoDate, formatIsoTime, fromEpochDay, isoWeek, joinValue, monthMatrix, monthNames, nextDateTimePickerId, numericFieldOrder, pad, parseDateInput, parseIsoDate, parseIsoTime, parseTimeInput, splitValue, toEpochDay, weekdayOf, withinRange };
|
|
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 };
|
|
2278
2481
|
|
|
2279
2482
|
//# sourceMappingURL=lilydesignsystem-angular-date-time-picker.mjs.map
|