@lekoala/date-picker 0.4.0 → 0.5.0
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 +281 -265
- package/custom-elements.json +10 -0
- package/dist/date-picker.css +20 -15
- package/dist/date-picker.js +199 -115
- package/dist/date-picker.min.css +1 -1
- package/dist/date-picker.min.js +13 -13
- package/dist/date-picker.standalone.min.js +34 -29
- package/dist/types/control-classes.d.ts +30 -0
- package/dist/types/control-classes.d.ts.map +1 -0
- package/dist/types/date-calendar.d.ts +15 -0
- package/dist/types/date-calendar.d.ts.map +1 -1
- package/dist/types/date-picker.d.ts +15 -0
- package/dist/types/date-picker.d.ts.map +1 -1
- package/dist/types/date.d.ts +4 -2
- package/dist/types/date.d.ts.map +1 -1
- package/dist/types/index.d.ts +1 -0
- package/dist/types/index.d.ts.map +1 -1
- package/dist/types/intl.d.ts.map +1 -1
- package/dist/types/source.d.ts +1 -0
- package/dist/types/source.d.ts.map +1 -1
- package/docs/API.md +430 -408
- package/docs/DECISIONS.md +68 -62
- package/docs/USE_CASES.md +156 -144
- package/package.json +3 -3
- package/src/control-classes.js +50 -0
- package/src/date-calendar.js +47 -16
- package/src/date-field.js +1 -1
- package/src/date-picker.css +20 -15
- package/src/date-picker.js +47 -46
- package/src/date.js +8 -3
- package/src/index.js +1 -0
- package/src/intl.js +39 -10
- package/src/source.js +14 -4
package/dist/date-picker.js
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
/*** @lekoala/date-picker v0.
|
|
1
|
+
/*** @lekoala/date-picker v0.5.0 - https://github.com/lekoala/date-picker ***/
|
|
2
2
|
(() => {
|
|
3
3
|
var __defProp = Object.defineProperty;
|
|
4
4
|
var __getOwnPropNames = Object.getOwnPropertyNames;
|
|
@@ -181,8 +181,10 @@
|
|
|
181
181
|
for (let i = 0;i < 7; i++)
|
|
182
182
|
week.push(addDays(cursor, i));
|
|
183
183
|
weeks.push(week);
|
|
184
|
-
if (compareDates(week[6], end) >= 0)
|
|
185
|
-
|
|
184
|
+
if (compareDates(week[6], end) >= 0) {
|
|
185
|
+
if (!options.fixedWeeks || weeks.length >= 6 || compareDates(week[6], addDays("9999-12-31", -7)) > 0)
|
|
186
|
+
break;
|
|
187
|
+
}
|
|
186
188
|
cursor = addDays(cursor, 7);
|
|
187
189
|
}
|
|
188
190
|
return weeks;
|
|
@@ -296,6 +298,30 @@
|
|
|
296
298
|
}
|
|
297
299
|
}
|
|
298
300
|
|
|
301
|
+
// src/control-classes.js
|
|
302
|
+
function normalizeControlClass(value) {
|
|
303
|
+
if (typeof value !== "string")
|
|
304
|
+
return "";
|
|
305
|
+
return [
|
|
306
|
+
...new Set(value.split(/\s+/).filter((token) => token && !token.startsWith("dp-") && ![...token].some((char) => char.charCodeAt(0) < 32 || char.charCodeAt(0) === 127)))
|
|
307
|
+
].join(" ");
|
|
308
|
+
}
|
|
309
|
+
function sameControlClasses(a, b) {
|
|
310
|
+
return a.month === b.month && a.year === b.year && a.nav === b.nav;
|
|
311
|
+
}
|
|
312
|
+
var defaults = { month: "", year: "", nav: "" };
|
|
313
|
+
function getDefaultControlClasses() {
|
|
314
|
+
return { ...defaults };
|
|
315
|
+
}
|
|
316
|
+
function resolveControlClasses(classes) {
|
|
317
|
+
const result = getDefaultControlClasses();
|
|
318
|
+
for (const role of ["month", "year", "nav"]) {
|
|
319
|
+
if (classes && Object.hasOwn(classes, role))
|
|
320
|
+
result[role] = normalizeControlClass(classes[role]);
|
|
321
|
+
}
|
|
322
|
+
return result;
|
|
323
|
+
}
|
|
324
|
+
|
|
299
325
|
// src/date-range.js
|
|
300
326
|
function normalizeRange(range) {
|
|
301
327
|
if (range == null)
|
|
@@ -480,6 +506,23 @@
|
|
|
480
506
|
|
|
481
507
|
// src/intl.js
|
|
482
508
|
var BIDI = /[\u200e\u200f\u061c\u202a-\u202e\u2066-\u2069]/g;
|
|
509
|
+
var dateFormatters = new Map;
|
|
510
|
+
var digitMaps = new Map;
|
|
511
|
+
function cached(cache, key, create) {
|
|
512
|
+
const existing = cache.get(key);
|
|
513
|
+
if (existing !== undefined)
|
|
514
|
+
return existing;
|
|
515
|
+
const value = create();
|
|
516
|
+
const oldest = cache.keys().next().value;
|
|
517
|
+
if (cache.size >= 64 && oldest !== undefined)
|
|
518
|
+
cache.delete(oldest);
|
|
519
|
+
cache.set(key, value);
|
|
520
|
+
return value;
|
|
521
|
+
}
|
|
522
|
+
function dateFormatter(locale, options) {
|
|
523
|
+
const key = JSON.stringify([locale, options]);
|
|
524
|
+
return cached(dateFormatters, key, () => new Intl.DateTimeFormat(locale, options));
|
|
525
|
+
}
|
|
483
526
|
function resolveLocale(locale = "") {
|
|
484
527
|
if (locale)
|
|
485
528
|
return locale;
|
|
@@ -490,11 +533,13 @@
|
|
|
490
533
|
return "en-US";
|
|
491
534
|
}
|
|
492
535
|
function digitMap(locale) {
|
|
493
|
-
|
|
494
|
-
|
|
495
|
-
|
|
496
|
-
|
|
497
|
-
|
|
536
|
+
return cached(digitMaps, locale, () => {
|
|
537
|
+
const formatter = new Intl.NumberFormat(locale, { useGrouping: false });
|
|
538
|
+
const map = new Map;
|
|
539
|
+
for (let i = 0;i <= 9; i++)
|
|
540
|
+
map.set(formatter.format(i), String(i));
|
|
541
|
+
return map;
|
|
542
|
+
});
|
|
498
543
|
}
|
|
499
544
|
function normalizeDigits(text, locale, options = {}) {
|
|
500
545
|
let result = String(text || "").replace(BIDI, "");
|
|
@@ -506,7 +551,7 @@
|
|
|
506
551
|
}
|
|
507
552
|
function formatLongDate(value, locale = "") {
|
|
508
553
|
const resolved = resolveLocale(locale);
|
|
509
|
-
return
|
|
554
|
+
return dateFormatter(resolved, {
|
|
510
555
|
calendar: "gregory",
|
|
511
556
|
weekday: "long",
|
|
512
557
|
year: "numeric",
|
|
@@ -517,7 +562,7 @@
|
|
|
517
562
|
}
|
|
518
563
|
function formatMonthYear(value, locale = "") {
|
|
519
564
|
const resolved = resolveLocale(locale);
|
|
520
|
-
return
|
|
565
|
+
return dateFormatter(resolved, {
|
|
521
566
|
calendar: "gregory",
|
|
522
567
|
year: "numeric",
|
|
523
568
|
month: "long",
|
|
@@ -527,7 +572,7 @@
|
|
|
527
572
|
function monthYearOrder(locale = "") {
|
|
528
573
|
const resolved = resolveLocale(locale);
|
|
529
574
|
try {
|
|
530
|
-
const parts =
|
|
575
|
+
const parts = dateFormatter(resolved, {
|
|
531
576
|
calendar: "gregory",
|
|
532
577
|
year: "numeric",
|
|
533
578
|
month: "long",
|
|
@@ -552,12 +597,12 @@
|
|
|
552
597
|
}
|
|
553
598
|
function monthNames(locale = "", style = "long") {
|
|
554
599
|
const resolved = resolveLocale(locale);
|
|
555
|
-
const formatter =
|
|
600
|
+
const formatter = dateFormatter(resolved, { calendar: "gregory", month: style, timeZone: "UTC" });
|
|
556
601
|
return Array.from({ length: 12 }, (_, index) => formatter.format(toIntlDate(`2026-${String(index + 1).padStart(2, "0")}-15`)));
|
|
557
602
|
}
|
|
558
603
|
function weekdayNames(locale = "", firstDay = 1, style = "short") {
|
|
559
604
|
const resolved = resolveLocale(locale);
|
|
560
|
-
const formatter =
|
|
605
|
+
const formatter = dateFormatter(resolved, {
|
|
561
606
|
calendar: "gregory",
|
|
562
607
|
weekday: style,
|
|
563
608
|
timeZone: "UTC"
|
|
@@ -575,7 +620,7 @@
|
|
|
575
620
|
}
|
|
576
621
|
function createDateAdapter(locale = "") {
|
|
577
622
|
const resolved = resolveLocale(locale);
|
|
578
|
-
const formatter =
|
|
623
|
+
const formatter = dateFormatter(resolved, {
|
|
579
624
|
calendar: "gregory",
|
|
580
625
|
year: "numeric",
|
|
581
626
|
month: "2-digit",
|
|
@@ -654,9 +699,9 @@
|
|
|
654
699
|
rangeOrderStart: "Start must be on or before end",
|
|
655
700
|
rangeOrderEnd: "End must be on or after start"
|
|
656
701
|
};
|
|
657
|
-
var
|
|
702
|
+
var defaults2 = { ...DEFAULT_MESSAGES };
|
|
658
703
|
function getDefaultMessages() {
|
|
659
|
-
return { ...
|
|
704
|
+
return { ...defaults2 };
|
|
660
705
|
}
|
|
661
706
|
|
|
662
707
|
// src/source.js
|
|
@@ -756,7 +801,9 @@
|
|
|
756
801
|
this._highlightedRange = { start: "", end: "" };
|
|
757
802
|
this._paintedRange = { start: "", end: "" };
|
|
758
803
|
this._paintedPreview = false;
|
|
804
|
+
this._renderedStates = new Map;
|
|
759
805
|
this._messages = getDefaultMessages();
|
|
806
|
+
this._controlClasses = getDefaultControlClasses();
|
|
760
807
|
this._onClick = this._onClick.bind(this);
|
|
761
808
|
this._onChange = this._onChange.bind(this);
|
|
762
809
|
this._onKeyDown = this._onKeyDown.bind(this);
|
|
@@ -893,6 +940,17 @@
|
|
|
893
940
|
set showWeekNumbers(value) {
|
|
894
941
|
this.toggleAttribute("show-week-numbers", Boolean(value));
|
|
895
942
|
}
|
|
943
|
+
get controlClasses() {
|
|
944
|
+
return { ...this._controlClasses };
|
|
945
|
+
}
|
|
946
|
+
set controlClasses(value) {
|
|
947
|
+
const classes = resolveControlClasses(value);
|
|
948
|
+
if (sameControlClasses(classes, this._controlClasses))
|
|
949
|
+
return;
|
|
950
|
+
this._controlClasses = classes;
|
|
951
|
+
if (this._connected)
|
|
952
|
+
this.render();
|
|
953
|
+
}
|
|
896
954
|
get messages() {
|
|
897
955
|
return this._messages;
|
|
898
956
|
}
|
|
@@ -973,18 +1031,10 @@
|
|
|
973
1031
|
return compareDates(candidate, last) > 0 ? last : candidate;
|
|
974
1032
|
}
|
|
975
1033
|
_weeks(display = this.display) {
|
|
976
|
-
|
|
977
|
-
|
|
978
|
-
|
|
979
|
-
|
|
980
|
-
while (weeks.length < 6 && cursor) {
|
|
981
|
-
const week = [];
|
|
982
|
-
for (let i = 1;i <= 7; i++)
|
|
983
|
-
week.push(addDays(cursor, i));
|
|
984
|
-
weeks.push(week);
|
|
985
|
-
cursor = week[6];
|
|
986
|
-
}
|
|
987
|
-
return weeks;
|
|
1034
|
+
return getMonthWeeks(clampDisplayMonth(display, this.firstDay), {
|
|
1035
|
+
firstDay: this.firstDay,
|
|
1036
|
+
fixedWeeks: this.fixedWeeks
|
|
1037
|
+
});
|
|
988
1038
|
}
|
|
989
1039
|
_focusTargetKey(element) {
|
|
990
1040
|
if (element.matches(".dp-month-select, .dp-year-input") && element.id) {
|
|
@@ -1171,6 +1221,8 @@
|
|
|
1171
1221
|
].filter(Boolean).join(". ");
|
|
1172
1222
|
}
|
|
1173
1223
|
_updateRangeDom() {
|
|
1224
|
+
const previousRange = this._paintedRange;
|
|
1225
|
+
const previousPreview = this._paintedPreview;
|
|
1174
1226
|
this._paintedRange = { ...this._highlightedRange };
|
|
1175
1227
|
this._paintedPreview = this.hasAttribute("data-range-preview");
|
|
1176
1228
|
for (const cell of this.querySelectorAll(".dp-day[data-date]")) {
|
|
@@ -1178,13 +1230,20 @@
|
|
|
1178
1230
|
continue;
|
|
1179
1231
|
const date = cell.dataset.date || "";
|
|
1180
1232
|
const position = rangePosition(date, this._highlightedRange);
|
|
1233
|
+
if (position === rangePosition(date, previousRange) && previousPreview === this._paintedPreview)
|
|
1234
|
+
continue;
|
|
1181
1235
|
for (const [name, on] of Object.entries(rangeAttributeMap(position))) {
|
|
1182
1236
|
if (on)
|
|
1183
1237
|
cell.setAttribute(name, "true");
|
|
1184
1238
|
else
|
|
1185
1239
|
cell.removeAttribute(name);
|
|
1186
1240
|
}
|
|
1187
|
-
|
|
1241
|
+
if (!previousPreview || !this._paintedPreview) {
|
|
1242
|
+
const state = this._renderedStates.get(date) || {};
|
|
1243
|
+
const label = this._dayLabel(date, state, position);
|
|
1244
|
+
if (cell.getAttribute("aria-label") !== label)
|
|
1245
|
+
cell.setAttribute("aria-label", label);
|
|
1246
|
+
}
|
|
1188
1247
|
}
|
|
1189
1248
|
}
|
|
1190
1249
|
focusGrid() {
|
|
@@ -1347,10 +1406,12 @@
|
|
|
1347
1406
|
return `<option value="${String(month).padStart(2, "0")}"${month === displayMonth ? " selected" : ""}${disabled ? " disabled" : ""}>${escapeHtml(name)}</option>`;
|
|
1348
1407
|
}).join("");
|
|
1349
1408
|
const dayHeaders = weekdayShort.map((name, index) => `<th scope="col" abbr="${escapeHtml(weekdayLong[index])}">${escapeHtml(name.replace(".", ""))}</th>`).join("");
|
|
1409
|
+
this._renderedStates.clear();
|
|
1350
1410
|
const rows = weeks.map((week) => {
|
|
1351
1411
|
const weekNumber = showWeeks ? `<th scope="row" class="dp-week-number">${isoWeekNumber(week[0])}</th>` : "";
|
|
1352
1412
|
const cells = week.map((date) => {
|
|
1353
1413
|
const state = this.getDateState(date);
|
|
1414
|
+
this._renderedStates.set(date, state);
|
|
1354
1415
|
const outside = monthKey(date) !== display;
|
|
1355
1416
|
const selected = this.value === date;
|
|
1356
1417
|
const focused = this.focusedDate === date;
|
|
@@ -1365,18 +1426,22 @@
|
|
|
1365
1426
|
const focusKey = focusedElement instanceof HTMLElement && this.contains(focusedElement) ? this._focusTargetKey(focusedElement) : "";
|
|
1366
1427
|
const yearFirst = monthYearOrder(locale)[0] === "year";
|
|
1367
1428
|
this.toggleAttribute("data-year-first", yearFirst);
|
|
1429
|
+
const classes = this._controlClasses;
|
|
1430
|
+
const monthClass = escapeHtml(classes.month || "dp-skin");
|
|
1431
|
+
const yearClass = escapeHtml(classes.year || "dp-skin");
|
|
1432
|
+
const navClass = escapeHtml(classes.nav || "dp-skin");
|
|
1368
1433
|
const monthControl = `<label class="dp-visually-hidden" for="${this._id}-month">${escapeHtml(this._messages.month)}</label>
|
|
1369
|
-
<select id="${this._id}-month" class="dp-month-select" aria-label="${escapeHtml(this._messages.month)}">${monthOptions}</select>`;
|
|
1434
|
+
<select id="${this._id}-month" class="dp-month-select ${monthClass}" aria-label="${escapeHtml(this._messages.month)}">${monthOptions}</select>`;
|
|
1370
1435
|
const yearControl = `<label class="dp-visually-hidden" for="${this._id}-year">${escapeHtml(this._messages.year)}</label>
|
|
1371
|
-
<input id="${this._id}-year" class="dp-year-input" type="number" inputmode="numeric" value="${displayYear}"${minYearAttr}${maxYearAttr} aria-label="${escapeHtml(this._messages.year)}">`;
|
|
1436
|
+
<input id="${this._id}-year" class="dp-year-input ${yearClass}" type="number" inputmode="numeric" value="${displayYear}"${minYearAttr}${maxYearAttr} aria-label="${escapeHtml(this._messages.year)}">`;
|
|
1372
1437
|
this._rendering = true;
|
|
1373
1438
|
this.innerHTML = `
|
|
1374
1439
|
<div class="dp-calendar-shell">
|
|
1375
1440
|
<div class="dp-calendar-header">
|
|
1376
1441
|
${yearFirst ? yearControl : monthControl}
|
|
1377
1442
|
${yearFirst ? monthControl : yearControl}
|
|
1378
|
-
<button type="button" class="dp-nav dp-prev" data-calendar-action="previous" aria-label="${escapeHtml(this._messages.previousMonth)}"${prevDisabled ? " disabled" : ""}><svg aria-hidden="true" viewBox="0 0 16 16" fill="none" stroke="currentColor" stroke-width="1.5" stroke-linecap="round" stroke-linejoin="round"><path d="m4 10 4-4 4 4"/></svg></button>
|
|
1379
|
-
<button type="button" class="dp-nav dp-next" data-calendar-action="next" aria-label="${escapeHtml(this._messages.nextMonth)}"${nextDisabled ? " disabled" : ""}><svg aria-hidden="true" viewBox="0 0 16 16" fill="none" stroke="currentColor" stroke-width="1.5" stroke-linecap="round" stroke-linejoin="round"><path d="m4 6 4 4 4-4"/></svg></button>
|
|
1443
|
+
<button type="button" class="dp-nav dp-prev ${navClass}" data-calendar-action="previous" aria-label="${escapeHtml(this._messages.previousMonth)}"${prevDisabled ? " disabled" : ""}><svg aria-hidden="true" viewBox="0 0 16 16" fill="none" stroke="currentColor" stroke-width="1.5" stroke-linecap="round" stroke-linejoin="round"><path d="m4 10 4-4 4 4"/></svg></button>
|
|
1444
|
+
<button type="button" class="dp-nav dp-next ${navClass}" data-calendar-action="next" aria-label="${escapeHtml(this._messages.nextMonth)}"${nextDisabled ? " disabled" : ""}><svg aria-hidden="true" viewBox="0 0 16 16" fill="none" stroke="currentColor" stroke-width="1.5" stroke-linecap="round" stroke-linejoin="round"><path d="m4 6 4 4 4-4"/></svg></button>
|
|
1380
1445
|
</div>
|
|
1381
1446
|
<h2 id="${headingId}" class="dp-calendar-heading dp-visually-hidden" aria-live="polite">${escapeHtml(formatMonthYear(`${display}-15`, locale))}</h2>
|
|
1382
1447
|
<table id="${gridId}" class="dp-grid" role="grid" aria-labelledby="${headingId}">
|
|
@@ -1406,7 +1471,7 @@
|
|
|
1406
1471
|
const extra = cell.querySelector(".dp-day-extra");
|
|
1407
1472
|
if (!(extra instanceof HTMLElement))
|
|
1408
1473
|
continue;
|
|
1409
|
-
const content = this._renderDay(date, this.
|
|
1474
|
+
const content = this._renderDay(date, this._renderedStates.get(date) || {});
|
|
1410
1475
|
if (content instanceof Node)
|
|
1411
1476
|
extra.append(content);
|
|
1412
1477
|
else if (content !== undefined && content !== null)
|
|
@@ -1422,13 +1487,15 @@
|
|
|
1422
1487
|
function crossAxisFor(side) {
|
|
1423
1488
|
return side === "top" || side === "bottom" ? "x" : "y";
|
|
1424
1489
|
}
|
|
1490
|
+
var OPPOSITE = { top: "bottom", bottom: "top", left: "right", right: "left" };
|
|
1491
|
+
var PLACEMENTS = new Set(Object.keys(OPPOSITE).flatMap((side) => [side, `${side}-start`, `${side}-end`]));
|
|
1492
|
+
var COORDINATE_SPACES = new Set(["viewport", "document"]);
|
|
1425
1493
|
function parsePlacement(placement) {
|
|
1494
|
+
if (!PLACEMENTS.has(placement))
|
|
1495
|
+
throw new TypeError(`Unknown placement: ${placement}`);
|
|
1426
1496
|
const [side, align = null] = placement.split("-");
|
|
1427
1497
|
return { side, align, crossAxis: crossAxisFor(side) };
|
|
1428
1498
|
}
|
|
1429
|
-
function flipSide(side) {
|
|
1430
|
-
return { top: "bottom", bottom: "top", left: "right", right: "left" }[side] || side;
|
|
1431
|
-
}
|
|
1432
1499
|
function computeCoords(reference, floating, side, align, rtl, distance) {
|
|
1433
1500
|
const crossAxis = crossAxisFor(side);
|
|
1434
1501
|
const commonX = reference.x + reference.width / 2 - floating.width / 2;
|
|
@@ -1460,17 +1527,12 @@
|
|
|
1460
1527
|
function overflowOn(position, size, start, end) {
|
|
1461
1528
|
return Math.max(start - position, 0) + Math.max(position + size - end, 0);
|
|
1462
1529
|
}
|
|
1463
|
-
function isRTL(
|
|
1464
|
-
const
|
|
1465
|
-
if (
|
|
1466
|
-
return
|
|
1467
|
-
if (direction === "ltr")
|
|
1468
|
-
return false;
|
|
1469
|
-
const win = element.ownerDocument?.defaultView;
|
|
1470
|
-
if (win?.CSS?.supports?.("selector(:dir(rtl))") && typeof element.matches === "function") {
|
|
1471
|
-
return element.matches(":dir(rtl)");
|
|
1530
|
+
function isRTL(reference) {
|
|
1531
|
+
const win = reference.ownerDocument?.defaultView;
|
|
1532
|
+
if (win && reference instanceof win.Element) {
|
|
1533
|
+
return win.getComputedStyle(reference).direction === "rtl";
|
|
1472
1534
|
}
|
|
1473
|
-
return
|
|
1535
|
+
return "dir" in reference && reference.dir === "rtl";
|
|
1474
1536
|
}
|
|
1475
1537
|
var STABLE_SCROLLBAR_MAX_WIDTH = 25;
|
|
1476
1538
|
function getViewportBoundary(doc) {
|
|
@@ -1508,8 +1570,14 @@
|
|
|
1508
1570
|
const percent = (referenceCenter - boxStart) / size * 100;
|
|
1509
1571
|
return Math.round(Math.min(100, Math.max(0, percent)) * 1000) / 1000;
|
|
1510
1572
|
}
|
|
1511
|
-
function isOutsideBoundary(
|
|
1512
|
-
|
|
1573
|
+
function isOutsideBoundary(rects, boundary) {
|
|
1574
|
+
for (let i = 0;i < rects.length; i++) {
|
|
1575
|
+
const rect = rects[i];
|
|
1576
|
+
if (rect.right >= boundary.x && rect.left <= boundary.right && rect.bottom >= boundary.y && rect.top <= boundary.bottom) {
|
|
1577
|
+
return false;
|
|
1578
|
+
}
|
|
1579
|
+
}
|
|
1580
|
+
return true;
|
|
1513
1581
|
}
|
|
1514
1582
|
function getAvailableHeight(referenceRect, side, boundary, distance, padding) {
|
|
1515
1583
|
if (side === "top") {
|
|
@@ -1564,10 +1632,22 @@
|
|
|
1564
1632
|
for (const [subscription, type] of notifications) {
|
|
1565
1633
|
if (!subscriptions.has(subscription) || !subscription.floating.isConnected)
|
|
1566
1634
|
continue;
|
|
1567
|
-
|
|
1635
|
+
try {
|
|
1636
|
+
subscription.callback({ type });
|
|
1637
|
+
} catch (error) {
|
|
1638
|
+
reportError(error);
|
|
1639
|
+
}
|
|
1568
1640
|
}
|
|
1569
1641
|
});
|
|
1570
1642
|
}
|
|
1643
|
+
function reportError(error) {
|
|
1644
|
+
if (typeof win.reportError === "function")
|
|
1645
|
+
win.reportError(error);
|
|
1646
|
+
else
|
|
1647
|
+
win.setTimeout(() => {
|
|
1648
|
+
throw error;
|
|
1649
|
+
});
|
|
1650
|
+
}
|
|
1571
1651
|
function notifyAll(type) {
|
|
1572
1652
|
for (const subscription of subscriptions)
|
|
1573
1653
|
queue(subscription, type);
|
|
@@ -1658,28 +1738,32 @@
|
|
|
1658
1738
|
return trackerFor(floating).add(reference, floating, callback);
|
|
1659
1739
|
}
|
|
1660
1740
|
function positionOnce(reference, floating, options) {
|
|
1741
|
+
const placement = options.placement === undefined ? "bottom-start" : options.placement;
|
|
1742
|
+
let { side, align, crossAxis } = parsePlacement(placement);
|
|
1743
|
+
const coordinateSpace = options.coordinateSpace === undefined ? "viewport" : options.coordinateSpace;
|
|
1744
|
+
if (!COORDINATE_SPACES.has(coordinateSpace)) {
|
|
1745
|
+
throw new TypeError(`Unknown coordinateSpace: ${coordinateSpace}`);
|
|
1746
|
+
}
|
|
1661
1747
|
if (!isVisible(floating))
|
|
1662
1748
|
return null;
|
|
1663
|
-
const placement = options.placement || "bottom-start";
|
|
1664
1749
|
const distance = options.distance || 0;
|
|
1665
1750
|
const flip = options.flip !== false;
|
|
1666
1751
|
const shift = options.shift !== false;
|
|
1667
1752
|
const shiftPadding = options.shiftPadding ?? 4;
|
|
1668
|
-
let { side, align, crossAxis } = parsePlacement(placement);
|
|
1669
1753
|
const rtl = align ? isRTL(reference) : false;
|
|
1670
1754
|
const rects = reference.getClientRects();
|
|
1671
|
-
|
|
1672
|
-
if (!referenceRect)
|
|
1755
|
+
if (!rects.length)
|
|
1673
1756
|
return null;
|
|
1757
|
+
const rectFor = (s) => s === "bottom" ? rects[rects.length - 1] : rects[0];
|
|
1674
1758
|
const boundary = getBoundary(reference, options);
|
|
1675
|
-
if (!boundary || isOutsideBoundary(
|
|
1759
|
+
if (!boundary || isOutsideBoundary(rects, boundary))
|
|
1676
1760
|
return null;
|
|
1677
1761
|
const floatingRect = getFloatingSize(floating);
|
|
1678
1762
|
const limits = {
|
|
1679
1763
|
x: { size: floatingRect.width, start: boundary.x, end: boundary.right },
|
|
1680
1764
|
y: { size: floatingRect.height, start: boundary.y, end: boundary.bottom }
|
|
1681
1765
|
};
|
|
1682
|
-
const place = (nextSide, nextAlign) => computeCoords(
|
|
1766
|
+
const place = (nextSide, nextAlign) => computeCoords(rectFor(nextSide), floatingRect, nextSide, nextAlign, rtl, distance);
|
|
1683
1767
|
const overflowAt = (position, axis) => {
|
|
1684
1768
|
const { size, start, end } = limits[axis];
|
|
1685
1769
|
return overflowOn(position, size, start + shiftPadding, end - shiftPadding);
|
|
@@ -1689,31 +1773,30 @@
|
|
|
1689
1773
|
return overflowAt(shift ? clampToBoundary(position, size, start, end, shiftPadding) : position, axis);
|
|
1690
1774
|
};
|
|
1691
1775
|
let coords = place(side, align);
|
|
1776
|
+
const overflowFor = (nextSide, at) => {
|
|
1777
|
+
const cross = crossAxisFor(nextSide);
|
|
1778
|
+
const main = cross === "x" ? "y" : "x";
|
|
1779
|
+
const mainOverflow = overflowAt(at[main], main);
|
|
1780
|
+
return { main: mainOverflow, total: mainOverflow + shiftedOverflowAt(at[cross], cross) };
|
|
1781
|
+
};
|
|
1692
1782
|
if (flip) {
|
|
1693
|
-
|
|
1694
|
-
|
|
1695
|
-
|
|
1696
|
-
const
|
|
1697
|
-
|
|
1698
|
-
|
|
1699
|
-
|
|
1700
|
-
|
|
1701
|
-
coords = flipped;
|
|
1702
|
-
overflow = flippedOverflow;
|
|
1703
|
-
}
|
|
1704
|
-
}
|
|
1705
|
-
if (mainAxis === "x" && overflow > 0) {
|
|
1706
|
-
const above = place("top", align);
|
|
1707
|
-
const below = place("bottom", align);
|
|
1708
|
-
const useBottom = overflowAt(below.y, "y") < overflowAt(above.y, "y");
|
|
1709
|
-
const candidate = useBottom ? below : above;
|
|
1710
|
-
const swapped = overflowAt(candidate.y, "y") + shiftedOverflowAt(candidate.x, "x");
|
|
1711
|
-
if (swapped < overflow + shiftedOverflowAt(coords.y, "y")) {
|
|
1712
|
-
side = useBottom ? "bottom" : "top";
|
|
1713
|
-
crossAxis = "x";
|
|
1714
|
-
coords = candidate;
|
|
1783
|
+
let best = overflowFor(side, coords);
|
|
1784
|
+
const consider = (nextSide) => {
|
|
1785
|
+
const next = place(nextSide, align);
|
|
1786
|
+
const overflow = overflowFor(nextSide, next);
|
|
1787
|
+
if (overflow.total < best.total) {
|
|
1788
|
+
side = nextSide;
|
|
1789
|
+
coords = next;
|
|
1790
|
+
best = overflow;
|
|
1715
1791
|
}
|
|
1792
|
+
};
|
|
1793
|
+
if (best.main > 0)
|
|
1794
|
+
consider(OPPOSITE[side]);
|
|
1795
|
+
if (crossAxis === "y" && best.main > 0) {
|
|
1796
|
+
consider("top");
|
|
1797
|
+
consider("bottom");
|
|
1716
1798
|
}
|
|
1799
|
+
crossAxis = crossAxisFor(side);
|
|
1717
1800
|
}
|
|
1718
1801
|
if (crossAxis === "x" && shift && align) {
|
|
1719
1802
|
const overflow = overflowAt(coords.x, "x");
|
|
@@ -1730,12 +1813,13 @@
|
|
|
1730
1813
|
const { size, start, end } = limits[crossAxis];
|
|
1731
1814
|
coords[crossAxis] = clampToBoundary(coords[crossAxis], size, start, end, shiftPadding);
|
|
1732
1815
|
}
|
|
1733
|
-
const
|
|
1734
|
-
const
|
|
1735
|
-
const
|
|
1816
|
+
const resolvedRect = rectFor(side);
|
|
1817
|
+
const arrowX = arrowPercent(resolvedRect.x + resolvedRect.width / 2, coords.x, floatingRect.width);
|
|
1818
|
+
const arrowY = arrowPercent(resolvedRect.y + resolvedRect.height / 2, coords.y, floatingRect.height);
|
|
1819
|
+
const availableHeight = `${getAvailableHeight(resolvedRect, side, boundary, distance, shiftPadding)}px`;
|
|
1736
1820
|
const { style } = floating;
|
|
1737
1821
|
const roomChanged = style.getPropertyValue("--available-height") !== availableHeight;
|
|
1738
|
-
const win =
|
|
1822
|
+
const win = coordinateSpace === "document" ? reference.ownerDocument.defaultView : null;
|
|
1739
1823
|
const originX = win ? win.scrollX : 0;
|
|
1740
1824
|
const originY = win ? win.scrollY : 0;
|
|
1741
1825
|
style.left = `${coords.x + originX}px`;
|
|
@@ -1863,7 +1947,7 @@
|
|
|
1863
1947
|
input.setCustomValidity("");
|
|
1864
1948
|
return;
|
|
1865
1949
|
}
|
|
1866
|
-
input.setCustomValidity(
|
|
1950
|
+
input.setCustomValidity(this.messages.invalidDate);
|
|
1867
1951
|
}
|
|
1868
1952
|
async commit(options = {}) {
|
|
1869
1953
|
const input = this.input;
|
|
@@ -1993,6 +2077,7 @@
|
|
|
1993
2077
|
this._open = false;
|
|
1994
2078
|
this._suppressFocusOpen = false;
|
|
1995
2079
|
this._messages = getDefaultMessages();
|
|
2080
|
+
this._controlClasses = getDefaultControlClasses();
|
|
1996
2081
|
this._source = null;
|
|
1997
2082
|
this._dateState = null;
|
|
1998
2083
|
this._renderDay = null;
|
|
@@ -2247,6 +2332,17 @@
|
|
|
2247
2332
|
get open() {
|
|
2248
2333
|
return this._open;
|
|
2249
2334
|
}
|
|
2335
|
+
get controlClasses() {
|
|
2336
|
+
return { ...this._controlClasses };
|
|
2337
|
+
}
|
|
2338
|
+
set controlClasses(value) {
|
|
2339
|
+
const classes = resolveControlClasses(value);
|
|
2340
|
+
if (sameControlClasses(classes, this._controlClasses))
|
|
2341
|
+
return;
|
|
2342
|
+
this._controlClasses = classes;
|
|
2343
|
+
if (this._calendar)
|
|
2344
|
+
this._calendar.controlClasses = this._controlClasses;
|
|
2345
|
+
}
|
|
2250
2346
|
get messages() {
|
|
2251
2347
|
return this._messages;
|
|
2252
2348
|
}
|
|
@@ -2410,6 +2506,23 @@
|
|
|
2410
2506
|
this._refreshLocale();
|
|
2411
2507
|
this._refreshButtonLabel();
|
|
2412
2508
|
}
|
|
2509
|
+
_bindPopup(signal, input, restore) {
|
|
2510
|
+
this.ownerDocument.addEventListener("pointerdown", (event) => {
|
|
2511
|
+
if (!this._open || event.composedPath().includes(this))
|
|
2512
|
+
return;
|
|
2513
|
+
this.hide(false);
|
|
2514
|
+
}, { capture: true, signal });
|
|
2515
|
+
this.ownerDocument.addEventListener("reset", (event) => {
|
|
2516
|
+
if (!(event.target instanceof HTMLFormElement) || !input || event.target !== input.form)
|
|
2517
|
+
return;
|
|
2518
|
+
this.hide(false);
|
|
2519
|
+
queueMicrotask(() => {
|
|
2520
|
+
if (!event.defaultPrevented)
|
|
2521
|
+
restore();
|
|
2522
|
+
});
|
|
2523
|
+
}, { capture: true, signal });
|
|
2524
|
+
this.addEventListener("keydown", (event) => this._onEscape(event), { signal });
|
|
2525
|
+
}
|
|
2413
2526
|
_bind() {
|
|
2414
2527
|
const input = this._input;
|
|
2415
2528
|
const button = this._buttons[0]?.button;
|
|
@@ -2472,22 +2585,7 @@
|
|
|
2472
2585
|
});
|
|
2473
2586
|
}, { signal });
|
|
2474
2587
|
calendar.addEventListener("dateloadend", () => void this.validate(), { signal });
|
|
2475
|
-
this.
|
|
2476
|
-
if (!this._open || event.composedPath().includes(this))
|
|
2477
|
-
return;
|
|
2478
|
-
this.hide(false);
|
|
2479
|
-
}, { capture: true, signal });
|
|
2480
|
-
this.ownerDocument.addEventListener("reset", (event) => {
|
|
2481
|
-
const form = event.target;
|
|
2482
|
-
if (form instanceof HTMLFormElement && this._input && form === this._input.form) {
|
|
2483
|
-
this.hide(false);
|
|
2484
|
-
queueMicrotask(() => {
|
|
2485
|
-
if (!event.defaultPrevented)
|
|
2486
|
-
this._restoreDefault();
|
|
2487
|
-
});
|
|
2488
|
-
}
|
|
2489
|
-
}, { capture: true, signal });
|
|
2490
|
-
this.addEventListener("keydown", (event) => this._onEscape(event), { signal });
|
|
2588
|
+
this._bindPopup(signal, this._input, () => this._restoreDefault());
|
|
2491
2589
|
}
|
|
2492
2590
|
_bindRange() {
|
|
2493
2591
|
const calendar = this._calendar;
|
|
@@ -2567,22 +2665,7 @@
|
|
|
2567
2665
|
calendar.addEventListener("pointercancel", (event) => this._onGridPointerCancel(event), { signal });
|
|
2568
2666
|
calendar.addEventListener("lostpointercapture", (event) => this._onGridPointerCancel(event), { signal });
|
|
2569
2667
|
calendar.addEventListener("dateloadend", () => void this.validate(), { signal });
|
|
2570
|
-
this.
|
|
2571
|
-
if (!this._open || event.composedPath().includes(this))
|
|
2572
|
-
return;
|
|
2573
|
-
this.hide(false);
|
|
2574
|
-
}, { capture: true, signal });
|
|
2575
|
-
this.ownerDocument.addEventListener("reset", (event) => {
|
|
2576
|
-
const form = event.target;
|
|
2577
|
-
if (form instanceof HTMLFormElement && this._fields && form === this._fields[0].input.form) {
|
|
2578
|
-
this.hide(false);
|
|
2579
|
-
queueMicrotask(() => {
|
|
2580
|
-
if (!event.defaultPrevented)
|
|
2581
|
-
this._restoreRangeDefault();
|
|
2582
|
-
});
|
|
2583
|
-
}
|
|
2584
|
-
}, { capture: true, signal });
|
|
2585
|
-
this.addEventListener("keydown", (event) => this._onEscape(event), { signal });
|
|
2668
|
+
this._bindPopup(signal, this._fields?.[0]?.input, () => this._restoreRangeDefault());
|
|
2586
2669
|
}
|
|
2587
2670
|
_activateRangeEndpoint(endpoint) {
|
|
2588
2671
|
const calendar = this._calendar;
|
|
@@ -2879,6 +2962,7 @@
|
|
|
2879
2962
|
calendar.min = this.min;
|
|
2880
2963
|
calendar.max = this.max;
|
|
2881
2964
|
calendar.monthFormat = this.monthFormat;
|
|
2965
|
+
calendar.controlClasses = this._controlClasses;
|
|
2882
2966
|
calendar.messages = this._messages;
|
|
2883
2967
|
calendar.source = this._source;
|
|
2884
2968
|
calendar.dateState = this._dateState;
|